🧑💻 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 -t -d test/fib.nas
|
||||
@ ./nasal -e test/filesystem.nas
|
||||
@ ./nasal -t -d test/globals_test.nas
|
||||
@ ./nasal -d test/hexdump.nas
|
||||
@ ./nasal -e test/json.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 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");
|
||||
}
|
||||
// avoid being sweeped
|
||||
var res=ngc.temp=ngc.alloc(vm_vec);
|
||||
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));
|
||||
}
|
||||
} else {
|
||||
for(const auto& iter : hash.map().mapper) {
|
||||
vec.push_back(ngc.newstr(iter.first));
|
||||
}
|
||||
}
|
||||
ngc.temp=nil;
|
||||
return res;
|
||||
}
|
||||
|
@ -372,6 +378,7 @@ var builtin_type(var* local, gc& ngc) {
|
|||
case vm_func: return ngc.newstr("func"); break;
|
||||
case vm_obj: return ngc.newstr("obj"); break;
|
||||
case vm_co: return ngc.newstr("coroutine");break;
|
||||
case vm_map: return ngc.newstr("mapper"); break;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
|
|
@ -1091,6 +1091,7 @@ const error& codegen::compile(parse& parse, linker& import) {
|
|||
fileindex = 0;
|
||||
file = import.filelist().data();
|
||||
in_iterloop.push(0);
|
||||
add_symbol("globals");
|
||||
find_symbol(parse.tree()); // search symbols first
|
||||
gen(op_intg, global.size(), 0);
|
||||
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<f64>& nums() const {return const_number_table;}
|
||||
const std::vector<opcode>& codes() const {return code;}
|
||||
const std::unordered_map<std::string, i32>& globals() const {return global;}
|
||||
|
||||
public:
|
||||
codegen(error& e): fileindex(0), err(e), file(nullptr) {}
|
||||
|
|
|
@ -163,7 +163,12 @@ void dbg::run(
|
|||
const std::vector<std::string>& argv) {
|
||||
verbose=true;
|
||||
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};
|
||||
typedef void (dbg::*nafunc)();
|
||||
const nafunc oprs[]={
|
||||
|
|
|
@ -153,6 +153,35 @@ void nas_co::clear() {
|
|||
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) {
|
||||
mark = gc_status::collected;
|
||||
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_obj: ptr.obj = new nas_ghost; 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_obj: delete ptr.obj; break;
|
||||
case vm_co: delete ptr.co; break;
|
||||
case vm_map: delete ptr.map; break;
|
||||
}
|
||||
type=vm_nil;
|
||||
}
|
||||
|
@ -190,6 +221,7 @@ void nas_val::clear() {
|
|||
case vm_upval:ptr.upval->clear(); break;
|
||||
case vm_obj: ptr.obj->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_obj: out << ref.obj(); break;
|
||||
case vm_co: out << "<coroutine>"; break;
|
||||
case vm_map: out << ref.map(); break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
@ -300,6 +333,10 @@ nas_co& var::co() {
|
|||
return *val.gcobj->ptr.co;
|
||||
}
|
||||
|
||||
nas_map& var::map() {
|
||||
return *val.gcobj->ptr.map;
|
||||
}
|
||||
|
||||
void gc::mark() {
|
||||
std::vector<var> 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_upval: mark_upval(bfs_queue, value.upval()); break;
|
||||
case vm_co: mark_co(bfs_queue, value.co()); break;
|
||||
case vm_map: mark_map(bfs_queue, value.map()); 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() {
|
||||
for(auto i : memory) {
|
||||
if (i->mark==gc_status::uncollected) {
|
||||
|
@ -469,7 +513,8 @@ void gc::info() {
|
|||
"function ",
|
||||
"upvalue ",
|
||||
"object ",
|
||||
"coroutine"
|
||||
"coroutine",
|
||||
"mapper "
|
||||
};
|
||||
|
||||
usize indent = 0;
|
||||
|
|
|
@ -47,10 +47,11 @@ enum vm_type:u8 {
|
|||
vm_func,
|
||||
vm_upval,
|
||||
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 {
|
||||
suspended,
|
||||
|
@ -70,6 +71,7 @@ struct nas_func; // function(lambda)
|
|||
struct nas_upval; // upvalue
|
||||
struct nas_ghost; // objects
|
||||
struct nas_co; // coroutine
|
||||
struct nas_map; // mapper
|
||||
struct nas_val; // nas_val includes gc-managed types
|
||||
|
||||
struct var {
|
||||
|
@ -127,6 +129,7 @@ public:
|
|||
nas_upval& upval();
|
||||
nas_ghost& obj();
|
||||
nas_co& co();
|
||||
nas_map& map();
|
||||
};
|
||||
|
||||
struct nas_vec {
|
||||
|
@ -295,6 +298,19 @@ struct nas_co {
|
|||
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 {
|
||||
gc_status mark;
|
||||
u8 type; // value type
|
||||
|
@ -307,6 +323,7 @@ struct nas_val {
|
|||
nas_upval* upval;
|
||||
nas_ghost* obj;
|
||||
nas_co* co;
|
||||
nas_map* map;
|
||||
} ptr;
|
||||
|
||||
nas_val(u8);
|
||||
|
@ -316,6 +333,7 @@ struct nas_val {
|
|||
|
||||
std::ostream& operator<<(std::ostream&, nas_vec&);
|
||||
std::ostream& operator<<(std::ostream&, nas_hash&);
|
||||
std::ostream& operator<<(std::ostream&, nas_map&);
|
||||
std::ostream& operator<<(std::ostream&, var&);
|
||||
|
||||
const var zero = var::num(0);
|
||||
|
@ -348,7 +366,8 @@ struct gc {
|
|||
128, // vm_func
|
||||
256, // vm_upval
|
||||
16, // vm_obj
|
||||
16 // vm_co
|
||||
16, // vm_co
|
||||
2, // vm_map
|
||||
};
|
||||
|
||||
/* values for analysis */
|
||||
|
@ -372,6 +391,7 @@ private:
|
|||
void mark_func(std::vector<var>&, nas_func&);
|
||||
void mark_upval(std::vector<var>&, nas_upval&);
|
||||
void mark_co(std::vector<var>&, nas_co&);
|
||||
void mark_map(std::vector<var>&, nas_map&);
|
||||
void sweep();
|
||||
|
||||
public:
|
||||
|
|
|
@ -4,6 +4,7 @@ void vm::init(
|
|||
const std::vector<std::string>& strs,
|
||||
const std::vector<f64>& nums,
|
||||
const std::vector<opcode>& code,
|
||||
const std::unordered_map<std::string, i32>& global,
|
||||
const std::vector<std::string>& filenames,
|
||||
const std::vector<std::string>& argv
|
||||
) {
|
||||
|
@ -27,6 +28,13 @@ void vm::init(
|
|||
|
||||
/* init gc */
|
||||
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) {
|
||||
|
@ -204,7 +212,12 @@ void vm::run(
|
|||
const bool 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
|
||||
const void* oprs[]={
|
||||
&&vmexit, &&intg, &&intl, &&loadg,
|
||||
|
|
|
@ -39,6 +39,7 @@ protected:
|
|||
const std::vector<std::string>&,
|
||||
const std::vector<f64>&,
|
||||
const std::vector<opcode>&,
|
||||
const std::unordered_map<std::string, i32>&,
|
||||
const std::vector<std::string>&,
|
||||
const std::vector<std::string>&);
|
||||
|
||||
|
@ -155,8 +156,7 @@ public:
|
|||
const codegen&,
|
||||
const linker&,
|
||||
const std::vector<std::string>&,
|
||||
const bool
|
||||
);
|
||||
const bool);
|
||||
};
|
||||
|
||||
inline bool vm::cond(var& val) {
|
||||
|
@ -172,7 +172,8 @@ inline bool vm::cond(var& val) {
|
|||
inline void vm::o_intg() {
|
||||
// global values store on stack
|
||||
ctx.top += imm[ctx.pc];
|
||||
--ctx.top;// point to the top
|
||||
// point to the top
|
||||
--ctx.top;
|
||||
}
|
||||
|
||||
inline void vm::o_intl() {
|
||||
|
@ -223,7 +224,7 @@ inline void vm::o_newh() {
|
|||
|
||||
inline void vm::o_newf() {
|
||||
(++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.psize = 1;
|
||||
|
||||
|
@ -246,7 +247,7 @@ inline void vm::o_happ() {
|
|||
}
|
||||
|
||||
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.keys[imm[ctx.pc]] = func.psize;
|
||||
func.local[func.psize++] = var::none();
|
||||
|
@ -254,7 +255,7 @@ inline void vm::o_para() {
|
|||
|
||||
inline void vm::o_deft() {
|
||||
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.keys[imm[ctx.pc]] = func.psize;
|
||||
func.local[func.psize++] = val;
|
||||
|
@ -277,10 +278,9 @@ inline void vm::o_lnot() {
|
|||
ctx.top[0] = num? zero:one;
|
||||
}
|
||||
} break;
|
||||
default:{
|
||||
default:
|
||||
die("incorrect value type");
|
||||
return;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,17 +293,23 @@ inline void vm::o_bnot() {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -556,6 +562,16 @@ inline void vm::o_callv() {
|
|||
return;
|
||||
}
|
||||
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 {
|
||||
die("must call a vector/hash/string");
|
||||
return;
|
||||
|
@ -578,13 +594,20 @@ inline void vm::o_callvi() {
|
|||
|
||||
inline void vm::o_callh() {
|
||||
var val = ctx.top[0];
|
||||
if (val.type!=vm_hash) {
|
||||
if (val.type!=vm_hash && val.type!=vm_map) {
|
||||
die("must call a hash");
|
||||
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) {
|
||||
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;
|
||||
} else if (ctx.top[0].type==vm_func) {
|
||||
ctx.top[0].func().local[0] = val; // 'me'
|
||||
|
@ -676,7 +699,7 @@ inline void vm::o_callfh() {
|
|||
local[i] = func.local[i];
|
||||
}
|
||||
|
||||
for(auto& i:func.keys) {
|
||||
for(const auto& i : func.keys) {
|
||||
auto& key = cstr[i.first];
|
||||
if (hash.count(key)) {
|
||||
local[i.second] = hash[key];
|
||||
|
@ -786,7 +809,10 @@ inline void vm::o_mcalll() {
|
|||
}
|
||||
|
||||
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];
|
||||
// push value in this memory space on stack
|
||||
// to avoid being garbage collected
|
||||
|
@ -813,6 +839,17 @@ inline void vm::o_mcallv() {
|
|||
ref.elems[str] = nil;
|
||||
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 {
|
||||
die("cannot get memory space in this type");
|
||||
return;
|
||||
|
@ -821,12 +858,19 @@ inline void vm::o_mcallv() {
|
|||
|
||||
inline void vm::o_mcallh() {
|
||||
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");
|
||||
return;
|
||||
}
|
||||
auto& ref=hash.hash();
|
||||
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);
|
||||
if (!ctx.memr) { // create a new key
|
||||
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
|
||||
# 2021/8/13
|
||||
import.std.file;
|
||||
|
||||
# init
|
||||
var hex=func(){
|
||||
|
@ -20,22 +21,7 @@ var hex=func(){
|
|||
|
||||
# read file
|
||||
var s=func(){
|
||||
var filename=[
|
||||
"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"
|
||||
];
|
||||
var filename = find_all_files_with_extension("./src","cpp","h");
|
||||
if(size(runtime.argv())!=0){
|
||||
var argv=runtime.argv();
|
||||
if(argv[0]=="-h" or argv[0]=="--h"){
|
||||
|
|
Loading…
Reference in New Issue