🔥 change codegen::gen to codegen::emit

This commit is contained in:
ValKmjolnir 2023-09-23 01:08:45 +08:00
parent 0a404694f6
commit f8ecd2ae53
9 changed files with 246 additions and 213 deletions

View File

@ -307,7 +307,9 @@ var builtin_substr(var* local, gc& ngc) {
var builtin_streq(var* local, gc& ngc) { var builtin_streq(var* local, gc& ngc) {
var a = local[1]; var a = local[1];
var b = local[2]; var b = local[2];
return var::num(f64((a.type!=vm_str || b.type!=vm_str)? 0:(a.str()==b.str()))); return var::num(static_cast<f64>(
(a.type!=vm_str || b.type!=vm_str)? 0:(a.str()==b.str())
));
} }
var builtin_left(var* local, gc& ngc) { var builtin_left(var* local, gc& ngc) {
@ -410,9 +412,11 @@ var builtin_sleep(var* local, gc& ngc) {
#if defined(_WIN32) && !defined(_GLIBCXX_HAS_GTHREADS) #if defined(_WIN32) && !defined(_GLIBCXX_HAS_GTHREADS)
// mingw-w64 win32 thread model has no std::this_thread // mingw-w64 win32 thread model has no std::this_thread
// also msvc will use this // also msvc will use this
Sleep(i64(val.num()*1e3)); Sleep(static_cast<i64>(val.num()*1e3));
#else #else
std::this_thread::sleep_for(std::chrono::microseconds(i64(val.num()*1e6))); std::this_thread::sleep_for(
std::chrono::microseconds(static_cast<i64>(val.num()*1e6))
);
#endif #endif
return nil; return nil;
} }
@ -469,7 +473,7 @@ std::string md5(const std::string& src) {
usize buffsize = num<<4; usize buffsize = num<<4;
buff.resize(buffsize,0); buff.resize(buffsize,0);
for(usize i = 0; i<src.length(); i++) { for(usize i = 0; i<src.length(); i++) {
buff[i>>2] |= ((u8)src[i])<<((i&0x3)<<3); buff[i>>2] |= (static_cast<u8>(src[i]))<<((i&0x3)<<3);
} }
buff[src.length()>>2] |= 0x80<<(((src.length()%4))<<3); buff[src.length()>>2] |= 0x80<<(((src.length()%4))<<3);
buff[buffsize-2] = (src.length()<<3)&0xffffffff; buff[buffsize-2] = (src.length()<<3)&0xffffffff;

View File

@ -133,44 +133,47 @@ i32 codegen::upvalue_find(const std::string& name) {
return index; return index;
} }
void codegen::gen(u8 operation_code, u32 num, const span& loc) { void codegen::emit(u8 operation_code, u32 immediate_num, const span& location) {
code.push_back({operation_code, code.push_back({
static_cast<u16>(file_map.at(loc.file)), operation_code,
num, loc.begin_line}); static_cast<u16>(file_map.at(location.file)),
immediate_num,
location.begin_line
});
} }
void codegen::num_gen(number_literal* node) { void codegen::num_gen(number_literal* node) {
f64 num = node->get_number(); f64 num = node->get_number();
regist_num(num); regist_num(num);
gen(op_pnum, const_number_map.at(num), node->get_location()); emit(op_pnum, const_number_map.at(num), node->get_location());
} }
void codegen::str_gen(string_literal* node) { void codegen::str_gen(string_literal* node) {
const auto& str = node->get_content(); const auto& str = node->get_content();
regist_str(str); regist_str(str);
gen(op_pstr, const_string_map.at(str), node->get_location()); emit(op_pstr, const_string_map.at(str), node->get_location());
} }
void codegen::bool_gen(bool_literal* node) { void codegen::bool_gen(bool_literal* node) {
f64 num = node->get_flag()? 1:0; f64 num = node->get_flag()? 1:0;
regist_num(num); regist_num(num);
gen(op_pnum, const_number_map.at(num), node->get_location()); emit(op_pnum, const_number_map.at(num), node->get_location());
} }
void codegen::vec_gen(vector_expr* node) { void codegen::vec_gen(vector_expr* node) {
for(auto child : node->get_elements()) { for(auto child : node->get_elements()) {
calc_gen(child); calc_gen(child);
} }
gen(op_newv, node->get_elements().size(), node->get_location()); emit(op_newv, node->get_elements().size(), node->get_location());
} }
void codegen::hash_gen(hash_expr* node) { void codegen::hash_gen(hash_expr* node) {
gen(op_newh, 0, node->get_location()); emit(op_newh, 0, node->get_location());
for(auto child : node->get_members()) { for(auto child : node->get_members()) {
calc_gen(child->get_value()); calc_gen(child->get_value());
const auto& field_name = child->get_name(); const auto& field_name = child->get_name();
regist_str(field_name); regist_str(field_name);
gen(op_happ, const_string_map.at(field_name), child->get_location()); emit(op_happ, const_string_map.at(field_name), child->get_location());
} }
} }
@ -210,9 +213,9 @@ void codegen::func_gen(function* node) {
} }
usize newf=code.size(); usize newf=code.size();
gen(op_newf, 0, node->get_location()); emit(op_newf, 0, node->get_location());
usize lsize=code.size(); usize lsize=code.size();
gen(op_intl, 0, node->get_location()); emit(op_intl, 0, node->get_location());
// add special keyword 'me' into symbol table // add special keyword 'me' into symbol table
// this symbol is only used in local scope(function's scope) // this symbol is only used in local scope(function's scope)
@ -231,14 +234,14 @@ void codegen::func_gen(function* node) {
regist_str(name); regist_str(name);
switch(tmp->get_parameter_type()) { switch(tmp->get_parameter_type()) {
case parameter::param_type::normal_parameter: case parameter::param_type::normal_parameter:
gen(op_para, const_string_map.at(name), tmp->get_location()); emit(op_para, const_string_map.at(name), tmp->get_location());
break; break;
case parameter::param_type::default_parameter: case parameter::param_type::default_parameter:
calc_gen(tmp->get_default_value()); calc_gen(tmp->get_default_value());
gen(op_deft, const_string_map.at(name), tmp->get_location()); emit(op_deft, const_string_map.at(name), tmp->get_location());
break; break;
case parameter::param_type::dynamic_parameter: case parameter::param_type::dynamic_parameter:
gen(op_dyn, const_string_map.at(name), tmp->get_location()); emit(op_dyn, const_string_map.at(name), tmp->get_location());
break; break;
} }
add_symbol(name); add_symbol(name);
@ -246,7 +249,7 @@ void codegen::func_gen(function* node) {
code[newf].num = code.size()+1; // entry code[newf].num = code.size()+1; // entry
usize jmp_ptr = code.size(); usize jmp_ptr = code.size();
gen(op_jmp, 0, node->get_location()); emit(op_jmp, 0, node->get_location());
auto block = node->get_code_block(); auto block = node->get_code_block();
// search symbols first, must use after loading parameters // search symbols first, must use after loading parameters
@ -279,8 +282,8 @@ void codegen::func_gen(function* node) {
if (!block->get_expressions().size() || if (!block->get_expressions().size() ||
block->get_expressions().back()->get_type()!=expr_type::ast_ret) { block->get_expressions().back()->get_type()!=expr_type::ast_ret) {
gen(op_pnil, 0, block->get_location()); emit(op_pnil, 0, block->get_location());
gen(op_ret, 0, block->get_location()); emit(op_ret, 0, block->get_location());
} }
code[jmp_ptr].num = code.size(); code[jmp_ptr].num = code.size();
} }
@ -303,7 +306,7 @@ void codegen::call_gen(call_expr* node) {
void codegen::call_id(identifier* node) { void codegen::call_id(identifier* node) {
const auto& name = node->get_name(); const auto& name = node->get_name();
if (native_function_mapper.count(name)) { if (native_function_mapper.count(name)) {
gen(op_callb, emit(op_callb,
static_cast<u32>(native_function_mapper.at(name)), static_cast<u32>(native_function_mapper.at(name)),
node->get_location()); node->get_location());
if (local.empty()) { if (local.empty()) {
@ -315,15 +318,15 @@ void codegen::call_id(identifier* node) {
i32 index; i32 index;
if ((index=local_find(name))>=0) { if ((index=local_find(name))>=0) {
gen(op_calll, index, node->get_location()); emit(op_calll, index, node->get_location());
return; return;
} }
if ((index=upvalue_find(name))>=0) { if ((index=upvalue_find(name))>=0) {
gen(op_upval, index, node->get_location()); emit(op_upval, index, node->get_location());
return; return;
} }
if ((index=global_find(name))>=0) { if ((index=global_find(name))>=0) {
gen(op_callg, index, node->get_location()); emit(op_callg, index, node->get_location());
return; return;
} }
die("undefined symbol \"" + name + "\"", node->get_location()); die("undefined symbol \"" + name + "\"", node->get_location());
@ -331,7 +334,7 @@ void codegen::call_id(identifier* node) {
void codegen::call_hash_gen(call_hash* node) { void codegen::call_hash_gen(call_hash* node) {
regist_str(node->get_field()); regist_str(node->get_field());
gen(op_callh, const_string_map.at(node->get_field()), node->get_location()); emit(op_callh, const_string_map.at(node->get_field()), node->get_location());
} }
void codegen::call_vector_gen(call_vector* node) { void codegen::call_vector_gen(call_vector* node) {
@ -339,39 +342,39 @@ void codegen::call_vector_gen(call_vector* node) {
if (node->get_slices().size()==1 && if (node->get_slices().size()==1 &&
!node->get_slices()[0]->get_end()) { !node->get_slices()[0]->get_end()) {
calc_gen(node->get_slices()[0]->get_begin()); calc_gen(node->get_slices()[0]->get_begin());
gen(op_callv, 0, node->get_slices()[0]->get_location()); emit(op_callv, 0, node->get_slices()[0]->get_location());
return; return;
} }
gen(op_slcbeg, 0, node->get_location()); emit(op_slcbeg, 0, node->get_location());
for(auto tmp : node->get_slices()) { for(auto tmp : node->get_slices()) {
if (!tmp->get_end()) { if (!tmp->get_end()) {
calc_gen(tmp->get_begin()); calc_gen(tmp->get_begin());
gen(op_slc, 0, tmp->get_location()); emit(op_slc, 0, tmp->get_location());
} else { } else {
calc_gen(tmp->get_begin()); calc_gen(tmp->get_begin());
calc_gen(tmp->get_end()); calc_gen(tmp->get_end());
gen(op_slc2, 0, tmp->get_location()); emit(op_slc2, 0, tmp->get_location());
} }
} }
gen(op_slcend, 0, node->get_location()); emit(op_slcend, 0, node->get_location());
} }
void codegen::call_func_gen(call_function* node) { void codegen::call_func_gen(call_function* node) {
if (node->get_argument().size() && if (node->get_argument().size() &&
node->get_argument()[0]->get_type()==expr_type::ast_pair) { node->get_argument()[0]->get_type()==expr_type::ast_pair) {
gen(op_newh, 0, node->get_location()); emit(op_newh, 0, node->get_location());
for(auto child : node->get_argument()) { for(auto child : node->get_argument()) {
calc_gen(((hash_pair*)child)->get_value()); calc_gen(((hash_pair*)child)->get_value());
const auto& field_name = ((hash_pair*)child)->get_name(); const auto& field_name = ((hash_pair*)child)->get_name();
regist_str(field_name); regist_str(field_name);
gen(op_happ, const_string_map.at(field_name), child->get_location()); emit(op_happ, const_string_map.at(field_name), child->get_location());
} }
gen(op_callfh, 0, node->get_location()); emit(op_callfh, 0, node->get_location());
} else { } else {
for(auto child : node->get_argument()) { for(auto child : node->get_argument()) {
calc_gen(child); calc_gen(child);
} }
gen(op_callfv, node->get_argument().size(), node->get_location()); emit(op_callfv, node->get_argument().size(), node->get_location());
} }
} }
@ -425,15 +428,15 @@ void codegen::mcall_id(identifier* node) {
i32 index; i32 index;
if ((index=local_find(name))>=0) { if ((index=local_find(name))>=0) {
gen(op_mcalll, index, node->get_location()); emit(op_mcalll, index, node->get_location());
return; return;
} }
if ((index=upvalue_find(name))>=0) { if ((index=upvalue_find(name))>=0) {
gen(op_mupval, index, node->get_location()); emit(op_mupval, index, node->get_location());
return; return;
} }
if ((index=global_find(name))>=0) { if ((index=global_find(name))>=0) {
gen(op_mcallg, index, node->get_location()); emit(op_mcallg, index, node->get_location());
return; return;
} }
die("undefined symbol \"" + name + "\"", node->get_location()); die("undefined symbol \"" + name + "\"", node->get_location());
@ -450,20 +453,22 @@ void codegen::mcall_vec(call_vector* node) {
return; return;
} }
calc_gen(call->get_begin()); calc_gen(call->get_begin());
gen(op_mcallv, 0, node->get_location()); emit(op_mcallv, 0, node->get_location());
} }
void codegen::mcall_hash(call_hash* node) { void codegen::mcall_hash(call_hash* node) {
regist_str(node->get_field()); regist_str(node->get_field());
gen(op_mcallh, const_string_map.at(node->get_field()), node->get_location()); emit(op_mcallh, const_string_map.at(node->get_field()), node->get_location());
} }
void codegen::single_def(definition_expr* node) { void codegen::single_def(definition_expr* node) {
const auto& str = node->get_variable_name()->get_name(); const auto& str = node->get_variable_name()->get_name();
calc_gen(node->get_value()); calc_gen(node->get_value());
local.empty()? if (local.empty()) {
gen(op_loadg, global_find(str), node->get_location()): emit(op_loadg, global_find(str), node->get_location());
gen(op_loadl, local_find(str), node->get_location()); } else {
emit(op_loadl, local_find(str), node->get_location());
}
} }
void codegen::multi_def(definition_expr* node) { void codegen::multi_def(definition_expr* node) {
@ -474,30 +479,32 @@ void codegen::multi_def(definition_expr* node) {
auto& vals = node->get_tuple()->get_elements(); auto& vals = node->get_tuple()->get_elements();
if (identifiers.size()<vals.size()) { if (identifiers.size()<vals.size()) {
die("lack values in multi-definition", die("lack values in multi-definition",
node->get_tuple()->get_location()); node->get_tuple()->get_location()
);
} else if (identifiers.size()>vals.size()) { } else if (identifiers.size()>vals.size()) {
die("too many values in multi-definition", die("too many values in multi-definition",
node->get_tuple()->get_location()); node->get_tuple()->get_location()
);
} }
for(usize i = 0; i<size; ++i) { for(usize i = 0; i<size; ++i) {
calc_gen(vals[i]); calc_gen(vals[i]);
const auto& name = identifiers[i]->get_name(); const auto& name = identifiers[i]->get_name();
local.empty()? local.empty()?
gen(op_loadg, global_find(name), identifiers[i]->get_location()): emit(op_loadg, global_find(name), identifiers[i]->get_location()):
gen(op_loadl, local_find(name), identifiers[i]->get_location()); emit(op_loadl, local_find(name), identifiers[i]->get_location());
} }
return; return;
} }
// (var a,b,c) = [0,1,2]; // (var a,b,c) = [0,1,2];
calc_gen(node->get_value()); calc_gen(node->get_value());
for(usize i = 0; i<size; ++i) { for(usize i = 0; i<size; ++i) {
gen(op_callvi, i, node->get_value()->get_location()); emit(op_callvi, i, node->get_value()->get_location());
const auto& name = identifiers[i]->get_name(); const auto& name = identifiers[i]->get_name();
local.empty()? local.empty()?
gen(op_loadg, global_find(name), identifiers[i]->get_location()): emit(op_loadg, global_find(name), identifiers[i]->get_location()):
gen(op_loadl, local_find(name), identifiers[i]->get_location()); emit(op_loadl, local_find(name), identifiers[i]->get_location());
} }
gen(op_pop, 0, node->get_location()); emit(op_pop, 0, node->get_location());
} }
void codegen::def_gen(definition_expr* node) { void codegen::def_gen(definition_expr* node) {
@ -512,7 +519,7 @@ void codegen::assignment_expression(assignment_expr* node) {
case assignment_expr::assign_type::equal: case assignment_expr::assign_type::equal:
calc_gen(node->get_right()); calc_gen(node->get_right());
mcall(node->get_left()); mcall(node->get_left());
gen(op_meq, 0, node->get_location()); emit(op_meq, 0, node->get_location());
break; break;
case assignment_expr::assign_type::add_equal: case assignment_expr::assign_type::add_equal:
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
@ -520,11 +527,11 @@ void codegen::assignment_expression(assignment_expr* node) {
} }
mcall(node->get_left()); mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
gen(op_addeq, 0, node->get_location()); emit(op_addeq, 0, node->get_location());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_addeqc, const_number_map[num], node->get_location()); emit(op_addeqc, const_number_map[num], node->get_location());
} }
break; break;
case assignment_expr::assign_type::sub_equal: case assignment_expr::assign_type::sub_equal:
@ -533,11 +540,11 @@ void codegen::assignment_expression(assignment_expr* node) {
} }
mcall(node->get_left()); mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
gen(op_subeq, 0, node->get_location()); emit(op_subeq, 0, node->get_location());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_subeqc, const_number_map[num], node->get_location()); emit(op_subeqc, const_number_map[num], node->get_location());
} }
break; break;
case assignment_expr::assign_type::mult_equal: case assignment_expr::assign_type::mult_equal:
@ -546,11 +553,11 @@ void codegen::assignment_expression(assignment_expr* node) {
} }
mcall(node->get_left()); mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
gen(op_muleq, 0, node->get_location()); emit(op_muleq, 0, node->get_location());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_muleqc, const_number_map[num], node->get_location()); emit(op_muleqc, const_number_map[num], node->get_location());
} }
break; break;
case assignment_expr::assign_type::div_equal: case assignment_expr::assign_type::div_equal:
@ -559,11 +566,11 @@ void codegen::assignment_expression(assignment_expr* node) {
} }
mcall(node->get_left()); mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
gen(op_diveq, 0, node->get_location()); emit(op_diveq, 0, node->get_location());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_diveqc, const_number_map[num], node->get_location()); emit(op_diveqc, const_number_map[num], node->get_location());
} }
break; break;
case assignment_expr::assign_type::concat_equal: case assignment_expr::assign_type::concat_equal:
@ -572,53 +579,63 @@ void codegen::assignment_expression(assignment_expr* node) {
} }
mcall(node->get_left()); mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_str) { if (node->get_right()->get_type()!=expr_type::ast_str) {
gen(op_lnkeq, 0, node->get_location()); emit(op_lnkeq, 0, node->get_location());
} else { } else {
const auto& str = ((string_literal*)node->get_right())->get_content(); const auto& str = ((string_literal*)node->get_right())->get_content();
regist_str(str); regist_str(str);
gen(op_lnkeqc, const_string_map[str], node->get_location()); emit(op_lnkeqc, const_string_map[str], node->get_location());
} }
break; break;
case assignment_expr::assign_type::bitwise_and_equal: case assignment_expr::assign_type::bitwise_and_equal:
calc_gen(node->get_right()); calc_gen(node->get_right());
mcall(node->get_left()); mcall(node->get_left());
gen(op_btandeq, 0, node->get_location()); emit(op_btandeq, 0, node->get_location());
break; break;
case assignment_expr::assign_type::bitwise_or_equal: case assignment_expr::assign_type::bitwise_or_equal:
calc_gen(node->get_right()); calc_gen(node->get_right());
mcall(node->get_left()); mcall(node->get_left());
gen(op_btoreq, 0, node->get_location()); emit(op_btoreq, 0, node->get_location());
break; break;
case assignment_expr::assign_type::bitwise_xor_equal: case assignment_expr::assign_type::bitwise_xor_equal:
calc_gen(node->get_right()); calc_gen(node->get_right());
mcall(node->get_left()); mcall(node->get_left());
gen(op_btxoreq, 0, node->get_location()); emit(op_btxoreq, 0, node->get_location());
break; break;
} }
} }
void codegen::gen_assignment_equal_statement(assignment_expr* node) {
// if is not symbol load type assignment, use calc_gen directly
// what is symbol load assignment? example:
// a = 1; # this is symbol load
// a.foo = "bar"; # this is not symbol load
if (node->get_left()->get_type()!=expr_type::ast_id) {
calc_gen(node);
if (code.back().op==op_meq) {
code.back().num = 1; // 1 means need pop after op_meq
} else {
emit(op_pop, 0, node->get_location());
}
return;
}
// generate symbol load
calc_gen(node->get_right());
// get memory space of left identifier
mcall_id((identifier*)node->get_left());
// check memory get operand type and replace it with load operand
switch(code.back().op) {
case op_mcallg: code.back().op = op_loadg; break;
case op_mcalll: code.back().op = op_loadl; break;
case op_mupval: code.back().op = op_loadu; break;
default: die("unexpected operand to replace", node->get_location());
}
}
void codegen::assignment_statement(assignment_expr* node) { void codegen::assignment_statement(assignment_expr* node) {
switch(node->get_assignment_type()) { switch(node->get_assignment_type()) {
case assignment_expr::assign_type::equal: case assignment_expr::assign_type::equal:
if (node->get_left()->get_type()==expr_type::ast_id) { gen_assignment_equal_statement(node);
calc_gen(node->get_right());
mcall_id((identifier*)node->get_left());
// only the first mcall_id can use load
if (code.back().op==op_mcalll) {
code.back().op=op_loadl;
} else if (code.back().op==op_mupval) {
code.back().op=op_loadu;
} else {
code.back().op=op_loadg;
}
} else {
calc_gen(node);
if (code.back().op==op_meq) {
code.back().num=1;
} else {
gen(op_pop, 0, node->get_location());
}
}
break; break;
case assignment_expr::assign_type::add_equal: case assignment_expr::assign_type::add_equal:
case assignment_expr::assign_type::sub_equal: case assignment_expr::assign_type::sub_equal:
@ -634,7 +651,7 @@ void codegen::assignment_statement(assignment_expr* node) {
} else if (op_addeqc<=code.back().op && code.back().op<=op_lnkeqc) { } else if (op_addeqc<=code.back().op && code.back().op<=op_lnkeqc) {
code.back().op=code.back().op-op_addeqc+op_addecp; code.back().op=code.back().op-op_addeqc+op_addecp;
} else { } else {
gen(op_pop, 0, node->get_location()); emit(op_pop, 0, node->get_location());
} }
break; break;
} }
@ -659,13 +676,13 @@ void codegen::multi_assign_gen(multi_assign* node) {
// multi assign user loadl and loadg to avoid meq's stack-- // multi assign user loadl and loadg to avoid meq's stack--
// and this operation changes local and global value directly // and this operation changes local and global value directly
if (code.back().op==op_mcalll) { if (code.back().op==op_mcalll) {
code.back().op=op_loadl; code.back().op = op_loadl;
} else if (code.back().op==op_mupval) { } else if (code.back().op==op_mupval) {
code.back().op=op_loadu; code.back().op = op_loadu;
} else if (code.back().op==op_mcallg) { } else if (code.back().op==op_mcallg) {
code.back().op=op_loadg; code.back().op = op_loadg;
} else { } else {
gen(op_meq, 1, tuple[i]->get_location()); emit(op_meq, 1, tuple[i]->get_location());
} }
} }
return; return;
@ -673,46 +690,46 @@ void codegen::multi_assign_gen(multi_assign* node) {
calc_gen(node->get_value()); calc_gen(node->get_value());
auto& tuple = node->get_tuple()->get_elements(); auto& tuple = node->get_tuple()->get_elements();
for(i32 i = 0; i<size; ++i) { for(i32 i = 0; i<size; ++i) {
gen(op_callvi, i, node->get_value()->get_location()); emit(op_callvi, i, node->get_value()->get_location());
// multi assign user loadl and loadg to avoid meq's stack-- // multi assign user loadl and loadg to avoid meq's stack--
// and this operation changes local and global value directly // and this operation changes local and global value directly
mcall(tuple[i]); mcall(tuple[i]);
if (code.back().op==op_mcalll) { if (code.back().op==op_mcalll) {
code.back().op=op_loadl; code.back().op = op_loadl;
} else if (code.back().op==op_mupval) { } else if (code.back().op==op_mupval) {
code.back().op=op_loadu; code.back().op = op_loadu;
} else if (code.back().op==op_mcallg) { } else if (code.back().op==op_mcallg) {
code.back().op=op_loadg; code.back().op = op_loadg;
} else { } else {
gen(op_meq, 1, tuple[i]->get_location()); emit(op_meq, 1, tuple[i]->get_location());
} }
} }
gen(op_pop, 0, node->get_location()); emit(op_pop, 0, node->get_location());
} }
void codegen::cond_gen(condition_expr* node) { void codegen::cond_gen(condition_expr* node) {
std::vector<usize> jmp_label; std::vector<usize> jmp_label;
calc_gen(node->get_if_statement()->get_condition()); calc_gen(node->get_if_statement()->get_condition());
auto ptr = code.size(); auto ptr = code.size();
gen(op_jf, 0, node->get_if_statement()->get_location()); emit(op_jf, 0, node->get_if_statement()->get_location());
block_gen(node->get_if_statement()->get_code_block()); block_gen(node->get_if_statement()->get_code_block());
if (node->get_elsif_stataments().size() || if (node->get_elsif_stataments().size() ||
node->get_else_statement()) { node->get_else_statement()) {
jmp_label.push_back(code.size()); jmp_label.push_back(code.size());
gen(op_jmp, 0, node->get_if_statement()->get_location()); emit(op_jmp, 0, node->get_if_statement()->get_location());
} }
code[ptr].num = code.size(); code[ptr].num = code.size();
for(auto tmp : node->get_elsif_stataments()) { for(auto tmp : node->get_elsif_stataments()) {
calc_gen(tmp->get_condition()); calc_gen(tmp->get_condition());
ptr = code.size(); ptr = code.size();
gen(op_jf, 0, tmp->get_location()); emit(op_jf, 0, tmp->get_location());
block_gen(tmp->get_code_block()); block_gen(tmp->get_code_block());
// the last condition doesn't need to jmp // the last condition doesn't need to jmp
if (tmp!=node->get_elsif_stataments().back() || if (tmp!=node->get_elsif_stataments().back() ||
node->get_else_statement()) { node->get_else_statement()) {
jmp_label.push_back(code.size()); jmp_label.push_back(code.size());
gen(op_jmp, 0, tmp->get_location()); emit(op_jmp, 0, tmp->get_location());
} }
code[ptr].num=code.size(); code[ptr].num=code.size();
} }
@ -729,12 +746,9 @@ void codegen::loop_gen(expr* node) {
continue_ptr.push_front({}); continue_ptr.push_front({});
break_ptr.push_front({}); break_ptr.push_front({});
switch(node->get_type()) { switch(node->get_type()) {
case expr_type::ast_while: case expr_type::ast_while: while_gen((while_expr*)node); break;
while_gen((while_expr*)node); break; case expr_type::ast_for: for_gen((for_expr*)node); break;
case expr_type::ast_for: case expr_type::ast_forei: forei_gen((forei_expr*)node); break;
for_gen((for_expr*)node); break;
case expr_type::ast_forei:
forei_gen((forei_expr*)node); break;
default: break; default: break;
} }
} }
@ -754,10 +768,10 @@ void codegen::while_gen(while_expr* node) {
usize loop_ptr = code.size(); usize loop_ptr = code.size();
calc_gen(node->get_condition()); calc_gen(node->get_condition());
usize condition_ptr = code.size(); usize condition_ptr = code.size();
gen(op_jf, 0, node->get_condition()->get_location()); emit(op_jf, 0, node->get_condition()->get_location());
block_gen(node->get_code_block()); block_gen(node->get_code_block());
gen(op_jmp, loop_ptr, node->get_code_block()->get_location()); emit(op_jmp, loop_ptr, node->get_code_block()->get_location());
code[condition_ptr].num = code.size(); code[condition_ptr].num = code.size();
load_continue_break(code.size()-1, code.size()); load_continue_break(code.size()-1, code.size());
} }
@ -767,17 +781,17 @@ void codegen::for_gen(for_expr* node) {
usize jmp_place = code.size(); usize jmp_place = code.size();
if (node->get_condition()->get_type()==expr_type::ast_null) { if (node->get_condition()->get_type()==expr_type::ast_null) {
regist_num(1); regist_num(1);
gen(op_pnum, const_number_map.at(1), node->get_condition()->get_location()); emit(op_pnum, const_number_map.at(1), node->get_condition()->get_location());
} else { } else {
calc_gen(node->get_condition()); calc_gen(node->get_condition());
} }
usize label_exit = code.size(); usize label_exit = code.size();
gen(op_jf, 0, node->get_condition()->get_location()); emit(op_jf, 0, node->get_condition()->get_location());
block_gen(node->get_code_block()); block_gen(node->get_code_block());
usize continue_place = code.size(); usize continue_place = code.size();
statement_generation(node->get_step()); statement_generation(node->get_step());
gen(op_jmp, jmp_place, node->get_step()->get_location()); emit(op_jmp, jmp_place, node->get_step()->get_location());
code[label_exit].num = code.size(); code[label_exit].num = code.size();
load_continue_break(continue_place, code.size()); load_continue_break(continue_place, code.size());
@ -785,39 +799,39 @@ void codegen::for_gen(for_expr* node) {
void codegen::forei_gen(forei_expr* node) { void codegen::forei_gen(forei_expr* node) {
calc_gen(node->get_value()); calc_gen(node->get_value());
gen(op_cnt, 0, node->get_value()->get_location()); emit(op_cnt, 0, node->get_value()->get_location());
usize ptr = code.size(); usize ptr = code.size();
if (node->get_loop_type()==forei_expr::forei_loop_type::forindex) { if (node->get_loop_type()==forei_expr::forei_loop_type::forindex) {
gen(op_findex, 0, node->get_location()); emit(op_findex, 0, node->get_location());
} else { } else {
gen(op_feach, 0, node->get_location()); emit(op_feach, 0, node->get_location());
} }
if (node->get_iterator()->get_name()) { // define a new iterator if (node->get_iterator()->get_name()) { // define a new iterator
auto name_node = node->get_iterator()->get_name(); auto name_node = node->get_iterator()->get_name();
const auto& str = name_node->get_name(); const auto& str = name_node->get_name();
local.empty()? local.empty()?
gen(op_loadg, global_find(str), name_node->get_location()): emit(op_loadg, global_find(str), name_node->get_location()):
gen(op_loadl, local_find(str), name_node->get_location()); emit(op_loadl, local_find(str), name_node->get_location());
} else { // use exist variable as the iterator } else { // use exist variable as the iterator
mcall(node->get_iterator()->get_call()); mcall(node->get_iterator()->get_call());
if (code.back().op==op_mcallg) { if (code.back().op==op_mcallg) {
code.back().op=op_loadg; code.back().op = op_loadg;
} else if (code.back().op==op_mcalll) { } else if (code.back().op==op_mcalll) {
code.back().op=op_loadl; code.back().op = op_loadl;
} else if (code.back().op==op_mupval) { } else if (code.back().op==op_mupval) {
code.back().op=op_loadu; code.back().op = op_loadu;
} else { } else {
gen(op_meq, 1, node->get_iterator()->get_location()); emit(op_meq, 1, node->get_iterator()->get_location());
} }
} }
++in_loop_level.back(); ++in_loop_level.back();
block_gen(node->get_code_block()); block_gen(node->get_code_block());
--in_loop_level.back(); --in_loop_level.back();
gen(op_jmp, ptr, node->get_location()); emit(op_jmp, ptr, node->get_location());
code[ptr].num=code.size(); code[ptr].num=code.size();
load_continue_break(code.size()-1, code.size()); load_continue_break(code.size()-1, code.size());
gen(op_pop, 0, node->get_value()->get_location());// pop vector emit(op_pop, 0, node->get_value()->get_location());// pop vector
gen(op_pop, 0, node->get_location());// pop iterator emit(op_pop, 0, node->get_location());// pop iterator
} }
void codegen::statement_generation(expr* node) { void codegen::statement_generation(expr* node) {
@ -841,7 +855,7 @@ void codegen::statement_generation(expr* node) {
case expr_type::ast_binary: case expr_type::ast_binary:
case expr_type::ast_ternary: case expr_type::ast_ternary:
calc_gen(node); calc_gen(node);
gen(op_pop, 0, node->get_location()); emit(op_pop, 0, node->get_location());
break; break;
default: break; default: break;
} }
@ -850,33 +864,33 @@ void codegen::statement_generation(expr* node) {
void codegen::or_gen(binary_operator* node) { void codegen::or_gen(binary_operator* node) {
calc_gen(node->get_left()); calc_gen(node->get_left());
usize label_jump_true_1 = code.size(); usize label_jump_true_1 = code.size();
gen(op_jt, 0, node->get_left()->get_location()); emit(op_jt, 0, node->get_left()->get_location());
gen(op_pop, 0, node->get_left()->get_location()); emit(op_pop, 0, node->get_left()->get_location());
calc_gen(node->get_right()); calc_gen(node->get_right());
usize label_jump_true_2 = code.size(); usize label_jump_true_2 = code.size();
gen(op_jt, 0, node->get_right()->get_location()); emit(op_jt, 0, node->get_right()->get_location());
gen(op_pop, 0, node->get_right()->get_location()); emit(op_pop, 0, node->get_right()->get_location());
gen(op_pnil, 0, node->get_right()->get_location()); emit(op_pnil, 0, node->get_right()->get_location());
code[label_jump_true_1].num = code[label_jump_true_2].num = code.size(); code[label_jump_true_1].num = code[label_jump_true_2].num = code.size();
} }
void codegen::and_gen(binary_operator* node) { void codegen::and_gen(binary_operator* node) {
calc_gen(node->get_left()); calc_gen(node->get_left());
gen(op_jt, code.size()+2, node->get_left()->get_location()); emit(op_jt, code.size()+2, node->get_left()->get_location());
usize lable_jump_false = code.size(); usize lable_jump_false = code.size();
gen(op_jmp, 0, node->get_left()->get_location()); emit(op_jmp, 0, node->get_left()->get_location());
gen(op_pop, 0, node->get_right()->get_location()); // jt jumps here emit(op_pop, 0, node->get_right()->get_location()); // jt jumps here
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_jt, code.size()+3, node->get_right()->get_location()); emit(op_jt, code.size()+3, node->get_right()->get_location());
code[lable_jump_false].num = code.size(); code[lable_jump_false].num = code.size();
gen(op_pop, 0, node->get_right()->get_location()); emit(op_pop, 0, node->get_right()->get_location());
gen(op_pnil, 0, node->get_right()->get_location()); emit(op_pnil, 0, node->get_right()->get_location());
// jt jumps here, avoid pop and pnil // jt jumps here, avoid pop and pnil
} }
@ -890,11 +904,11 @@ void codegen::unary_gen(unary_operator* node) {
calc_gen(node->get_value()); calc_gen(node->get_value());
switch(node->get_operator_type()) { switch(node->get_operator_type()) {
case unary_operator::unary_type::negative: case unary_operator::unary_type::negative:
gen(op_usub, 0, node->get_location()); break; emit(op_usub, 0, node->get_location()); break;
case unary_operator::unary_type::logical_not: case unary_operator::unary_type::logical_not:
gen(op_lnot, 0, node->get_location()); break; emit(op_lnot, 0, node->get_location()); break;
case unary_operator::unary_type::bitwise_not: case unary_operator::unary_type::bitwise_not:
gen(op_bnot, 0, node->get_location()); break; emit(op_bnot, 0, node->get_location()); break;
} }
} }
@ -918,27 +932,27 @@ void codegen::binary_gen(binary_operator* node) {
case binary_operator::binary_type::cmpeq: case binary_operator::binary_type::cmpeq:
calc_gen(node->get_left()); calc_gen(node->get_left());
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_eq, 0, node->get_location()); emit(op_eq, 0, node->get_location());
return; return;
case binary_operator::binary_type::cmpneq: case binary_operator::binary_type::cmpneq:
calc_gen(node->get_left()); calc_gen(node->get_left());
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_neq, 0, node->get_location()); emit(op_neq, 0, node->get_location());
return; return;
case binary_operator::binary_type::bitwise_or: case binary_operator::binary_type::bitwise_or:
calc_gen(node->get_left()); calc_gen(node->get_left());
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_btor, 0, node->get_location()); emit(op_btor, 0, node->get_location());
return; return;
case binary_operator::binary_type::bitwise_xor: case binary_operator::binary_type::bitwise_xor:
calc_gen(node->get_left()); calc_gen(node->get_left());
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_btxor, 0, node->get_location()); emit(op_btxor, 0, node->get_location());
return; return;
case binary_operator::binary_type::bitwise_and: case binary_operator::binary_type::bitwise_and:
calc_gen(node->get_left()); calc_gen(node->get_left());
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_btand, 0, node->get_location()); emit(op_btand, 0, node->get_location());
return; return;
default: break; default: break;
} }
@ -947,99 +961,99 @@ void codegen::binary_gen(binary_operator* node) {
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_add, 0, node->get_location()); emit(op_add, 0, node->get_location());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_addc, const_number_map.at(num), node->get_location()); emit(op_addc, const_number_map.at(num), node->get_location());
} }
return; return;
case binary_operator::binary_type::sub: case binary_operator::binary_type::sub:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_sub, 0, node->get_location()); emit(op_sub, 0, node->get_location());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_subc, const_number_map.at(num), node->get_location()); emit(op_subc, const_number_map.at(num), node->get_location());
} }
return; return;
case binary_operator::binary_type::mult: case binary_operator::binary_type::mult:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_mul, 0, node->get_location()); emit(op_mul, 0, node->get_location());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_mulc, const_number_map.at(num), node->get_location()); emit(op_mulc, const_number_map.at(num), node->get_location());
} }
return; return;
case binary_operator::binary_type::div: case binary_operator::binary_type::div:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_div, 0, node->get_location()); emit(op_div, 0, node->get_location());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_divc, const_number_map.at(num), node->get_location()); emit(op_divc, const_number_map.at(num), node->get_location());
} }
return; return;
case binary_operator::binary_type::concat: case binary_operator::binary_type::concat:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_str) { if (node->get_right()->get_type()!=expr_type::ast_str) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_lnk, 0, node->get_location()); emit(op_lnk, 0, node->get_location());
} else { } else {
const auto& str = ((string_literal*)node->get_right())->get_content(); const auto& str = ((string_literal*)node->get_right())->get_content();
regist_str(str); regist_str(str);
gen(op_lnkc, const_string_map.at(str), node->get_location()); emit(op_lnkc, const_string_map.at(str), node->get_location());
} }
break; break;
case binary_operator::binary_type::less: case binary_operator::binary_type::less:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_less, 0, node->get_location()); emit(op_less, 0, node->get_location());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_lessc, const_number_map.at(num), node->get_location()); emit(op_lessc, const_number_map.at(num), node->get_location());
} }
return; return;
case binary_operator::binary_type::leq: case binary_operator::binary_type::leq:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_leq, 0, node->get_location()); emit(op_leq, 0, node->get_location());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_leqc, const_number_map.at(num), node->get_location()); emit(op_leqc, const_number_map.at(num), node->get_location());
} }
return; return;
case binary_operator::binary_type::grt: case binary_operator::binary_type::grt:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_grt, 0, node->get_location()); emit(op_grt, 0, node->get_location());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_grtc, const_number_map.at(num), node->get_location()); emit(op_grtc, const_number_map.at(num), node->get_location());
} }
return; return;
case binary_operator::binary_type::geq: case binary_operator::binary_type::geq:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_geq, 0, node->get_location()); emit(op_geq, 0, node->get_location());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_geqc, const_number_map.at(num), node->get_location()); emit(op_geqc, const_number_map.at(num), node->get_location());
} }
return; return;
default: break; default: break;
@ -1049,10 +1063,10 @@ void codegen::binary_gen(binary_operator* node) {
void codegen::trino_gen(ternary_operator* node) { void codegen::trino_gen(ternary_operator* node) {
calc_gen(node->get_condition()); calc_gen(node->get_condition());
usize label_jump_false = code.size(); usize label_jump_false = code.size();
gen(op_jf, 0, node->get_condition()->get_location()); emit(op_jf, 0, node->get_condition()->get_location());
calc_gen(node->get_left()); calc_gen(node->get_left());
usize label_jump_to_exit = code.size(); usize label_jump_to_exit = code.size();
gen(op_jmp, 0, node->get_left()->get_location()); emit(op_jmp, 0, node->get_left()->get_location());
code[label_jump_false].num = code.size(); code[label_jump_false].num = code.size();
calc_gen(node->get_right()); calc_gen(node->get_right());
code[label_jump_to_exit].num = code.size(); code[label_jump_to_exit].num = code.size();
@ -1061,7 +1075,7 @@ void codegen::trino_gen(ternary_operator* node) {
void codegen::calc_gen(expr* node) { void codegen::calc_gen(expr* node) {
switch(node->get_type()) { switch(node->get_type()) {
case expr_type::ast_nil: case expr_type::ast_nil:
gen(op_pnil, 0, node->get_location()); break; emit(op_pnil, 0, node->get_location()); break;
case expr_type::ast_num: case expr_type::ast_num:
num_gen((number_literal*)node); break; num_gen((number_literal*)node); break;
case expr_type::ast_str: case expr_type::ast_str:
@ -1109,11 +1123,11 @@ void codegen::block_gen(code_block* node) {
cond_gen((condition_expr*)tmp); break; cond_gen((condition_expr*)tmp); break;
case expr_type::ast_continue: case expr_type::ast_continue:
continue_ptr.front().push_back(code.size()); continue_ptr.front().push_back(code.size());
gen(op_jmp, 0, tmp->get_location()); emit(op_jmp, 0, tmp->get_location());
break; break;
case expr_type::ast_break: case expr_type::ast_break:
break_ptr.front().push_back(code.size()); break_ptr.front().push_back(code.size());
gen(op_jmp, 0, tmp->get_location()); emit(op_jmp, 0, tmp->get_location());
break; break;
case expr_type::ast_while: case expr_type::ast_while:
case expr_type::ast_for: case expr_type::ast_for:
@ -1139,11 +1153,11 @@ void codegen::block_gen(code_block* node) {
void codegen::ret_gen(return_expr* node) { void codegen::ret_gen(return_expr* node) {
for(u32 i = 0; i<in_loop_level.back(); ++i) { for(u32 i = 0; i<in_loop_level.back(); ++i) {
gen(op_pop, 0, node->get_location()); emit(op_pop, 0, node->get_location());
gen(op_pop, 0, node->get_location()); emit(op_pop, 0, node->get_location());
} }
calc_gen(node->get_value()); calc_gen(node->get_value());
gen(op_ret, 0, node->get_location()); emit(op_ret, 0, node->get_location());
} }
const error& codegen::compile(parse& parse, linker& import) { const error& codegen::compile(parse& parse, linker& import) {
@ -1159,23 +1173,24 @@ const error& codegen::compile(parse& parse, linker& import) {
// search global symbols first // search global symbols first
find_symbol(parse.tree()); find_symbol(parse.tree());
gen(op_intg, global.size(), parse.tree()->get_location());
// generate main block // generate main block
block_gen(parse.tree()); block_gen(parse.tree());
// generate exit operand, vm stops here // generate exit operand, vm stops here
gen(op_exit, 0, parse.tree()->get_location()); emit(op_exit, 0, parse.tree()->get_location());
// size out of bound check // size out of bound check
if (const_number_table.size()>0xffffff) { if (const_number_table.size()>0xffffff) {
err.err("code", err.err("code",
"too many constant numbers: " + "too many constant numbers: " +
std::to_string(const_number_table.size())); std::to_string(const_number_table.size())
);
} }
if (const_string_table.size()>0xffffff) { if (const_string_table.size()>0xffffff) {
err.err("code", err.err("code",
"too many constant strings: " + "too many constant strings: " +
std::to_string(const_string_table.size())); std::to_string(const_string_table.size())
);
} }
// check global variables size // check global variables size

View File

@ -83,7 +83,7 @@ private:
i32 global_find(const std::string&); i32 global_find(const std::string&);
i32 upvalue_find(const std::string&); i32 upvalue_find(const std::string&);
void gen(u8, u32, const span&); void emit(u8, u32, const span&);
void num_gen(number_literal*); void num_gen(number_literal*);
void str_gen(string_literal*); void str_gen(string_literal*);
@ -104,6 +104,7 @@ private:
void single_def(definition_expr*); void single_def(definition_expr*);
void def_gen(definition_expr*); void def_gen(definition_expr*);
void assignment_expression(assignment_expr*); void assignment_expression(assignment_expr*);
void gen_assignment_equal_statement(assignment_expr*);
void assignment_statement(assignment_expr*); void assignment_statement(assignment_expr*);
void multi_assign_gen(multi_assign*); void multi_assign_gen(multi_assign*);
void cond_gen(condition_expr*); void cond_gen(condition_expr*);

View File

@ -183,7 +183,7 @@ f64 str2num(const char* str) {
i32 utf8_hdchk(const char head) { i32 utf8_hdchk(const char head) {
// RFC-2279 but now we use RFC-3629 so nbytes is less than 4 // RFC-2279 but now we use RFC-3629 so nbytes is less than 4
const u8 c = (u8)head; const auto c = static_cast<u8>(head);
if ((c>>5)==0x06) { // 110x xxxx (10xx xxxx)^1 if ((c>>5)==0x06) { // 110x xxxx (10xx xxxx)^1
return 1; return 1;
} }

View File

@ -9,7 +9,7 @@ namespace nasal {
enum op_code_type:u8 { enum op_code_type:u8 {
op_exit, // stop the virtual machine op_exit, // stop the virtual machine
op_intg, // init global scope op_intg, // [deprecated] init global scope
op_intl, // local scope size op_intl, // local scope size
op_loadg, // load global value op_loadg, // load global value
op_loadl, // load local value op_loadl, // load local value

View File

@ -150,11 +150,7 @@ public:
public: public:
parse(): ptr(0), in_func(0), in_loop(0), toks(nullptr), root(nullptr) {} parse(): ptr(0), in_func(0), in_loop(0), toks(nullptr), root(nullptr) {}
~parse() { ~parse() {delete root;}
if (root) {
delete root;
}
}
const error& compile(const lexer&); const error& compile(const lexer&);
static void easter_egg(); static void easter_egg();
}; };

View File

@ -55,7 +55,7 @@ void vm::context_and_global_init() {
ctx.canary = ctx.stack+STACK_DEPTH-1; ctx.canary = ctx.stack+STACK_DEPTH-1;
/* nothing is on stack */ /* nothing is on stack */
ctx.top = ctx.stack; ctx.top = ctx.stack - 1;
/* clear main stack and global */ /* clear main stack and global */
for(u32 i = 0; i<STACK_DEPTH; ++i) { for(u32 i = 0; i<STACK_DEPTH; ++i) {

View File

@ -193,10 +193,8 @@ inline bool vm::cond(var& val) {
} }
inline void vm::o_intg() { inline void vm::o_intg() {
// global values store on stack // reserved for another usage
// ctx.top += imm[ctx.pc]; std::cout << "[vm] do nothing\n";
// point to the top
--ctx.top;
} }
inline void vm::o_intl() { inline void vm::o_intl() {
@ -301,9 +299,7 @@ inline void vm::o_lnot() {
ctx.top[0] = num? zero:one; ctx.top[0] = num? zero:one;
} }
} break; } break;
default: default: die("incorrect value type"); return;
die("incorrect value type");
return;
} }
} }
@ -317,22 +313,25 @@ inline void vm::o_bnot() {
inline void vm::o_btor() { inline void vm::o_btor() {
ctx.top[-1] = var::num( ctx.top[-1] = var::num(
static_cast<int32_t>(ctx.top[-1].tonum())| static_cast<i32>(ctx.top[-1].tonum())|
static_cast<int32_t>(ctx.top[0].tonum())); static_cast<i32>(ctx.top[0].tonum())
);
--ctx.top; --ctx.top;
} }
inline void vm::o_btxor() { inline void vm::o_btxor() {
ctx.top[-1] = var::num( ctx.top[-1] = var::num(
static_cast<int32_t>(ctx.top[-1].tonum())^ static_cast<i32>(ctx.top[-1].tonum())^
static_cast<int32_t>(ctx.top[0].tonum())); static_cast<i32>(ctx.top[0].tonum())
);
--ctx.top; --ctx.top;
} }
inline void vm::o_btand() { inline void vm::o_btand() {
ctx.top[-1] = var::num( ctx.top[-1] = var::num(
static_cast<int32_t>(ctx.top[-1].tonum())& static_cast<i32>(ctx.top[-1].tonum())&
static_cast<int32_t>(ctx.top[0].tonum())); static_cast<i32>(ctx.top[0].tonum())
);
--ctx.top; --ctx.top;
} }
@ -388,25 +387,36 @@ inline void vm::o_subeq() {op_calc_eq(-);}
inline void vm::o_muleq() {op_calc_eq(*);} inline void vm::o_muleq() {op_calc_eq(*);}
inline void vm::o_diveq() {op_calc_eq(/);} inline void vm::o_diveq() {op_calc_eq(/);}
inline void vm::o_lnkeq() { inline void vm::o_lnkeq() {
ctx.top[-1] = ctx.memr[0] = ngc.newstr(ctx.memr[0].tostr()+ctx.top[-1].tostr()); ctx.top[-1] = ctx.memr[0] = ngc.newstr(
ctx.memr[0].tostr()+ctx.top[-1].tostr()
);
ctx.memr = nullptr; ctx.memr = nullptr;
ctx.top -= imm[ctx.pc]+1; ctx.top -= imm[ctx.pc]+1;
} }
inline void vm::o_bandeq() { inline void vm::o_bandeq() {
ctx.top[-1] = ctx.memr[0] = var::num(i32(ctx.memr[0].tonum())&i32(ctx.top[-1].tonum())); ctx.top[-1] = ctx.memr[0] = var::num(
static_cast<i32>(ctx.memr[0].tonum())&
static_cast<i32>(ctx.top[-1].tonum())
);
ctx.memr = nullptr; ctx.memr = nullptr;
ctx.top -= imm[ctx.pc]+1; ctx.top -= imm[ctx.pc]+1;
} }
inline void vm::o_boreq() { inline void vm::o_boreq() {
ctx.top[-1] = ctx.memr[0] = var::num(i32(ctx.memr[0].tonum())|i32(ctx.top[-1].tonum())); ctx.top[-1] = ctx.memr[0] = var::num(
static_cast<i32>(ctx.memr[0].tonum())|
static_cast<i32>(ctx.top[-1].tonum())
);
ctx.memr = nullptr; ctx.memr = nullptr;
ctx.top -= imm[ctx.pc]+1; ctx.top -= imm[ctx.pc]+1;
} }
inline void vm::o_bxoreq() { inline void vm::o_bxoreq() {
ctx.top[-1] = ctx.memr[0] = var::num(i32(ctx.memr[0].tonum())^i32(ctx.top[-1].tonum())); ctx.top[-1] = ctx.memr[0] = var::num(
static_cast<i32>(ctx.memr[0].tonum())^
static_cast<i32>(ctx.top[-1].tonum())
);
ctx.memr = nullptr; ctx.memr = nullptr;
ctx.top -= imm[ctx.pc]+1; ctx.top -= imm[ctx.pc]+1;
} }
@ -439,7 +449,9 @@ inline void vm::o_subecp() {op_calc_eq_const_and_pop(-);}
inline void vm::o_mulecp() {op_calc_eq_const_and_pop(*);} inline void vm::o_mulecp() {op_calc_eq_const_and_pop(*);}
inline void vm::o_divecp() {op_calc_eq_const_and_pop(/);} inline void vm::o_divecp() {op_calc_eq_const_and_pop(/);}
inline void vm::o_lnkecp() { inline void vm::o_lnkecp() {
ctx.top[0] = ctx.memr[0] = ngc.newstr(ctx.memr[0].tostr()+cstr[imm[ctx.pc]]); ctx.top[0] = ctx.memr[0] = ngc.newstr(
ctx.memr[0].tostr()+cstr[imm[ctx.pc]]
);
ctx.memr = nullptr; ctx.memr = nullptr;
--ctx.top; --ctx.top;
} }
@ -461,12 +473,12 @@ inline void vm::o_eq() {
if (val1.type==vm_nil && val2.type==vm_nil) { if (val1.type==vm_nil && val2.type==vm_nil) {
ctx.top[0] = one; ctx.top[0] = one;
} else if (val1.type==vm_str && val2.type==vm_str) { } else if (val1.type==vm_str && val2.type==vm_str) {
ctx.top[0] = (val1.str()==val2.str())?one:zero; ctx.top[0] = (val1.str()==val2.str())? one:zero;
} else if ((val1.type==vm_num || val2.type==vm_num) } else if ((val1.type==vm_num || val2.type==vm_num)
&& val1.type!=vm_nil && val2.type!=vm_nil) { && val1.type!=vm_nil && val2.type!=vm_nil) {
ctx.top[0] = (val1.tonum()==val2.tonum())?one:zero; ctx.top[0] = (val1.tonum()==val2.tonum())? one:zero;
} else { } else {
ctx.top[0] = (val1==val2)?one:zero; ctx.top[0] = (val1==val2)? one:zero;
} }
} }
@ -476,12 +488,12 @@ inline void vm::o_neq() {
if (val1.type==vm_nil && val2.type==vm_nil) { if (val1.type==vm_nil && val2.type==vm_nil) {
ctx.top[0] = zero; ctx.top[0] = zero;
} else if (val1.type==vm_str && val2.type==vm_str) { } else if (val1.type==vm_str && val2.type==vm_str) {
ctx.top[0] = (val1.str()!=val2.str())?one:zero; ctx.top[0] = (val1.str()!=val2.str())? one:zero;
} else if ((val1.type==vm_num || val2.type==vm_num) } else if ((val1.type==vm_num || val2.type==vm_num)
&& val1.type!=vm_nil && val2.type!=vm_nil) { && val1.type!=vm_nil && val2.type!=vm_nil) {
ctx.top[0] = (val1.tonum()!=val2.tonum())?one:zero; ctx.top[0] = (val1.tonum()!=val2.tonum())? one:zero;
} else { } else {
ctx.top[0] = (val1!=val2)?one:zero; ctx.top[0] = (val1!=val2)? one:zero;
} }
} }
@ -597,7 +609,9 @@ inline void vm::o_callv() {
die("out of range:"+std::to_string(val.tonum())); die("out of range:"+std::to_string(val.tonum()));
return; return;
} }
ctx.top[0] = var::num(f64((u8)str[num>=0? num:num+len])); ctx.top[0] = var::num(
static_cast<f64>(static_cast<u8>(str[num>=0? num:num+len]))
);
} else if (vec.type==vm_map) { } else if (vec.type==vm_map) {
if (val.type!=vm_str) { if (val.type!=vm_str) {
die("must use string as the key"); die("must use string as the key");

View File

@ -32,11 +32,11 @@ void optimizer::const_number(
case binary_operator::binary_type::grt: res = left>right; break; case binary_operator::binary_type::grt: res = left>right; break;
case binary_operator::binary_type::geq: res = left>=right; break; case binary_operator::binary_type::geq: res = left>=right; break;
case binary_operator::binary_type::bitwise_or: case binary_operator::binary_type::bitwise_or:
res = i32(left)|i32(right); break; res = static_cast<i32>(left)|static_cast<i32>(right); break;
case binary_operator::binary_type::bitwise_xor: case binary_operator::binary_type::bitwise_xor:
res = i32(left)^i32(right); break; res = static_cast<i32>(left)^static_cast<i32>(right); break;
case binary_operator::binary_type::bitwise_and: case binary_operator::binary_type::bitwise_and:
res = i32(left)&i32(right); break; res = static_cast<i32>(left)&static_cast<i32>(right); break;
default: return; default: return;
} }
if (std::isinf(res) || std::isnan(res)) { if (std::isinf(res) || std::isnan(res)) {
@ -51,9 +51,12 @@ void optimizer::const_number(
number_literal* value_node) { number_literal* value_node) {
auto res = value_node->get_number(); auto res = value_node->get_number();
switch(node->get_operator_type()) { switch(node->get_operator_type()) {
case unary_operator::unary_type::negative: res = -res; break; case unary_operator::unary_type::negative:
case unary_operator::unary_type::bitwise_not: res = ~i32(res); break; res = -res; break;
case unary_operator::unary_type::logical_not: res = !res; break; case unary_operator::unary_type::bitwise_not:
res = ~static_cast<i32>(res); break;
case unary_operator::unary_type::logical_not:
res = !res; break;
} }
if (std::isinf(res) || std::isnan(res)) { if (std::isinf(res) || std::isnan(res)) {
return; return;