🧑‍💻 add important symbol "globals"

This commit is contained in:
ValKmjolnir 2023-07-06 22:10:07 +08:00
parent eca6141408
commit b4482792c8
11 changed files with 381 additions and 243 deletions

View File

@ -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

View File

@ -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;
} }

View File

@ -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

View File

@ -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) {}

View File

@ -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[]={

View File

@ -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;

View File

@ -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:

View File

@ -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,

View File

@ -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;

15
test/globals_test.nas Normal file
View File

@ -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();

View File

@ -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"){