✨ finish new codegen
This commit is contained in:
parent
90ad1a53d7
commit
b6886cc957
|
@ -1,8 +1,8 @@
|
|||
#include "nasal_new_codegen.h"
|
||||
|
||||
bool codegen::check_memory_reachable(call_expr* node) {
|
||||
if (node->get_first()->get_type()==expr_type::ast_call) {
|
||||
const auto tmp=node->get_calls().back();
|
||||
bool codegen::check_memory_reachable(expr* node) {
|
||||
if (node->get_type()==expr_type::ast_call) {
|
||||
const auto tmp=((call_expr*)node)->get_calls().back();
|
||||
if (tmp->get_type()==expr_type::ast_callf) {
|
||||
die("bad left-value with function call", node->get_location());
|
||||
return false;
|
||||
|
@ -13,7 +13,7 @@ bool codegen::check_memory_reachable(call_expr* node) {
|
|||
die("bad left-value with subvec", node->get_location());
|
||||
return false;
|
||||
}
|
||||
} else if (node->get_first()->get_type()!=expr_type::ast_id) {
|
||||
} else if (node->get_type()!=expr_type::ast_id) {
|
||||
die("bad left-value", node->get_location());
|
||||
return false;
|
||||
}
|
||||
|
@ -441,40 +441,127 @@ void codegen::assignment_gen(assignment_expr* node) {
|
|||
gen(op_meq, 0, node->get_location().begin_line);
|
||||
break;
|
||||
case assignment_expr::assign_type::add_equal:
|
||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||
calc_gen(node->get_right());
|
||||
}
|
||||
mcall((call_expr*)node->get_left());
|
||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||
gen(op_addeq, 0, node->get_location().begin_line);
|
||||
} else {
|
||||
auto num = ((number_literal*)node->get_right())->get_number();
|
||||
regist_num(num);
|
||||
gen(op_addeqc, num_table[num], node->get_location().begin_line);
|
||||
}
|
||||
break;
|
||||
case assignment_expr::assign_type::sub_equal:
|
||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||
calc_gen(node->get_right());
|
||||
}
|
||||
mcall((call_expr*)node->get_left());
|
||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||
gen(op_subeq, 0, node->get_location().begin_line);
|
||||
} else {
|
||||
auto num = ((number_literal*)node->get_right())->get_number();
|
||||
regist_num(num);
|
||||
gen(op_subeqc, num_table[num], node->get_location().begin_line);
|
||||
}
|
||||
break;
|
||||
case assignment_expr::assign_type::mult_equal:
|
||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||
calc_gen(node->get_right());
|
||||
}
|
||||
mcall((call_expr*)node->get_left());
|
||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||
gen(op_muleq, 0, node->get_location().begin_line);
|
||||
} else {
|
||||
auto num = ((number_literal*)node->get_right())->get_number();
|
||||
regist_num(num);
|
||||
gen(op_muleqc, num_table[num], node->get_location().begin_line);
|
||||
}
|
||||
break;
|
||||
case assignment_expr::assign_type::div_equal:
|
||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||
calc_gen(node->get_right());
|
||||
}
|
||||
mcall((call_expr*)node->get_left());
|
||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||
gen(node->get_type()-ast_addeq+op_addeq, 0, node->get_location().begin_line);
|
||||
gen(op_diveq, 0, node->get_location().begin_line);
|
||||
} else {
|
||||
auto num = ((number_literal*)node->get_right())->get_number();
|
||||
regist_num(num);
|
||||
gen(node->get_type()-ast_addeq+op_addeqc, num_table[num], node->get_location().begin_line);
|
||||
gen(op_diveqc, num_table[num], node->get_location().begin_line);
|
||||
}
|
||||
break;
|
||||
case assignment_expr::assign_type::concat_equal:
|
||||
if (node[1]->get_type()!=ast_str) {
|
||||
calc_gen(node[1]);
|
||||
} else {
|
||||
regist_str(node[1].str());
|
||||
if (node->get_right()->get_type()!=expr_type::ast_str) {
|
||||
calc_gen(node->get_right());
|
||||
}
|
||||
mcall(node[0]);
|
||||
if (node[1]->get_type()!=ast_str) {
|
||||
mcall((call_expr*)node->get_left());
|
||||
if (node->get_right()->get_type()!=expr_type::ast_str) {
|
||||
gen(op_lnkeq, 0, node->get_location().begin_line);
|
||||
} else {
|
||||
gen(op_lnkeqc, str_table[node[1].str()], node->get_location().begin_line);
|
||||
const auto& str = ((string_literal*)node->get_right())->get_content();
|
||||
regist_str(str);
|
||||
gen(op_lnkeqc, str_table[str], node->get_location().begin_line);
|
||||
}
|
||||
break;
|
||||
case assignment_expr::assign_type::bitwise_and_equal:
|
||||
calc_gen(node->get_right());
|
||||
mcall((call_expr*)node->get_left());
|
||||
gen(op_btandeq, 0, node->get_location().begin_line);
|
||||
break;
|
||||
case assignment_expr::assign_type::bitwise_or_equal:
|
||||
calc_gen(node->get_right());
|
||||
mcall((call_expr*)node->get_left());
|
||||
gen(op_btoreq, 0, node->get_location().begin_line);
|
||||
break;
|
||||
case assignment_expr::assign_type::bitwise_xor_equal:
|
||||
calc_gen(node->get_right());
|
||||
mcall((call_expr*)node->get_left());
|
||||
gen(node->get_type()-ast_btandeq+op_btandeq, 0, node->get_location().begin_line);
|
||||
gen(op_btxoreq, 0, node->get_location().begin_line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void codegen::assign_statement(assignment_expr* node) {
|
||||
switch(node->get_assignment_type()) {
|
||||
case assignment_expr::assign_type::equal:
|
||||
if (node->get_left()->get_type()==expr_type::ast_id) {
|
||||
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().begin_line);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case assignment_expr::assign_type::add_equal:
|
||||
case assignment_expr::assign_type::sub_equal:
|
||||
case assignment_expr::assign_type::mult_equal:
|
||||
case assignment_expr::assign_type::div_equal:
|
||||
case assignment_expr::assign_type::concat_equal:
|
||||
case assignment_expr::assign_type::bitwise_and_equal:
|
||||
case assignment_expr::assign_type::bitwise_or_equal:
|
||||
case assignment_expr::assign_type::bitwise_xor_equal:
|
||||
calc_gen(node);
|
||||
if (op_addeq<=code.back().op && code.back().op<=op_btxoreq) {
|
||||
code.back().num=1;
|
||||
} 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_location().begin_line);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -624,50 +711,21 @@ void codegen::expr_gen(expr* node) {
|
|||
switch(node->get_type()) {
|
||||
case expr_type::ast_null:break;
|
||||
case expr_type::ast_def:
|
||||
def_gen((definition_expr*)node);break;
|
||||
def_gen((definition_expr*)node); break;
|
||||
case expr_type::ast_multi_assign:
|
||||
multi_assign_gen((multi_assign*)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_vec:case expr_type::ast_hash:case expr_type::ast_func:case expr_type::ast_call:
|
||||
multi_assign_gen((multi_assign*)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_vec:case expr_type::ast_hash:
|
||||
case expr_type::ast_func:case expr_type::ast_call:
|
||||
case expr_type::ast_unary:
|
||||
case expr_type::ast_binary:
|
||||
case expr_type::ast_ternary:
|
||||
calc_gen(node);
|
||||
gen(op_pop, 0, node->get_location().begin_line);
|
||||
break;
|
||||
case expr_type::ast_equal:
|
||||
if (node[0]->get_type()==expr_type::ast_id) {
|
||||
calc_gen(node[1]);
|
||||
mcall_id(node[0]);
|
||||
// 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().begin_line);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case expr_type::ast_addeq:case expr_type::ast_subeq:
|
||||
case expr_type::ast_multeq:case expr_type::ast_diveq:case expr_type::ast_lnkeq:
|
||||
case expr_type::ast_btandeq:case expr_type::ast_btoreq:case expr_type::ast_btxoreq:
|
||||
calc_gen(node);
|
||||
if (op_addeq<=code.back().op && code.back().op<=op_btxoreq) {
|
||||
code.back().num=1;
|
||||
} 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_location().begin_line);
|
||||
}
|
||||
break;
|
||||
case expr_type::ast_assign:
|
||||
assign_statement((assignment_expr*)node); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ private:
|
|||
// but in fact local scope also has less than STACK_DEPTH value
|
||||
std::list<std::unordered_map<std::string,i32>> local;
|
||||
|
||||
bool check_memory_reachable(call_expr*);
|
||||
bool check_memory_reachable(expr*);
|
||||
void check_id_exist(identifier*);
|
||||
|
||||
void die(const std::string& info, const span& loc) {
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
#include "nasal_new_dbg.h"
|
||||
|
||||
std::vector<std::string> dbg::parse(const std::string& cmd) {
|
||||
std::vector<std::string> res;
|
||||
usize last=0;
|
||||
usize pos=cmd.find(" ", 0);
|
||||
while(pos!=std::string::npos) {
|
||||
if (pos>last) {
|
||||
res.push_back(cmd.substr(last, pos-last));
|
||||
}
|
||||
last=pos+1;
|
||||
pos=cmd.find(" ", last);
|
||||
}
|
||||
if (last<cmd.length()) {
|
||||
res.push_back(cmd.substr(last));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
u16 dbg::file_index(const std::string& filename) const {
|
||||
for(u16 i=0;i<fsize;++i) {
|
||||
if (filename==files[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 65535;
|
||||
}
|
||||
|
||||
void dbg::err() {
|
||||
std::cerr
|
||||
<<"incorrect command\n"
|
||||
<<"input \'h\' to get help\n";
|
||||
}
|
||||
|
||||
void dbg::help() {
|
||||
std::clog
|
||||
<<"<option>\n"
|
||||
<<" h, help | get help\n"
|
||||
<<" bt, backtrace | get function call trace\n"
|
||||
<<" c, continue | run program until break point or exit\n"
|
||||
<<" f, file | see all the compiled files\n"
|
||||
<<" g, global | see global values\n"
|
||||
<<" l, local | see local values\n"
|
||||
<<" u, upval | see upvalue\n"
|
||||
<<" r, register | show vm register detail\n"
|
||||
<<" a, all | show global,local and upvalue\n"
|
||||
<<" n, next | execute next bytecode\n"
|
||||
<<" q, exit | exit debugger\n"
|
||||
<<"<option> <filename> <line>\n"
|
||||
<<" bk, break | set break point\n";
|
||||
}
|
||||
|
||||
void dbg::list_file() const {
|
||||
for(usize i=0; i<fsize; ++i) {
|
||||
std::clog<<"["<<i<<"] "<<files[i]<<"\n";
|
||||
}
|
||||
}
|
||||
|
||||
void dbg::call_sort(const u64* arr) const {
|
||||
typedef std::pair<u32,u64> op;
|
||||
std::vector<op> opcall;
|
||||
u64 total=0;
|
||||
for(u32 i=0;i<op_ret+1;++i) {
|
||||
total+=arr[i];
|
||||
opcall.push_back({i, arr[i]});
|
||||
}
|
||||
std::sort(opcall.begin(), opcall.end(),
|
||||
[](const op& a, const op& b) {return a.second>b.second;}
|
||||
);
|
||||
std::clog<<"\noperands call info (<1% ignored)\n";
|
||||
for(auto& i:opcall) {
|
||||
u64 rate=i.second*100/total;
|
||||
if (!rate) {
|
||||
break;
|
||||
}
|
||||
std::clog<<" "<<opname[i.first]<<" : "<<i.second<<" ("<<rate<<"%)\n";
|
||||
}
|
||||
std::clog<<" total : "<<total<<'\n';
|
||||
}
|
||||
|
||||
void dbg::step_info() {
|
||||
u32 line=bytecode[ctx.pc].line==0?0:bytecode[ctx.pc].line-1;
|
||||
u32 begin=(line>>3)==0?0:((line>>3)<<3);
|
||||
u32 end=(1+(line>>3))<<3;
|
||||
src.load(files[bytecode[ctx.pc].fidx]);
|
||||
std::clog<<"\nsource code:\n";
|
||||
for(u32 i=begin;i<end && i<src.size();++i) {
|
||||
std::clog<<(i==line?back_white:reset)<<(i==line?"--> ":" ")<<src[i]<<reset<<"\n";
|
||||
}
|
||||
|
||||
begin=(ctx.pc>>3)==0?0:((ctx.pc>>3)<<3);
|
||||
end=(1+(ctx.pc>>3))<<3;
|
||||
codestream::set(cnum, cstr, files);
|
||||
std::clog<<"next bytecode:\n";
|
||||
for(u32 i=begin;i<end && bytecode[i].op!=op_exit;++i) {
|
||||
std::clog
|
||||
<<(i==ctx.pc?back_white:reset)
|
||||
<<(i==ctx.pc?"--> ":" ")
|
||||
<<codestream(bytecode[i], i)
|
||||
<<reset<<"\n";
|
||||
}
|
||||
stackinfo(10);
|
||||
}
|
||||
|
||||
void dbg::interact() {
|
||||
// special operand, end execution
|
||||
if (bytecode[ctx.pc].op==op_exit) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((bytecode[ctx.pc].fidx!=bk_fidx ||
|
||||
bytecode[ctx.pc].line!=bk_line) && // break point
|
||||
!next) {// next step
|
||||
return;
|
||||
}
|
||||
|
||||
next=false;
|
||||
std::string cmd;
|
||||
step_info();
|
||||
while(true) {
|
||||
std::clog<<">> ";
|
||||
std::getline(std::cin, cmd);
|
||||
auto res=parse(cmd);
|
||||
if (res.size()==0) {
|
||||
step_info();
|
||||
} else if (res.size()==1) {
|
||||
switch(get_cmd_type(res[0])) {
|
||||
case dbg_cmd::cmd_help: help(); break;
|
||||
case dbg_cmd::cmd_backtrace: traceback(); break;
|
||||
case dbg_cmd::cmd_continue: return;
|
||||
case dbg_cmd::cmd_list_file: list_file(); break;
|
||||
case dbg_cmd::cmd_global: gstate(); break;
|
||||
case dbg_cmd::cmd_local: lstate(); break;
|
||||
case dbg_cmd::cmd_upval: ustate(); break;
|
||||
case dbg_cmd::cmd_register: reginfo(); break;
|
||||
case dbg_cmd::cmd_show_all: detail(); break;
|
||||
case dbg_cmd::cmd_next: next=true; return;
|
||||
case dbg_cmd::cmd_exit: std::exit(0);
|
||||
default: err(); break;
|
||||
}
|
||||
} else if (res.size()==3 &&
|
||||
get_cmd_type(res[0])==dbg_cmd::cmd_break_point) {
|
||||
bk_fidx=file_index(res[1]);
|
||||
if (bk_fidx==65535) {
|
||||
std::clog<<"cannot find file named `"<<res[1]<<"`\n";
|
||||
continue;
|
||||
}
|
||||
i32 tmp=atoi(res[2].c_str());
|
||||
if (tmp<=0) {
|
||||
std::clog<<"incorrect line number `"<<res[2]<<"`\n";
|
||||
} else {
|
||||
bk_line=tmp;
|
||||
}
|
||||
} else {
|
||||
err();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dbg::run(
|
||||
const codegen& gen,
|
||||
const linker& linker,
|
||||
const std::vector<std::string>& argv) {
|
||||
verbose=true;
|
||||
fsize=linker.filelist().size();
|
||||
init(gen.strs(), gen.nums(), gen.codes(), linker.filelist(), argv);
|
||||
u64 count[op_ret+1]={0};
|
||||
typedef void (dbg::*nafunc)();
|
||||
const nafunc oprs[]={
|
||||
nullptr, &dbg::o_intg,
|
||||
&dbg::o_intl, &dbg::o_loadg,
|
||||
&dbg::o_loadl, &dbg::o_loadu,
|
||||
&dbg::o_pnum, &dbg::o_pnil,
|
||||
&dbg::o_pstr, &dbg::o_newv,
|
||||
&dbg::o_newh, &dbg::o_newf,
|
||||
&dbg::o_happ, &dbg::o_para,
|
||||
&dbg::o_deft, &dbg::o_dyn,
|
||||
&dbg::o_lnot, &dbg::o_usub,
|
||||
&dbg::o_bnot, &dbg::o_btor,
|
||||
&dbg::o_btxor, &dbg::o_btand,
|
||||
&dbg::o_add, &dbg::o_sub,
|
||||
&dbg::o_mul, &dbg::o_div,
|
||||
&dbg::o_lnk, &dbg::o_addc,
|
||||
&dbg::o_subc, &dbg::o_mulc,
|
||||
&dbg::o_divc, &dbg::o_lnkc,
|
||||
&dbg::o_addeq, &dbg::o_subeq,
|
||||
&dbg::o_muleq, &dbg::o_diveq,
|
||||
&dbg::o_lnkeq, &dbg::o_bandeq,
|
||||
&dbg::o_boreq, &dbg::o_bxoreq,
|
||||
&dbg::o_addeqc, &dbg::o_subeqc,
|
||||
&dbg::o_muleqc, &dbg::o_diveqc,
|
||||
&dbg::o_lnkeqc, &dbg::o_addecp,
|
||||
&dbg::o_subecp, &dbg::o_mulecp,
|
||||
&dbg::o_divecp, &dbg::o_lnkecp,
|
||||
&dbg::o_meq, &dbg::o_eq,
|
||||
&dbg::o_neq, &dbg::o_less,
|
||||
&dbg::o_leq, &dbg::o_grt,
|
||||
&dbg::o_geq, &dbg::o_lessc,
|
||||
&dbg::o_leqc, &dbg::o_grtc,
|
||||
&dbg::o_geqc, &dbg::o_pop,
|
||||
&dbg::o_jmp, &dbg::o_jt,
|
||||
&dbg::o_jf, &dbg::o_cnt,
|
||||
&dbg::o_findex, &dbg::o_feach,
|
||||
&dbg::o_callg, &dbg::o_calll,
|
||||
&dbg::o_upval, &dbg::o_callv,
|
||||
&dbg::o_callvi, &dbg::o_callh,
|
||||
&dbg::o_callfv, &dbg::o_callfh,
|
||||
&dbg::o_callb, &dbg::o_slcbeg,
|
||||
&dbg::o_slcend, &dbg::o_slc,
|
||||
&dbg::o_slc2, &dbg::o_mcallg,
|
||||
&dbg::o_mcalll, &dbg::o_mupval,
|
||||
&dbg::o_mcallv, &dbg::o_mcallh,
|
||||
&dbg::o_ret
|
||||
};
|
||||
std::vector<u32> code;
|
||||
for(auto& i:gen.codes()) {
|
||||
code.push_back(i.op);
|
||||
imm.push_back(i.num);
|
||||
}
|
||||
while(oprs[code[ctx.pc]]) {
|
||||
interact();
|
||||
++count[code[ctx.pc]];
|
||||
(this->*oprs[code[ctx.pc]])();
|
||||
if (ctx.top>=ctx.canary) {
|
||||
die("stack overflow");
|
||||
}
|
||||
++ctx.pc;
|
||||
}
|
||||
|
||||
call_sort(count);
|
||||
ngc.info();
|
||||
ngc.clear();
|
||||
imm.clear();
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
#pragma once
|
||||
|
||||
#include "nasal_new_import.h"
|
||||
#include "nasal_new_err.h"
|
||||
#include "nasal_new_opcode.h"
|
||||
#include "nasal_new_vm.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
|
||||
class dbg:public vm {
|
||||
private:
|
||||
enum class dbg_cmd {
|
||||
cmd_error,
|
||||
cmd_help,
|
||||
cmd_backtrace,
|
||||
cmd_continue,
|
||||
cmd_list_file,
|
||||
cmd_global,
|
||||
cmd_local,
|
||||
cmd_upval,
|
||||
cmd_register,
|
||||
cmd_show_all,
|
||||
cmd_next,
|
||||
cmd_break_point,
|
||||
cmd_exit
|
||||
};
|
||||
|
||||
private:
|
||||
const std::unordered_map<std::string, dbg_cmd> command_table = {
|
||||
{"h", dbg_cmd::cmd_help},
|
||||
{"help", dbg_cmd::cmd_help},
|
||||
{"bt", dbg_cmd::cmd_backtrace},
|
||||
{"backtrace", dbg_cmd::cmd_backtrace},
|
||||
{"c", dbg_cmd::cmd_continue},
|
||||
{"continue", dbg_cmd::cmd_continue},
|
||||
{"f", dbg_cmd::cmd_list_file},
|
||||
{"file", dbg_cmd::cmd_list_file},
|
||||
{"g", dbg_cmd::cmd_global},
|
||||
{"global", dbg_cmd::cmd_global},
|
||||
{"l", dbg_cmd::cmd_local},
|
||||
{"local", dbg_cmd::cmd_local},
|
||||
{"u", dbg_cmd::cmd_upval},
|
||||
{"upval", dbg_cmd::cmd_upval},
|
||||
{"r", dbg_cmd::cmd_register},
|
||||
{"register", dbg_cmd::cmd_register},
|
||||
{"a", dbg_cmd::cmd_show_all},
|
||||
{"all", dbg_cmd::cmd_show_all},
|
||||
{"n", dbg_cmd::cmd_next},
|
||||
{"next", dbg_cmd::cmd_next},
|
||||
{"bk", dbg_cmd::cmd_break_point},
|
||||
{"break", dbg_cmd::cmd_break_point},
|
||||
{"q", dbg_cmd::cmd_exit},
|
||||
{"exit", dbg_cmd::cmd_exit}
|
||||
};
|
||||
dbg_cmd get_cmd_type(const std::string& cmd) const {
|
||||
return command_table.count(cmd)?
|
||||
command_table.at(cmd):dbg_cmd::cmd_error;
|
||||
}
|
||||
|
||||
private:
|
||||
bool next;
|
||||
usize fsize;
|
||||
u16 bk_fidx;
|
||||
u32 bk_line;
|
||||
error& src;
|
||||
|
||||
std::vector<std::string> parse(const std::string&);
|
||||
u16 file_index(const std::string&) const;
|
||||
void err();
|
||||
void help();
|
||||
void list_file() const;
|
||||
void call_sort(const u64*) const;
|
||||
void step_info();
|
||||
void interact();
|
||||
public:
|
||||
dbg(error& err):
|
||||
next(false), fsize(0),
|
||||
bk_fidx(0), bk_line(0),
|
||||
src(err) {}
|
||||
void run(
|
||||
const codegen&,
|
||||
const linker&,
|
||||
const std::vector<std::string>&
|
||||
);
|
||||
};
|
|
@ -8,6 +8,9 @@
|
|||
#include "ast_dumper.h"
|
||||
#include "symbol_finder.h"
|
||||
#include "optimizer.h"
|
||||
#include "nasal_new_codegen.h"
|
||||
#include "nasal_new_vm.h"
|
||||
#include "nasal_new_dbg.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <thread>
|
||||
|
@ -73,8 +76,8 @@ void err() {
|
|||
void execute(
|
||||
const std::string& file,
|
||||
const std::vector<std::string>& argv,
|
||||
const u32 cmd
|
||||
) {
|
||||
const u32 cmd) {
|
||||
|
||||
using clk=std::chrono::high_resolution_clock;
|
||||
const auto den=clk::duration::period::den;
|
||||
|
||||
|
@ -82,8 +85,8 @@ void execute(
|
|||
lexer lex(err);
|
||||
parse parse(err);
|
||||
linker ld(err);
|
||||
// codegen gen(err);
|
||||
// vm ctx;
|
||||
codegen gen(err);
|
||||
vm ctx;
|
||||
|
||||
// lexer scans file to get tokens
|
||||
lex.scan(file).chkerr();
|
||||
|
@ -103,24 +106,19 @@ void execute(
|
|||
opt->do_optimization(parse.tree());
|
||||
delete opt;
|
||||
|
||||
auto finder = new symbol_finder;
|
||||
for(const auto& symbol : finder->do_find(parse.tree())) {
|
||||
std::cout << symbol << std::endl;
|
||||
}
|
||||
|
||||
// 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.compile(parse, ld).chkerr();
|
||||
if (cmd&VM_CODE) {
|
||||
gen.print();
|
||||
}
|
||||
|
||||
// run
|
||||
auto start=clk::now();
|
||||
// if (cmd&VM_DEBUG) {
|
||||
// dbg(err).run(gen, ld, argv);
|
||||
// } else if (cmd&VM_TIME || cmd&VM_EXEC) {
|
||||
// ctx.run(gen, ld, argv, cmd&VM_DETAIL);
|
||||
// }
|
||||
if (cmd&VM_DEBUG) {
|
||||
dbg(err).run(gen, ld, argv);
|
||||
} else if (cmd&VM_TIME || cmd&VM_EXEC) {
|
||||
ctx.run(gen, ld, argv, cmd&VM_DETAIL);
|
||||
}
|
||||
|
||||
// get running time
|
||||
if (cmd&VM_TIME) {
|
||||
|
|
|
@ -1,5 +1,30 @@
|
|||
#include "nasal_new_opcode.h"
|
||||
|
||||
const char* opname[]={
|
||||
"exit ","intg ","intl ","loadg ",
|
||||
"loadl ","loadu ","pnum ","pnil ",
|
||||
"pstr ","newv ","newh ","newf ",
|
||||
"happ ","para ","def ","dyn ",
|
||||
"lnot ","usub ","bnot ","btor ",
|
||||
"btxor ","btand ","add ","sub ",
|
||||
"mult ","div ","lnk ","addc ",
|
||||
"subc ","multc ","divc ","lnkc ",
|
||||
"addeq ","subeq ","muleq ","diveq ",
|
||||
"lnkeq ","bandeq","boreq ","bxoreq",
|
||||
"addeqc","subeqc","muleqc","diveqc",
|
||||
"lnkeqc","addecp","subecp","mulecp",
|
||||
"divecp","lnkecp","meq ","eq ",
|
||||
"neq ","less ","leq ","grt ",
|
||||
"geq ","lessc ","leqc ","grtc ",
|
||||
"geqc ","pop ","jmp ","jt ",
|
||||
"jf ","cnt ","findx ","feach ",
|
||||
"callg ","calll ","upval ","callv ",
|
||||
"callvi","callh ","callfv","callfh",
|
||||
"callb ","slcbeg","slcend","slc ",
|
||||
"slc2 ","mcallg","mcalll","mupval",
|
||||
"mcallv","mcallh","ret "
|
||||
};
|
||||
|
||||
void codestream::set(
|
||||
const f64* numbuff,
|
||||
const std::string* strbuff,
|
||||
|
|
|
@ -95,31 +95,6 @@ enum op_code_type:u8 {
|
|||
op_ret // return
|
||||
};
|
||||
|
||||
const char* opname[]={
|
||||
"exit ","intg ","intl ","loadg ",
|
||||
"loadl ","loadu ","pnum ","pnil ",
|
||||
"pstr ","newv ","newh ","newf ",
|
||||
"happ ","para ","def ","dyn ",
|
||||
"lnot ","usub ","bnot ","btor ",
|
||||
"btxor ","btand ","add ","sub ",
|
||||
"mult ","div ","lnk ","addc ",
|
||||
"subc ","multc ","divc ","lnkc ",
|
||||
"addeq ","subeq ","muleq ","diveq ",
|
||||
"lnkeq ","bandeq","boreq ","bxoreq",
|
||||
"addeqc","subeqc","muleqc","diveqc",
|
||||
"lnkeqc","addecp","subecp","mulecp",
|
||||
"divecp","lnkecp","meq ","eq ",
|
||||
"neq ","less ","leq ","grt ",
|
||||
"geq ","lessc ","leqc ","grtc ",
|
||||
"geqc ","pop ","jmp ","jt ",
|
||||
"jf ","cnt ","findx ","feach ",
|
||||
"callg ","calll ","upval ","callv ",
|
||||
"callvi","callh ","callfv","callfh",
|
||||
"callb ","slcbeg","slcend","slc ",
|
||||
"slc2 ","mcallg","mcalll","mupval",
|
||||
"mcallv","mcallh","ret "
|
||||
};
|
||||
|
||||
struct opcode {
|
||||
u8 op; // opcode
|
||||
u16 fidx; // source code file index
|
||||
|
@ -143,4 +118,6 @@ public:
|
|||
void dump(std::ostream&) const;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream&, const codestream&);
|
||||
std::ostream& operator<<(std::ostream&, const codestream&);
|
||||
|
||||
extern const char* opname[];
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,159 @@
|
|||
#pragma once
|
||||
|
||||
#include <iomanip>
|
||||
#include <stack>
|
||||
|
||||
#include "nasal_new_import.h"
|
||||
#include "nasal_new_gc.h"
|
||||
#include "nasal_new_codegen.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable:4244)
|
||||
#pragma warning (disable:4267)
|
||||
#pragma warning (disable:4102)
|
||||
#endif
|
||||
|
||||
class vm {
|
||||
protected:
|
||||
|
||||
/* registers and constants of vm */
|
||||
context ctx;
|
||||
|
||||
/* constants */
|
||||
const f64* cnum=nullptr; // constant numbers
|
||||
const std::string* cstr=nullptr; // constant symbols and strings
|
||||
std::vector<u32> imm; // immediate number table
|
||||
|
||||
/* garbage collector */
|
||||
gc ngc;
|
||||
|
||||
/* main stack */
|
||||
var stack[STACK_DEPTH];
|
||||
|
||||
/* values used for debugger */
|
||||
const std::string* files=nullptr; // file name list
|
||||
const opcode* bytecode=nullptr; // bytecode buffer address
|
||||
|
||||
/* vm initializing function */
|
||||
void init(
|
||||
const std::vector<std::string>&,
|
||||
const std::vector<f64>&,
|
||||
const std::vector<opcode>&,
|
||||
const std::vector<std::string>&,
|
||||
const std::vector<std::string>&);
|
||||
|
||||
/* debug functions */
|
||||
bool verbose;
|
||||
void valinfo(var&);
|
||||
void traceback();
|
||||
void stackinfo(const u32);
|
||||
void reginfo();
|
||||
void gstate();
|
||||
void lstate();
|
||||
void ustate();
|
||||
void detail();
|
||||
void die(const std::string&);
|
||||
|
||||
/* vm calculation functions*/
|
||||
bool cond(var&);
|
||||
|
||||
/* vm operands */
|
||||
void o_intg();
|
||||
void o_intl();
|
||||
void o_loadg();
|
||||
void o_loadl();
|
||||
void o_loadu();
|
||||
void o_pnum();
|
||||
void o_pnil();
|
||||
void o_pstr();
|
||||
void o_newv();
|
||||
void o_newh();
|
||||
void o_newf();
|
||||
void o_happ();
|
||||
void o_para();
|
||||
void o_deft();
|
||||
void o_dyn();
|
||||
void o_lnot();
|
||||
void o_usub();
|
||||
void o_bnot();
|
||||
void o_btor();
|
||||
void o_btxor();
|
||||
void o_btand();
|
||||
void o_add();
|
||||
void o_sub();
|
||||
void o_mul();
|
||||
void o_div();
|
||||
void o_lnk();
|
||||
void o_addc();
|
||||
void o_subc();
|
||||
void o_mulc();
|
||||
void o_divc();
|
||||
void o_lnkc();
|
||||
void o_addeq();
|
||||
void o_subeq();
|
||||
void o_muleq();
|
||||
void o_diveq();
|
||||
void o_lnkeq();
|
||||
void o_bandeq();
|
||||
void o_boreq();
|
||||
void o_bxoreq();
|
||||
void o_addeqc();
|
||||
void o_subeqc();
|
||||
void o_muleqc();
|
||||
void o_diveqc();
|
||||
void o_lnkeqc();
|
||||
void o_addecp();
|
||||
void o_subecp();
|
||||
void o_mulecp();
|
||||
void o_divecp();
|
||||
void o_lnkecp();
|
||||
void o_meq();
|
||||
void o_eq();
|
||||
void o_neq();
|
||||
void o_less();
|
||||
void o_leq();
|
||||
void o_grt();
|
||||
void o_geq();
|
||||
void o_lessc();
|
||||
void o_leqc();
|
||||
void o_grtc();
|
||||
void o_geqc();
|
||||
void o_pop();
|
||||
void o_jmp();
|
||||
void o_jt();
|
||||
void o_jf();
|
||||
void o_cnt();
|
||||
void o_findex();
|
||||
void o_feach();
|
||||
void o_callg();
|
||||
void o_calll();
|
||||
void o_upval();
|
||||
void o_callv();
|
||||
void o_callvi();
|
||||
void o_callh();
|
||||
void o_callfv();
|
||||
void o_callfh();
|
||||
void o_callb();
|
||||
void o_slcbeg();
|
||||
void o_slcend();
|
||||
void o_slc();
|
||||
void o_slc2();
|
||||
void o_mcallg();
|
||||
void o_mcalll();
|
||||
void o_mupval();
|
||||
void o_mcallv();
|
||||
void o_mcallh();
|
||||
void o_ret();
|
||||
public:
|
||||
|
||||
/* constructor of vm instance */
|
||||
vm(): ngc(&ctx), verbose(false) {}
|
||||
|
||||
/* execution entry */
|
||||
void run(
|
||||
const codegen&,
|
||||
const linker&,
|
||||
const std::vector<std::string>&,
|
||||
const bool
|
||||
);
|
||||
};
|
10
makefile
10
makefile
|
@ -84,6 +84,8 @@ NASAL_NEW_AST=\
|
|||
nasal_new_codegen.o\
|
||||
nasal_new_opcode.o\
|
||||
nasal_new_parse.o\
|
||||
nasal_new_vm.o\
|
||||
nasal_new_dbg.o\
|
||||
optimizer.o\
|
||||
symbol_finder.o\
|
||||
ast_visitor.o\
|
||||
|
@ -120,7 +122,7 @@ nasal_new_builtin.o: ast/nasal_new_builtin.h ast/nasal_new_builtin.cpp
|
|||
$(CXX) -std=$(STD) -c -O3 ast/nasal_new_builtin.cpp -fno-exceptions -fPIC -o nasal_new_builtin.o -I .
|
||||
|
||||
nasal_new_codegen.o: ast/nasal_new_codegen.h ast/nasal_new_codegen.cpp
|
||||
# $(CXX) -std=$(STD) -c -O3 ast/nasal_new_codegen.cpp -fno-exceptions -fPIC -o nasal_new_codegen.o -I .
|
||||
$(CXX) -std=$(STD) -c -O3 ast/nasal_new_codegen.cpp -fno-exceptions -fPIC -o nasal_new_codegen.o -I .
|
||||
|
||||
nasal_new_opcode.o: ast/nasal_new_opcode.h ast/nasal_new_opcode.cpp
|
||||
$(CXX) -std=$(STD) -c -O3 ast/nasal_new_opcode.cpp -fno-exceptions -fPIC -o nasal_new_opcode.o -I .
|
||||
|
@ -140,6 +142,12 @@ ast_visitor.o: ast/nasal_new_ast.h ast/ast_visitor.h ast/ast_visitor.cpp
|
|||
ast_dumper.o: ast/nasal_new_ast.h ast/ast_visitor.h ast/ast_dumper.h ast/ast_dumper.cpp
|
||||
$(CXX) -std=$(STD) -c -O3 ast/ast_dumper.cpp -fno-exceptions -fPIC -o ast_dumper.o -I .
|
||||
|
||||
nasal_new_vm.o: ast/nasal_new_vm.h ast/nasal_new_vm.cpp
|
||||
$(CXX) -std=$(STD) -c -O3 ast/nasal_new_vm.cpp -fno-exceptions -fPIC -o nasal_new_vm.o -I .
|
||||
|
||||
nasal_new_dbg.o: ast/nasal_new_dbg.h ast/nasal_new_dbg.cpp
|
||||
$(CXX) -std=$(STD) -c -O3 ast/nasal_new_dbg.cpp -fno-exceptions -fPIC -o nasal_new_dbg.o -I .
|
||||
|
||||
.PHONY: nasal_new_clean
|
||||
nasal_new_clean:
|
||||
rm $(NASAL_NEW_AST)
|
Loading…
Reference in New Issue