🔥 change codegen::gen to codegen::emit
This commit is contained in:
parent
0a404694f6
commit
f8ecd2ae53
|
@ -307,7 +307,9 @@ var builtin_substr(var* local, gc& ngc) {
|
||||||
var builtin_streq(var* local, gc& ngc) {
|
var builtin_streq(var* local, gc& ngc) {
|
||||||
var a = local[1];
|
var a = local[1];
|
||||||
var b = local[2];
|
var b = local[2];
|
||||||
return var::num(f64((a.type!=vm_str || b.type!=vm_str)? 0:(a.str()==b.str())));
|
return var::num(static_cast<f64>(
|
||||||
|
(a.type!=vm_str || b.type!=vm_str)? 0:(a.str()==b.str())
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_left(var* local, gc& ngc) {
|
var builtin_left(var* local, gc& ngc) {
|
||||||
|
@ -410,9 +412,11 @@ var builtin_sleep(var* local, gc& ngc) {
|
||||||
#if defined(_WIN32) && !defined(_GLIBCXX_HAS_GTHREADS)
|
#if defined(_WIN32) && !defined(_GLIBCXX_HAS_GTHREADS)
|
||||||
// mingw-w64 win32 thread model has no std::this_thread
|
// mingw-w64 win32 thread model has no std::this_thread
|
||||||
// also msvc will use this
|
// also msvc will use this
|
||||||
Sleep(i64(val.num()*1e3));
|
Sleep(static_cast<i64>(val.num()*1e3));
|
||||||
#else
|
#else
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(i64(val.num()*1e6)));
|
std::this_thread::sleep_for(
|
||||||
|
std::chrono::microseconds(static_cast<i64>(val.num()*1e6))
|
||||||
|
);
|
||||||
#endif
|
#endif
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -469,7 +473,7 @@ std::string md5(const std::string& src) {
|
||||||
usize buffsize = num<<4;
|
usize buffsize = num<<4;
|
||||||
buff.resize(buffsize,0);
|
buff.resize(buffsize,0);
|
||||||
for(usize i = 0; i<src.length(); i++) {
|
for(usize i = 0; i<src.length(); i++) {
|
||||||
buff[i>>2] |= ((u8)src[i])<<((i&0x3)<<3);
|
buff[i>>2] |= (static_cast<u8>(src[i]))<<((i&0x3)<<3);
|
||||||
}
|
}
|
||||||
buff[src.length()>>2] |= 0x80<<(((src.length()%4))<<3);
|
buff[src.length()>>2] |= 0x80<<(((src.length()%4))<<3);
|
||||||
buff[buffsize-2] = (src.length()<<3)&0xffffffff;
|
buff[buffsize-2] = (src.length()<<3)&0xffffffff;
|
||||||
|
|
|
@ -133,44 +133,47 @@ i32 codegen::upvalue_find(const std::string& name) {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::gen(u8 operation_code, u32 num, const span& loc) {
|
void codegen::emit(u8 operation_code, u32 immediate_num, const span& location) {
|
||||||
code.push_back({operation_code,
|
code.push_back({
|
||||||
static_cast<u16>(file_map.at(loc.file)),
|
operation_code,
|
||||||
num, loc.begin_line});
|
static_cast<u16>(file_map.at(location.file)),
|
||||||
|
immediate_num,
|
||||||
|
location.begin_line
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::num_gen(number_literal* node) {
|
void codegen::num_gen(number_literal* node) {
|
||||||
f64 num = node->get_number();
|
f64 num = node->get_number();
|
||||||
regist_num(num);
|
regist_num(num);
|
||||||
gen(op_pnum, const_number_map.at(num), node->get_location());
|
emit(op_pnum, const_number_map.at(num), node->get_location());
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::str_gen(string_literal* node) {
|
void codegen::str_gen(string_literal* node) {
|
||||||
const auto& str = node->get_content();
|
const auto& str = node->get_content();
|
||||||
regist_str(str);
|
regist_str(str);
|
||||||
gen(op_pstr, const_string_map.at(str), node->get_location());
|
emit(op_pstr, const_string_map.at(str), node->get_location());
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::bool_gen(bool_literal* node) {
|
void codegen::bool_gen(bool_literal* node) {
|
||||||
f64 num = node->get_flag()? 1:0;
|
f64 num = node->get_flag()? 1:0;
|
||||||
regist_num(num);
|
regist_num(num);
|
||||||
gen(op_pnum, const_number_map.at(num), node->get_location());
|
emit(op_pnum, const_number_map.at(num), node->get_location());
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::vec_gen(vector_expr* node) {
|
void codegen::vec_gen(vector_expr* node) {
|
||||||
for(auto child : node->get_elements()) {
|
for(auto child : node->get_elements()) {
|
||||||
calc_gen(child);
|
calc_gen(child);
|
||||||
}
|
}
|
||||||
gen(op_newv, node->get_elements().size(), node->get_location());
|
emit(op_newv, node->get_elements().size(), node->get_location());
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::hash_gen(hash_expr* node) {
|
void codegen::hash_gen(hash_expr* node) {
|
||||||
gen(op_newh, 0, node->get_location());
|
emit(op_newh, 0, node->get_location());
|
||||||
for(auto child : node->get_members()) {
|
for(auto child : node->get_members()) {
|
||||||
calc_gen(child->get_value());
|
calc_gen(child->get_value());
|
||||||
const auto& field_name = child->get_name();
|
const auto& field_name = child->get_name();
|
||||||
regist_str(field_name);
|
regist_str(field_name);
|
||||||
gen(op_happ, const_string_map.at(field_name), child->get_location());
|
emit(op_happ, const_string_map.at(field_name), child->get_location());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,9 +213,9 @@ void codegen::func_gen(function* node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
usize newf=code.size();
|
usize newf=code.size();
|
||||||
gen(op_newf, 0, node->get_location());
|
emit(op_newf, 0, node->get_location());
|
||||||
usize lsize=code.size();
|
usize lsize=code.size();
|
||||||
gen(op_intl, 0, node->get_location());
|
emit(op_intl, 0, node->get_location());
|
||||||
|
|
||||||
// add special keyword 'me' into symbol table
|
// add special keyword 'me' into symbol table
|
||||||
// this symbol is only used in local scope(function's scope)
|
// this symbol is only used in local scope(function's scope)
|
||||||
|
@ -231,14 +234,14 @@ void codegen::func_gen(function* node) {
|
||||||
regist_str(name);
|
regist_str(name);
|
||||||
switch(tmp->get_parameter_type()) {
|
switch(tmp->get_parameter_type()) {
|
||||||
case parameter::param_type::normal_parameter:
|
case parameter::param_type::normal_parameter:
|
||||||
gen(op_para, const_string_map.at(name), tmp->get_location());
|
emit(op_para, const_string_map.at(name), tmp->get_location());
|
||||||
break;
|
break;
|
||||||
case parameter::param_type::default_parameter:
|
case parameter::param_type::default_parameter:
|
||||||
calc_gen(tmp->get_default_value());
|
calc_gen(tmp->get_default_value());
|
||||||
gen(op_deft, const_string_map.at(name), tmp->get_location());
|
emit(op_deft, const_string_map.at(name), tmp->get_location());
|
||||||
break;
|
break;
|
||||||
case parameter::param_type::dynamic_parameter:
|
case parameter::param_type::dynamic_parameter:
|
||||||
gen(op_dyn, const_string_map.at(name), tmp->get_location());
|
emit(op_dyn, const_string_map.at(name), tmp->get_location());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
add_symbol(name);
|
add_symbol(name);
|
||||||
|
@ -246,7 +249,7 @@ void codegen::func_gen(function* node) {
|
||||||
|
|
||||||
code[newf].num = code.size()+1; // entry
|
code[newf].num = code.size()+1; // entry
|
||||||
usize jmp_ptr = code.size();
|
usize jmp_ptr = code.size();
|
||||||
gen(op_jmp, 0, node->get_location());
|
emit(op_jmp, 0, node->get_location());
|
||||||
|
|
||||||
auto block = node->get_code_block();
|
auto block = node->get_code_block();
|
||||||
// search symbols first, must use after loading parameters
|
// search symbols first, must use after loading parameters
|
||||||
|
@ -279,8 +282,8 @@ void codegen::func_gen(function* node) {
|
||||||
|
|
||||||
if (!block->get_expressions().size() ||
|
if (!block->get_expressions().size() ||
|
||||||
block->get_expressions().back()->get_type()!=expr_type::ast_ret) {
|
block->get_expressions().back()->get_type()!=expr_type::ast_ret) {
|
||||||
gen(op_pnil, 0, block->get_location());
|
emit(op_pnil, 0, block->get_location());
|
||||||
gen(op_ret, 0, block->get_location());
|
emit(op_ret, 0, block->get_location());
|
||||||
}
|
}
|
||||||
code[jmp_ptr].num = code.size();
|
code[jmp_ptr].num = code.size();
|
||||||
}
|
}
|
||||||
|
@ -303,7 +306,7 @@ void codegen::call_gen(call_expr* node) {
|
||||||
void codegen::call_id(identifier* node) {
|
void codegen::call_id(identifier* node) {
|
||||||
const auto& name = node->get_name();
|
const auto& name = node->get_name();
|
||||||
if (native_function_mapper.count(name)) {
|
if (native_function_mapper.count(name)) {
|
||||||
gen(op_callb,
|
emit(op_callb,
|
||||||
static_cast<u32>(native_function_mapper.at(name)),
|
static_cast<u32>(native_function_mapper.at(name)),
|
||||||
node->get_location());
|
node->get_location());
|
||||||
if (local.empty()) {
|
if (local.empty()) {
|
||||||
|
@ -315,15 +318,15 @@ void codegen::call_id(identifier* node) {
|
||||||
|
|
||||||
i32 index;
|
i32 index;
|
||||||
if ((index=local_find(name))>=0) {
|
if ((index=local_find(name))>=0) {
|
||||||
gen(op_calll, index, node->get_location());
|
emit(op_calll, index, node->get_location());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((index=upvalue_find(name))>=0) {
|
if ((index=upvalue_find(name))>=0) {
|
||||||
gen(op_upval, index, node->get_location());
|
emit(op_upval, index, node->get_location());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((index=global_find(name))>=0) {
|
if ((index=global_find(name))>=0) {
|
||||||
gen(op_callg, index, node->get_location());
|
emit(op_callg, index, node->get_location());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
die("undefined symbol \"" + name + "\"", node->get_location());
|
die("undefined symbol \"" + name + "\"", node->get_location());
|
||||||
|
@ -331,7 +334,7 @@ void codegen::call_id(identifier* node) {
|
||||||
|
|
||||||
void codegen::call_hash_gen(call_hash* node) {
|
void codegen::call_hash_gen(call_hash* node) {
|
||||||
regist_str(node->get_field());
|
regist_str(node->get_field());
|
||||||
gen(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::call_vector_gen(call_vector* node) {
|
void codegen::call_vector_gen(call_vector* node) {
|
||||||
|
@ -339,39 +342,39 @@ void codegen::call_vector_gen(call_vector* node) {
|
||||||
if (node->get_slices().size()==1 &&
|
if (node->get_slices().size()==1 &&
|
||||||
!node->get_slices()[0]->get_end()) {
|
!node->get_slices()[0]->get_end()) {
|
||||||
calc_gen(node->get_slices()[0]->get_begin());
|
calc_gen(node->get_slices()[0]->get_begin());
|
||||||
gen(op_callv, 0, node->get_slices()[0]->get_location());
|
emit(op_callv, 0, node->get_slices()[0]->get_location());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gen(op_slcbeg, 0, node->get_location());
|
emit(op_slcbeg, 0, node->get_location());
|
||||||
for(auto tmp : node->get_slices()) {
|
for(auto tmp : node->get_slices()) {
|
||||||
if (!tmp->get_end()) {
|
if (!tmp->get_end()) {
|
||||||
calc_gen(tmp->get_begin());
|
calc_gen(tmp->get_begin());
|
||||||
gen(op_slc, 0, tmp->get_location());
|
emit(op_slc, 0, tmp->get_location());
|
||||||
} else {
|
} else {
|
||||||
calc_gen(tmp->get_begin());
|
calc_gen(tmp->get_begin());
|
||||||
calc_gen(tmp->get_end());
|
calc_gen(tmp->get_end());
|
||||||
gen(op_slc2, 0, tmp->get_location());
|
emit(op_slc2, 0, tmp->get_location());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gen(op_slcend, 0, node->get_location());
|
emit(op_slcend, 0, node->get_location());
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::call_func_gen(call_function* node) {
|
void codegen::call_func_gen(call_function* node) {
|
||||||
if (node->get_argument().size() &&
|
if (node->get_argument().size() &&
|
||||||
node->get_argument()[0]->get_type()==expr_type::ast_pair) {
|
node->get_argument()[0]->get_type()==expr_type::ast_pair) {
|
||||||
gen(op_newh, 0, node->get_location());
|
emit(op_newh, 0, node->get_location());
|
||||||
for(auto child : node->get_argument()) {
|
for(auto child : node->get_argument()) {
|
||||||
calc_gen(((hash_pair*)child)->get_value());
|
calc_gen(((hash_pair*)child)->get_value());
|
||||||
const auto& field_name = ((hash_pair*)child)->get_name();
|
const auto& field_name = ((hash_pair*)child)->get_name();
|
||||||
regist_str(field_name);
|
regist_str(field_name);
|
||||||
gen(op_happ, const_string_map.at(field_name), child->get_location());
|
emit(op_happ, const_string_map.at(field_name), child->get_location());
|
||||||
}
|
}
|
||||||
gen(op_callfh, 0, node->get_location());
|
emit(op_callfh, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
for(auto child : node->get_argument()) {
|
for(auto child : node->get_argument()) {
|
||||||
calc_gen(child);
|
calc_gen(child);
|
||||||
}
|
}
|
||||||
gen(op_callfv, node->get_argument().size(), node->get_location());
|
emit(op_callfv, node->get_argument().size(), node->get_location());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,15 +428,15 @@ void codegen::mcall_id(identifier* node) {
|
||||||
|
|
||||||
i32 index;
|
i32 index;
|
||||||
if ((index=local_find(name))>=0) {
|
if ((index=local_find(name))>=0) {
|
||||||
gen(op_mcalll, index, node->get_location());
|
emit(op_mcalll, index, node->get_location());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((index=upvalue_find(name))>=0) {
|
if ((index=upvalue_find(name))>=0) {
|
||||||
gen(op_mupval, index, node->get_location());
|
emit(op_mupval, index, node->get_location());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((index=global_find(name))>=0) {
|
if ((index=global_find(name))>=0) {
|
||||||
gen(op_mcallg, index, node->get_location());
|
emit(op_mcallg, index, node->get_location());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
die("undefined symbol \"" + name + "\"", node->get_location());
|
die("undefined symbol \"" + name + "\"", node->get_location());
|
||||||
|
@ -450,20 +453,22 @@ void codegen::mcall_vec(call_vector* node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
calc_gen(call->get_begin());
|
calc_gen(call->get_begin());
|
||||||
gen(op_mcallv, 0, node->get_location());
|
emit(op_mcallv, 0, node->get_location());
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::mcall_hash(call_hash* node) {
|
void codegen::mcall_hash(call_hash* node) {
|
||||||
regist_str(node->get_field());
|
regist_str(node->get_field());
|
||||||
gen(op_mcallh, const_string_map.at(node->get_field()), node->get_location());
|
emit(op_mcallh, const_string_map.at(node->get_field()), node->get_location());
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::single_def(definition_expr* node) {
|
void codegen::single_def(definition_expr* node) {
|
||||||
const auto& str = node->get_variable_name()->get_name();
|
const auto& str = node->get_variable_name()->get_name();
|
||||||
calc_gen(node->get_value());
|
calc_gen(node->get_value());
|
||||||
local.empty()?
|
if (local.empty()) {
|
||||||
gen(op_loadg, global_find(str), node->get_location()):
|
emit(op_loadg, global_find(str), node->get_location());
|
||||||
gen(op_loadl, local_find(str), node->get_location());
|
} else {
|
||||||
|
emit(op_loadl, local_find(str), node->get_location());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::multi_def(definition_expr* node) {
|
void codegen::multi_def(definition_expr* node) {
|
||||||
|
@ -474,30 +479,32 @@ void codegen::multi_def(definition_expr* node) {
|
||||||
auto& vals = node->get_tuple()->get_elements();
|
auto& vals = node->get_tuple()->get_elements();
|
||||||
if (identifiers.size()<vals.size()) {
|
if (identifiers.size()<vals.size()) {
|
||||||
die("lack values in multi-definition",
|
die("lack values in multi-definition",
|
||||||
node->get_tuple()->get_location());
|
node->get_tuple()->get_location()
|
||||||
|
);
|
||||||
} else if (identifiers.size()>vals.size()) {
|
} else if (identifiers.size()>vals.size()) {
|
||||||
die("too many values in multi-definition",
|
die("too many values in multi-definition",
|
||||||
node->get_tuple()->get_location());
|
node->get_tuple()->get_location()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
for(usize i = 0; i<size; ++i) {
|
for(usize i = 0; i<size; ++i) {
|
||||||
calc_gen(vals[i]);
|
calc_gen(vals[i]);
|
||||||
const auto& name = identifiers[i]->get_name();
|
const auto& name = identifiers[i]->get_name();
|
||||||
local.empty()?
|
local.empty()?
|
||||||
gen(op_loadg, global_find(name), identifiers[i]->get_location()):
|
emit(op_loadg, global_find(name), identifiers[i]->get_location()):
|
||||||
gen(op_loadl, local_find(name), identifiers[i]->get_location());
|
emit(op_loadl, local_find(name), identifiers[i]->get_location());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// (var a,b,c) = [0,1,2];
|
// (var a,b,c) = [0,1,2];
|
||||||
calc_gen(node->get_value());
|
calc_gen(node->get_value());
|
||||||
for(usize i = 0; i<size; ++i) {
|
for(usize i = 0; i<size; ++i) {
|
||||||
gen(op_callvi, i, node->get_value()->get_location());
|
emit(op_callvi, i, node->get_value()->get_location());
|
||||||
const auto& name = identifiers[i]->get_name();
|
const auto& name = identifiers[i]->get_name();
|
||||||
local.empty()?
|
local.empty()?
|
||||||
gen(op_loadg, global_find(name), identifiers[i]->get_location()):
|
emit(op_loadg, global_find(name), identifiers[i]->get_location()):
|
||||||
gen(op_loadl, local_find(name), identifiers[i]->get_location());
|
emit(op_loadl, local_find(name), identifiers[i]->get_location());
|
||||||
}
|
}
|
||||||
gen(op_pop, 0, node->get_location());
|
emit(op_pop, 0, node->get_location());
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::def_gen(definition_expr* node) {
|
void codegen::def_gen(definition_expr* node) {
|
||||||
|
@ -512,7 +519,7 @@ void codegen::assignment_expression(assignment_expr* node) {
|
||||||
case assignment_expr::assign_type::equal:
|
case assignment_expr::assign_type::equal:
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
mcall(node->get_left());
|
mcall(node->get_left());
|
||||||
gen(op_meq, 0, node->get_location());
|
emit(op_meq, 0, node->get_location());
|
||||||
break;
|
break;
|
||||||
case assignment_expr::assign_type::add_equal:
|
case assignment_expr::assign_type::add_equal:
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||||
|
@ -520,11 +527,11 @@ void codegen::assignment_expression(assignment_expr* node) {
|
||||||
}
|
}
|
||||||
mcall(node->get_left());
|
mcall(node->get_left());
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||||
gen(op_addeq, 0, node->get_location());
|
emit(op_addeq, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
auto num = ((number_literal*)node->get_right())->get_number();
|
auto num = ((number_literal*)node->get_right())->get_number();
|
||||||
regist_num(num);
|
regist_num(num);
|
||||||
gen(op_addeqc, const_number_map[num], node->get_location());
|
emit(op_addeqc, const_number_map[num], node->get_location());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case assignment_expr::assign_type::sub_equal:
|
case assignment_expr::assign_type::sub_equal:
|
||||||
|
@ -533,11 +540,11 @@ void codegen::assignment_expression(assignment_expr* node) {
|
||||||
}
|
}
|
||||||
mcall(node->get_left());
|
mcall(node->get_left());
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||||
gen(op_subeq, 0, node->get_location());
|
emit(op_subeq, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
auto num = ((number_literal*)node->get_right())->get_number();
|
auto num = ((number_literal*)node->get_right())->get_number();
|
||||||
regist_num(num);
|
regist_num(num);
|
||||||
gen(op_subeqc, const_number_map[num], node->get_location());
|
emit(op_subeqc, const_number_map[num], node->get_location());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case assignment_expr::assign_type::mult_equal:
|
case assignment_expr::assign_type::mult_equal:
|
||||||
|
@ -546,11 +553,11 @@ void codegen::assignment_expression(assignment_expr* node) {
|
||||||
}
|
}
|
||||||
mcall(node->get_left());
|
mcall(node->get_left());
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||||
gen(op_muleq, 0, node->get_location());
|
emit(op_muleq, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
auto num = ((number_literal*)node->get_right())->get_number();
|
auto num = ((number_literal*)node->get_right())->get_number();
|
||||||
regist_num(num);
|
regist_num(num);
|
||||||
gen(op_muleqc, const_number_map[num], node->get_location());
|
emit(op_muleqc, const_number_map[num], node->get_location());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case assignment_expr::assign_type::div_equal:
|
case assignment_expr::assign_type::div_equal:
|
||||||
|
@ -559,11 +566,11 @@ void codegen::assignment_expression(assignment_expr* node) {
|
||||||
}
|
}
|
||||||
mcall(node->get_left());
|
mcall(node->get_left());
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||||
gen(op_diveq, 0, node->get_location());
|
emit(op_diveq, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
auto num = ((number_literal*)node->get_right())->get_number();
|
auto num = ((number_literal*)node->get_right())->get_number();
|
||||||
regist_num(num);
|
regist_num(num);
|
||||||
gen(op_diveqc, const_number_map[num], node->get_location());
|
emit(op_diveqc, const_number_map[num], node->get_location());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case assignment_expr::assign_type::concat_equal:
|
case assignment_expr::assign_type::concat_equal:
|
||||||
|
@ -572,53 +579,63 @@ void codegen::assignment_expression(assignment_expr* node) {
|
||||||
}
|
}
|
||||||
mcall(node->get_left());
|
mcall(node->get_left());
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_str) {
|
if (node->get_right()->get_type()!=expr_type::ast_str) {
|
||||||
gen(op_lnkeq, 0, node->get_location());
|
emit(op_lnkeq, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
const auto& str = ((string_literal*)node->get_right())->get_content();
|
const auto& str = ((string_literal*)node->get_right())->get_content();
|
||||||
regist_str(str);
|
regist_str(str);
|
||||||
gen(op_lnkeqc, const_string_map[str], node->get_location());
|
emit(op_lnkeqc, const_string_map[str], node->get_location());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case assignment_expr::assign_type::bitwise_and_equal:
|
case assignment_expr::assign_type::bitwise_and_equal:
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
mcall(node->get_left());
|
mcall(node->get_left());
|
||||||
gen(op_btandeq, 0, node->get_location());
|
emit(op_btandeq, 0, node->get_location());
|
||||||
break;
|
break;
|
||||||
case assignment_expr::assign_type::bitwise_or_equal:
|
case assignment_expr::assign_type::bitwise_or_equal:
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
mcall(node->get_left());
|
mcall(node->get_left());
|
||||||
gen(op_btoreq, 0, node->get_location());
|
emit(op_btoreq, 0, node->get_location());
|
||||||
break;
|
break;
|
||||||
case assignment_expr::assign_type::bitwise_xor_equal:
|
case assignment_expr::assign_type::bitwise_xor_equal:
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
mcall(node->get_left());
|
mcall(node->get_left());
|
||||||
gen(op_btxoreq, 0, node->get_location());
|
emit(op_btxoreq, 0, node->get_location());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void codegen::gen_assignment_equal_statement(assignment_expr* node) {
|
||||||
|
// if is not symbol load type assignment, use calc_gen directly
|
||||||
|
// what is symbol load assignment? example:
|
||||||
|
// a = 1; # this is symbol load
|
||||||
|
// a.foo = "bar"; # this is not symbol load
|
||||||
|
if (node->get_left()->get_type()!=expr_type::ast_id) {
|
||||||
|
calc_gen(node);
|
||||||
|
if (code.back().op==op_meq) {
|
||||||
|
code.back().num = 1; // 1 means need pop after op_meq
|
||||||
|
} else {
|
||||||
|
emit(op_pop, 0, node->get_location());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate symbol load
|
||||||
|
calc_gen(node->get_right());
|
||||||
|
// get memory space of left identifier
|
||||||
|
mcall_id((identifier*)node->get_left());
|
||||||
|
// check memory get operand type and replace it with load operand
|
||||||
|
switch(code.back().op) {
|
||||||
|
case op_mcallg: code.back().op = op_loadg; break;
|
||||||
|
case op_mcalll: code.back().op = op_loadl; break;
|
||||||
|
case op_mupval: code.back().op = op_loadu; break;
|
||||||
|
default: die("unexpected operand to replace", node->get_location());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void codegen::assignment_statement(assignment_expr* node) {
|
void codegen::assignment_statement(assignment_expr* node) {
|
||||||
switch(node->get_assignment_type()) {
|
switch(node->get_assignment_type()) {
|
||||||
case assignment_expr::assign_type::equal:
|
case assignment_expr::assign_type::equal:
|
||||||
if (node->get_left()->get_type()==expr_type::ast_id) {
|
gen_assignment_equal_statement(node);
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case assignment_expr::assign_type::add_equal:
|
case assignment_expr::assign_type::add_equal:
|
||||||
case assignment_expr::assign_type::sub_equal:
|
case assignment_expr::assign_type::sub_equal:
|
||||||
|
@ -634,7 +651,7 @@ void codegen::assignment_statement(assignment_expr* node) {
|
||||||
} else if (op_addeqc<=code.back().op && code.back().op<=op_lnkeqc) {
|
} else if (op_addeqc<=code.back().op && code.back().op<=op_lnkeqc) {
|
||||||
code.back().op=code.back().op-op_addeqc+op_addecp;
|
code.back().op=code.back().op-op_addeqc+op_addecp;
|
||||||
} else {
|
} else {
|
||||||
gen(op_pop, 0, node->get_location());
|
emit(op_pop, 0, node->get_location());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -659,13 +676,13 @@ void codegen::multi_assign_gen(multi_assign* node) {
|
||||||
// multi assign user loadl and loadg to avoid meq's stack--
|
// multi assign user loadl and loadg to avoid meq's stack--
|
||||||
// and this operation changes local and global value directly
|
// and this operation changes local and global value directly
|
||||||
if (code.back().op==op_mcalll) {
|
if (code.back().op==op_mcalll) {
|
||||||
code.back().op=op_loadl;
|
code.back().op = op_loadl;
|
||||||
} else if (code.back().op==op_mupval) {
|
} else if (code.back().op==op_mupval) {
|
||||||
code.back().op=op_loadu;
|
code.back().op = op_loadu;
|
||||||
} else if (code.back().op==op_mcallg) {
|
} else if (code.back().op==op_mcallg) {
|
||||||
code.back().op=op_loadg;
|
code.back().op = op_loadg;
|
||||||
} else {
|
} else {
|
||||||
gen(op_meq, 1, tuple[i]->get_location());
|
emit(op_meq, 1, tuple[i]->get_location());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -673,46 +690,46 @@ void codegen::multi_assign_gen(multi_assign* node) {
|
||||||
calc_gen(node->get_value());
|
calc_gen(node->get_value());
|
||||||
auto& tuple = node->get_tuple()->get_elements();
|
auto& tuple = node->get_tuple()->get_elements();
|
||||||
for(i32 i = 0; i<size; ++i) {
|
for(i32 i = 0; i<size; ++i) {
|
||||||
gen(op_callvi, i, node->get_value()->get_location());
|
emit(op_callvi, i, node->get_value()->get_location());
|
||||||
// multi assign user loadl and loadg to avoid meq's stack--
|
// multi assign user loadl and loadg to avoid meq's stack--
|
||||||
// and this operation changes local and global value directly
|
// and this operation changes local and global value directly
|
||||||
mcall(tuple[i]);
|
mcall(tuple[i]);
|
||||||
if (code.back().op==op_mcalll) {
|
if (code.back().op==op_mcalll) {
|
||||||
code.back().op=op_loadl;
|
code.back().op = op_loadl;
|
||||||
} else if (code.back().op==op_mupval) {
|
} else if (code.back().op==op_mupval) {
|
||||||
code.back().op=op_loadu;
|
code.back().op = op_loadu;
|
||||||
} else if (code.back().op==op_mcallg) {
|
} else if (code.back().op==op_mcallg) {
|
||||||
code.back().op=op_loadg;
|
code.back().op = op_loadg;
|
||||||
} else {
|
} else {
|
||||||
gen(op_meq, 1, tuple[i]->get_location());
|
emit(op_meq, 1, tuple[i]->get_location());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gen(op_pop, 0, node->get_location());
|
emit(op_pop, 0, node->get_location());
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::cond_gen(condition_expr* node) {
|
void codegen::cond_gen(condition_expr* node) {
|
||||||
std::vector<usize> jmp_label;
|
std::vector<usize> jmp_label;
|
||||||
calc_gen(node->get_if_statement()->get_condition());
|
calc_gen(node->get_if_statement()->get_condition());
|
||||||
auto ptr = code.size();
|
auto ptr = code.size();
|
||||||
gen(op_jf, 0, node->get_if_statement()->get_location());
|
emit(op_jf, 0, node->get_if_statement()->get_location());
|
||||||
block_gen(node->get_if_statement()->get_code_block());
|
block_gen(node->get_if_statement()->get_code_block());
|
||||||
if (node->get_elsif_stataments().size() ||
|
if (node->get_elsif_stataments().size() ||
|
||||||
node->get_else_statement()) {
|
node->get_else_statement()) {
|
||||||
jmp_label.push_back(code.size());
|
jmp_label.push_back(code.size());
|
||||||
gen(op_jmp, 0, node->get_if_statement()->get_location());
|
emit(op_jmp, 0, node->get_if_statement()->get_location());
|
||||||
}
|
}
|
||||||
code[ptr].num = code.size();
|
code[ptr].num = code.size();
|
||||||
|
|
||||||
for(auto tmp : node->get_elsif_stataments()) {
|
for(auto tmp : node->get_elsif_stataments()) {
|
||||||
calc_gen(tmp->get_condition());
|
calc_gen(tmp->get_condition());
|
||||||
ptr = code.size();
|
ptr = code.size();
|
||||||
gen(op_jf, 0, tmp->get_location());
|
emit(op_jf, 0, tmp->get_location());
|
||||||
block_gen(tmp->get_code_block());
|
block_gen(tmp->get_code_block());
|
||||||
// the last condition doesn't need to jmp
|
// the last condition doesn't need to jmp
|
||||||
if (tmp!=node->get_elsif_stataments().back() ||
|
if (tmp!=node->get_elsif_stataments().back() ||
|
||||||
node->get_else_statement()) {
|
node->get_else_statement()) {
|
||||||
jmp_label.push_back(code.size());
|
jmp_label.push_back(code.size());
|
||||||
gen(op_jmp, 0, tmp->get_location());
|
emit(op_jmp, 0, tmp->get_location());
|
||||||
}
|
}
|
||||||
code[ptr].num=code.size();
|
code[ptr].num=code.size();
|
||||||
}
|
}
|
||||||
|
@ -729,12 +746,9 @@ void codegen::loop_gen(expr* node) {
|
||||||
continue_ptr.push_front({});
|
continue_ptr.push_front({});
|
||||||
break_ptr.push_front({});
|
break_ptr.push_front({});
|
||||||
switch(node->get_type()) {
|
switch(node->get_type()) {
|
||||||
case expr_type::ast_while:
|
case expr_type::ast_while: while_gen((while_expr*)node); break;
|
||||||
while_gen((while_expr*)node); break;
|
case expr_type::ast_for: for_gen((for_expr*)node); break;
|
||||||
case expr_type::ast_for:
|
case expr_type::ast_forei: forei_gen((forei_expr*)node); break;
|
||||||
for_gen((for_expr*)node); break;
|
|
||||||
case expr_type::ast_forei:
|
|
||||||
forei_gen((forei_expr*)node); break;
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -754,10 +768,10 @@ void codegen::while_gen(while_expr* node) {
|
||||||
usize loop_ptr = code.size();
|
usize loop_ptr = code.size();
|
||||||
calc_gen(node->get_condition());
|
calc_gen(node->get_condition());
|
||||||
usize condition_ptr = code.size();
|
usize condition_ptr = code.size();
|
||||||
gen(op_jf, 0, node->get_condition()->get_location());
|
emit(op_jf, 0, node->get_condition()->get_location());
|
||||||
|
|
||||||
block_gen(node->get_code_block());
|
block_gen(node->get_code_block());
|
||||||
gen(op_jmp, loop_ptr, node->get_code_block()->get_location());
|
emit(op_jmp, loop_ptr, node->get_code_block()->get_location());
|
||||||
code[condition_ptr].num = code.size();
|
code[condition_ptr].num = code.size();
|
||||||
load_continue_break(code.size()-1, code.size());
|
load_continue_break(code.size()-1, code.size());
|
||||||
}
|
}
|
||||||
|
@ -767,17 +781,17 @@ void codegen::for_gen(for_expr* node) {
|
||||||
usize jmp_place = code.size();
|
usize jmp_place = code.size();
|
||||||
if (node->get_condition()->get_type()==expr_type::ast_null) {
|
if (node->get_condition()->get_type()==expr_type::ast_null) {
|
||||||
regist_num(1);
|
regist_num(1);
|
||||||
gen(op_pnum, const_number_map.at(1), node->get_condition()->get_location());
|
emit(op_pnum, const_number_map.at(1), node->get_condition()->get_location());
|
||||||
} else {
|
} else {
|
||||||
calc_gen(node->get_condition());
|
calc_gen(node->get_condition());
|
||||||
}
|
}
|
||||||
usize label_exit = code.size();
|
usize label_exit = code.size();
|
||||||
gen(op_jf, 0, node->get_condition()->get_location());
|
emit(op_jf, 0, node->get_condition()->get_location());
|
||||||
|
|
||||||
block_gen(node->get_code_block());
|
block_gen(node->get_code_block());
|
||||||
usize continue_place = code.size();
|
usize continue_place = code.size();
|
||||||
statement_generation(node->get_step());
|
statement_generation(node->get_step());
|
||||||
gen(op_jmp, jmp_place, node->get_step()->get_location());
|
emit(op_jmp, jmp_place, node->get_step()->get_location());
|
||||||
code[label_exit].num = code.size();
|
code[label_exit].num = code.size();
|
||||||
|
|
||||||
load_continue_break(continue_place, code.size());
|
load_continue_break(continue_place, code.size());
|
||||||
|
@ -785,39 +799,39 @@ void codegen::for_gen(for_expr* node) {
|
||||||
|
|
||||||
void codegen::forei_gen(forei_expr* node) {
|
void codegen::forei_gen(forei_expr* node) {
|
||||||
calc_gen(node->get_value());
|
calc_gen(node->get_value());
|
||||||
gen(op_cnt, 0, node->get_value()->get_location());
|
emit(op_cnt, 0, node->get_value()->get_location());
|
||||||
usize ptr = code.size();
|
usize ptr = code.size();
|
||||||
if (node->get_loop_type()==forei_expr::forei_loop_type::forindex) {
|
if (node->get_loop_type()==forei_expr::forei_loop_type::forindex) {
|
||||||
gen(op_findex, 0, node->get_location());
|
emit(op_findex, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
gen(op_feach, 0, node->get_location());
|
emit(op_feach, 0, node->get_location());
|
||||||
}
|
}
|
||||||
if (node->get_iterator()->get_name()) { // define a new iterator
|
if (node->get_iterator()->get_name()) { // define a new iterator
|
||||||
auto name_node = node->get_iterator()->get_name();
|
auto name_node = node->get_iterator()->get_name();
|
||||||
const auto& str = name_node->get_name();
|
const auto& str = name_node->get_name();
|
||||||
local.empty()?
|
local.empty()?
|
||||||
gen(op_loadg, global_find(str), name_node->get_location()):
|
emit(op_loadg, global_find(str), name_node->get_location()):
|
||||||
gen(op_loadl, local_find(str), name_node->get_location());
|
emit(op_loadl, local_find(str), name_node->get_location());
|
||||||
} else { // use exist variable as the iterator
|
} else { // use exist variable as the iterator
|
||||||
mcall(node->get_iterator()->get_call());
|
mcall(node->get_iterator()->get_call());
|
||||||
if (code.back().op==op_mcallg) {
|
if (code.back().op==op_mcallg) {
|
||||||
code.back().op=op_loadg;
|
code.back().op = op_loadg;
|
||||||
} else if (code.back().op==op_mcalll) {
|
} else if (code.back().op==op_mcalll) {
|
||||||
code.back().op=op_loadl;
|
code.back().op = op_loadl;
|
||||||
} else if (code.back().op==op_mupval) {
|
} else if (code.back().op==op_mupval) {
|
||||||
code.back().op=op_loadu;
|
code.back().op = op_loadu;
|
||||||
} else {
|
} else {
|
||||||
gen(op_meq, 1, node->get_iterator()->get_location());
|
emit(op_meq, 1, node->get_iterator()->get_location());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++in_loop_level.back();
|
++in_loop_level.back();
|
||||||
block_gen(node->get_code_block());
|
block_gen(node->get_code_block());
|
||||||
--in_loop_level.back();
|
--in_loop_level.back();
|
||||||
gen(op_jmp, ptr, node->get_location());
|
emit(op_jmp, ptr, node->get_location());
|
||||||
code[ptr].num=code.size();
|
code[ptr].num=code.size();
|
||||||
load_continue_break(code.size()-1, code.size());
|
load_continue_break(code.size()-1, code.size());
|
||||||
gen(op_pop, 0, node->get_value()->get_location());// pop vector
|
emit(op_pop, 0, node->get_value()->get_location());// pop vector
|
||||||
gen(op_pop, 0, node->get_location());// pop iterator
|
emit(op_pop, 0, node->get_location());// pop iterator
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::statement_generation(expr* node) {
|
void codegen::statement_generation(expr* node) {
|
||||||
|
@ -841,7 +855,7 @@ void codegen::statement_generation(expr* node) {
|
||||||
case expr_type::ast_binary:
|
case expr_type::ast_binary:
|
||||||
case expr_type::ast_ternary:
|
case expr_type::ast_ternary:
|
||||||
calc_gen(node);
|
calc_gen(node);
|
||||||
gen(op_pop, 0, node->get_location());
|
emit(op_pop, 0, node->get_location());
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
@ -850,33 +864,33 @@ void codegen::statement_generation(expr* node) {
|
||||||
void codegen::or_gen(binary_operator* node) {
|
void codegen::or_gen(binary_operator* node) {
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
usize label_jump_true_1 = code.size();
|
usize label_jump_true_1 = code.size();
|
||||||
gen(op_jt, 0, node->get_left()->get_location());
|
emit(op_jt, 0, node->get_left()->get_location());
|
||||||
|
|
||||||
gen(op_pop, 0, node->get_left()->get_location());
|
emit(op_pop, 0, node->get_left()->get_location());
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
usize label_jump_true_2 = code.size();
|
usize label_jump_true_2 = code.size();
|
||||||
gen(op_jt, 0, node->get_right()->get_location());
|
emit(op_jt, 0, node->get_right()->get_location());
|
||||||
|
|
||||||
gen(op_pop, 0, node->get_right()->get_location());
|
emit(op_pop, 0, node->get_right()->get_location());
|
||||||
gen(op_pnil, 0, node->get_right()->get_location());
|
emit(op_pnil, 0, node->get_right()->get_location());
|
||||||
|
|
||||||
code[label_jump_true_1].num = code[label_jump_true_2].num = code.size();
|
code[label_jump_true_1].num = code[label_jump_true_2].num = code.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::and_gen(binary_operator* node) {
|
void codegen::and_gen(binary_operator* node) {
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
gen(op_jt, code.size()+2, node->get_left()->get_location());
|
emit(op_jt, code.size()+2, node->get_left()->get_location());
|
||||||
|
|
||||||
usize lable_jump_false = code.size();
|
usize lable_jump_false = code.size();
|
||||||
gen(op_jmp, 0, node->get_left()->get_location());
|
emit(op_jmp, 0, node->get_left()->get_location());
|
||||||
gen(op_pop, 0, node->get_right()->get_location()); // jt jumps here
|
emit(op_pop, 0, node->get_right()->get_location()); // jt jumps here
|
||||||
|
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_jt, code.size()+3, node->get_right()->get_location());
|
emit(op_jt, code.size()+3, node->get_right()->get_location());
|
||||||
|
|
||||||
code[lable_jump_false].num = code.size();
|
code[lable_jump_false].num = code.size();
|
||||||
gen(op_pop, 0, node->get_right()->get_location());
|
emit(op_pop, 0, node->get_right()->get_location());
|
||||||
gen(op_pnil, 0, node->get_right()->get_location());
|
emit(op_pnil, 0, node->get_right()->get_location());
|
||||||
// jt jumps here, avoid pop and pnil
|
// jt jumps here, avoid pop and pnil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -890,11 +904,11 @@ void codegen::unary_gen(unary_operator* node) {
|
||||||
calc_gen(node->get_value());
|
calc_gen(node->get_value());
|
||||||
switch(node->get_operator_type()) {
|
switch(node->get_operator_type()) {
|
||||||
case unary_operator::unary_type::negative:
|
case unary_operator::unary_type::negative:
|
||||||
gen(op_usub, 0, node->get_location()); break;
|
emit(op_usub, 0, node->get_location()); break;
|
||||||
case unary_operator::unary_type::logical_not:
|
case unary_operator::unary_type::logical_not:
|
||||||
gen(op_lnot, 0, node->get_location()); break;
|
emit(op_lnot, 0, node->get_location()); break;
|
||||||
case unary_operator::unary_type::bitwise_not:
|
case unary_operator::unary_type::bitwise_not:
|
||||||
gen(op_bnot, 0, node->get_location()); break;
|
emit(op_bnot, 0, node->get_location()); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -918,27 +932,27 @@ void codegen::binary_gen(binary_operator* node) {
|
||||||
case binary_operator::binary_type::cmpeq:
|
case binary_operator::binary_type::cmpeq:
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_eq, 0, node->get_location());
|
emit(op_eq, 0, node->get_location());
|
||||||
return;
|
return;
|
||||||
case binary_operator::binary_type::cmpneq:
|
case binary_operator::binary_type::cmpneq:
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_neq, 0, node->get_location());
|
emit(op_neq, 0, node->get_location());
|
||||||
return;
|
return;
|
||||||
case binary_operator::binary_type::bitwise_or:
|
case binary_operator::binary_type::bitwise_or:
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_btor, 0, node->get_location());
|
emit(op_btor, 0, node->get_location());
|
||||||
return;
|
return;
|
||||||
case binary_operator::binary_type::bitwise_xor:
|
case binary_operator::binary_type::bitwise_xor:
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_btxor, 0, node->get_location());
|
emit(op_btxor, 0, node->get_location());
|
||||||
return;
|
return;
|
||||||
case binary_operator::binary_type::bitwise_and:
|
case binary_operator::binary_type::bitwise_and:
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_btand, 0, node->get_location());
|
emit(op_btand, 0, node->get_location());
|
||||||
return;
|
return;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
@ -947,99 +961,99 @@ void codegen::binary_gen(binary_operator* node) {
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_add, 0, node->get_location());
|
emit(op_add, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
auto num = ((number_literal*)node->get_right())->get_number();
|
auto num = ((number_literal*)node->get_right())->get_number();
|
||||||
regist_num(num);
|
regist_num(num);
|
||||||
gen(op_addc, const_number_map.at(num), node->get_location());
|
emit(op_addc, const_number_map.at(num), node->get_location());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case binary_operator::binary_type::sub:
|
case binary_operator::binary_type::sub:
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_sub, 0, node->get_location());
|
emit(op_sub, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
auto num = ((number_literal*)node->get_right())->get_number();
|
auto num = ((number_literal*)node->get_right())->get_number();
|
||||||
regist_num(num);
|
regist_num(num);
|
||||||
gen(op_subc, const_number_map.at(num), node->get_location());
|
emit(op_subc, const_number_map.at(num), node->get_location());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case binary_operator::binary_type::mult:
|
case binary_operator::binary_type::mult:
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_mul, 0, node->get_location());
|
emit(op_mul, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
auto num = ((number_literal*)node->get_right())->get_number();
|
auto num = ((number_literal*)node->get_right())->get_number();
|
||||||
regist_num(num);
|
regist_num(num);
|
||||||
gen(op_mulc, const_number_map.at(num), node->get_location());
|
emit(op_mulc, const_number_map.at(num), node->get_location());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case binary_operator::binary_type::div:
|
case binary_operator::binary_type::div:
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_div, 0, node->get_location());
|
emit(op_div, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
auto num = ((number_literal*)node->get_right())->get_number();
|
auto num = ((number_literal*)node->get_right())->get_number();
|
||||||
regist_num(num);
|
regist_num(num);
|
||||||
gen(op_divc, const_number_map.at(num), node->get_location());
|
emit(op_divc, const_number_map.at(num), node->get_location());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case binary_operator::binary_type::concat:
|
case binary_operator::binary_type::concat:
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_str) {
|
if (node->get_right()->get_type()!=expr_type::ast_str) {
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_lnk, 0, node->get_location());
|
emit(op_lnk, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
const auto& str = ((string_literal*)node->get_right())->get_content();
|
const auto& str = ((string_literal*)node->get_right())->get_content();
|
||||||
regist_str(str);
|
regist_str(str);
|
||||||
gen(op_lnkc, const_string_map.at(str), node->get_location());
|
emit(op_lnkc, const_string_map.at(str), node->get_location());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case binary_operator::binary_type::less:
|
case binary_operator::binary_type::less:
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_less, 0, node->get_location());
|
emit(op_less, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
auto num = ((number_literal*)node->get_right())->get_number();
|
auto num = ((number_literal*)node->get_right())->get_number();
|
||||||
regist_num(num);
|
regist_num(num);
|
||||||
gen(op_lessc, const_number_map.at(num), node->get_location());
|
emit(op_lessc, const_number_map.at(num), node->get_location());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case binary_operator::binary_type::leq:
|
case binary_operator::binary_type::leq:
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_leq, 0, node->get_location());
|
emit(op_leq, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
auto num = ((number_literal*)node->get_right())->get_number();
|
auto num = ((number_literal*)node->get_right())->get_number();
|
||||||
regist_num(num);
|
regist_num(num);
|
||||||
gen(op_leqc, const_number_map.at(num), node->get_location());
|
emit(op_leqc, const_number_map.at(num), node->get_location());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case binary_operator::binary_type::grt:
|
case binary_operator::binary_type::grt:
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_grt, 0, node->get_location());
|
emit(op_grt, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
auto num = ((number_literal*)node->get_right())->get_number();
|
auto num = ((number_literal*)node->get_right())->get_number();
|
||||||
regist_num(num);
|
regist_num(num);
|
||||||
gen(op_grtc, const_number_map.at(num), node->get_location());
|
emit(op_grtc, const_number_map.at(num), node->get_location());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case binary_operator::binary_type::geq:
|
case binary_operator::binary_type::geq:
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
if (node->get_right()->get_type()!=expr_type::ast_num) {
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
gen(op_geq, 0, node->get_location());
|
emit(op_geq, 0, node->get_location());
|
||||||
} else {
|
} else {
|
||||||
auto num = ((number_literal*)node->get_right())->get_number();
|
auto num = ((number_literal*)node->get_right())->get_number();
|
||||||
regist_num(num);
|
regist_num(num);
|
||||||
gen(op_geqc, const_number_map.at(num), node->get_location());
|
emit(op_geqc, const_number_map.at(num), node->get_location());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
default: break;
|
default: break;
|
||||||
|
@ -1049,10 +1063,10 @@ void codegen::binary_gen(binary_operator* node) {
|
||||||
void codegen::trino_gen(ternary_operator* node) {
|
void codegen::trino_gen(ternary_operator* node) {
|
||||||
calc_gen(node->get_condition());
|
calc_gen(node->get_condition());
|
||||||
usize label_jump_false = code.size();
|
usize label_jump_false = code.size();
|
||||||
gen(op_jf, 0, node->get_condition()->get_location());
|
emit(op_jf, 0, node->get_condition()->get_location());
|
||||||
calc_gen(node->get_left());
|
calc_gen(node->get_left());
|
||||||
usize label_jump_to_exit = code.size();
|
usize label_jump_to_exit = code.size();
|
||||||
gen(op_jmp, 0, node->get_left()->get_location());
|
emit(op_jmp, 0, node->get_left()->get_location());
|
||||||
code[label_jump_false].num = code.size();
|
code[label_jump_false].num = code.size();
|
||||||
calc_gen(node->get_right());
|
calc_gen(node->get_right());
|
||||||
code[label_jump_to_exit].num = code.size();
|
code[label_jump_to_exit].num = code.size();
|
||||||
|
@ -1061,7 +1075,7 @@ void codegen::trino_gen(ternary_operator* node) {
|
||||||
void codegen::calc_gen(expr* node) {
|
void codegen::calc_gen(expr* node) {
|
||||||
switch(node->get_type()) {
|
switch(node->get_type()) {
|
||||||
case expr_type::ast_nil:
|
case expr_type::ast_nil:
|
||||||
gen(op_pnil, 0, node->get_location()); break;
|
emit(op_pnil, 0, node->get_location()); break;
|
||||||
case expr_type::ast_num:
|
case expr_type::ast_num:
|
||||||
num_gen((number_literal*)node); break;
|
num_gen((number_literal*)node); break;
|
||||||
case expr_type::ast_str:
|
case expr_type::ast_str:
|
||||||
|
@ -1109,11 +1123,11 @@ void codegen::block_gen(code_block* node) {
|
||||||
cond_gen((condition_expr*)tmp); break;
|
cond_gen((condition_expr*)tmp); break;
|
||||||
case expr_type::ast_continue:
|
case expr_type::ast_continue:
|
||||||
continue_ptr.front().push_back(code.size());
|
continue_ptr.front().push_back(code.size());
|
||||||
gen(op_jmp, 0, tmp->get_location());
|
emit(op_jmp, 0, tmp->get_location());
|
||||||
break;
|
break;
|
||||||
case expr_type::ast_break:
|
case expr_type::ast_break:
|
||||||
break_ptr.front().push_back(code.size());
|
break_ptr.front().push_back(code.size());
|
||||||
gen(op_jmp, 0, tmp->get_location());
|
emit(op_jmp, 0, tmp->get_location());
|
||||||
break;
|
break;
|
||||||
case expr_type::ast_while:
|
case expr_type::ast_while:
|
||||||
case expr_type::ast_for:
|
case expr_type::ast_for:
|
||||||
|
@ -1139,11 +1153,11 @@ void codegen::block_gen(code_block* node) {
|
||||||
|
|
||||||
void codegen::ret_gen(return_expr* node) {
|
void codegen::ret_gen(return_expr* node) {
|
||||||
for(u32 i = 0; i<in_loop_level.back(); ++i) {
|
for(u32 i = 0; i<in_loop_level.back(); ++i) {
|
||||||
gen(op_pop, 0, node->get_location());
|
emit(op_pop, 0, node->get_location());
|
||||||
gen(op_pop, 0, node->get_location());
|
emit(op_pop, 0, node->get_location());
|
||||||
}
|
}
|
||||||
calc_gen(node->get_value());
|
calc_gen(node->get_value());
|
||||||
gen(op_ret, 0, node->get_location());
|
emit(op_ret, 0, node->get_location());
|
||||||
}
|
}
|
||||||
|
|
||||||
const error& codegen::compile(parse& parse, linker& import) {
|
const error& codegen::compile(parse& parse, linker& import) {
|
||||||
|
@ -1159,23 +1173,24 @@ const error& codegen::compile(parse& parse, linker& import) {
|
||||||
|
|
||||||
// search global symbols first
|
// search global symbols first
|
||||||
find_symbol(parse.tree());
|
find_symbol(parse.tree());
|
||||||
gen(op_intg, global.size(), parse.tree()->get_location());
|
|
||||||
|
|
||||||
// generate main block
|
// generate main block
|
||||||
block_gen(parse.tree());
|
block_gen(parse.tree());
|
||||||
// generate exit operand, vm stops here
|
// generate exit operand, vm stops here
|
||||||
gen(op_exit, 0, parse.tree()->get_location());
|
emit(op_exit, 0, parse.tree()->get_location());
|
||||||
|
|
||||||
// size out of bound check
|
// size out of bound check
|
||||||
if (const_number_table.size()>0xffffff) {
|
if (const_number_table.size()>0xffffff) {
|
||||||
err.err("code",
|
err.err("code",
|
||||||
"too many constant numbers: " +
|
"too many constant numbers: " +
|
||||||
std::to_string(const_number_table.size()));
|
std::to_string(const_number_table.size())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (const_string_table.size()>0xffffff) {
|
if (const_string_table.size()>0xffffff) {
|
||||||
err.err("code",
|
err.err("code",
|
||||||
"too many constant strings: " +
|
"too many constant strings: " +
|
||||||
std::to_string(const_string_table.size()));
|
std::to_string(const_string_table.size())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check global variables size
|
// check global variables size
|
||||||
|
|
|
@ -83,7 +83,7 @@ private:
|
||||||
i32 global_find(const std::string&);
|
i32 global_find(const std::string&);
|
||||||
i32 upvalue_find(const std::string&);
|
i32 upvalue_find(const std::string&);
|
||||||
|
|
||||||
void gen(u8, u32, const span&);
|
void emit(u8, u32, const span&);
|
||||||
|
|
||||||
void num_gen(number_literal*);
|
void num_gen(number_literal*);
|
||||||
void str_gen(string_literal*);
|
void str_gen(string_literal*);
|
||||||
|
@ -104,6 +104,7 @@ private:
|
||||||
void single_def(definition_expr*);
|
void single_def(definition_expr*);
|
||||||
void def_gen(definition_expr*);
|
void def_gen(definition_expr*);
|
||||||
void assignment_expression(assignment_expr*);
|
void assignment_expression(assignment_expr*);
|
||||||
|
void gen_assignment_equal_statement(assignment_expr*);
|
||||||
void assignment_statement(assignment_expr*);
|
void assignment_statement(assignment_expr*);
|
||||||
void multi_assign_gen(multi_assign*);
|
void multi_assign_gen(multi_assign*);
|
||||||
void cond_gen(condition_expr*);
|
void cond_gen(condition_expr*);
|
||||||
|
|
|
@ -183,7 +183,7 @@ f64 str2num(const char* str) {
|
||||||
|
|
||||||
i32 utf8_hdchk(const char head) {
|
i32 utf8_hdchk(const char head) {
|
||||||
// RFC-2279 but now we use RFC-3629 so nbytes is less than 4
|
// RFC-2279 but now we use RFC-3629 so nbytes is less than 4
|
||||||
const u8 c = (u8)head;
|
const auto c = static_cast<u8>(head);
|
||||||
if ((c>>5)==0x06) { // 110x xxxx (10xx xxxx)^1
|
if ((c>>5)==0x06) { // 110x xxxx (10xx xxxx)^1
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace nasal {
|
||||||
|
|
||||||
enum op_code_type:u8 {
|
enum op_code_type:u8 {
|
||||||
op_exit, // stop the virtual machine
|
op_exit, // stop the virtual machine
|
||||||
op_intg, // init global scope
|
op_intg, // [deprecated] init global scope
|
||||||
op_intl, // local scope size
|
op_intl, // local scope size
|
||||||
op_loadg, // load global value
|
op_loadg, // load global value
|
||||||
op_loadl, // load local value
|
op_loadl, // load local value
|
||||||
|
|
|
@ -150,11 +150,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
parse(): ptr(0), in_func(0), in_loop(0), toks(nullptr), root(nullptr) {}
|
parse(): ptr(0), in_func(0), in_loop(0), toks(nullptr), root(nullptr) {}
|
||||||
~parse() {
|
~parse() {delete root;}
|
||||||
if (root) {
|
|
||||||
delete root;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const error& compile(const lexer&);
|
const error& compile(const lexer&);
|
||||||
static void easter_egg();
|
static void easter_egg();
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,7 +55,7 @@ void vm::context_and_global_init() {
|
||||||
ctx.canary = ctx.stack+STACK_DEPTH-1;
|
ctx.canary = ctx.stack+STACK_DEPTH-1;
|
||||||
|
|
||||||
/* nothing is on stack */
|
/* nothing is on stack */
|
||||||
ctx.top = ctx.stack;
|
ctx.top = ctx.stack - 1;
|
||||||
|
|
||||||
/* clear main stack and global */
|
/* clear main stack and global */
|
||||||
for(u32 i = 0; i<STACK_DEPTH; ++i) {
|
for(u32 i = 0; i<STACK_DEPTH; ++i) {
|
||||||
|
|
|
@ -193,10 +193,8 @@ inline bool vm::cond(var& val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_intg() {
|
inline void vm::o_intg() {
|
||||||
// global values store on stack
|
// reserved for another usage
|
||||||
// ctx.top += imm[ctx.pc];
|
std::cout << "[vm] do nothing\n";
|
||||||
// point to the top
|
|
||||||
--ctx.top;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_intl() {
|
inline void vm::o_intl() {
|
||||||
|
@ -301,9 +299,7 @@ inline void vm::o_lnot() {
|
||||||
ctx.top[0] = num? zero:one;
|
ctx.top[0] = num? zero:one;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default:
|
default: die("incorrect value type"); return;
|
||||||
die("incorrect value type");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,22 +313,25 @@ inline void vm::o_bnot() {
|
||||||
|
|
||||||
inline void vm::o_btor() {
|
inline void vm::o_btor() {
|
||||||
ctx.top[-1] = var::num(
|
ctx.top[-1] = var::num(
|
||||||
static_cast<int32_t>(ctx.top[-1].tonum())|
|
static_cast<i32>(ctx.top[-1].tonum())|
|
||||||
static_cast<int32_t>(ctx.top[0].tonum()));
|
static_cast<i32>(ctx.top[0].tonum())
|
||||||
|
);
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_btxor() {
|
inline void vm::o_btxor() {
|
||||||
ctx.top[-1] = var::num(
|
ctx.top[-1] = var::num(
|
||||||
static_cast<int32_t>(ctx.top[-1].tonum())^
|
static_cast<i32>(ctx.top[-1].tonum())^
|
||||||
static_cast<int32_t>(ctx.top[0].tonum()));
|
static_cast<i32>(ctx.top[0].tonum())
|
||||||
|
);
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_btand() {
|
inline void vm::o_btand() {
|
||||||
ctx.top[-1] = var::num(
|
ctx.top[-1] = var::num(
|
||||||
static_cast<int32_t>(ctx.top[-1].tonum())&
|
static_cast<i32>(ctx.top[-1].tonum())&
|
||||||
static_cast<int32_t>(ctx.top[0].tonum()));
|
static_cast<i32>(ctx.top[0].tonum())
|
||||||
|
);
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,25 +387,36 @@ inline void vm::o_subeq() {op_calc_eq(-);}
|
||||||
inline void vm::o_muleq() {op_calc_eq(*);}
|
inline void vm::o_muleq() {op_calc_eq(*);}
|
||||||
inline void vm::o_diveq() {op_calc_eq(/);}
|
inline void vm::o_diveq() {op_calc_eq(/);}
|
||||||
inline void vm::o_lnkeq() {
|
inline void vm::o_lnkeq() {
|
||||||
ctx.top[-1] = ctx.memr[0] = ngc.newstr(ctx.memr[0].tostr()+ctx.top[-1].tostr());
|
ctx.top[-1] = ctx.memr[0] = ngc.newstr(
|
||||||
|
ctx.memr[0].tostr()+ctx.top[-1].tostr()
|
||||||
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc]+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_bandeq() {
|
inline void vm::o_bandeq() {
|
||||||
ctx.top[-1] = ctx.memr[0] = var::num(i32(ctx.memr[0].tonum())&i32(ctx.top[-1].tonum()));
|
ctx.top[-1] = ctx.memr[0] = var::num(
|
||||||
|
static_cast<i32>(ctx.memr[0].tonum())&
|
||||||
|
static_cast<i32>(ctx.top[-1].tonum())
|
||||||
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc]+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_boreq() {
|
inline void vm::o_boreq() {
|
||||||
ctx.top[-1] = ctx.memr[0] = var::num(i32(ctx.memr[0].tonum())|i32(ctx.top[-1].tonum()));
|
ctx.top[-1] = ctx.memr[0] = var::num(
|
||||||
|
static_cast<i32>(ctx.memr[0].tonum())|
|
||||||
|
static_cast<i32>(ctx.top[-1].tonum())
|
||||||
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc]+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_bxoreq() {
|
inline void vm::o_bxoreq() {
|
||||||
ctx.top[-1] = ctx.memr[0] = var::num(i32(ctx.memr[0].tonum())^i32(ctx.top[-1].tonum()));
|
ctx.top[-1] = ctx.memr[0] = var::num(
|
||||||
|
static_cast<i32>(ctx.memr[0].tonum())^
|
||||||
|
static_cast<i32>(ctx.top[-1].tonum())
|
||||||
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc]+1;
|
||||||
}
|
}
|
||||||
|
@ -439,7 +449,9 @@ inline void vm::o_subecp() {op_calc_eq_const_and_pop(-);}
|
||||||
inline void vm::o_mulecp() {op_calc_eq_const_and_pop(*);}
|
inline void vm::o_mulecp() {op_calc_eq_const_and_pop(*);}
|
||||||
inline void vm::o_divecp() {op_calc_eq_const_and_pop(/);}
|
inline void vm::o_divecp() {op_calc_eq_const_and_pop(/);}
|
||||||
inline void vm::o_lnkecp() {
|
inline void vm::o_lnkecp() {
|
||||||
ctx.top[0] = ctx.memr[0] = ngc.newstr(ctx.memr[0].tostr()+cstr[imm[ctx.pc]]);
|
ctx.top[0] = ctx.memr[0] = ngc.newstr(
|
||||||
|
ctx.memr[0].tostr()+cstr[imm[ctx.pc]]
|
||||||
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
@ -461,12 +473,12 @@ inline void vm::o_eq() {
|
||||||
if (val1.type==vm_nil && val2.type==vm_nil) {
|
if (val1.type==vm_nil && val2.type==vm_nil) {
|
||||||
ctx.top[0] = one;
|
ctx.top[0] = one;
|
||||||
} else if (val1.type==vm_str && val2.type==vm_str) {
|
} else if (val1.type==vm_str && val2.type==vm_str) {
|
||||||
ctx.top[0] = (val1.str()==val2.str())?one:zero;
|
ctx.top[0] = (val1.str()==val2.str())? one:zero;
|
||||||
} else if ((val1.type==vm_num || val2.type==vm_num)
|
} else if ((val1.type==vm_num || val2.type==vm_num)
|
||||||
&& val1.type!=vm_nil && val2.type!=vm_nil) {
|
&& val1.type!=vm_nil && val2.type!=vm_nil) {
|
||||||
ctx.top[0] = (val1.tonum()==val2.tonum())?one:zero;
|
ctx.top[0] = (val1.tonum()==val2.tonum())? one:zero;
|
||||||
} else {
|
} else {
|
||||||
ctx.top[0] = (val1==val2)?one:zero;
|
ctx.top[0] = (val1==val2)? one:zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,12 +488,12 @@ inline void vm::o_neq() {
|
||||||
if (val1.type==vm_nil && val2.type==vm_nil) {
|
if (val1.type==vm_nil && val2.type==vm_nil) {
|
||||||
ctx.top[0] = zero;
|
ctx.top[0] = zero;
|
||||||
} else if (val1.type==vm_str && val2.type==vm_str) {
|
} else if (val1.type==vm_str && val2.type==vm_str) {
|
||||||
ctx.top[0] = (val1.str()!=val2.str())?one:zero;
|
ctx.top[0] = (val1.str()!=val2.str())? one:zero;
|
||||||
} else if ((val1.type==vm_num || val2.type==vm_num)
|
} else if ((val1.type==vm_num || val2.type==vm_num)
|
||||||
&& val1.type!=vm_nil && val2.type!=vm_nil) {
|
&& val1.type!=vm_nil && val2.type!=vm_nil) {
|
||||||
ctx.top[0] = (val1.tonum()!=val2.tonum())?one:zero;
|
ctx.top[0] = (val1.tonum()!=val2.tonum())? one:zero;
|
||||||
} else {
|
} else {
|
||||||
ctx.top[0] = (val1!=val2)?one:zero;
|
ctx.top[0] = (val1!=val2)? one:zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,7 +609,9 @@ inline void vm::o_callv() {
|
||||||
die("out of range:"+std::to_string(val.tonum()));
|
die("out of range:"+std::to_string(val.tonum()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx.top[0] = var::num(f64((u8)str[num>=0? num:num+len]));
|
ctx.top[0] = var::num(
|
||||||
|
static_cast<f64>(static_cast<u8>(str[num>=0? num:num+len]))
|
||||||
|
);
|
||||||
} else if (vec.type==vm_map) {
|
} else if (vec.type==vm_map) {
|
||||||
if (val.type!=vm_str) {
|
if (val.type!=vm_str) {
|
||||||
die("must use string as the key");
|
die("must use string as the key");
|
||||||
|
|
|
@ -32,11 +32,11 @@ void optimizer::const_number(
|
||||||
case binary_operator::binary_type::grt: res = left>right; break;
|
case binary_operator::binary_type::grt: res = left>right; break;
|
||||||
case binary_operator::binary_type::geq: res = left>=right; break;
|
case binary_operator::binary_type::geq: res = left>=right; break;
|
||||||
case binary_operator::binary_type::bitwise_or:
|
case binary_operator::binary_type::bitwise_or:
|
||||||
res = i32(left)|i32(right); break;
|
res = static_cast<i32>(left)|static_cast<i32>(right); break;
|
||||||
case binary_operator::binary_type::bitwise_xor:
|
case binary_operator::binary_type::bitwise_xor:
|
||||||
res = i32(left)^i32(right); break;
|
res = static_cast<i32>(left)^static_cast<i32>(right); break;
|
||||||
case binary_operator::binary_type::bitwise_and:
|
case binary_operator::binary_type::bitwise_and:
|
||||||
res = i32(left)&i32(right); break;
|
res = static_cast<i32>(left)&static_cast<i32>(right); break;
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
if (std::isinf(res) || std::isnan(res)) {
|
if (std::isinf(res) || std::isnan(res)) {
|
||||||
|
@ -51,9 +51,12 @@ void optimizer::const_number(
|
||||||
number_literal* value_node) {
|
number_literal* value_node) {
|
||||||
auto res = value_node->get_number();
|
auto res = value_node->get_number();
|
||||||
switch(node->get_operator_type()) {
|
switch(node->get_operator_type()) {
|
||||||
case unary_operator::unary_type::negative: res = -res; break;
|
case unary_operator::unary_type::negative:
|
||||||
case unary_operator::unary_type::bitwise_not: res = ~i32(res); break;
|
res = -res; break;
|
||||||
case unary_operator::unary_type::logical_not: res = !res; break;
|
case unary_operator::unary_type::bitwise_not:
|
||||||
|
res = ~static_cast<i32>(res); break;
|
||||||
|
case unary_operator::unary_type::logical_not:
|
||||||
|
res = !res; break;
|
||||||
}
|
}
|
||||||
if (std::isinf(res) || std::isnan(res)) {
|
if (std::isinf(res) || std::isnan(res)) {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue