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.
|
[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.
|
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.
|
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.
|
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[])
|
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")))
|
if(argc==2 && (!strcmp(argv[1],"-v") || !strcmp(argv[1],"--version")))
|
||||||
logo();
|
logo();
|
||||||
else if(argc==2 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help")))
|
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
|
uint32_t entry; // pc will set to entry-1 to call this function
|
||||||
std::vector<nasal_val*> default_para;// default value(nasal_val*)
|
std::vector<nasal_val*> default_para;// default value(nasal_val*)
|
||||||
std::unordered_map<std::string,int> key_table;// parameter name hash
|
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();
|
nasal_func();
|
||||||
void clear();
|
void clear();
|
||||||
|
@ -214,7 +214,6 @@ void nasal_func::clear()
|
||||||
dynpara=-1;
|
dynpara=-1;
|
||||||
default_para.clear();
|
default_para.clear();
|
||||||
key_table.clear();
|
key_table.clear();
|
||||||
closure.clear();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +271,7 @@ struct nasal_gc
|
||||||
std::vector<nasal_val*> str_addrs; // reserved address for const vm_str
|
std::vector<nasal_val*> str_addrs; // reserved address for const vm_str
|
||||||
std::vector<nasal_val*> memory; // gc memory
|
std::vector<nasal_val*> memory; // gc memory
|
||||||
std::queue <nasal_val*> free_list[vm_type_size]; // gc free list
|
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 mark();
|
||||||
void sweep();
|
void sweep();
|
||||||
void gc_init(std::vector<double>&,std::vector<std::string>&);
|
void gc_init(std::vector<double>&,std::vector<std::string>&);
|
||||||
|
@ -285,9 +284,8 @@ struct nasal_gc
|
||||||
void nasal_gc::mark()
|
void nasal_gc::mark()
|
||||||
{
|
{
|
||||||
std::queue<nasal_val*> bfs;
|
std::queue<nasal_val*> bfs;
|
||||||
for(auto& i:local)
|
for(auto i:local)
|
||||||
for(auto j:i)
|
bfs.push(i);
|
||||||
bfs.push(j);
|
|
||||||
for(nasal_val** i=val_stack;i<=stack_top;++i)
|
for(nasal_val** i=val_stack;i<=stack_top;++i)
|
||||||
bfs.push(*i);
|
bfs.push(*i);
|
||||||
while(!bfs.empty())
|
while(!bfs.empty())
|
||||||
|
@ -307,8 +305,7 @@ void nasal_gc::mark()
|
||||||
bfs.push(i.second);
|
bfs.push(i.second);
|
||||||
break;
|
break;
|
||||||
case vm_func:
|
case vm_func:
|
||||||
for(auto i:tmp->ptr.func->closure)
|
bfs.push(tmp->ptr.func->closure);
|
||||||
bfs.push(i);
|
|
||||||
for(auto i:tmp->ptr.func->default_para)
|
for(auto i:tmp->ptr.func->default_para)
|
||||||
if(i)
|
if(i)
|
||||||
bfs.push(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()
|
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;
|
return;
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_offset()
|
inline void nasal_vm::opr_offset()
|
||||||
|
@ -260,7 +265,7 @@ inline void nasal_vm::opr_loadg()
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_loadl()
|
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;
|
return;
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_pnum()
|
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]=gc.gc_alloc(vm_func);
|
||||||
stack_top[0]->ptr.func->entry=imm[pc];
|
stack_top[0]->ptr.func->entry=imm[pc];
|
||||||
|
stack_top[0]->ptr.func->closure=gc.nil_addr;
|
||||||
if(gc.local.empty())
|
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
|
else
|
||||||
stack_top[0]->ptr.func->closure=gc.local.back();// local contains 'me'
|
stack_top[0]->ptr.func->closure=gc.local.back();// local contains 'me'
|
||||||
return;
|
return;
|
||||||
|
@ -557,7 +563,7 @@ inline void nasal_vm::opr_callg()
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_calll()
|
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;
|
return;
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_callv()
|
inline void nasal_vm::opr_callv()
|
||||||
|
@ -584,7 +590,7 @@ inline void nasal_vm::opr_callv()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(stack_top[0]->type==vm_func)
|
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)
|
else if(vec_addr->type==vm_str)
|
||||||
{
|
{
|
||||||
|
@ -632,7 +638,7 @@ inline void nasal_vm::opr_callh()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(stack_top[0]->type==vm_func)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_callfv()
|
inline void nasal_vm::opr_callfv()
|
||||||
|
@ -648,10 +654,11 @@ inline void nasal_vm::opr_callfv()
|
||||||
}
|
}
|
||||||
// push new local scope
|
// push new local scope
|
||||||
auto& ref_func=*func_addr->ptr.func;
|
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
|
// load parameters
|
||||||
auto& ref_default=ref_func.default_para;
|
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 offset=ref_func.offset;
|
||||||
uint32_t para_size=ref_func.key_table.size();
|
uint32_t para_size=ref_func.key_table.size();
|
||||||
|
@ -694,10 +701,11 @@ inline void nasal_vm::opr_callfh()
|
||||||
}
|
}
|
||||||
// push new local scope
|
// push new local scope
|
||||||
auto& ref_func=*func_addr->ptr.func;
|
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
|
// load parameters
|
||||||
auto& ref_default=ref_func.default_para;
|
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)
|
if(ref_func.dynpara>=0)
|
||||||
{
|
{
|
||||||
|
@ -725,7 +733,7 @@ inline void nasal_vm::opr_callfh()
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_callb()
|
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])
|
if(!stack_top[0])
|
||||||
die("native function error.");
|
die("native function error.");
|
||||||
return;
|
return;
|
||||||
|
@ -796,7 +804,7 @@ inline void nasal_vm::opr_mcallg()
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_mcalll()
|
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];
|
(++stack_top)[0]=mem_addr[0];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -851,9 +859,13 @@ inline void nasal_vm::opr_mcallh()
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_ret()
|
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
|
gc.local.pop_back();// delete local scope
|
||||||
pc=ret.top();ret.pop();// fetch pc
|
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
|
stack_top[0]=stack_top[1];// rewrite nasal_func with returned value
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
50
stl/list.nas
50
stl/list.nas
|
@ -2,65 +2,65 @@
|
||||||
# valkmjolnir 2021/3/31
|
# valkmjolnir 2021/3/31
|
||||||
var list=func()
|
var list=func()
|
||||||
{
|
{
|
||||||
var _={begin:nil,end:nil};
|
var (begin,end)=(nil,nil);
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
push_back:func(elem)
|
push_back:func(elem)
|
||||||
{
|
{
|
||||||
var tmp={elem:elem,prev:nil,next:nil};
|
var tmp={elem:elem,prev:nil,next:nil};
|
||||||
if(_.end!=nil)
|
if(end!=nil)
|
||||||
{
|
{
|
||||||
_.end.next=tmp;
|
end.next=tmp;
|
||||||
tmp.prev=_.end;
|
tmp.prev=end;
|
||||||
_.end=tmp;
|
end=tmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_.begin=_.end=tmp;
|
begin=end=tmp;
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
push_front:func(elem)
|
push_front:func(elem)
|
||||||
{
|
{
|
||||||
var tmp={elem:elem,prev:nil,next:nil};
|
var tmp={elem:elem,prev:nil,next:nil};
|
||||||
if(_.begin!=nil)
|
if(begin!=nil)
|
||||||
{
|
{
|
||||||
_.begin.prev=tmp;
|
begin.prev=tmp;
|
||||||
tmp.next=_.begin;
|
tmp.next=begin;
|
||||||
_.begin=tmp;
|
begin=tmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_.begin=_.end=tmp;
|
begin=end=tmp;
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
pop_back:func()
|
pop_back:func()
|
||||||
{
|
{
|
||||||
if(_.end!=nil)
|
if(end!=nil)
|
||||||
_.end=_.end.prev;
|
end=end.prev;
|
||||||
if(_.end==nil)
|
if(end==nil)
|
||||||
_.begin=nil;
|
begin=nil;
|
||||||
else
|
else
|
||||||
_.end.next=nil;
|
end.next=nil;
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
pop_front:func()
|
pop_front:func()
|
||||||
{
|
{
|
||||||
if(_.begin!=nil)
|
if(begin!=nil)
|
||||||
_.begin=_.begin.next;
|
begin=begin.next;
|
||||||
if(_.begin==nil)
|
if(begin==nil)
|
||||||
_.end=nil;
|
end=nil;
|
||||||
else
|
else
|
||||||
_.begin.prev=nil;
|
begin.prev=nil;
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
front:func()
|
front:func()
|
||||||
{
|
{
|
||||||
if(_.begin!=nil)
|
if(begin!=nil)
|
||||||
return _.begin.elem;
|
return begin.elem;
|
||||||
return nil;
|
return nil;
|
||||||
},
|
},
|
||||||
back:func()
|
back:func()
|
||||||
{
|
{
|
||||||
if(_.end!=nil)
|
if(end!=nil)
|
||||||
return _.end.elem;
|
return end.elem;
|
||||||
return nil;
|
return nil;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# valkmjolnir 2021/3/31
|
# valkmjolnir 2021/3/31
|
||||||
var queue=func()
|
var queue=func()
|
||||||
{
|
{
|
||||||
var _={begin:nil,end:nil};
|
var (begin,end)=(nil,nil);
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
push:func(elem)
|
push:func(elem)
|
||||||
|
@ -12,35 +12,35 @@ var queue=func()
|
||||||
elem:elem,
|
elem:elem,
|
||||||
next:nil
|
next:nil
|
||||||
};
|
};
|
||||||
if(_.begin==nil)
|
if(begin==nil)
|
||||||
_.begin=_.end=new_node;
|
begin=end=new_node;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_.end.next=new_node;
|
end.next=new_node;
|
||||||
_.end=new_node;
|
end=new_node;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
pop:func()
|
pop:func()
|
||||||
{
|
{
|
||||||
if(_.begin!=nil)
|
if(begin!=nil)
|
||||||
_.begin=_.begin.next;
|
begin=begin.next;
|
||||||
if(_.begin==nil)
|
if(begin==nil)
|
||||||
_.end=nil;
|
end=nil;
|
||||||
},
|
},
|
||||||
front:func()
|
front:func()
|
||||||
{
|
{
|
||||||
if(_.begin!=nil)
|
if(begin!=nil)
|
||||||
return _.begin.elem;
|
return begin.elem;
|
||||||
return nil;
|
return nil;
|
||||||
},
|
},
|
||||||
clear:func()
|
clear:func()
|
||||||
{
|
{
|
||||||
_.begin=_.end=nil;
|
begin=end=nil;
|
||||||
},
|
},
|
||||||
empty:func()
|
empty:func()
|
||||||
{
|
{
|
||||||
return _.begin==nil;
|
return begin==nil;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,35 +2,35 @@
|
||||||
# valkmjolnir 2021/3/31
|
# valkmjolnir 2021/3/31
|
||||||
var stack=func()
|
var stack=func()
|
||||||
{
|
{
|
||||||
var _={next:nil};
|
var next=nil;
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
push:func(elem)
|
push:func(elem)
|
||||||
{
|
{
|
||||||
_.next={elem:elem,next:_.next};
|
next={elem:elem,next:next};
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
pop:func()
|
pop:func()
|
||||||
{
|
{
|
||||||
var tmp=_.next;
|
var tmp=next;
|
||||||
if(tmp!=nil)
|
if(tmp!=nil)
|
||||||
_.next=tmp.next;
|
next=tmp.next;
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
top:func()
|
top:func()
|
||||||
{
|
{
|
||||||
var tmp=_.next;
|
var tmp=next;
|
||||||
if(tmp!=nil)
|
if(tmp!=nil)
|
||||||
return tmp.elem;
|
return tmp.elem;
|
||||||
return nil;
|
return nil;
|
||||||
},
|
},
|
||||||
clear:func()
|
clear:func()
|
||||||
{
|
{
|
||||||
_.next=nil;
|
next=nil;
|
||||||
},
|
},
|
||||||
empty:func()
|
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));
|
rand(time(0));
|
||||||
|
|
||||||
|
var pixel=[' ','#','.','*'];
|
||||||
var map=[];
|
var map=[];
|
||||||
for(var i=0;i<10;i+=1)
|
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 i=0;i<10;i+=1)
|
||||||
{
|
{
|
||||||
for(var j=0;j<10;j+=1)
|
for(var j=0;j<10;j+=1)
|
||||||
s~=map[i][j];
|
s~=pixel[map[i][j]];
|
||||||
s~='\n';
|
s~='\n';
|
||||||
}
|
}
|
||||||
s~='----------\n';
|
s~='----------\n';
|
||||||
|
@ -29,7 +30,7 @@ var bfs=func(begin,end)
|
||||||
var move=[[1,0],[0,1],[-1,0],[0,-1]];
|
var move=[[1,0],[0,1],[-1,0],[0,-1]];
|
||||||
var que=queue();
|
var que=queue();
|
||||||
que.push(begin);
|
que.push(begin);
|
||||||
map[begin[0]][begin[1]]=3;
|
map[begin[0]][begin[1]]=2;
|
||||||
while(!que.empty())
|
while(!que.empty())
|
||||||
{
|
{
|
||||||
var vertex=que.front();
|
var vertex=que.front();
|
||||||
|
@ -40,13 +41,14 @@ var bfs=func(begin,end)
|
||||||
var y=vertex[1]+i[1];
|
var y=vertex[1]+i[1];
|
||||||
if(x==end[0] and y==end[1])
|
if(x==end[0] and y==end[1])
|
||||||
{
|
{
|
||||||
map[x][y]='*';
|
map[x][y]=3;
|
||||||
|
prt();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(0<=x and x<10 and 0<=y and y<10 and map[x][y]==0)
|
if(0<=x and x<10 and 0<=y and y<10 and map[x][y]==0)
|
||||||
{
|
{
|
||||||
que.push([x,y]);
|
que.push([x,y]);
|
||||||
map[x][y]=3;
|
map[x][y]=2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prt();
|
prt();
|
||||||
|
|
|
@ -2,16 +2,13 @@ import("lib.nas");
|
||||||
|
|
||||||
var student=func(name,age)
|
var student=func(name,age)
|
||||||
{
|
{
|
||||||
var val={
|
var (n,a)=(name,age);
|
||||||
name:name,
|
|
||||||
age:age
|
|
||||||
};
|
|
||||||
return {
|
return {
|
||||||
print_info:func(){println(val.name,' ',val.age);},
|
print_info:func println(n,' ',a),
|
||||||
set_age: func(age){val.age=age;},
|
set_age: func(age) a=age,
|
||||||
get_age: func(){return val.age;},
|
get_age: func return a,
|
||||||
set_name: func(name){val.name=name;},
|
set_name: func(name) n=name,
|
||||||
get_name: func(){return val.name;}
|
get_name: func return n
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
var s=student('valk',24);
|
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));
|
println(fib(i));
|
Loading…
Reference in New Issue