optimize location info gen in codegen

and refactor lib.nas, add multiple native modules
This commit is contained in:
ValKmjolnir
2023-07-23 23:57:25 +08:00
parent 51a0ef6b0c
commit 788e0026c2
31 changed files with 477 additions and 356 deletions

View File

@@ -100,42 +100,44 @@ i32 codegen::upvalue_find(const std::string& name) {
return index;
}
void codegen::gen(u8 operation_code, u32 num, u32 line) {
code.push_back({operation_code, fileindex, num, line});
void codegen::gen(u8 operation_code, u32 num, const span& loc) {
code.push_back({operation_code,
static_cast<u16>(file_map.at(loc.file)),
num, loc.begin_line});
}
void codegen::num_gen(number_literal* node) {
f64 num = node->get_number();
regist_num(num);
gen(op_pnum,const_number_map.at(num), node->get_line());
gen(op_pnum, const_number_map.at(num), node->get_location());
}
void codegen::str_gen(string_literal* node) {
const auto& str = node->get_content();
regist_str(str);
gen(op_pstr, const_string_map.at(str), node->get_line());
gen(op_pstr, const_string_map.at(str), node->get_location());
}
void codegen::bool_gen(bool_literal* node) {
f64 num = node->get_flag()? 1:0;
regist_num(num);
gen(op_pnum, const_number_map.at(num), node->get_line());
gen(op_pnum, const_number_map.at(num), node->get_location());
}
void codegen::vec_gen(vector_expr* node) {
for(auto child : node->get_elements()) {
calc_gen(child);
}
gen(op_newv, node->get_elements().size(), node->get_line());
gen(op_newv, node->get_elements().size(), node->get_location());
}
void codegen::hash_gen(hash_expr* node) {
gen(op_newh, 0, node->get_line());
gen(op_newh, 0, node->get_location());
for(auto child : node->get_members()) {
calc_gen(child->get_value());
const auto& field_name = child->get_name();
regist_str(field_name);
gen(op_happ, const_string_map.at(field_name), child->get_line());
gen(op_happ, const_string_map.at(field_name), child->get_location());
}
}
@@ -175,9 +177,9 @@ void codegen::func_gen(function* node) {
}
usize newf=code.size();
gen(op_newf, 0, node->get_line());
gen(op_newf, 0, node->get_location());
usize lsize=code.size();
gen(op_intl, 0, node->get_line());
gen(op_intl, 0, node->get_location());
// add special keyword 'me' into symbol table
// this symbol is only used in local scope(function's scope)
@@ -196,14 +198,14 @@ void codegen::func_gen(function* node) {
regist_str(name);
switch(tmp->get_parameter_type()) {
case parameter::param_type::normal_parameter:
gen(op_para, const_string_map.at(name), tmp->get_line());
gen(op_para, const_string_map.at(name), tmp->get_location());
break;
case parameter::param_type::default_parameter:
calc_gen(tmp->get_default_value());
gen(op_deft, const_string_map.at(name), tmp->get_line());
gen(op_deft, const_string_map.at(name), tmp->get_location());
break;
case parameter::param_type::dynamic_parameter:
gen(op_dyn, const_string_map.at(name), tmp->get_line());
gen(op_dyn, const_string_map.at(name), tmp->get_location());
break;
}
add_symbol(name);
@@ -211,7 +213,7 @@ void codegen::func_gen(function* node) {
code[newf].num = code.size()+1; // entry
usize jmp_ptr = code.size();
gen(op_jmp, 0, node->get_line());
gen(op_jmp, 0, node->get_location());
auto block = node->get_code_block();
// search symbols first, must use after loading parameters
@@ -244,8 +246,8 @@ void codegen::func_gen(function* node) {
if (!block->get_expressions().size() ||
block->get_expressions().back()->get_type()!=expr_type::ast_ret) {
gen(op_pnil, 0, block->get_line());
gen(op_ret, 0, block->get_line());
gen(op_pnil, 0, block->get_location());
gen(op_ret, 0, block->get_location());
}
code[jmp_ptr].num = code.size();
}
@@ -269,7 +271,7 @@ void codegen::call_id(identifier* node) {
const auto& name = node->get_name();
for(u32 i = 0; builtin[i].name; ++i) {
if (builtin[i].name==name) {
gen(op_callb, i, node->get_line());
gen(op_callb, i, node->get_location());
if (local.empty()) {
die("should warp native function in local scope",
node->get_location());
@@ -279,15 +281,15 @@ void codegen::call_id(identifier* node) {
}
i32 index;
if ((index=local_find(name))>=0) {
gen(op_calll, index, node->get_line());
gen(op_calll, index, node->get_location());
return;
}
if ((index=upvalue_find(name))>=0) {
gen(op_upval, index, node->get_line());
gen(op_upval, index, node->get_location());
return;
}
if ((index=global_find(name))>=0) {
gen(op_callg, index, node->get_line());
gen(op_callg, index, node->get_location());
return;
}
die("undefined symbol \"" + name + "\"", node->get_location());
@@ -295,7 +297,7 @@ void codegen::call_id(identifier* node) {
void codegen::call_hash_gen(call_hash* node) {
regist_str(node->get_field());
gen(op_callh, const_string_map.at(node->get_field()), node->get_line());
gen(op_callh, const_string_map.at(node->get_field()), node->get_location());
}
void codegen::call_vector_gen(call_vector* node) {
@@ -303,39 +305,39 @@ void codegen::call_vector_gen(call_vector* node) {
if (node->get_slices().size()==1 &&
!node->get_slices()[0]->get_end()) {
calc_gen(node->get_slices()[0]->get_begin());
gen(op_callv, 0, node->get_slices()[0]->get_line());
gen(op_callv, 0, node->get_slices()[0]->get_location());
return;
}
gen(op_slcbeg, 0, node->get_line());
gen(op_slcbeg, 0, node->get_location());
for(auto tmp : node->get_slices()) {
if (!tmp->get_end()) {
calc_gen(tmp->get_begin());
gen(op_slc, 0, tmp->get_line());
gen(op_slc, 0, tmp->get_location());
} else {
calc_gen(tmp->get_begin());
calc_gen(tmp->get_end());
gen(op_slc2, 0, tmp->get_line());
gen(op_slc2, 0, tmp->get_location());
}
}
gen(op_slcend, 0, node->get_line());
gen(op_slcend, 0, node->get_location());
}
void codegen::call_func_gen(call_function* node) {
if (node->get_argument().size() &&
node->get_argument()[0]->get_type()==expr_type::ast_pair) {
gen(op_newh, 0, node->get_line());
gen(op_newh, 0, node->get_location());
for(auto child : node->get_argument()) {
calc_gen(((hash_pair*)child)->get_value());
const auto& field_name = ((hash_pair*)child)->get_name();
regist_str(field_name);
gen(op_happ, const_string_map.at(field_name), child->get_line());
gen(op_happ, const_string_map.at(field_name), child->get_location());
}
gen(op_callfh, 0, node->get_line());
gen(op_callfh, 0, node->get_location());
} else {
for(auto child : node->get_argument()) {
calc_gen(child);
}
gen(op_callfv, node->get_argument().size(), node->get_line());
gen(op_callfv, node->get_argument().size(), node->get_location());
}
}
@@ -390,15 +392,15 @@ void codegen::mcall_id(identifier* node) {
}
i32 index;
if ((index=local_find(name))>=0) {
gen(op_mcalll, index, node->get_line());
gen(op_mcalll, index, node->get_location());
return;
}
if ((index=upvalue_find(name))>=0) {
gen(op_mupval, index, node->get_line());
gen(op_mupval, index, node->get_location());
return;
}
if ((index=global_find(name))>=0) {
gen(op_mcallg, index, node->get_line());
gen(op_mcallg, index, node->get_location());
return;
}
die("undefined symbol \"" + name + "\"", node->get_location());
@@ -415,20 +417,20 @@ void codegen::mcall_vec(call_vector* node) {
return;
}
calc_gen(call->get_begin());
gen(op_mcallv, 0, node->get_line());
gen(op_mcallv, 0, node->get_location());
}
void codegen::mcall_hash(call_hash* node) {
regist_str(node->get_field());
gen(op_mcallh, const_string_map.at(node->get_field()), node->get_line());
gen(op_mcallh, const_string_map.at(node->get_field()), node->get_location());
}
void codegen::single_def(definition_expr* node) {
const auto& str = node->get_variable_name()->get_name();
calc_gen(node->get_value());
local.empty()?
gen(op_loadg, global_find(str), node->get_line()):
gen(op_loadl, local_find(str), node->get_line());
gen(op_loadg, global_find(str), node->get_location()):
gen(op_loadl, local_find(str), node->get_location());
}
void codegen::multi_def(definition_expr* node) {
@@ -448,21 +450,21 @@ void codegen::multi_def(definition_expr* node) {
calc_gen(vals[i]);
const auto& name = identifiers[i]->get_name();
local.empty()?
gen(op_loadg, global_find(name), identifiers[i]->get_line()):
gen(op_loadl, local_find(name), identifiers[i]->get_line());
gen(op_loadg, global_find(name), identifiers[i]->get_location()):
gen(op_loadl, local_find(name), identifiers[i]->get_location());
}
return;
}
// (var a,b,c) = [0,1,2];
calc_gen(node->get_value());
for(usize i = 0; i<size; ++i) {
gen(op_callvi, i, node->get_value()->get_line());
gen(op_callvi, i, node->get_value()->get_location());
const auto& name = identifiers[i]->get_name();
local.empty()?
gen(op_loadg, global_find(name), identifiers[i]->get_line()):
gen(op_loadl, local_find(name), identifiers[i]->get_line());
gen(op_loadg, global_find(name), identifiers[i]->get_location()):
gen(op_loadl, local_find(name), identifiers[i]->get_location());
}
gen(op_pop, 0, node->get_line());
gen(op_pop, 0, node->get_location());
}
void codegen::def_gen(definition_expr* node) {
@@ -477,7 +479,7 @@ void codegen::assignment_expression(assignment_expr* node) {
case assignment_expr::assign_type::equal:
calc_gen(node->get_right());
mcall(node->get_left());
gen(op_meq, 0, node->get_line());
gen(op_meq, 0, node->get_location());
break;
case assignment_expr::assign_type::add_equal:
if (node->get_right()->get_type()!=expr_type::ast_num) {
@@ -485,11 +487,11 @@ void codegen::assignment_expression(assignment_expr* node) {
}
mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) {
gen(op_addeq, 0, node->get_line());
gen(op_addeq, 0, node->get_location());
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_addeqc, const_number_map[num], node->get_line());
gen(op_addeqc, const_number_map[num], node->get_location());
}
break;
case assignment_expr::assign_type::sub_equal:
@@ -498,11 +500,11 @@ void codegen::assignment_expression(assignment_expr* node) {
}
mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) {
gen(op_subeq, 0, node->get_line());
gen(op_subeq, 0, node->get_location());
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_subeqc, const_number_map[num], node->get_line());
gen(op_subeqc, const_number_map[num], node->get_location());
}
break;
case assignment_expr::assign_type::mult_equal:
@@ -511,11 +513,11 @@ void codegen::assignment_expression(assignment_expr* node) {
}
mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) {
gen(op_muleq, 0, node->get_line());
gen(op_muleq, 0, node->get_location());
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_muleqc, const_number_map[num], node->get_line());
gen(op_muleqc, const_number_map[num], node->get_location());
}
break;
case assignment_expr::assign_type::div_equal:
@@ -524,11 +526,11 @@ void codegen::assignment_expression(assignment_expr* node) {
}
mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) {
gen(op_diveq, 0, node->get_line());
gen(op_diveq, 0, node->get_location());
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_diveqc, const_number_map[num], node->get_line());
gen(op_diveqc, const_number_map[num], node->get_location());
}
break;
case assignment_expr::assign_type::concat_equal:
@@ -537,27 +539,27 @@ void codegen::assignment_expression(assignment_expr* node) {
}
mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_str) {
gen(op_lnkeq, 0, node->get_line());
gen(op_lnkeq, 0, node->get_location());
} else {
const auto& str = ((string_literal*)node->get_right())->get_content();
regist_str(str);
gen(op_lnkeqc, const_string_map[str], node->get_line());
gen(op_lnkeqc, const_string_map[str], node->get_location());
}
break;
case assignment_expr::assign_type::bitwise_and_equal:
calc_gen(node->get_right());
mcall(node->get_left());
gen(op_btandeq, 0, node->get_line());
gen(op_btandeq, 0, node->get_location());
break;
case assignment_expr::assign_type::bitwise_or_equal:
calc_gen(node->get_right());
mcall(node->get_left());
gen(op_btoreq, 0, node->get_line());
gen(op_btoreq, 0, node->get_location());
break;
case assignment_expr::assign_type::bitwise_xor_equal:
calc_gen(node->get_right());
mcall(node->get_left());
gen(op_btxoreq, 0, node->get_line());
gen(op_btxoreq, 0, node->get_location());
break;
}
}
@@ -581,7 +583,7 @@ void codegen::assignment_statement(assignment_expr* node) {
if (code.back().op==op_meq) {
code.back().num=1;
} else {
gen(op_pop, 0, node->get_line());
gen(op_pop, 0, node->get_location());
}
}
break;
@@ -599,7 +601,7 @@ void codegen::assignment_statement(assignment_expr* node) {
} else if (op_addeqc<=code.back().op && code.back().op<=op_lnkeqc) {
code.back().op=code.back().op-op_addeqc+op_addecp;
} else {
gen(op_pop, 0, node->get_line());
gen(op_pop, 0, node->get_location());
}
break;
}
@@ -630,7 +632,7 @@ void codegen::multi_assign_gen(multi_assign* node) {
} else if (code.back().op==op_mcallg) {
code.back().op=op_loadg;
} else {
gen(op_meq, 1, tuple[i]->get_line());
gen(op_meq, 1, tuple[i]->get_location());
}
}
return;
@@ -638,7 +640,7 @@ void codegen::multi_assign_gen(multi_assign* node) {
calc_gen(node->get_value());
auto& tuple = node->get_tuple()->get_elements();
for(i32 i = 0; i<size; ++i) {
gen(op_callvi, i, node->get_value()->get_line());
gen(op_callvi, i, node->get_value()->get_location());
// multi assign user loadl and loadg to avoid meq's stack--
// and this operation changes local and global value directly
mcall(tuple[i]);
@@ -649,35 +651,35 @@ void codegen::multi_assign_gen(multi_assign* node) {
} else if (code.back().op==op_mcallg) {
code.back().op=op_loadg;
} else {
gen(op_meq, 1, tuple[i]->get_line());
gen(op_meq, 1, tuple[i]->get_location());
}
}
gen(op_pop, 0, node->get_line());
gen(op_pop, 0, node->get_location());
}
void codegen::cond_gen(condition_expr* node) {
std::vector<usize> jmp_label;
calc_gen(node->get_if_statement()->get_condition());
auto ptr = code.size();
gen(op_jf, 0, node->get_if_statement()->get_line());
gen(op_jf, 0, node->get_if_statement()->get_location());
block_gen(node->get_if_statement()->get_code_block());
if (node->get_elsif_stataments().size() ||
node->get_else_statement()) {
jmp_label.push_back(code.size());
gen(op_jmp, 0, node->get_if_statement()->get_line());
gen(op_jmp, 0, node->get_if_statement()->get_location());
}
code[ptr].num = code.size();
for(auto tmp : node->get_elsif_stataments()) {
calc_gen(tmp->get_condition());
ptr = code.size();
gen(op_jf, 0, tmp->get_line());
gen(op_jf, 0, tmp->get_location());
block_gen(tmp->get_code_block());
// the last condition doesn't need to jmp
if (tmp!=node->get_elsif_stataments().back() ||
node->get_else_statement()) {
jmp_label.push_back(code.size());
gen(op_jmp, 0, tmp->get_line());
gen(op_jmp, 0, tmp->get_location());
}
code[ptr].num=code.size();
}
@@ -719,10 +721,10 @@ void codegen::while_gen(while_expr* node) {
usize loop_ptr = code.size();
calc_gen(node->get_condition());
usize condition_ptr = code.size();
gen(op_jf, 0, node->get_condition()->get_line());
gen(op_jf, 0, node->get_condition()->get_location());
block_gen(node->get_code_block());
gen(op_jmp, loop_ptr, node->get_code_block()->get_line());
gen(op_jmp, loop_ptr, node->get_code_block()->get_location());
code[condition_ptr].num = code.size();
load_continue_break(code.size()-1, code.size());
}
@@ -732,17 +734,17 @@ void codegen::for_gen(for_expr* node) {
usize jmp_place = code.size();
if (node->get_condition()->get_type()==expr_type::ast_null) {
regist_num(1);
gen(op_pnum, const_number_map.at(1), node->get_condition()->get_line());
gen(op_pnum, const_number_map.at(1), node->get_condition()->get_location());
} else {
calc_gen(node->get_condition());
}
usize label_exit = code.size();
gen(op_jf, 0, node->get_condition()->get_line());
gen(op_jf, 0, node->get_condition()->get_location());
block_gen(node->get_code_block());
usize continue_place = code.size();
statement_generation(node->get_step());
gen(op_jmp, jmp_place, node->get_step()->get_line());
gen(op_jmp, jmp_place, node->get_step()->get_location());
code[label_exit].num = code.size();
load_continue_break(continue_place, code.size());
@@ -750,19 +752,19 @@ void codegen::for_gen(for_expr* node) {
void codegen::forei_gen(forei_expr* node) {
calc_gen(node->get_value());
gen(op_cnt, 0, node->get_value()->get_line());
gen(op_cnt, 0, node->get_value()->get_location());
usize ptr = code.size();
if (node->get_loop_type()==forei_expr::forei_loop_type::forindex) {
gen(op_findex, 0, node->get_line());
gen(op_findex, 0, node->get_location());
} else {
gen(op_feach, 0, node->get_line());
gen(op_feach, 0, node->get_location());
}
if (node->get_iterator()->get_name()) { // define a new iterator
auto name_node = node->get_iterator()->get_name();
const auto& str = name_node->get_name();
local.empty()?
gen(op_loadg, global_find(str), name_node->get_line()):
gen(op_loadl, local_find(str), name_node->get_line());
gen(op_loadg, global_find(str), name_node->get_location()):
gen(op_loadl, local_find(str), name_node->get_location());
} else { // use exist variable as the iterator
mcall(node->get_iterator()->get_call());
if (code.back().op==op_mcallg) {
@@ -772,17 +774,17 @@ void codegen::forei_gen(forei_expr* node) {
} else if (code.back().op==op_mupval) {
code.back().op=op_loadu;
} else {
gen(op_meq, 1, node->get_iterator()->get_line());
gen(op_meq, 1, node->get_iterator()->get_location());
}
}
++in_loop_level.back();
block_gen(node->get_code_block());
--in_loop_level.back();
gen(op_jmp, ptr, node->get_line());
gen(op_jmp, ptr, node->get_location());
code[ptr].num=code.size();
load_continue_break(code.size()-1, code.size());
gen(op_pop, 0, node->get_value()->get_line());// pop vector
gen(op_pop, 0, node->get_line());// pop iterator
gen(op_pop, 0, node->get_value()->get_location());// pop vector
gen(op_pop, 0, node->get_location());// pop iterator
}
void codegen::statement_generation(expr* node) {
@@ -806,7 +808,7 @@ void codegen::statement_generation(expr* node) {
case expr_type::ast_binary:
case expr_type::ast_ternary:
calc_gen(node);
gen(op_pop, 0, node->get_line());
gen(op_pop, 0, node->get_location());
break;
default: break;
}
@@ -815,33 +817,33 @@ void codegen::statement_generation(expr* node) {
void codegen::or_gen(binary_operator* node) {
calc_gen(node->get_left());
usize label_jump_true_1 = code.size();
gen(op_jt, 0, node->get_left()->get_line());
gen(op_jt, 0, node->get_left()->get_location());
gen(op_pop, 0, node->get_left()->get_line());
gen(op_pop, 0, node->get_left()->get_location());
calc_gen(node->get_right());
usize label_jump_true_2 = code.size();
gen(op_jt, 0, node->get_right()->get_line());
gen(op_jt, 0, node->get_right()->get_location());
gen(op_pop, 0, node->get_right()->get_line());
gen(op_pnil, 0, node->get_right()->get_line());
gen(op_pop, 0, node->get_right()->get_location());
gen(op_pnil, 0, node->get_right()->get_location());
code[label_jump_true_1].num = code[label_jump_true_2].num = code.size();
}
void codegen::and_gen(binary_operator* node) {
calc_gen(node->get_left());
gen(op_jt, code.size()+2, node->get_left()->get_line());
gen(op_jt, code.size()+2, node->get_left()->get_location());
usize lable_jump_false = code.size();
gen(op_jmp, 0, node->get_left()->get_line());
gen(op_pop, 0, node->get_right()->get_line()); // jt jumps here
gen(op_jmp, 0, node->get_left()->get_location());
gen(op_pop, 0, node->get_right()->get_location()); // jt jumps here
calc_gen(node->get_right());
gen(op_jt, code.size()+3, node->get_right()->get_line());
gen(op_jt, code.size()+3, node->get_right()->get_location());
code[lable_jump_false].num = code.size();
gen(op_pop, 0, node->get_right()->get_line());
gen(op_pnil, 0, node->get_right()->get_line());
gen(op_pop, 0, node->get_right()->get_location());
gen(op_pnil, 0, node->get_right()->get_location());
// jt jumps here, avoid pop and pnil
}
@@ -849,11 +851,11 @@ void codegen::unary_gen(unary_operator* node) {
calc_gen(node->get_value());
switch(node->get_operator_type()) {
case unary_operator::unary_type::negative:
gen(op_usub, 0, node->get_line()); break;
gen(op_usub, 0, node->get_location()); break;
case unary_operator::unary_type::logical_not:
gen(op_lnot, 0, node->get_line()); break;
gen(op_lnot, 0, node->get_location()); break;
case unary_operator::unary_type::bitwise_not:
gen(op_bnot, 0, node->get_line()); break;
gen(op_bnot, 0, node->get_location()); break;
}
}
@@ -877,27 +879,27 @@ void codegen::binary_gen(binary_operator* node) {
case binary_operator::binary_type::cmpeq:
calc_gen(node->get_left());
calc_gen(node->get_right());
gen(op_eq, 0, node->get_line());
gen(op_eq, 0, node->get_location());
return;
case binary_operator::binary_type::cmpneq:
calc_gen(node->get_left());
calc_gen(node->get_right());
gen(op_neq, 0, node->get_line());
gen(op_neq, 0, node->get_location());
return;
case binary_operator::binary_type::bitwise_or:
calc_gen(node->get_left());
calc_gen(node->get_right());
gen(op_btor, 0, node->get_line());
gen(op_btor, 0, node->get_location());
return;
case binary_operator::binary_type::bitwise_xor:
calc_gen(node->get_left());
calc_gen(node->get_right());
gen(op_btxor, 0, node->get_line());
gen(op_btxor, 0, node->get_location());
return;
case binary_operator::binary_type::bitwise_and:
calc_gen(node->get_left());
calc_gen(node->get_right());
gen(op_btand, 0, node->get_line());
gen(op_btand, 0, node->get_location());
return;
default: break;
}
@@ -906,99 +908,99 @@ void codegen::binary_gen(binary_operator* node) {
calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right());
gen(op_add, 0, node->get_line());
gen(op_add, 0, node->get_location());
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_addc, const_number_map.at(num), node->get_line());
gen(op_addc, const_number_map.at(num), node->get_location());
}
return;
case binary_operator::binary_type::sub:
calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right());
gen(op_sub, 0, node->get_line());
gen(op_sub, 0, node->get_location());
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_subc, const_number_map.at(num), node->get_line());
gen(op_subc, const_number_map.at(num), node->get_location());
}
return;
case binary_operator::binary_type::mult:
calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right());
gen(op_mul, 0, node->get_line());
gen(op_mul, 0, node->get_location());
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_mulc, const_number_map.at(num), node->get_line());
gen(op_mulc, const_number_map.at(num), node->get_location());
}
return;
case binary_operator::binary_type::div:
calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right());
gen(op_div, 0, node->get_line());
gen(op_div, 0, node->get_location());
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_divc, const_number_map.at(num), node->get_line());
gen(op_divc, const_number_map.at(num), node->get_location());
}
return;
case binary_operator::binary_type::concat:
calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_str) {
calc_gen(node->get_right());
gen(op_lnk, 0, node->get_line());
gen(op_lnk, 0, node->get_location());
} else {
const auto& str = ((string_literal*)node->get_right())->get_content();
regist_str(str);
gen(op_lnkc, const_string_map.at(str), node->get_line());
gen(op_lnkc, const_string_map.at(str), node->get_location());
}
break;
case binary_operator::binary_type::less:
calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right());
gen(op_less, 0, node->get_line());
gen(op_less, 0, node->get_location());
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_lessc, const_number_map.at(num), node->get_line());
gen(op_lessc, const_number_map.at(num), node->get_location());
}
return;
case binary_operator::binary_type::leq:
calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right());
gen(op_leq, 0, node->get_line());
gen(op_leq, 0, node->get_location());
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_leqc, const_number_map.at(num), node->get_line());
gen(op_leqc, const_number_map.at(num), node->get_location());
}
return;
case binary_operator::binary_type::grt:
calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right());
gen(op_grt, 0, node->get_line());
gen(op_grt, 0, node->get_location());
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_grtc, const_number_map.at(num), node->get_line());
gen(op_grtc, const_number_map.at(num), node->get_location());
}
return;
case binary_operator::binary_type::geq:
calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right());
gen(op_geq, 0, node->get_line());
gen(op_geq, 0, node->get_location());
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_geqc, const_number_map.at(num), node->get_line());
gen(op_geqc, const_number_map.at(num), node->get_location());
}
return;
default: break;
@@ -1008,10 +1010,10 @@ void codegen::binary_gen(binary_operator* node) {
void codegen::trino_gen(ternary_operator* node) {
calc_gen(node->get_condition());
usize label_jump_false = code.size();
gen(op_jf, 0, node->get_condition()->get_line());
gen(op_jf, 0, node->get_condition()->get_location());
calc_gen(node->get_left());
usize label_jump_to_exit = code.size();
gen(op_jmp, 0, node->get_left()->get_line());
gen(op_jmp, 0, node->get_left()->get_location());
code[label_jump_false].num = code.size();
calc_gen(node->get_right());
code[label_jump_to_exit].num = code.size();
@@ -1020,7 +1022,7 @@ void codegen::trino_gen(ternary_operator* node) {
void codegen::calc_gen(expr* node) {
switch(node->get_type()) {
case expr_type::ast_nil:
gen(op_pnil, 0, node->get_line()); break;
gen(op_pnil, 0, node->get_location()); break;
case expr_type::ast_num:
num_gen((number_literal*)node); break;
case expr_type::ast_str:
@@ -1064,18 +1066,15 @@ void codegen::block_gen(code_block* node) {
case expr_type::ast_num:
case expr_type::ast_str:
case expr_type::ast_bool: break;
case expr_type::ast_file_info:
// special node type in main block
fileindex = ((file_info*)tmp)->get_index(); break;
case expr_type::ast_cond:
cond_gen((condition_expr*)tmp); break;
case expr_type::ast_continue:
continue_ptr.front().push_back(code.size());
gen(op_jmp, 0, tmp->get_line());
gen(op_jmp, 0, tmp->get_location());
break;
case expr_type::ast_break:
break_ptr.front().push_back(code.size());
gen(op_jmp, 0, tmp->get_line());
gen(op_jmp, 0, tmp->get_location());
break;
case expr_type::ast_while:
case expr_type::ast_for:
@@ -1101,16 +1100,20 @@ void codegen::block_gen(code_block* node) {
void codegen::ret_gen(return_expr* node) {
for(u32 i = 0; i<in_loop_level.back(); ++i) {
gen(op_pop, 0, node->get_line());
gen(op_pop, 0, node->get_line());
gen(op_pop, 0, node->get_location());
gen(op_pop, 0, node->get_location());
}
calc_gen(node->get_value());
gen(op_ret, 0, node->get_line());
gen(op_ret, 0, node->get_location());
}
const error& codegen::compile(parse& parse, linker& import) {
fileindex = 0;
file = import.filelist();
const auto& file = import.filelist();
file_map = {};
for(usize i = 0; i<file.size(); ++i) {
file_map[file[i]] = i;
}
in_loop_level.push_back(0);
// add special symbol globals, which is a hash stores all global variables
@@ -1119,9 +1122,9 @@ const error& codegen::compile(parse& parse, linker& import) {
add_symbol("arg");
find_symbol(parse.tree()); // search symbols first
gen(op_intg, global.size(), 0);
gen(op_intg, global.size(), parse.tree()->get_location());
block_gen(parse.tree()); // generate main block
gen(op_exit, 0, 0);
gen(op_exit, 0, parse.tree()->get_location());
// size out of bound check
if (const_number_table.size()>0xffffff) {