optimize codegen

This commit is contained in:
ValKmjolnir 2023-07-05 00:24:34 +08:00
parent 5c714d26aa
commit eca6141408
13 changed files with 403 additions and 356 deletions

View File

@ -5,6 +5,11 @@ bool ast_visitor::visit_expr(expr* node) {
return true;
}
bool ast_visitor::visit_call(call* node) {
node->accept(this);
return true;
}
bool ast_visitor::visit_file_info(file_info* node) {
return true;
}

View File

@ -5,6 +5,7 @@
class ast_visitor {
public:
virtual bool visit_expr(expr*);
virtual bool visit_call(call*);
virtual bool visit_file_info(file_info*);
virtual bool visit_null_expr(null_expr*);
virtual bool visit_nil_expr(nil_expr*);

View File

@ -131,7 +131,7 @@ void execute(
// code generator gets parser's ast and import file list to generate code
gen.compile(parse, ld).chkerr();
if (cmd&VM_CODE) {
gen.print();
gen.print(std::cout);
}
// run

View File

@ -5,6 +5,10 @@ void expr::accept(ast_visitor* visitor) {
visitor->visit_expr(this);
}
void call::accept(ast_visitor* visitor) {
visitor->visit_call(this);
}
void file_info::accept(ast_visitor* visitor) {
visitor->visit_file_info(this);
}

View File

@ -76,6 +76,14 @@ public:
virtual void accept(ast_visitor*);
};
class call:public expr {
public:
call(const span& location, expr_type node_type):
expr(location, node_type) {}
~call() = default;
virtual void accept(ast_visitor*);
};
class file_info:public expr {
private:
uint16_t index;
@ -353,7 +361,7 @@ public:
class call_expr:public expr {
private:
expr* first;
std::vector<expr*> calls;
std::vector<call*> calls;
public:
call_expr(const span& location):
@ -361,45 +369,45 @@ public:
first(nullptr) {}
~call_expr();
void set_first(expr* node) {first = node;}
void add_call(expr* node) {calls.push_back(node);}
void add_call(call* node) {calls.push_back(node);}
expr* get_first() {return first;}
std::vector<expr*>& get_calls() {return calls;}
std::vector<call*>& get_calls() {return calls;}
void accept(ast_visitor*) override;
};
class call_hash:public expr {
class call_hash:public call {
private:
std::string field;
public:
call_hash(const span& location, const std::string& name):
expr(location, expr_type::ast_callh),
call(location, expr_type::ast_callh),
field(name) {}
~call_hash() = default;
const std::string& get_field() const {return field;}
void accept(ast_visitor*) override;
};
class call_vector:public expr {
class call_vector:public call {
private:
std::vector<slice_vector*> calls;
public:
call_vector(const span& location):
expr(location, expr_type::ast_callv) {}
call(location, expr_type::ast_callv) {}
~call_vector();
void add_slice(slice_vector* node) {calls.push_back(node);}
std::vector<slice_vector*>& get_slices() {return calls;}
void accept(ast_visitor*) override;
};
class call_function:public expr {
class call_function:public call {
private:
std::vector<expr*> args;
public:
call_function(const span& location):
expr(location, expr_type::ast_callf) {}
call(location, expr_type::ast_callf) {}
~call_function();
void add_argument(expr* node) {args.push_back(node);}
std::vector<expr*>& get_argument() {return args;}

View File

@ -27,31 +27,31 @@ void codegen::check_id_exist(identifier* node) {
}
void codegen::regist_num(const f64 num) {
if (num_table.count(num)) {
if (const_number_map.count(num)) {
return;
}
u32 size = num_table.size();
num_table[num] = size;
num_res.push_back(num);
u32 size = const_number_map.size();
const_number_map[num] = size;
const_number_table.push_back(num);
}
void codegen::regist_str(const std::string& str) {
if (str_table.count(str)) {
if (const_string_map.count(str)) {
return;
}
u32 size = str_table.size();
str_table[str] = size;
str_res.push_back(str);
u32 size = const_string_map.size();
const_string_map[str] = size;
const_string_table.push_back(str);
}
void codegen::find_symbol(code_block* node) {
auto finder = std::unique_ptr<symbol_finder>(new symbol_finder);
for(const auto& i : finder->do_find(node)) {
add_sym(i);
add_symbol(i);
}
}
void codegen::add_sym(const std::string& name) {
void codegen::add_symbol(const std::string& name) {
if (local.empty()) {
if (global.count(name)) {
return;
@ -101,19 +101,19 @@ void codegen::gen(u8 operation_code, u32 num, u32 line) {
void codegen::num_gen(number_literal* node) {
f64 num = node->get_number();
regist_num(num);
gen(op_pnum,num_table.at(num), node->get_line());
gen(op_pnum,const_number_map.at(num), node->get_line());
}
void codegen::str_gen(string_literal* node) {
const auto& str = node->get_content();
regist_str(str);
gen(op_pstr, str_table.at(str), node->get_line());
gen(op_pstr, const_string_map.at(str), node->get_line());
}
void codegen::bool_gen(bool_literal* node) {
f64 num = node->get_flag()? 1:0;
regist_num(num);
gen(op_pnum, num_table.at(num), node->get_line());
gen(op_pnum, const_number_map.at(num), node->get_line());
}
void codegen::vec_gen(vector_expr* node) {
@ -129,7 +129,7 @@ void codegen::hash_gen(hash_expr* node) {
calc_gen(child->get_value());
const auto& field_name = child->get_name();
regist_str(field_name);
gen(op_happ, str_table.at(field_name), child->get_line());
gen(op_happ, const_string_map.at(field_name), child->get_line());
}
}
@ -190,17 +190,17 @@ void codegen::func_gen(function* node) {
regist_str(name);
switch(tmp->get_parameter_type()) {
case parameter::param_type::normal_parameter:
gen(op_para, str_table.at(name), tmp->get_line());
gen(op_para, const_string_map.at(name), tmp->get_line());
break;
case parameter::param_type::default_parameter:
calc_gen(tmp->get_default_value());
gen(op_deft, str_table.at(name), tmp->get_line());
gen(op_deft, const_string_map.at(name), tmp->get_line());
break;
case parameter::param_type::dynamic_parameter:
gen(op_dyn, str_table.at(name), tmp->get_line());
gen(op_dyn, const_string_map.at(name), tmp->get_line());
break;
}
add_sym(name);
add_symbol(name);
}
code[newf].num = code.size()+1; // entry
@ -274,7 +274,7 @@ void codegen::call_id(identifier* node) {
void codegen::call_hash_gen(call_hash* node) {
regist_str(node->get_field());
gen(op_callh, str_table.at(node->get_field()), node->get_line());
gen(op_callh, const_string_map.at(node->get_field()), node->get_line());
}
void codegen::call_vector_gen(call_vector* node) {
@ -307,7 +307,7 @@ void codegen::call_func_gen(call_function* node) {
calc_gen(((hash_pair*)child)->get_value());
const auto& field_name = ((hash_pair*)child)->get_name();
regist_str(field_name);
gen(op_happ, str_table.at(field_name), child->get_line());
gen(op_happ, const_string_map.at(field_name), child->get_line());
}
gen(op_callfh, 0, node->get_line());
} else {
@ -399,7 +399,7 @@ void codegen::mcall_vec(call_vector* node) {
void codegen::mcall_hash(call_hash* node) {
regist_str(node->get_field());
gen(op_mcallh, str_table.at(node->get_field()), node->get_line());
gen(op_mcallh, const_string_map.at(node->get_field()), node->get_line());
}
void codegen::single_def(definition_expr* node) {
@ -417,9 +417,11 @@ void codegen::multi_def(definition_expr* node) {
if (node->get_tuple()) {
auto& vals = node->get_tuple()->get_elements();
if (identifiers.size()<vals.size()) {
die("lack values in multi-definition", node->get_tuple()->get_location());
die("lack values in multi-definition",
node->get_tuple()->get_location());
} else if (identifiers.size()>vals.size()) {
die("too many values in multi-definition", node->get_tuple()->get_location());
die("too many values in multi-definition",
node->get_tuple()->get_location());
}
for(usize i = 0; i<size; ++i) {
calc_gen(vals[i]);
@ -466,7 +468,7 @@ void codegen::assignment_expression(assignment_expr* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_addeqc, num_table[num], node->get_line());
gen(op_addeqc, const_number_map[num], node->get_line());
}
break;
case assignment_expr::assign_type::sub_equal:
@ -479,7 +481,7 @@ void codegen::assignment_expression(assignment_expr* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_subeqc, num_table[num], node->get_line());
gen(op_subeqc, const_number_map[num], node->get_line());
}
break;
case assignment_expr::assign_type::mult_equal:
@ -492,7 +494,7 @@ void codegen::assignment_expression(assignment_expr* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_muleqc, num_table[num], node->get_line());
gen(op_muleqc, const_number_map[num], node->get_line());
}
break;
case assignment_expr::assign_type::div_equal:
@ -505,7 +507,7 @@ void codegen::assignment_expression(assignment_expr* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_diveqc, num_table[num], node->get_line());
gen(op_diveqc, const_number_map[num], node->get_line());
}
break;
case assignment_expr::assign_type::concat_equal:
@ -518,7 +520,7 @@ void codegen::assignment_expression(assignment_expr* node) {
} else {
const auto& str = ((string_literal*)node->get_right())->get_content();
regist_str(str);
gen(op_lnkeqc, str_table[str], node->get_line());
gen(op_lnkeqc, const_string_map[str], node->get_line());
}
break;
case assignment_expr::assign_type::bitwise_and_equal:
@ -610,7 +612,8 @@ void codegen::multi_assign_gen(multi_assign* node) {
gen(op_meq, 1, tuple[i]->get_line());
}
}
} else {
return;
}
calc_gen(node->get_value());
auto& tuple = node->get_tuple()->get_elements();
for(i32 i = 0; i<size; ++i) {
@ -630,7 +633,6 @@ void codegen::multi_assign_gen(multi_assign* node) {
}
gen(op_pop, 0, node->get_line());
}
}
void codegen::cond_gen(condition_expr* node) {
std::vector<usize> jmp_label;
@ -709,7 +711,7 @@ 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, num_table.at(1), node->get_condition()->get_line());
gen(op_pnum, const_number_map.at(1), node->get_condition()->get_line());
} else {
calc_gen(node->get_condition());
}
@ -735,10 +737,11 @@ void codegen::forei_gen(forei_expr* node) {
gen(op_feach, 0, node->get_line());
}
if (node->get_iterator()->get_name()) { // define a new iterator
const auto& str = node->get_iterator()->get_name()->get_name();
auto name_node = node->get_iterator()->get_name();
const auto& str = name_node->get_name();
local.empty()?
gen(op_loadg, global_find(str), node->get_iterator()->get_name()->get_line()):
gen(op_loadl, local_find(str), node->get_iterator()->get_name()->get_line());
gen(op_loadg, global_find(str), name_node->get_line()):
gen(op_loadl, local_find(str), name_node->get_line());
} else { // use exist variable as the iterator
mcall(node->get_iterator()->get_call());
if (code.back().op==op_mcallg) {
@ -770,8 +773,10 @@ void codegen::statement_generation(expr* node) {
multi_assign_gen((multi_assign*)node); break;
case expr_type::ast_assign:
assignment_statement((assignment_expr*)node); break;
case expr_type::ast_nil:case expr_type::ast_num:
case expr_type::ast_str:case expr_type::ast_bool: break;
case expr_type::ast_nil:
case expr_type::ast_num:
case expr_type::ast_str:
case expr_type::ast_bool: break;
case expr_type::ast_vec:
case expr_type::ast_hash:
case expr_type::ast_func:
@ -788,35 +793,35 @@ void codegen::statement_generation(expr* node) {
void codegen::or_gen(binary_operator* node) {
calc_gen(node->get_left());
usize l1 = code.size();
usize label_jump_true_1 = code.size();
gen(op_jt, 0, node->get_left()->get_line());
gen(op_pop, 0, node->get_left()->get_line());
calc_gen(node->get_right());
usize l2=code.size();
usize label_jump_true_2 = code.size();
gen(op_jt, 0, node->get_right()->get_line());
gen(op_pop, 0, node->get_right()->get_line());
gen(op_pnil, 0, node->get_right()->get_line());
code[l1].num = code[l2].num = code.size();
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());
usize lfalse = code.size();
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
calc_gen(node->get_right());
gen(op_jt, code.size()+3, node->get_right()->get_line());
code[lfalse].num = code.size();
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());
// jt jumps here
// jt jumps here, avoid pop and pnil
}
void codegen::unary_gen(unary_operator* node) {
@ -884,7 +889,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_addc, num_table.at(num), node->get_line());
gen(op_addc, const_number_map.at(num), node->get_line());
}
return;
case binary_operator::binary_type::sub:
@ -895,7 +900,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_subc, num_table.at(num), node->get_line());
gen(op_subc, const_number_map.at(num), node->get_line());
}
return;
case binary_operator::binary_type::mult:
@ -906,7 +911,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_mulc, num_table.at(num), node->get_line());
gen(op_mulc, const_number_map.at(num), node->get_line());
}
return;
case binary_operator::binary_type::div:
@ -917,7 +922,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_divc, num_table.at(num), node->get_line());
gen(op_divc, const_number_map.at(num), node->get_line());
}
return;
case binary_operator::binary_type::concat:
@ -928,7 +933,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
const auto& str = ((string_literal*)node->get_right())->get_content();
regist_str(str);
gen(op_lnkc, str_table.at(str), node->get_line());
gen(op_lnkc, const_string_map.at(str), node->get_line());
}
break;
case binary_operator::binary_type::less:
@ -939,7 +944,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_lessc, num_table.at(num), node->get_line());
gen(op_lessc, const_number_map.at(num), node->get_line());
}
return;
case binary_operator::binary_type::leq:
@ -950,7 +955,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_leqc, num_table.at(num), node->get_line());
gen(op_leqc, const_number_map.at(num), node->get_line());
}
return;
case binary_operator::binary_type::grt:
@ -961,7 +966,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_grtc, num_table.at(num), node->get_line());
gen(op_grtc, const_number_map.at(num), node->get_line());
}
return;
case binary_operator::binary_type::geq:
@ -972,7 +977,7 @@ void codegen::binary_gen(binary_operator* node) {
} else {
auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num);
gen(op_geqc, num_table.at(num), node->get_line());
gen(op_geqc, const_number_map.at(num), node->get_line());
}
return;
default: break;
@ -981,14 +986,14 @@ void codegen::binary_gen(binary_operator* node) {
void codegen::trino_gen(ternary_operator* node) {
calc_gen(node->get_condition());
usize lfalse = code.size();
usize label_jump_false = code.size();
gen(op_jf, 0, node->get_condition()->get_line());
calc_gen(node->get_left());
usize lexit = code.size();
usize label_jump_to_exit = code.size();
gen(op_jmp, 0, node->get_left()->get_line());
code[lfalse].num = code.size();
code[label_jump_false].num = code.size();
calc_gen(node->get_right());
code[lexit].num = code.size();
code[label_jump_to_exit].num = code.size();
}
void codegen::calc_gen(expr* node) {
@ -1034,8 +1039,10 @@ void codegen::block_gen(code_block* node) {
case expr_type::ast_null: break;
case expr_type::ast_id:
check_id_exist((identifier*)tmp); break;
case expr_type::ast_nil:case expr_type::ast_num:
case expr_type::ast_str:case expr_type::ast_bool:break;
case expr_type::ast_nil:
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;
@ -1090,73 +1097,76 @@ const error& codegen::compile(parse& parse, linker& import) {
gen(op_exit, 0, 0);
// size out of bound check
if (num_res.size()>0xffffff) {
err.load(file[0]); // load main execute file
if (const_number_table.size()>0xffffff) {
err.err("code",
"too many constant numbers: " + std::to_string(num_res.size()));
"too many constant numbers: " +
std::to_string(const_number_table.size()));
}
if (str_res.size()>0xffffff) {
err.load(file[0]); // load main execute file
if (const_string_table.size()>0xffffff) {
err.err("code",
"too many constant strings: " + std::to_string(str_res.size()));
"too many constant strings: " +
std::to_string(const_string_table.size()));
}
if (global.size()>=STACK_DEPTH) {
err.load(file[0]); // load main execute file
err.err("code",
"too many global variants: " + std::to_string(global.size()));
"too many global variables: " + std::to_string(global.size()));
}
if (code.size()>0xffffff) {
err.load(file[0]); // load main execute file
err.err("code",
"bytecode size overflow: " + std::to_string(code.size()));
}
return err;
}
void codegen::print() {
void codegen::print(std::ostream& out) {
// func end stack, reserved for code print
std::stack<u32> fbstk;
std::stack<u32> festk;
std::stack<u32> func_begin_stack;
std::stack<u32> func_end_stack;
// print const numbers
for(auto num : num_res) {
std::cout << " .number " << num << "\n";
for(auto num : const_number_table) {
out << " .number " << num << "\n";
}
// print const strings
for(const auto& str : str_res) {
std::cout << " .symbol \"" << rawstr(str) << "\"\n";
for(const auto& str : const_string_table) {
out << " .symbol \"" << rawstr(str) << "\"\n";
}
// print blank line
if (const_number_table.size() || const_string_table.size()) {
out << "\n";
}
// print code
std::cout<<"\n";
codestream::set(num_res.data(), str_res.data());
codestream::set(const_number_table.data(), const_string_table.data());
for(u32 i = 0; i<code.size(); ++i) {
// print opcode index, opcode name, opcode immediate number
const auto& c = code[i];
if (!festk.empty() && i==festk.top()) {
std::cout << std::hex << "<0x" << fbstk.top() << std::dec << ">;\n";
if (!func_end_stack.empty() && i==func_end_stack.top()) {
out << std::hex << "<0x" << func_begin_stack.top() << std::dec << ">;\n";
// avoid two empty lines
if (c.op!=op_newf) {
std::cout<<"\n";
out<<"\n";
}
fbstk.pop();
festk.pop();
func_begin_stack.pop();
func_end_stack.pop();
}
// get function begin index and end index
if (c.op==op_newf) {
std::cout << std::hex << "\nfunc <0x" << i << std::dec << ">:\n";
out << std::hex << "\nfunc <0x" << i << std::dec << ">:\n";
for(u32 j = i; j<code.size(); ++j) {
if (code[j].op==op_jmp) {
fbstk.push(i);
festk.push(code[j].num);
func_begin_stack.push(i);
func_end_stack.push(code[j].num);
break;
}
}
}
// output bytecode
std::cout << " " << codestream(c,i) << "\n";
out << " " << codestream(c,i) << "\n";
}
}

View File

@ -25,10 +25,10 @@ private:
error& err;
const std::string* file;
std::stack<u32> in_iterloop;
std::unordered_map<f64,u32> num_table;
std::unordered_map<std::string,u32> str_table;
std::vector<f64> num_res;
std::vector<std::string> str_res;
std::unordered_map<f64,u32> const_number_map;
std::unordered_map<std::string,u32> const_string_map;
std::vector<f64> const_number_table;
std::vector<std::string> const_string_table;
std::vector<opcode> code;
std::list<std::vector<i32>> continue_ptr;
std::list<std::vector<i32>> break_ptr;
@ -49,7 +49,7 @@ private:
void regist_num(const f64);
void regist_str(const std::string&);
void find_symbol(code_block*);
void add_sym(const std::string&);
void add_symbol(const std::string&);
i32 local_find(const std::string&);
i32 global_find(const std::string&);
i32 upvalue_find(const std::string&);
@ -93,11 +93,13 @@ private:
void block_gen(code_block*);
void ret_gen(return_expr*);
public:
const std::vector<std::string>& strs() const {return const_string_table;}
const std::vector<f64>& nums() const {return const_number_table;}
const std::vector<opcode>& codes() const {return code;}
public:
codegen(error& e): fileindex(0), err(e), file(nullptr) {}
const error& compile(parse&, linker&);
void print();
const std::vector<std::string>& strs() const {return str_res;}
const std::vector<f64>& nums() const {return num_res;}
const std::vector<opcode>& codes() const {return code;}
void print(std::ostream&);
};

View File

@ -5,8 +5,8 @@ const char* opname[]={
"loadl ", "loadu ", "pnum ", "pnil ",
"pstr ", "newv ", "newh ", "newf ",
"happ ", "para ", "def ", "dyn ",
"lnot ","usub ","bnot ","btor ",
"btxor ","btand ","add ","sub ",
"lnot ", "usub ", "bitnot", "bitor ",
"bitxor", "bitand", "add ", "sub ",
"mult ", "div ", "lnk ", "addc ",
"subc ", "multc ", "divc ", "lnkc ",
"addeq ", "subeq ", "muleq ", "diveq ",
@ -20,16 +20,15 @@ const char* opname[]={
"jf ", "cnt ", "findx ", "feach ",
"callg ", "calll ", "upval ", "callv ",
"callvi", "callh ", "callfv", "callfh",
"callb ","slcbeg","slcend","slc ",
"slc2 ","mcallg","mcalll","mupval",
"callb ", "slcbeg", "slcend", "slice ",
"slice2", "mcallg", "mcalll", "mupval",
"mcallv", "mcallh", "ret "
};
void codestream::set(
const f64* numbuff,
const std::string* strbuff,
const std::string* filelist
) {
const std::string* filelist) {
nums = numbuff;
strs = strbuff;
files = filelist;
@ -58,20 +57,25 @@ void codestream::dump(std::ostream& out) const {
out << hex << "0x" << num << dec << " sp-" << num; break;
case op_addeqc: case op_subeqc:
case op_muleqc:case op_diveqc:
out<<hex<<"0x"<<num<<dec<<" ("<<nums[num]<<")";break;
out << hex << "0x" << num << dec
<< " (" << nums[num] << ")"; break;
case op_lnkeqc:
out<<hex<<"0x"<<num<<dec<<" ("<<rawstr(strs[num], 16)<<")";break;
out << hex << "0x" << num << dec
<< " (" << rawstr(strs[num], 16) << ")"; break;
case op_addecp: case op_subecp:
case op_mulecp: case op_divecp:
out<<hex<<"0x"<<num<<dec<<" ("<<nums[num]<<") sp-1";break;
out << hex << "0x" << num << dec
<< " (" << nums[num] << ") sp-1"; break;
case op_lnkecp:
out<<hex<<"0x"<<num<<dec<<" ("<<rawstr(strs[num], 16)<<") sp-1";break;
out << hex << "0x" << num << dec
<< " (" << rawstr(strs[num], 16) << ") sp-1"; break;
case op_addc: case op_subc:
case op_mulc: case op_divc:
case op_lessc: case op_leqc:
case op_grtc: case op_geqc:
case op_pnum:
out<<hex<<"0x"<<num<<dec<<" ("<<nums[num]<<")";break;
out << hex << "0x" << num << dec
<< " (" << nums[num] << ")"; break;
case op_callvi: case op_newv:
case op_callfv: case op_intg:
case op_intl: case op_findex:
@ -93,7 +97,8 @@ void codestream::dump(std::ostream& out) const {
case op_lnkc: case op_callh:
case op_mcallh: case op_para:
case op_deft: case op_dyn:
out<<hex<<"0x"<<num<<dec<<" ("<<rawstr(strs[num], 16)<<")";break;
out << hex << "0x" << num << dec
<< " (" << rawstr(strs[num], 16) << ")"; break;
default:
if (files) {
out << hex << "0x" << num << dec;

View File

@ -639,7 +639,7 @@ expr* parse::scalar() {
return node;
}
expr* parse::call_scalar() {
call* parse::call_scalar() {
switch(toks[ptr].type) {
case tok::lcurve: return callf(); break;
case tok::lbracket: return callv(); break;
@ -647,7 +647,7 @@ expr* parse::call_scalar() {
default: break;
}
// unreachable
return null();
return new call(toks[ptr].loc, expr_type::ast_null);
}
call_hash* parse::callh() {

View File

@ -114,7 +114,7 @@ private:
expr* multive_expr();
unary_operator* unary();
expr* scalar();
expr* call_scalar();
call* call_scalar();
call_hash* callh();
call_vector* callv();
call_function* callf();

View File

@ -133,7 +133,7 @@ var systime=func(){
# die is a special native function.
# use it at where you want the program to crash immediately.
var die=func(str){
var die = func(str = "error occurred.") {
return __die(str);
}

12
test/gc_test.nas Normal file
View File

@ -0,0 +1,12 @@
var res = [];
for(var i=0;i<1e6;i+=1) {
append(res, []);
}
res = [];
for(var i=0;i<1e6;i+=1) {
append(res, {});
}
res = [];
for(var i=0;i<1e6;i+=1) {
append(res, func {});
}