add codegen for `?.`

This commit is contained in:
ValKmjolnir 2024-06-05 01:13:39 +08:00
parent 4adf9541b9
commit 1436693cd6
8 changed files with 389 additions and 130 deletions

View File

@ -339,6 +339,8 @@ void codegen::call_gen(call_expr* node) {
call_vector_gen(reinterpret_cast<call_vector*>(i)); break; call_vector_gen(reinterpret_cast<call_vector*>(i)); break;
case expr_type::ast_callf: case expr_type::ast_callf:
call_func_gen(reinterpret_cast<call_function*>(i)); break; call_func_gen(reinterpret_cast<call_function*>(i)); break;
case expr_type::ast_nullaccess:
null_access_gen(reinterpret_cast<null_access*>(i)); break;
default: break; default: break;
} }
} }
@ -382,6 +384,24 @@ void codegen::call_hash_gen(call_hash* node) {
emit(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::null_access_gen(null_access* node) {
regist_string(node->get_field());
emit(op_dup, 0, node->get_location());
emit(op_pnil, 0, node->get_location());
emit(op_eq, 0, node->get_location());
const auto jmp_false_point = code.size();
emit(op_jf, 0, node->get_location());
const auto jmp_direct_point = code.size();
emit(op_jmp, 0, node->get_location());
code[jmp_false_point].num = code.size();
emit(op_callh, const_string_map.at(node->get_field()), node->get_location());
code[jmp_direct_point].num = code.size();
}
void codegen::call_vector_gen(call_vector* node) { void codegen::call_vector_gen(call_vector* node) {
// maybe this place can use callv-const if ast's first child is ast_num // maybe this place can use callv-const if ast's first child is ast_num
if (node->get_slices().size()==1 && if (node->get_slices().size()==1 &&
@ -455,6 +475,8 @@ void codegen::mcall(expr* node) {
call_vector_gen(reinterpret_cast<call_vector*>(tmp)); break; call_vector_gen(reinterpret_cast<call_vector*>(tmp)); break;
case expr_type::ast_callf: case expr_type::ast_callf:
call_func_gen(reinterpret_cast<call_function*>(tmp)); break; call_func_gen(reinterpret_cast<call_function*>(tmp)); break;
case expr_type::ast_nullaccess:
null_access_gen(reinterpret_cast<null_access*>(tmp)); break;
default: break; default: break;
} }
} }
@ -467,6 +489,8 @@ void codegen::mcall(expr* node) {
mcall_vec(reinterpret_cast<call_vector*>(tmp)); break; mcall_vec(reinterpret_cast<call_vector*>(tmp)); break;
case expr_type::ast_callf: case expr_type::ast_callf:
die("bad left-value: function call", tmp->get_location()); break; die("bad left-value: function call", tmp->get_location()); break;
case expr_type::ast_nullaccess:
die("bad left-value: null access test", tmp->get_location()); break;
default: default:
die("bad left-value: unknown call", tmp->get_location()); break; die("bad left-value: unknown call", tmp->get_location()); break;
} }

View File

@ -123,6 +123,7 @@ private:
void call_gen(call_expr*); void call_gen(call_expr*);
void call_identifier(identifier*); void call_identifier(identifier*);
void call_hash_gen(call_hash*); void call_hash_gen(call_hash*);
void null_access_gen(null_access*);
void call_vector_gen(call_vector*); void call_vector_gen(call_vector*);
void call_func_gen(call_function*); void call_func_gen(call_function*);
void mcall(expr*); void mcall(expr*);

View File

@ -43,49 +43,93 @@ class dbg: public vm {
private: private:
typedef void (dbg::*nasal_vm_func)(); typedef void (dbg::*nasal_vm_func)();
const nasal_vm_func operand_function[op_ret + 1] = { const nasal_vm_func operand_function[op_ret + 1] = {
nullptr, &dbg::o_repl, nullptr,
&dbg::o_intl, &dbg::o_loadg, &dbg::o_repl,
&dbg::o_loadl, &dbg::o_loadu, &dbg::o_intl,
&dbg::o_pnum, &dbg::o_pnil, &dbg::o_loadg,
&dbg::o_pstr, &dbg::o_newv, &dbg::o_loadl,
&dbg::o_newh, &dbg::o_newf, &dbg::o_loadu,
&dbg::o_happ, &dbg::o_para, &dbg::o_dup,
&dbg::o_deft, &dbg::o_dyn, &dbg::o_pnum,
&dbg::o_lnot, &dbg::o_usub, &dbg::o_pnil,
&dbg::o_bnot, &dbg::o_btor, &dbg::o_pstr,
&dbg::o_btxor, &dbg::o_btand, &dbg::o_newv,
&dbg::o_add, &dbg::o_sub, &dbg::o_newh,
&dbg::o_mul, &dbg::o_div, &dbg::o_newf,
&dbg::o_lnk, &dbg::o_addc, &dbg::o_happ,
&dbg::o_subc, &dbg::o_mulc, &dbg::o_para,
&dbg::o_divc, &dbg::o_lnkc, &dbg::o_deft,
&dbg::o_addeq, &dbg::o_subeq, &dbg::o_dyn,
&dbg::o_muleq, &dbg::o_diveq, &dbg::o_lnot,
&dbg::o_lnkeq, &dbg::o_bandeq, &dbg::o_usub,
&dbg::o_boreq, &dbg::o_bxoreq, &dbg::o_bnot,
&dbg::o_addeqc, &dbg::o_subeqc, &dbg::o_btor,
&dbg::o_muleqc, &dbg::o_diveqc, &dbg::o_btxor,
&dbg::o_lnkeqc, &dbg::o_addecp, &dbg::o_btand,
&dbg::o_subecp, &dbg::o_mulecp, &dbg::o_add,
&dbg::o_divecp, &dbg::o_lnkecp, &dbg::o_sub,
&dbg::o_meq, &dbg::o_eq, &dbg::o_mul,
&dbg::o_neq, &dbg::o_less, &dbg::o_div,
&dbg::o_leq, &dbg::o_grt, &dbg::o_lnk,
&dbg::o_geq, &dbg::o_lessc, &dbg::o_addc,
&dbg::o_leqc, &dbg::o_grtc, &dbg::o_subc,
&dbg::o_geqc, &dbg::o_pop, &dbg::o_mulc,
&dbg::o_jmp, &dbg::o_jt, &dbg::o_divc,
&dbg::o_jf, &dbg::o_cnt, &dbg::o_lnkc,
&dbg::o_findex, &dbg::o_feach, &dbg::o_addeq,
&dbg::o_callg, &dbg::o_calll, &dbg::o_subeq,
&dbg::o_upval, &dbg::o_callv, &dbg::o_muleq,
&dbg::o_callvi, &dbg::o_callh, &dbg::o_diveq,
&dbg::o_callfv, &dbg::o_callfh, &dbg::o_lnkeq,
&dbg::o_callb, &dbg::o_slcbeg, &dbg::o_bandeq,
&dbg::o_slcend, &dbg::o_slc, &dbg::o_boreq,
&dbg::o_slc2, &dbg::o_mcallg, &dbg::o_bxoreq,
&dbg::o_mcalll, &dbg::o_mupval, &dbg::o_addeqc,
&dbg::o_mcallv, &dbg::o_mcallh, &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 &dbg::o_ret
}; };

View File

@ -4,28 +4,94 @@
namespace nasal { namespace nasal {
const char* oprand_name_table[] = { const char* oprand_name_table[] = {
"exit ", "repl ", "intl ", "loadg ", "exit ",
"loadl ", "loadu ", "pnum ", "pnil ", "repl ",
"pstr ", "newv ", "newh ", "newf ", "intl ",
"happ ", "para ", "def ", "dyn ", "loadg ",
"lnot ", "usub ", "bitnot", "bitor ", "loadl ",
"bitxor", "bitand", "add ", "sub ", "loadu ",
"mult ", "div ", "lnk ", "addc ", "dup ",
"subc ", "multc ", "divc ", "lnkc ", "pnum ",
"addeq ", "subeq ", "muleq ", "diveq ", "pnil ",
"lnkeq ", "bandeq", "boreq ", "bxoreq", "pstr ",
"addeqc", "subeqc", "muleqc", "diveqc", "newv ",
"lnkeqc", "addecp", "subecp", "mulecp", "newh ",
"divecp", "lnkecp", "meq ", "eq ", "newf ",
"neq ", "less ", "leq ", "grt ", "happ ",
"geq ", "lessc ", "leqc ", "grtc ", "para ",
"geqc ", "pop ", "jmp ", "jt ", "def ",
"jf ", "cnt ", "findx ", "feach ", "dyn ",
"callg ", "calll ", "upval ", "callv ", "lnot ",
"callvi", "callh ", "callfv", "callfh", "usub ",
"callb ", "slcbeg", "slcend", "slice ", "bitnot",
"slice2", "mcallg", "mcalll", "mupval", "bitor ",
"mcallv", "mcallh", "ret " "bitxor",
"bitand",
"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",
"slice ",
"slice2",
"mcallg",
"mcalll",
"mupval",
"mcallv",
"mcallh",
"ret "
}; };
void codestream::set(const f64* number_list, void codestream::set(const f64* number_list,

View File

@ -14,6 +14,7 @@ enum op_code_type: u8 {
op_loadg, // load global value op_loadg, // load global value
op_loadl, // load local value op_loadl, // load local value
op_loadu, // load upvalue op_loadu, // load upvalue
op_dup, // copy value on stack top
op_pnum, // push constant number to the stack op_pnum, // push constant number to the stack
op_pnil, // push constant nil to the stack op_pnil, // push constant nil to the stack
op_pstr, // push constant std::string to the stack op_pstr, // push constant std::string to the stack

View File

@ -429,28 +429,94 @@ void vm::run(const codegen& gen,
#ifndef _MSC_VER #ifndef _MSC_VER
// using labels as values/computed goto // using labels as values/computed goto
const void* oprs[] = { const void* oprs[] = {
&&vmexit, &&repl, &&intl, &&loadg, &&vmexit,
&&loadl, &&loadu, &&pnum, &&pnil, &&repl,
&&pstr, &&newv, &&newh, &&newf, &&intl,
&&happ, &&para, &&deft, &&dyn, &&loadg,
&&lnot, &&usub, &&bnot, &&btor, &&loadl,
&&btxor, &&btand, &&add, &&sub, &&loadu,
&&mul, &&div, &&lnk, &&addc, &&dup,
&&subc, &&mulc, &&divc, &&lnkc, &&pnum,
&&addeq, &&subeq, &&muleq, &&diveq, &&pnil,
&&lnkeq, &&bandeq, &&boreq, &&bxoreq, &&pstr,
&&addeqc, &&subeqc, &&muleqc, &&diveqc, &&newv,
&&lnkeqc, &&addecp, &&subecp, &&mulecp, &&newh,
&&divecp, &&lnkecp, &&meq, &&eq, &&newf,
&&neq, &&less, &&leq, &&grt, &&happ,
&&geq, &&lessc, &&leqc, &&grtc, &&para,
&&geqc, &&pop, &&jmp, &&jt, &&deft,
&&jf, &&cnt, &&findex, &&feach, &&dyn,
&&callg, &&calll, &&upval, &&callv, &&lnot,
&&callvi, &&callh, &&callfv, &&callfh, &&usub,
&&callb, &&slcbeg, &&slcend, &&slc, &&bnot,
&&slc2, &&mcallg, &&mcalll, &&mupval, &&btor,
&&mcallv, &&mcallh, &&ret &&btxor,
&&btand,
&&add,
&&sub,
&&mul,
&&div,
&&lnk,
&&addc,
&&subc,
&&mulc,
&&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,
&&findex,
&&feach,
&&callg,
&&calll,
&&upval,
&&callv,
&&callvi,
&&callh,
&&callfv,
&&callfh,
&&callb,
&&slcbeg,
&&slcend,
&&slc,
&&slc2,
&&mcallg,
&&mcalll,
&&mupval,
&&mcallv,
&&mcallh,
&&ret
}; };
std::vector<const void*> code; std::vector<const void*> code;
for(const auto& i : gen.codes()) { for(const auto& i : gen.codes()) {
@ -462,49 +528,93 @@ void vm::run(const codegen& gen,
#else #else
typedef void (vm::*nafunc)(); typedef void (vm::*nafunc)();
const nafunc oprs[] = { const nafunc oprs[] = {
nullptr, &vm::o_repl, nullptr,
&vm::o_intl, &vm::o_loadg, &vm::o_repl,
&vm::o_loadl, &vm::o_loadu, &vm::o_intl,
&vm::o_pnum, &vm::o_pnil, &vm::o_loadg,
&vm::o_pstr, &vm::o_newv, &vm::o_loadl,
&vm::o_newh, &vm::o_newf, &vm::o_loadu,
&vm::o_happ, &vm::o_para, &vm::o_dup,
&vm::o_deft, &vm::o_dyn, &vm::o_pnum,
&vm::o_lnot, &vm::o_usub, &vm::o_pnil,
&vm::o_bnot, &vm::o_btor, &vm::o_pstr,
&vm::o_btxor, &vm::o_btand, &vm::o_newv,
&vm::o_add, &vm::o_sub, &vm::o_newh,
&vm::o_mul, &vm::o_div, &vm::o_newf,
&vm::o_lnk, &vm::o_addc, &vm::o_happ,
&vm::o_subc, &vm::o_mulc, &vm::o_para,
&vm::o_divc, &vm::o_lnkc, &vm::o_deft,
&vm::o_addeq, &vm::o_subeq, &vm::o_dyn,
&vm::o_muleq, &vm::o_diveq, &vm::o_lnot,
&vm::o_lnkeq, &vm::o_bandeq, &vm::o_usub,
&vm::o_boreq, &vm::o_bxoreq, &vm::o_bnot,
&vm::o_addeqc, &vm::o_subeqc, &vm::o_btor,
&vm::o_muleqc, &vm::o_diveqc, &vm::o_btxor,
&vm::o_lnkeqc, &vm::o_addecp, &vm::o_btand,
&vm::o_subecp, &vm::o_mulecp, &vm::o_add,
&vm::o_divecp, &vm::o_lnkecp, &vm::o_sub,
&vm::o_meq, &vm::o_eq, &vm::o_mul,
&vm::o_neq, &vm::o_less, &vm::o_div,
&vm::o_leq, &vm::o_grt, &vm::o_lnk,
&vm::o_geq, &vm::o_lessc, &vm::o_addc,
&vm::o_leqc, &vm::o_grtc, &vm::o_subc,
&vm::o_geqc, &vm::o_pop, &vm::o_mulc,
&vm::o_jmp, &vm::o_jt, &vm::o_divc,
&vm::o_jf, &vm::o_cnt, &vm::o_lnkc,
&vm::o_findex, &vm::o_feach, &vm::o_addeq,
&vm::o_callg, &vm::o_calll, &vm::o_subeq,
&vm::o_upval, &vm::o_callv, &vm::o_muleq,
&vm::o_callvi, &vm::o_callh, &vm::o_diveq,
&vm::o_callfv, &vm::o_callfh, &vm::o_lnkeq,
&vm::o_callb, &vm::o_slcbeg, &vm::o_bandeq,
&vm::o_slcend, &vm::o_slc, &vm::o_boreq,
&vm::o_slc2, &vm::o_mcallg, &vm::o_bxoreq,
&vm::o_mcalll, &vm::o_mupval, &vm::o_addeqc,
&vm::o_mcallv, &vm::o_mcallh, &vm::o_subeqc,
&vm::o_muleqc,
&vm::o_diveqc,
&vm::o_lnkeqc,
&vm::o_addecp,
&vm::o_subecp,
&vm::o_mulecp,
&vm::o_divecp,
&vm::o_lnkecp,
&vm::o_meq,
&vm::o_eq,
&vm::o_neq,
&vm::o_less,
&vm::o_leq,
&vm::o_grt,
&vm::o_geq,
&vm::o_lessc,
&vm::o_leqc,
&vm::o_grtc,
&vm::o_geqc,
&vm::o_pop,
&vm::o_jmp,
&vm::o_jt,
&vm::o_jf,
&vm::o_cnt,
&vm::o_findex,
&vm::o_feach,
&vm::o_callg,
&vm::o_calll,
&vm::o_upval,
&vm::o_callv,
&vm::o_callvi,
&vm::o_callh,
&vm::o_callfv,
&vm::o_callfh,
&vm::o_callb,
&vm::o_slcbeg,
&vm::o_slcend,
&vm::o_slc,
&vm::o_slc2,
&vm::o_mcallg,
&vm::o_mcalll,
&vm::o_mupval,
&vm::o_mcallv,
&vm::o_mcallh,
&vm::o_ret &vm::o_ret
}; };
std::vector<nafunc> code; std::vector<nafunc> code;
@ -551,6 +661,7 @@ intl: exec_nodie(o_intl ); // -0
loadg: exec_nodie(o_loadg ); // -1 loadg: exec_nodie(o_loadg ); // -1
loadl: exec_nodie(o_loadl ); // -1 loadl: exec_nodie(o_loadl ); // -1
loadu: exec_nodie(o_loadu ); // -1 loadu: exec_nodie(o_loadu ); // -1
dup: exec_check(o_dup ); // +1
pnum: exec_check(o_pnum ); // +1 pnum: exec_check(o_pnum ); // +1
pnil: exec_check(o_pnil ); // +1 pnil: exec_check(o_pnil ); // +1
pstr: exec_check(o_pstr ); // +1 pstr: exec_check(o_pstr ); // +1

View File

@ -93,6 +93,7 @@ protected:
inline void o_loadg(); inline void o_loadg();
inline void o_loadl(); inline void o_loadl();
inline void o_loadu(); inline void o_loadu();
inline void o_dup();
inline void o_pnum(); inline void o_pnum();
inline void o_pnil(); inline void o_pnil();
inline void o_pstr(); inline void o_pstr();
@ -248,6 +249,11 @@ inline void vm::o_loadu() {
.upval()[imm[ctx.pc]&0xffff] = (ctx.top--)[0]; .upval()[imm[ctx.pc]&0xffff] = (ctx.top--)[0];
} }
inline void vm::o_dup() {
ctx.top[1] = ctx.top[0];
++ctx.top;
}
inline void vm::o_pnum() { inline void vm::o_pnum() {
(++ctx.top)[0] = var::num(const_number[imm[ctx.pc]]); (++ctx.top)[0] = var::num(const_number[imm[ctx.pc]]);
} }

View File

@ -273,4 +273,10 @@ func() {
var b = nil; var b = nil;
var c = nil; var c = nil;
println(a??b??c??"a??b??c?? -> should print this text"); println(a??b??c??"a??b??c?? -> should print this text");
var a = {b: 2};
println(a?.b); # should be 2
var a = nil;
println(a?.b); # should be nil
}(); }();