fully functional closure
This commit is contained in:
parent
e3f3bd7387
commit
35fc848672
|
@ -829,7 +829,7 @@ But in this new interpreter, it will get:
|
|||
[codegen] in <test.nas>: error(s) occurred,stop.
|
||||
```
|
||||
|
||||
This difference is caused by different kinds of ways of lexical analysis.
|
||||
(outdated)This difference is caused by different kinds of ways of lexical analysis.
|
||||
In most script language interpreters, they use dynamic analysis to check if this symbol is defined yet.
|
||||
However, this kind of analysis is at the cost of lower efficiency.
|
||||
To make sure the interpreter runs at higher efficiency, i choose static analysis to manage the memory space of each symbol.
|
||||
|
|
2
main.cpp
2
main.cpp
|
@ -115,7 +115,7 @@ void execute(std::string& file,std::string& command)
|
|||
}
|
||||
int main(int argc,const char* argv[])
|
||||
{
|
||||
std::string command,file="null";
|
||||
std::string command,file;
|
||||
if(argc==2 && (!strcmp(argv[1],"-v") || !strcmp(argv[1],"--version")))
|
||||
logo();
|
||||
else if(argc==2 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help")))
|
||||
|
|
13
nasal_gc.h
13
nasal_gc.h
|
@ -51,7 +51,7 @@ struct nasal_func// 120 bytes
|
|||
uint32_t entry; // pc will set to entry-1 to call this function
|
||||
std::vector<nasal_val*> default_para;// default value(nasal_val*)
|
||||
std::unordered_map<std::string,int> key_table;// parameter name hash
|
||||
std::vector<nasal_val*> closure;// closure will be loaded to gc.local.back() as the local scope
|
||||
nasal_val* closure;// closure will be loaded to gc.local.back() as the local scope
|
||||
|
||||
nasal_func();
|
||||
void clear();
|
||||
|
@ -214,7 +214,6 @@ void nasal_func::clear()
|
|||
dynpara=-1;
|
||||
default_para.clear();
|
||||
key_table.clear();
|
||||
closure.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -272,7 +271,7 @@ struct nasal_gc
|
|||
std::vector<nasal_val*> str_addrs; // reserved address for const vm_str
|
||||
std::vector<nasal_val*> memory; // gc memory
|
||||
std::queue <nasal_val*> free_list[vm_type_size]; // gc free list
|
||||
std::list<std::vector<nasal_val*>> local;
|
||||
std::vector<nasal_val*> local;
|
||||
void mark();
|
||||
void sweep();
|
||||
void gc_init(std::vector<double>&,std::vector<std::string>&);
|
||||
|
@ -285,9 +284,8 @@ struct nasal_gc
|
|||
void nasal_gc::mark()
|
||||
{
|
||||
std::queue<nasal_val*> bfs;
|
||||
for(auto& i:local)
|
||||
for(auto j:i)
|
||||
bfs.push(j);
|
||||
for(auto i:local)
|
||||
bfs.push(i);
|
||||
for(nasal_val** i=val_stack;i<=stack_top;++i)
|
||||
bfs.push(*i);
|
||||
while(!bfs.empty())
|
||||
|
@ -307,8 +305,7 @@ void nasal_gc::mark()
|
|||
bfs.push(i.second);
|
||||
break;
|
||||
case vm_func:
|
||||
for(auto i:tmp->ptr.func->closure)
|
||||
bfs.push(i);
|
||||
bfs.push(tmp->ptr.func->closure);
|
||||
for(auto i:tmp->ptr.func->default_para)
|
||||
if(i)
|
||||
bfs.push(i);
|
||||
|
|
38
nasal_vm.h
38
nasal_vm.h
|
@ -245,7 +245,12 @@ inline void nasal_vm::opr_intg()
|
|||
}
|
||||
inline void nasal_vm::opr_intl()
|
||||
{
|
||||
stack_top[0]->ptr.func->closure.resize(imm[pc],gc.nil_addr);
|
||||
auto& vec=stack_top[0]->ptr.func->closure->ptr.vec->elems;
|
||||
// if many functions share the same closure
|
||||
// resize will break the size of vector and cause exe_bad_access
|
||||
// so choose the maximum size as the size of this closure
|
||||
if(vec.size()<imm[pc])
|
||||
vec.resize(imm[pc],gc.nil_addr);
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_offset()
|
||||
|
@ -260,7 +265,7 @@ inline void nasal_vm::opr_loadg()
|
|||
}
|
||||
inline void nasal_vm::opr_loadl()
|
||||
{
|
||||
gc.local.back()[imm[pc]]=(stack_top--)[0];
|
||||
gc.local.back()->ptr.vec->elems[imm[pc]]=(stack_top--)[0];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_pnum()
|
||||
|
@ -309,8 +314,9 @@ inline void nasal_vm::opr_newf()
|
|||
{
|
||||
(++stack_top)[0]=gc.gc_alloc(vm_func);
|
||||
stack_top[0]->ptr.func->entry=imm[pc];
|
||||
stack_top[0]->ptr.func->closure=gc.nil_addr;
|
||||
if(gc.local.empty())
|
||||
stack_top[0]->ptr.func->closure.push_back(gc.nil_addr);// me
|
||||
stack_top[0]->ptr.func->closure=gc.gc_alloc(vm_vec);
|
||||
else
|
||||
stack_top[0]->ptr.func->closure=gc.local.back();// local contains 'me'
|
||||
return;
|
||||
|
@ -557,7 +563,7 @@ inline void nasal_vm::opr_callg()
|
|||
}
|
||||
inline void nasal_vm::opr_calll()
|
||||
{
|
||||
(++stack_top)[0]=gc.local.back()[imm[pc]];
|
||||
(++stack_top)[0]=gc.local.back()->ptr.vec->elems[imm[pc]];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_callv()
|
||||
|
@ -584,7 +590,7 @@ inline void nasal_vm::opr_callv()
|
|||
return;
|
||||
}
|
||||
if(stack_top[0]->type==vm_func)
|
||||
stack_top[0]->ptr.func->closure[0]=val;// me
|
||||
stack_top[0]->ptr.func->closure->ptr.vec->elems[0]=val;// me
|
||||
}
|
||||
else if(vec_addr->type==vm_str)
|
||||
{
|
||||
|
@ -632,7 +638,7 @@ inline void nasal_vm::opr_callh()
|
|||
return;
|
||||
}
|
||||
if(stack_top[0]->type==vm_func)
|
||||
stack_top[0]->ptr.func->closure[0]=val;// me
|
||||
stack_top[0]->ptr.func->closure->ptr.vec->elems[0]=val;// me
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_callfv()
|
||||
|
@ -648,10 +654,11 @@ inline void nasal_vm::opr_callfv()
|
|||
}
|
||||
// push new local scope
|
||||
auto& ref_func=*func_addr->ptr.func;
|
||||
gc.local.push_back(ref_func.closure);
|
||||
gc.local.push_back(gc.gc_alloc(vm_vec));
|
||||
gc.local.back()->ptr.vec->elems=ref_func.closure->ptr.vec->elems;
|
||||
// load parameters
|
||||
auto& ref_default=ref_func.default_para;
|
||||
auto& ref_closure=gc.local.back();
|
||||
auto& ref_closure=gc.local.back()->ptr.vec->elems;
|
||||
|
||||
uint32_t offset=ref_func.offset;
|
||||
uint32_t para_size=ref_func.key_table.size();
|
||||
|
@ -694,10 +701,11 @@ inline void nasal_vm::opr_callfh()
|
|||
}
|
||||
// push new local scope
|
||||
auto& ref_func=*func_addr->ptr.func;
|
||||
gc.local.push_back(ref_func.closure);
|
||||
gc.local.push_back(gc.gc_alloc(vm_vec));
|
||||
gc.local.back()->ptr.vec->elems=ref_func.closure->ptr.vec->elems;
|
||||
// load parameters
|
||||
auto& ref_default=ref_func.default_para;
|
||||
auto& ref_closure=gc.local.back();
|
||||
auto& ref_closure=gc.local.back()->ptr.vec->elems;
|
||||
|
||||
if(ref_func.dynpara>=0)
|
||||
{
|
||||
|
@ -725,7 +733,7 @@ inline void nasal_vm::opr_callfh()
|
|||
}
|
||||
inline void nasal_vm::opr_callb()
|
||||
{
|
||||
(++stack_top)[0]=(*builtin_func[imm[pc]].func)(gc.local.back(),gc);
|
||||
(++stack_top)[0]=(*builtin_func[imm[pc]].func)(gc.local.back()->ptr.vec->elems,gc);
|
||||
if(!stack_top[0])
|
||||
die("native function error.");
|
||||
return;
|
||||
|
@ -796,7 +804,7 @@ inline void nasal_vm::opr_mcallg()
|
|||
}
|
||||
inline void nasal_vm::opr_mcalll()
|
||||
{
|
||||
mem_addr=&gc.local.back()[imm[pc]];
|
||||
mem_addr=&(gc.local.back()->ptr.vec->elems[imm[pc]]);
|
||||
(++stack_top)[0]=mem_addr[0];
|
||||
return;
|
||||
}
|
||||
|
@ -851,9 +859,13 @@ inline void nasal_vm::opr_mcallh()
|
|||
}
|
||||
inline void nasal_vm::opr_ret()
|
||||
{
|
||||
auto& vec=stack_top[-1]->ptr.func->closure->ptr.vec->elems;
|
||||
for(uint32_t i=0;i<stack_top[-1]->ptr.func->offset;++i)
|
||||
vec[i]=gc.local.back()->ptr.vec->elems[i];
|
||||
vec[0]=gc.nil_addr;// set 'me' to nil
|
||||
gc.local.pop_back();// delete local scope
|
||||
pc=ret.top();ret.pop();// fetch pc
|
||||
(--stack_top)[0]->ptr.func->closure[0]=gc.nil_addr;// set 'me' to nil
|
||||
--stack_top;
|
||||
stack_top[0]=stack_top[1];// rewrite nasal_func with returned value
|
||||
return;
|
||||
}
|
||||
|
|
50
stl/list.nas
50
stl/list.nas
|
@ -2,65 +2,65 @@
|
|||
# valkmjolnir 2021/3/31
|
||||
var list=func()
|
||||
{
|
||||
var _={begin:nil,end:nil};
|
||||
var (begin,end)=(nil,nil);
|
||||
return
|
||||
{
|
||||
push_back:func(elem)
|
||||
{
|
||||
var tmp={elem:elem,prev:nil,next:nil};
|
||||
if(_.end!=nil)
|
||||
if(end!=nil)
|
||||
{
|
||||
_.end.next=tmp;
|
||||
tmp.prev=_.end;
|
||||
_.end=tmp;
|
||||
end.next=tmp;
|
||||
tmp.prev=end;
|
||||
end=tmp;
|
||||
}
|
||||
else
|
||||
_.begin=_.end=tmp;
|
||||
begin=end=tmp;
|
||||
return;
|
||||
},
|
||||
push_front:func(elem)
|
||||
{
|
||||
var tmp={elem:elem,prev:nil,next:nil};
|
||||
if(_.begin!=nil)
|
||||
if(begin!=nil)
|
||||
{
|
||||
_.begin.prev=tmp;
|
||||
tmp.next=_.begin;
|
||||
_.begin=tmp;
|
||||
begin.prev=tmp;
|
||||
tmp.next=begin;
|
||||
begin=tmp;
|
||||
}
|
||||
else
|
||||
_.begin=_.end=tmp;
|
||||
begin=end=tmp;
|
||||
return;
|
||||
},
|
||||
pop_back:func()
|
||||
{
|
||||
if(_.end!=nil)
|
||||
_.end=_.end.prev;
|
||||
if(_.end==nil)
|
||||
_.begin=nil;
|
||||
if(end!=nil)
|
||||
end=end.prev;
|
||||
if(end==nil)
|
||||
begin=nil;
|
||||
else
|
||||
_.end.next=nil;
|
||||
end.next=nil;
|
||||
return;
|
||||
},
|
||||
pop_front:func()
|
||||
{
|
||||
if(_.begin!=nil)
|
||||
_.begin=_.begin.next;
|
||||
if(_.begin==nil)
|
||||
_.end=nil;
|
||||
if(begin!=nil)
|
||||
begin=begin.next;
|
||||
if(begin==nil)
|
||||
end=nil;
|
||||
else
|
||||
_.begin.prev=nil;
|
||||
begin.prev=nil;
|
||||
return;
|
||||
},
|
||||
front:func()
|
||||
{
|
||||
if(_.begin!=nil)
|
||||
return _.begin.elem;
|
||||
if(begin!=nil)
|
||||
return begin.elem;
|
||||
return nil;
|
||||
},
|
||||
back:func()
|
||||
{
|
||||
if(_.end!=nil)
|
||||
return _.end.elem;
|
||||
if(end!=nil)
|
||||
return end.elem;
|
||||
return nil;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# valkmjolnir 2021/3/31
|
||||
var queue=func()
|
||||
{
|
||||
var _={begin:nil,end:nil};
|
||||
var (begin,end)=(nil,nil);
|
||||
return
|
||||
{
|
||||
push:func(elem)
|
||||
|
@ -12,35 +12,35 @@ var queue=func()
|
|||
elem:elem,
|
||||
next:nil
|
||||
};
|
||||
if(_.begin==nil)
|
||||
_.begin=_.end=new_node;
|
||||
if(begin==nil)
|
||||
begin=end=new_node;
|
||||
else
|
||||
{
|
||||
_.end.next=new_node;
|
||||
_.end=new_node;
|
||||
end.next=new_node;
|
||||
end=new_node;
|
||||
}
|
||||
return;
|
||||
},
|
||||
pop:func()
|
||||
{
|
||||
if(_.begin!=nil)
|
||||
_.begin=_.begin.next;
|
||||
if(_.begin==nil)
|
||||
_.end=nil;
|
||||
if(begin!=nil)
|
||||
begin=begin.next;
|
||||
if(begin==nil)
|
||||
end=nil;
|
||||
},
|
||||
front:func()
|
||||
{
|
||||
if(_.begin!=nil)
|
||||
return _.begin.elem;
|
||||
if(begin!=nil)
|
||||
return begin.elem;
|
||||
return nil;
|
||||
},
|
||||
clear:func()
|
||||
{
|
||||
_.begin=_.end=nil;
|
||||
begin=end=nil;
|
||||
},
|
||||
empty:func()
|
||||
{
|
||||
return _.begin==nil;
|
||||
return begin==nil;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,35 +2,35 @@
|
|||
# valkmjolnir 2021/3/31
|
||||
var stack=func()
|
||||
{
|
||||
var _={next:nil};
|
||||
var next=nil;
|
||||
return
|
||||
{
|
||||
push:func(elem)
|
||||
{
|
||||
_.next={elem:elem,next:_.next};
|
||||
next={elem:elem,next:next};
|
||||
return;
|
||||
},
|
||||
pop:func()
|
||||
{
|
||||
var tmp=_.next;
|
||||
var tmp=next;
|
||||
if(tmp!=nil)
|
||||
_.next=tmp.next;
|
||||
next=tmp.next;
|
||||
return;
|
||||
},
|
||||
top:func()
|
||||
{
|
||||
var tmp=_.next;
|
||||
var tmp=next;
|
||||
if(tmp!=nil)
|
||||
return tmp.elem;
|
||||
return nil;
|
||||
},
|
||||
clear:func()
|
||||
{
|
||||
_.next=nil;
|
||||
next=nil;
|
||||
},
|
||||
empty:func()
|
||||
{
|
||||
return _.next==nil;
|
||||
return next==nil;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
10
test/bfs.nas
10
test/bfs.nas
|
@ -3,6 +3,7 @@ import("stl/queue.nas");
|
|||
|
||||
rand(time(0));
|
||||
|
||||
var pixel=[' ','#','.','*'];
|
||||
var map=[];
|
||||
for(var i=0;i<10;i+=1)
|
||||
{
|
||||
|
@ -17,7 +18,7 @@ var prt=func()
|
|||
for(var i=0;i<10;i+=1)
|
||||
{
|
||||
for(var j=0;j<10;j+=1)
|
||||
s~=map[i][j];
|
||||
s~=pixel[map[i][j]];
|
||||
s~='\n';
|
||||
}
|
||||
s~='----------\n';
|
||||
|
@ -29,7 +30,7 @@ var bfs=func(begin,end)
|
|||
var move=[[1,0],[0,1],[-1,0],[0,-1]];
|
||||
var que=queue();
|
||||
que.push(begin);
|
||||
map[begin[0]][begin[1]]=3;
|
||||
map[begin[0]][begin[1]]=2;
|
||||
while(!que.empty())
|
||||
{
|
||||
var vertex=que.front();
|
||||
|
@ -40,13 +41,14 @@ var bfs=func(begin,end)
|
|||
var y=vertex[1]+i[1];
|
||||
if(x==end[0] and y==end[1])
|
||||
{
|
||||
map[x][y]='*';
|
||||
map[x][y]=3;
|
||||
prt();
|
||||
return;
|
||||
}
|
||||
if(0<=x and x<10 and 0<=y and y<10 and map[x][y]==0)
|
||||
{
|
||||
que.push([x,y]);
|
||||
map[x][y]=3;
|
||||
map[x][y]=2;
|
||||
}
|
||||
}
|
||||
prt();
|
||||
|
|
|
@ -2,16 +2,13 @@ import("lib.nas");
|
|||
|
||||
var student=func(name,age)
|
||||
{
|
||||
var val={
|
||||
name:name,
|
||||
age:age
|
||||
};
|
||||
var (n,a)=(name,age);
|
||||
return {
|
||||
print_info:func(){println(val.name,' ',val.age);},
|
||||
set_age: func(age){val.age=age;},
|
||||
get_age: func(){return val.age;},
|
||||
set_name: func(name){val.name=name;},
|
||||
get_name: func(){return val.name;}
|
||||
print_info:func println(n,' ',a),
|
||||
set_age: func(age) a=age,
|
||||
get_age: func return a,
|
||||
set_name: func(name) n=name,
|
||||
get_name: func return n
|
||||
};
|
||||
}
|
||||
var s=student('valk',24);
|
||||
|
|
|
@ -14,5 +14,5 @@ var fib=func(f){
|
|||
}
|
||||
);
|
||||
|
||||
for(var i=1;i<=20;i+=1)
|
||||
for(var i=1;i<31;i+=1)
|
||||
println(fib(i));
|
Loading…
Reference in New Issue