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;
case expr_type::ast_callf:
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;
}
}
@ -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());
}
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) {
// maybe this place can use callv-const if ast's first child is ast_num
if (node->get_slices().size()==1 &&
@ -455,6 +475,8 @@ void codegen::mcall(expr* node) {
call_vector_gen(reinterpret_cast<call_vector*>(tmp)); break;
case expr_type::ast_callf:
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;
}
}
@ -467,6 +489,8 @@ void codegen::mcall(expr* node) {
mcall_vec(reinterpret_cast<call_vector*>(tmp)); break;
case expr_type::ast_callf:
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:
die("bad left-value: unknown call", tmp->get_location()); break;
}

View File

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

View File

@ -43,49 +43,93 @@ class dbg: public vm {
private:
typedef void (dbg::*nasal_vm_func)();
const nasal_vm_func operand_function[op_ret + 1] = {
nullptr, &dbg::o_repl,
&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,
nullptr,
&dbg::o_repl,
&dbg::o_intl,
&dbg::o_loadg,
&dbg::o_loadl,
&dbg::o_loadu,
&dbg::o_dup,
&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
};

View File

@ -4,28 +4,94 @@
namespace nasal {
const char* oprand_name_table[] = {
"exit ", "repl ", "intl ", "loadg ",
"loadl ", "loadu ", "pnum ", "pnil ",
"pstr ", "newv ", "newh ", "newf ",
"happ ", "para ", "def ", "dyn ",
"lnot ", "usub ", "bitnot", "bitor ",
"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 "
"exit ",
"repl ",
"intl ",
"loadg ",
"loadl ",
"loadu ",
"dup ",
"pnum ",
"pnil ",
"pstr ",
"newv ",
"newh ",
"newf ",
"happ ",
"para ",
"def ",
"dyn ",
"lnot ",
"usub ",
"bitnot",
"bitor ",
"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,

View File

@ -14,6 +14,7 @@ enum op_code_type: u8 {
op_loadg, // load global value
op_loadl, // load local value
op_loadu, // load upvalue
op_dup, // copy value on stack top
op_pnum, // push constant number to the stack
op_pnil, // push constant nil 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
// using labels as values/computed goto
const void* oprs[] = {
&&vmexit, &&repl, &&intl, &&loadg,
&&loadl, &&loadu, &&pnum, &&pnil,
&&pstr, &&newv, &&newh, &&newf,
&&happ, &&para, &&deft, &&dyn,
&&lnot, &&usub, &&bnot, &&btor,
&&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
&&vmexit,
&&repl,
&&intl,
&&loadg,
&&loadl,
&&loadu,
&&dup,
&&pnum,
&&pnil,
&&pstr,
&&newv,
&&newh,
&&newf,
&&happ,
&&para,
&&deft,
&&dyn,
&&lnot,
&&usub,
&&bnot,
&&btor,
&&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;
for(const auto& i : gen.codes()) {
@ -462,49 +528,93 @@ void vm::run(const codegen& gen,
#else
typedef void (vm::*nafunc)();
const nafunc oprs[] = {
nullptr, &vm::o_repl,
&vm::o_intl, &vm::o_loadg,
&vm::o_loadl, &vm::o_loadu,
&vm::o_pnum, &vm::o_pnil,
&vm::o_pstr, &vm::o_newv,
&vm::o_newh, &vm::o_newf,
&vm::o_happ, &vm::o_para,
&vm::o_deft, &vm::o_dyn,
&vm::o_lnot, &vm::o_usub,
&vm::o_bnot, &vm::o_btor,
&vm::o_btxor, &vm::o_btand,
&vm::o_add, &vm::o_sub,
&vm::o_mul, &vm::o_div,
&vm::o_lnk, &vm::o_addc,
&vm::o_subc, &vm::o_mulc,
&vm::o_divc, &vm::o_lnkc,
&vm::o_addeq, &vm::o_subeq,
&vm::o_muleq, &vm::o_diveq,
&vm::o_lnkeq, &vm::o_bandeq,
&vm::o_boreq, &vm::o_bxoreq,
&vm::o_addeqc, &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,
nullptr,
&vm::o_repl,
&vm::o_intl,
&vm::o_loadg,
&vm::o_loadl,
&vm::o_loadu,
&vm::o_dup,
&vm::o_pnum,
&vm::o_pnil,
&vm::o_pstr,
&vm::o_newv,
&vm::o_newh,
&vm::o_newf,
&vm::o_happ,
&vm::o_para,
&vm::o_deft,
&vm::o_dyn,
&vm::o_lnot,
&vm::o_usub,
&vm::o_bnot,
&vm::o_btor,
&vm::o_btxor,
&vm::o_btand,
&vm::o_add,
&vm::o_sub,
&vm::o_mul,
&vm::o_div,
&vm::o_lnk,
&vm::o_addc,
&vm::o_subc,
&vm::o_mulc,
&vm::o_divc,
&vm::o_lnkc,
&vm::o_addeq,
&vm::o_subeq,
&vm::o_muleq,
&vm::o_diveq,
&vm::o_lnkeq,
&vm::o_bandeq,
&vm::o_boreq,
&vm::o_bxoreq,
&vm::o_addeqc,
&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
};
std::vector<nafunc> code;
@ -551,6 +661,7 @@ intl: exec_nodie(o_intl ); // -0
loadg: exec_nodie(o_loadg ); // -1
loadl: exec_nodie(o_loadl ); // -1
loadu: exec_nodie(o_loadu ); // -1
dup: exec_check(o_dup ); // +1
pnum: exec_check(o_pnum ); // +1
pnil: exec_check(o_pnil ); // +1
pstr: exec_check(o_pstr ); // +1

View File

@ -93,6 +93,7 @@ protected:
inline void o_loadg();
inline void o_loadl();
inline void o_loadu();
inline void o_dup();
inline void o_pnum();
inline void o_pnil();
inline void o_pstr();
@ -248,6 +249,11 @@ inline void vm::o_loadu() {
.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() {
(++ctx.top)[0] = var::num(const_number[imm[ctx.pc]]);
}

View File

@ -273,4 +273,10 @@ func() {
var b = nil;
var c = nil;
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
}();