🧑💻 add important symbol "globals"
This commit is contained in:
parent
eca6141408
commit
b4482792c8
1
makefile
1
makefile
|
@ -100,6 +100,7 @@ test:nasal
|
||||||
-@ ./nasal -d test/exception.nas
|
-@ ./nasal -d test/exception.nas
|
||||||
@ ./nasal -t -d test/fib.nas
|
@ ./nasal -t -d test/fib.nas
|
||||||
@ ./nasal -e test/filesystem.nas
|
@ ./nasal -e test/filesystem.nas
|
||||||
|
@ ./nasal -t -d test/globals_test.nas
|
||||||
@ ./nasal -d test/hexdump.nas
|
@ ./nasal -d test/hexdump.nas
|
||||||
@ ./nasal -e test/json.nas
|
@ ./nasal -e test/json.nas
|
||||||
@ ./nasal -e test/leetcode1319.nas
|
@ ./nasal -e test/leetcode1319.nas
|
||||||
|
|
|
@ -334,15 +334,21 @@ var builtin_delete(var* local, gc& ngc) {
|
||||||
|
|
||||||
var builtin_keys(var* local, gc& ngc) {
|
var builtin_keys(var* local, gc& ngc) {
|
||||||
var hash=local[1];
|
var hash=local[1];
|
||||||
if (hash.type!=vm_hash) {
|
if (hash.type!=vm_hash && hash.type!=vm_map) {
|
||||||
return nas_err("keys", "\"hash\" must be hash");
|
return nas_err("keys", "\"hash\" must be hash");
|
||||||
}
|
}
|
||||||
// avoid being sweeped
|
// avoid being sweeped
|
||||||
var res=ngc.temp=ngc.alloc(vm_vec);
|
var res=ngc.temp=ngc.alloc(vm_vec);
|
||||||
auto& vec=res.vec().elems;
|
auto& vec=res.vec().elems;
|
||||||
for(auto& iter:hash.hash().elems) {
|
if (hash.type==vm_hash) {
|
||||||
|
for(const auto& iter : hash.hash().elems) {
|
||||||
vec.push_back(ngc.newstr(iter.first));
|
vec.push_back(ngc.newstr(iter.first));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for(const auto& iter : hash.map().mapper) {
|
||||||
|
vec.push_back(ngc.newstr(iter.first));
|
||||||
|
}
|
||||||
|
}
|
||||||
ngc.temp=nil;
|
ngc.temp=nil;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -372,6 +378,7 @@ var builtin_type(var* local, gc& ngc) {
|
||||||
case vm_func: return ngc.newstr("func"); break;
|
case vm_func: return ngc.newstr("func"); break;
|
||||||
case vm_obj: return ngc.newstr("obj"); break;
|
case vm_obj: return ngc.newstr("obj"); break;
|
||||||
case vm_co: return ngc.newstr("coroutine");break;
|
case vm_co: return ngc.newstr("coroutine");break;
|
||||||
|
case vm_map: return ngc.newstr("mapper"); break;
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1091,6 +1091,7 @@ const error& codegen::compile(parse& parse, linker& import) {
|
||||||
fileindex = 0;
|
fileindex = 0;
|
||||||
file = import.filelist().data();
|
file = import.filelist().data();
|
||||||
in_iterloop.push(0);
|
in_iterloop.push(0);
|
||||||
|
add_symbol("globals");
|
||||||
find_symbol(parse.tree()); // search symbols first
|
find_symbol(parse.tree()); // search symbols first
|
||||||
gen(op_intg, global.size(), 0);
|
gen(op_intg, global.size(), 0);
|
||||||
block_gen(parse.tree()); // generate main block
|
block_gen(parse.tree()); // generate main block
|
||||||
|
|
|
@ -97,6 +97,7 @@ public:
|
||||||
const std::vector<std::string>& strs() const {return const_string_table;}
|
const std::vector<std::string>& strs() const {return const_string_table;}
|
||||||
const std::vector<f64>& nums() const {return const_number_table;}
|
const std::vector<f64>& nums() const {return const_number_table;}
|
||||||
const std::vector<opcode>& codes() const {return code;}
|
const std::vector<opcode>& codes() const {return code;}
|
||||||
|
const std::unordered_map<std::string, i32>& globals() const {return global;}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
codegen(error& e): fileindex(0), err(e), file(nullptr) {}
|
codegen(error& e): fileindex(0), err(e), file(nullptr) {}
|
||||||
|
|
|
@ -163,7 +163,12 @@ void dbg::run(
|
||||||
const std::vector<std::string>& argv) {
|
const std::vector<std::string>& argv) {
|
||||||
verbose=true;
|
verbose=true;
|
||||||
fsize=linker.filelist().size();
|
fsize=linker.filelist().size();
|
||||||
init(gen.strs(), gen.nums(), gen.codes(), linker.filelist(), argv);
|
init(gen.strs(),
|
||||||
|
gen.nums(),
|
||||||
|
gen.codes(),
|
||||||
|
gen.globals(),
|
||||||
|
linker.filelist(),
|
||||||
|
argv);
|
||||||
u64 count[op_ret+1]={0};
|
u64 count[op_ret+1]={0};
|
||||||
typedef void (dbg::*nafunc)();
|
typedef void (dbg::*nafunc)();
|
||||||
const nafunc oprs[]={
|
const nafunc oprs[]={
|
||||||
|
|
|
@ -153,6 +153,35 @@ void nas_co::clear() {
|
||||||
status = coroutine_status::suspended;
|
status = coroutine_status::suspended;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var nas_map::get_val(const std::string& key) {
|
||||||
|
if (mapper.count(key)) {
|
||||||
|
return *mapper.at(key);
|
||||||
|
}
|
||||||
|
return var::none();
|
||||||
|
}
|
||||||
|
|
||||||
|
var* nas_map::get_mem(const std::string& key) {
|
||||||
|
if (mapper.count(key)) {
|
||||||
|
return mapper.at(key);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, nas_map& mp) {
|
||||||
|
if (!mp.mapper.size() || mp.printed) {
|
||||||
|
out << (mp.mapper.size()? "{..}":"{}");
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
mp.printed = true;
|
||||||
|
usize iter = 0, size = mp.mapper.size();
|
||||||
|
out << "{";
|
||||||
|
for(auto& i : mp.mapper) {
|
||||||
|
out << i.first << ":" << *i.second << ",}"[(++iter)==size];
|
||||||
|
}
|
||||||
|
mp.printed = false;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
nas_val::nas_val(u8 val_type) {
|
nas_val::nas_val(u8 val_type) {
|
||||||
mark = gc_status::collected;
|
mark = gc_status::collected;
|
||||||
type = val_type;
|
type = val_type;
|
||||||
|
@ -165,6 +194,7 @@ nas_val::nas_val(u8 val_type) {
|
||||||
case vm_upval: ptr.upval = new nas_upval; break;
|
case vm_upval: ptr.upval = new nas_upval; break;
|
||||||
case vm_obj: ptr.obj = new nas_ghost; break;
|
case vm_obj: ptr.obj = new nas_ghost; break;
|
||||||
case vm_co: ptr.co = new nas_co; break;
|
case vm_co: ptr.co = new nas_co; break;
|
||||||
|
case vm_map: ptr.map = new nas_map; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,6 +207,7 @@ nas_val::~nas_val() {
|
||||||
case vm_upval:delete ptr.upval;break;
|
case vm_upval:delete ptr.upval;break;
|
||||||
case vm_obj: delete ptr.obj; break;
|
case vm_obj: delete ptr.obj; break;
|
||||||
case vm_co: delete ptr.co; break;
|
case vm_co: delete ptr.co; break;
|
||||||
|
case vm_map: delete ptr.map; break;
|
||||||
}
|
}
|
||||||
type=vm_nil;
|
type=vm_nil;
|
||||||
}
|
}
|
||||||
|
@ -190,6 +221,7 @@ void nas_val::clear() {
|
||||||
case vm_upval:ptr.upval->clear(); break;
|
case vm_upval:ptr.upval->clear(); break;
|
||||||
case vm_obj: ptr.obj->clear(); break;
|
case vm_obj: ptr.obj->clear(); break;
|
||||||
case vm_co: ptr.co->clear(); break;
|
case vm_co: ptr.co->clear(); break;
|
||||||
|
case vm_map: ptr.map->clear(); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,6 +252,7 @@ std::ostream& operator<<(std::ostream& out, var& ref) {
|
||||||
case vm_func: out << "func(..) {..}"; break;
|
case vm_func: out << "func(..) {..}"; break;
|
||||||
case vm_obj: out << ref.obj(); break;
|
case vm_obj: out << ref.obj(); break;
|
||||||
case vm_co: out << "<coroutine>"; break;
|
case vm_co: out << "<coroutine>"; break;
|
||||||
|
case vm_map: out << ref.map(); break;
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -300,6 +333,10 @@ nas_co& var::co() {
|
||||||
return *val.gcobj->ptr.co;
|
return *val.gcobj->ptr.co;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nas_map& var::map() {
|
||||||
|
return *val.gcobj->ptr.map;
|
||||||
|
}
|
||||||
|
|
||||||
void gc::mark() {
|
void gc::mark() {
|
||||||
std::vector<var> bfs;
|
std::vector<var> bfs;
|
||||||
mark_context(bfs);
|
mark_context(bfs);
|
||||||
|
@ -345,6 +382,7 @@ void gc::mark_var(std::vector<var>& bfs_queue, var& value) {
|
||||||
case vm_func: mark_func(bfs_queue, value.func()); break;
|
case vm_func: mark_func(bfs_queue, value.func()); break;
|
||||||
case vm_upval: mark_upval(bfs_queue, value.upval()); break;
|
case vm_upval: mark_upval(bfs_queue, value.upval()); break;
|
||||||
case vm_co: mark_co(bfs_queue, value.co()); break;
|
case vm_co: mark_co(bfs_queue, value.co()); break;
|
||||||
|
case vm_map: mark_map(bfs_queue, value.map()); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,6 +422,12 @@ void gc::mark_co(std::vector<var>& bfs_queue, nas_co& co) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gc::mark_map(std::vector<var>& bfs_queue, nas_map& mp) {
|
||||||
|
for(const auto& i : mp.mapper) {
|
||||||
|
bfs_queue.push_back(*i.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void gc::sweep() {
|
void gc::sweep() {
|
||||||
for(auto i : memory) {
|
for(auto i : memory) {
|
||||||
if (i->mark==gc_status::uncollected) {
|
if (i->mark==gc_status::uncollected) {
|
||||||
|
@ -469,7 +513,8 @@ void gc::info() {
|
||||||
"function ",
|
"function ",
|
||||||
"upvalue ",
|
"upvalue ",
|
||||||
"object ",
|
"object ",
|
||||||
"coroutine"
|
"coroutine",
|
||||||
|
"mapper "
|
||||||
};
|
};
|
||||||
|
|
||||||
usize indent = 0;
|
usize indent = 0;
|
||||||
|
|
|
@ -47,10 +47,11 @@ enum vm_type:u8 {
|
||||||
vm_func,
|
vm_func,
|
||||||
vm_upval,
|
vm_upval,
|
||||||
vm_obj,
|
vm_obj,
|
||||||
vm_co
|
vm_co,
|
||||||
|
vm_map // for globals, arg
|
||||||
};
|
};
|
||||||
|
|
||||||
const u32 gc_type_size = vm_co-vm_str+1;
|
const u32 gc_type_size = vm_map-vm_str+1;
|
||||||
|
|
||||||
enum class coroutine_status:u32 {
|
enum class coroutine_status:u32 {
|
||||||
suspended,
|
suspended,
|
||||||
|
@ -70,6 +71,7 @@ struct nas_func; // function(lambda)
|
||||||
struct nas_upval; // upvalue
|
struct nas_upval; // upvalue
|
||||||
struct nas_ghost; // objects
|
struct nas_ghost; // objects
|
||||||
struct nas_co; // coroutine
|
struct nas_co; // coroutine
|
||||||
|
struct nas_map; // mapper
|
||||||
struct nas_val; // nas_val includes gc-managed types
|
struct nas_val; // nas_val includes gc-managed types
|
||||||
|
|
||||||
struct var {
|
struct var {
|
||||||
|
@ -127,6 +129,7 @@ public:
|
||||||
nas_upval& upval();
|
nas_upval& upval();
|
||||||
nas_ghost& obj();
|
nas_ghost& obj();
|
||||||
nas_co& co();
|
nas_co& co();
|
||||||
|
nas_map& map();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_vec {
|
struct nas_vec {
|
||||||
|
@ -295,6 +298,19 @@ struct nas_co {
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct nas_map {
|
||||||
|
bool printed = false;
|
||||||
|
std::unordered_map<std::string, var*> mapper;
|
||||||
|
|
||||||
|
nas_map() {}
|
||||||
|
void clear() {
|
||||||
|
mapper.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
var get_val(const std::string&);
|
||||||
|
var* get_mem(const std::string&);
|
||||||
|
};
|
||||||
|
|
||||||
struct nas_val {
|
struct nas_val {
|
||||||
gc_status mark;
|
gc_status mark;
|
||||||
u8 type; // value type
|
u8 type; // value type
|
||||||
|
@ -307,6 +323,7 @@ struct nas_val {
|
||||||
nas_upval* upval;
|
nas_upval* upval;
|
||||||
nas_ghost* obj;
|
nas_ghost* obj;
|
||||||
nas_co* co;
|
nas_co* co;
|
||||||
|
nas_map* map;
|
||||||
} ptr;
|
} ptr;
|
||||||
|
|
||||||
nas_val(u8);
|
nas_val(u8);
|
||||||
|
@ -316,6 +333,7 @@ struct nas_val {
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream&, nas_vec&);
|
std::ostream& operator<<(std::ostream&, nas_vec&);
|
||||||
std::ostream& operator<<(std::ostream&, nas_hash&);
|
std::ostream& operator<<(std::ostream&, nas_hash&);
|
||||||
|
std::ostream& operator<<(std::ostream&, nas_map&);
|
||||||
std::ostream& operator<<(std::ostream&, var&);
|
std::ostream& operator<<(std::ostream&, var&);
|
||||||
|
|
||||||
const var zero = var::num(0);
|
const var zero = var::num(0);
|
||||||
|
@ -348,7 +366,8 @@ struct gc {
|
||||||
128, // vm_func
|
128, // vm_func
|
||||||
256, // vm_upval
|
256, // vm_upval
|
||||||
16, // vm_obj
|
16, // vm_obj
|
||||||
16 // vm_co
|
16, // vm_co
|
||||||
|
2, // vm_map
|
||||||
};
|
};
|
||||||
|
|
||||||
/* values for analysis */
|
/* values for analysis */
|
||||||
|
@ -372,6 +391,7 @@ private:
|
||||||
void mark_func(std::vector<var>&, nas_func&);
|
void mark_func(std::vector<var>&, nas_func&);
|
||||||
void mark_upval(std::vector<var>&, nas_upval&);
|
void mark_upval(std::vector<var>&, nas_upval&);
|
||||||
void mark_co(std::vector<var>&, nas_co&);
|
void mark_co(std::vector<var>&, nas_co&);
|
||||||
|
void mark_map(std::vector<var>&, nas_map&);
|
||||||
void sweep();
|
void sweep();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -4,6 +4,7 @@ void vm::init(
|
||||||
const std::vector<std::string>& strs,
|
const std::vector<std::string>& strs,
|
||||||
const std::vector<f64>& nums,
|
const std::vector<f64>& nums,
|
||||||
const std::vector<opcode>& code,
|
const std::vector<opcode>& code,
|
||||||
|
const std::unordered_map<std::string, i32>& global,
|
||||||
const std::vector<std::string>& filenames,
|
const std::vector<std::string>& filenames,
|
||||||
const std::vector<std::string>& argv
|
const std::vector<std::string>& argv
|
||||||
) {
|
) {
|
||||||
|
@ -27,6 +28,13 @@ void vm::init(
|
||||||
|
|
||||||
/* init gc */
|
/* init gc */
|
||||||
ngc.init(strs,argv);
|
ngc.init(strs,argv);
|
||||||
|
|
||||||
|
/* init vm globals */
|
||||||
|
auto map_instance = ngc.alloc(vm_map);
|
||||||
|
stack[global.at("globals")] = map_instance;
|
||||||
|
for(const auto& i : global) {
|
||||||
|
map_instance.map().mapper[i.first] = stack+i.second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm::valinfo(var& val) {
|
void vm::valinfo(var& val) {
|
||||||
|
@ -204,7 +212,12 @@ void vm::run(
|
||||||
const bool detail
|
const bool detail
|
||||||
) {
|
) {
|
||||||
verbose=detail;
|
verbose=detail;
|
||||||
init(gen.strs(), gen.nums(), gen.codes(), linker.filelist(), argv);
|
init(gen.strs(),
|
||||||
|
gen.nums(),
|
||||||
|
gen.codes(),
|
||||||
|
gen.globals(),
|
||||||
|
linker.filelist(),
|
||||||
|
argv);
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
const void* oprs[]={
|
const void* oprs[]={
|
||||||
&&vmexit, &&intg, &&intl, &&loadg,
|
&&vmexit, &&intg, &&intl, &&loadg,
|
||||||
|
|
|
@ -39,6 +39,7 @@ protected:
|
||||||
const std::vector<std::string>&,
|
const std::vector<std::string>&,
|
||||||
const std::vector<f64>&,
|
const std::vector<f64>&,
|
||||||
const std::vector<opcode>&,
|
const std::vector<opcode>&,
|
||||||
|
const std::unordered_map<std::string, i32>&,
|
||||||
const std::vector<std::string>&,
|
const std::vector<std::string>&,
|
||||||
const std::vector<std::string>&);
|
const std::vector<std::string>&);
|
||||||
|
|
||||||
|
@ -155,8 +156,7 @@ public:
|
||||||
const codegen&,
|
const codegen&,
|
||||||
const linker&,
|
const linker&,
|
||||||
const std::vector<std::string>&,
|
const std::vector<std::string>&,
|
||||||
const bool
|
const bool);
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool vm::cond(var& val) {
|
inline bool vm::cond(var& val) {
|
||||||
|
@ -172,7 +172,8 @@ inline bool vm::cond(var& val) {
|
||||||
inline void vm::o_intg() {
|
inline void vm::o_intg() {
|
||||||
// global values store on stack
|
// global values store on stack
|
||||||
ctx.top += imm[ctx.pc];
|
ctx.top += imm[ctx.pc];
|
||||||
--ctx.top;// point to the top
|
// point to the top
|
||||||
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_intl() {
|
inline void vm::o_intl() {
|
||||||
|
@ -223,7 +224,7 @@ inline void vm::o_newh() {
|
||||||
|
|
||||||
inline void vm::o_newf() {
|
inline void vm::o_newf() {
|
||||||
(++ctx.top)[0] = ngc.alloc(vm_func);
|
(++ctx.top)[0] = ngc.alloc(vm_func);
|
||||||
nas_func& func=ctx.top[0].func();
|
auto& func = ctx.top[0].func();
|
||||||
func.entry = imm[ctx.pc];
|
func.entry = imm[ctx.pc];
|
||||||
func.psize = 1;
|
func.psize = 1;
|
||||||
|
|
||||||
|
@ -246,7 +247,7 @@ inline void vm::o_happ() {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_para() {
|
inline void vm::o_para() {
|
||||||
nas_func& func=ctx.top[0].func();
|
auto& func = ctx.top[0].func();
|
||||||
// func->size has 1 place reserved for "me"
|
// func->size has 1 place reserved for "me"
|
||||||
func.keys[imm[ctx.pc]] = func.psize;
|
func.keys[imm[ctx.pc]] = func.psize;
|
||||||
func.local[func.psize++] = var::none();
|
func.local[func.psize++] = var::none();
|
||||||
|
@ -254,7 +255,7 @@ inline void vm::o_para() {
|
||||||
|
|
||||||
inline void vm::o_deft() {
|
inline void vm::o_deft() {
|
||||||
var val = ctx.top[0];
|
var val = ctx.top[0];
|
||||||
nas_func& func=(--ctx.top)[0].func();
|
auto& func = (--ctx.top)[0].func();
|
||||||
// func->size has 1 place reserved for "me"
|
// func->size has 1 place reserved for "me"
|
||||||
func.keys[imm[ctx.pc]] = func.psize;
|
func.keys[imm[ctx.pc]] = func.psize;
|
||||||
func.local[func.psize++] = val;
|
func.local[func.psize++] = val;
|
||||||
|
@ -277,10 +278,9 @@ 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");
|
die("incorrect value type");
|
||||||
return;
|
return;
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,17 +293,23 @@ inline void vm::o_bnot() {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_btor() {
|
inline void vm::o_btor() {
|
||||||
ctx.top[-1]=var::num(static_cast<int32_t>(ctx.top[-1].tonum())|static_cast<int32_t>(ctx.top[0].tonum()));
|
ctx.top[-1] = var::num(
|
||||||
|
static_cast<int32_t>(ctx.top[-1].tonum())|
|
||||||
|
static_cast<int32_t>(ctx.top[0].tonum()));
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_btxor() {
|
inline void vm::o_btxor() {
|
||||||
ctx.top[-1]=var::num(static_cast<int32_t>(ctx.top[-1].tonum())^static_cast<int32_t>(ctx.top[0].tonum()));
|
ctx.top[-1] = var::num(
|
||||||
|
static_cast<int32_t>(ctx.top[-1].tonum())^
|
||||||
|
static_cast<int32_t>(ctx.top[0].tonum()));
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_btand() {
|
inline void vm::o_btand() {
|
||||||
ctx.top[-1]=var::num(static_cast<int32_t>(ctx.top[-1].tonum())&static_cast<int32_t>(ctx.top[0].tonum()));
|
ctx.top[-1] = var::num(
|
||||||
|
static_cast<int32_t>(ctx.top[-1].tonum())&
|
||||||
|
static_cast<int32_t>(ctx.top[0].tonum()));
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,6 +562,16 @@ inline void vm::o_callv() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx.top[0] = var::num(f64((u8)str[num>=0? num:num+len]));
|
ctx.top[0] = var::num(f64((u8)str[num>=0? num:num+len]));
|
||||||
|
} else if (vec.type==vm_map) {
|
||||||
|
if (val.type!=vm_str) {
|
||||||
|
die("must use string as the key");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx.top[0] = vec.map().get_val(val.str());
|
||||||
|
if (ctx.top[0].type==vm_none) {
|
||||||
|
die("cannot find symbol \""+val.str()+"\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
die("must call a vector/hash/string");
|
die("must call a vector/hash/string");
|
||||||
return;
|
return;
|
||||||
|
@ -578,13 +594,20 @@ inline void vm::o_callvi() {
|
||||||
|
|
||||||
inline void vm::o_callh() {
|
inline void vm::o_callh() {
|
||||||
var val = ctx.top[0];
|
var val = ctx.top[0];
|
||||||
if (val.type!=vm_hash) {
|
if (val.type!=vm_hash && val.type!=vm_map) {
|
||||||
die("must call a hash");
|
die("must call a hash");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx.top[0]=val.hash().get_val(cstr[imm[ctx.pc]]);
|
const auto& str = cstr[imm[ctx.pc]];
|
||||||
|
if (val.type==vm_hash) {
|
||||||
|
ctx.top[0] = val.hash().get_val(str);
|
||||||
|
} else {
|
||||||
|
ctx.top[0] = val.map().get_val(str);
|
||||||
|
}
|
||||||
if (ctx.top[0].type==vm_none) {
|
if (ctx.top[0].type==vm_none) {
|
||||||
die("member \""+cstr[imm[ctx.pc]]+"\" does not exist");
|
val.type==vm_hash?
|
||||||
|
die("member \"" + str + "\" does not exist"):
|
||||||
|
die("cannot find symbol \"" + str + "\"");
|
||||||
return;
|
return;
|
||||||
} else if (ctx.top[0].type==vm_func) {
|
} else if (ctx.top[0].type==vm_func) {
|
||||||
ctx.top[0].func().local[0] = val; // 'me'
|
ctx.top[0].func().local[0] = val; // 'me'
|
||||||
|
@ -676,7 +699,7 @@ inline void vm::o_callfh() {
|
||||||
local[i] = func.local[i];
|
local[i] = func.local[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& i:func.keys) {
|
for(const auto& i : func.keys) {
|
||||||
auto& key = cstr[i.first];
|
auto& key = cstr[i.first];
|
||||||
if (hash.count(key)) {
|
if (hash.count(key)) {
|
||||||
local[i.second] = hash[key];
|
local[i.second] = hash[key];
|
||||||
|
@ -786,7 +809,10 @@ inline void vm::o_mcalll() {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_mupval() {
|
inline void vm::o_mupval() {
|
||||||
ctx.memr=&(ctx.funcr.func().upval[(imm[ctx.pc]>>16)&0xffff].upval()[imm[ctx.pc]&0xffff]);
|
ctx.memr = &(
|
||||||
|
ctx.funcr.func()
|
||||||
|
.upval[(imm[ctx.pc]>>16)&0xffff]
|
||||||
|
.upval()[imm[ctx.pc]&0xffff]);
|
||||||
(++ctx.top)[0] = ctx.memr[0];
|
(++ctx.top)[0] = ctx.memr[0];
|
||||||
// push value in this memory space on stack
|
// push value in this memory space on stack
|
||||||
// to avoid being garbage collected
|
// to avoid being garbage collected
|
||||||
|
@ -813,6 +839,17 @@ inline void vm::o_mcallv() {
|
||||||
ref.elems[str] = nil;
|
ref.elems[str] = nil;
|
||||||
ctx.memr = ref.get_mem(str);
|
ctx.memr = ref.get_mem(str);
|
||||||
}
|
}
|
||||||
|
} else if (vec.type==vm_map) {
|
||||||
|
if (val.type!=vm_str) {
|
||||||
|
die("key must be string");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto& ref = vec.map();
|
||||||
|
auto& str = val.str();
|
||||||
|
ctx.memr = ref.get_mem(str);
|
||||||
|
if (!ctx.memr) {
|
||||||
|
die("cannot find symbol \"" + str + "\"");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
die("cannot get memory space in this type");
|
die("cannot get memory space in this type");
|
||||||
return;
|
return;
|
||||||
|
@ -821,12 +858,19 @@ inline void vm::o_mcallv() {
|
||||||
|
|
||||||
inline void vm::o_mcallh() {
|
inline void vm::o_mcallh() {
|
||||||
var hash = ctx.top[0]; // mcall hash, reserved on stack to avoid gc
|
var hash = ctx.top[0]; // mcall hash, reserved on stack to avoid gc
|
||||||
if (hash.type!=vm_hash) {
|
if (hash.type!=vm_hash && hash.type!=vm_map) {
|
||||||
die("must call a hash");
|
die("must call a hash");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& ref=hash.hash();
|
|
||||||
auto& str = cstr[imm[ctx.pc]];
|
auto& str = cstr[imm[ctx.pc]];
|
||||||
|
if (hash.type==vm_map) {
|
||||||
|
ctx.memr = hash.map().get_mem(str);
|
||||||
|
if (!ctx.memr) {
|
||||||
|
die("cannot find symbol \"" + str + "\"");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto& ref = hash.hash();
|
||||||
ctx.memr = ref.get_mem(str);
|
ctx.memr = ref.get_mem(str);
|
||||||
if (!ctx.memr) { // create a new key
|
if (!ctx.memr) { // create a new key
|
||||||
ref.elems[str] = nil;
|
ref.elems[str] = nil;
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# test if globals run correctly
|
||||||
|
|
||||||
|
println(globals);
|
||||||
|
println(keys(globals));
|
||||||
|
foreach(var i; keys(globals)) {
|
||||||
|
println("var ", i, " = ", typeof(globals[i]), ";");
|
||||||
|
}
|
||||||
|
|
||||||
|
var test_func = nil;
|
||||||
|
globals.test_func = func() {
|
||||||
|
println("succeed!");
|
||||||
|
}
|
||||||
|
println();
|
||||||
|
println(globals.test_func);
|
||||||
|
globals.test_func();
|
|
@ -1,5 +1,6 @@
|
||||||
# hexdump.nas by ValKmjolnir
|
# hexdump.nas by ValKmjolnir
|
||||||
# 2021/8/13
|
# 2021/8/13
|
||||||
|
import.std.file;
|
||||||
|
|
||||||
# init
|
# init
|
||||||
var hex=func(){
|
var hex=func(){
|
||||||
|
@ -20,22 +21,7 @@ var hex=func(){
|
||||||
|
|
||||||
# read file
|
# read file
|
||||||
var s=func(){
|
var s=func(){
|
||||||
var filename=[
|
var filename = find_all_files_with_extension("./src","cpp","h");
|
||||||
"main.cpp",
|
|
||||||
"nasal_ast.h",
|
|
||||||
"nasal_builtin.h",
|
|
||||||
"nasal_codegen.h",
|
|
||||||
"nasal_dbg.h",
|
|
||||||
"nasal_err.h",
|
|
||||||
"nasal_gc.h",
|
|
||||||
"nasal_import.h",
|
|
||||||
"nasal_lexer.h",
|
|
||||||
"nasal_opt.h",
|
|
||||||
"nasal_parse.h",
|
|
||||||
"nasal_vm.h",
|
|
||||||
"nasal.ebnf",
|
|
||||||
"nasal.h"
|
|
||||||
];
|
|
||||||
if(size(runtime.argv())!=0){
|
if(size(runtime.argv())!=0){
|
||||||
var argv=runtime.argv();
|
var argv=runtime.argv();
|
||||||
if(argv[0]=="-h" or argv[0]=="--h"){
|
if(argv[0]=="-h" or argv[0]=="--h"){
|
||||||
|
|
Loading…
Reference in New Issue