optimize code & add comments

This commit is contained in:
ValKmjolnir 2023-01-02 01:00:16 +08:00
parent 9d7f799ad3
commit e6e89039b8
8 changed files with 192 additions and 167 deletions

View File

@ -23,7 +23,7 @@ using std::string;
const u32 STACK_DEPTH=1024; const u32 STACK_DEPTH=1024;
inline f64 hex2f(const char* str) { f64 hex2f(const char* str) {
f64 ret=0; f64 ret=0;
for(;*str;++str) { for(;*str;++str) {
if ('0'<=*str && *str<='9') { if ('0'<=*str && *str<='9') {
@ -39,7 +39,7 @@ inline f64 hex2f(const char* str) {
return ret; return ret;
} }
inline f64 oct2f(const char* str) { f64 oct2f(const char* str) {
f64 ret=0; f64 ret=0;
while('0'<=*str && *str<'8') { while('0'<=*str && *str<'8') {
ret=ret*8+(*str++-'0'); ret=ret*8+(*str++-'0');
@ -54,7 +54,7 @@ inline f64 oct2f(const char* str) {
// it is not platform independent, and may have strange output. // it is not platform independent, and may have strange output.
// so we write a new function here to convert str to number manually. // so we write a new function here to convert str to number manually.
// but this also makes 0.1+0.2==0.3, not another result that you may get in other languages. // but this also makes 0.1+0.2==0.3, not another result that you may get in other languages.
inline f64 dec2f(const char* str) { f64 dec2f(const char* str) {
f64 ret=0,negative=1,num_pow=0; f64 ret=0,negative=1,num_pow=0;
while('0'<=*str && *str<='9') { while('0'<=*str && *str<='9') {
ret=ret*10+(*str++-'0'); ret=ret*10+(*str++-'0');

View File

@ -157,13 +157,13 @@ public:
void set_str(const string& s) {nd_str=s;} void set_str(const string& s) {nd_str=s;}
void set_num(const f64 n) {nd_num=n;} void set_num(const f64 n) {nd_num=n;}
inline u32 line() const {return nd_line;} u32 line() const {return nd_line;}
inline u32 col() const {return nd_col;} u32 col() const {return nd_col;}
inline u32 type() const {return nd_type;} u32 type() const {return nd_type;}
inline f64 num() const {return nd_num;} f64 num() const {return nd_num;}
inline const string& str() const {return nd_str;} const string& str() const {return nd_str;}
inline const std::vector<ast>& child() const {return nd_child;} const std::vector<ast>& child() const {return nd_child;}
inline std::vector<ast>& child() {return nd_child;} std::vector<ast>& child() {return nd_child;}
}; };
ast::ast(const ast& tmp): ast::ast(const ast& tmp):

View File

@ -1151,13 +1151,20 @@ var builtin_coresume(var* local,gc& ngc) {
return nas_err("coroutine::resume","cannot start another coroutine when one is running"); return nas_err("coroutine::resume","cannot start another coroutine when one is running");
} }
var co=local[1]; var co=local[1];
// return nil if is not a coroutine object
if (co.type!=vm_co) { if (co.type!=vm_co) {
return nas_err("coroutine::resume","must use a coroutine object"); return nil;
} }
// cannot resume a dead coroutine
if (co.co().status==nas_co::dead) { if (co.co().status==nas_co::dead) {
return nil; return nil;
} }
// change to coroutine context
ngc.ctxchg(co.co()); ngc.ctxchg(co.co());
// fetch coroutine's stack top and return
// so the coroutine's stack top in fact is not changed
return ngc.top[0]; return ngc.top[0];
} }
@ -1165,16 +1172,21 @@ var builtin_coyield(var* local,gc& ngc) {
if (!ngc.cort) { if (!ngc.cort) {
return nas_err("coroutine::yield","no coroutine is running"); return nas_err("coroutine::yield","no coroutine is running");
} }
ngc.ctxreserve();
// this will set to main stack top // this will set to main stack top
// then builtin_coresume will return it ngc.ctxreserve();
// then this will return value to main's stack top[0]
// the procedure seems like coroutine.resume returns the value
// but in fact coroutine.resume stop the main context
// until coroutine calls the coroutine.yield
return local[1]; return local[1];
} }
var builtin_costatus(var* local,gc& ngc) { var builtin_costatus(var* local,gc& ngc) {
var co=local[1]; var co=local[1];
if (co.type!=vm_co) { if (co.type!=vm_co) {
return nas_err("coroutine::status","must use a coroutine object"); return ngc.newstr("error");
} }
switch(co.co().status) { switch(co.co().status) {
case nas_co::suspended: return ngc.newstr("suspended");break; case nas_co::suspended: return ngc.newstr("suspended");break;

View File

@ -80,17 +80,17 @@ struct var {
string tostr(); string tostr();
friend std::ostream& operator<<(std::ostream&,var&); friend std::ostream& operator<<(std::ostream&,var&);
bool objchk(u32); bool objchk(u32);
inline var* addr(); var* addr();
inline u32 ret (); u32 ret ();
inline i64& cnt (); i64& cnt ();
inline f64 num (); f64 num ();
inline string& str (); string& str ();
inline nas_vec& vec (); nas_vec& vec ();
inline nas_hash& hash(); nas_hash& hash();
inline nas_func& func(); nas_func& func();
inline nas_upval& upval(); nas_upval& upval();
inline nas_obj& obj (); nas_obj& obj ();
inline nas_co& co (); nas_co& co ();
}; };
struct nas_vec { struct nas_vec {
@ -412,17 +412,17 @@ bool var::objchk(u32 objtype) {
return type==vm_obj && obj().type==objtype && obj().ptr; return type==vm_obj && obj().type==objtype && obj().ptr;
} }
inline var* var::addr () {return val.addr; } var* var::addr () {return val.addr; }
inline u32 var::ret () {return val.ret; } u32 var::ret () {return val.ret; }
inline i64& var::cnt () {return val.cnt; } i64& var::cnt () {return val.cnt; }
inline f64 var::num () {return val.num; } f64 var::num () {return val.num; }
inline string& var::str () {return *val.gcobj->ptr.str; } string& var::str () {return *val.gcobj->ptr.str; }
inline nas_vec& var::vec () {return *val.gcobj->ptr.vec; } nas_vec& var::vec () {return *val.gcobj->ptr.vec; }
inline nas_hash& var::hash () {return *val.gcobj->ptr.hash; } nas_hash& var::hash () {return *val.gcobj->ptr.hash; }
inline nas_func& var::func () {return *val.gcobj->ptr.func; } nas_func& var::func () {return *val.gcobj->ptr.func; }
inline nas_upval& var::upval() {return *val.gcobj->ptr.upval;} nas_upval& var::upval() {return *val.gcobj->ptr.upval;}
inline nas_obj& var::obj () {return *val.gcobj->ptr.obj; } nas_obj& var::obj () {return *val.gcobj->ptr.obj; }
inline nas_co& var::co () {return *val.gcobj->ptr.co; } nas_co& var::co () {return *val.gcobj->ptr.co; }
const var zero={vm_num,(f64)0}; const var zero={vm_num,(f64)0};
const var one ={vm_num,(f64)1}; const var one ={vm_num,(f64)1};

View File

@ -238,28 +238,31 @@ string lexer::utf8_gen() {
while(ptr<res.size() && res[ptr]<0) { while(ptr<res.size() && res[ptr]<0) {
string tmp=""; string tmp="";
u32 nbytes=utf8_hdchk(res[ptr]); u32 nbytes=utf8_hdchk(res[ptr]);
if (nbytes) { if (!nbytes) {
tmp+=res[ptr++];
for(u32 i=0;i<nbytes;++i,++ptr) {
if (ptr<res.size() && (res[ptr]&0xc0)==0x80) {
tmp+=res[ptr];
}
}
if (tmp.length()!=1+nbytes) {
++column;
string utf_info="0x"+chrhex(tmp[0]);
for(u32 i=1;i<tmp.size();++i) {
utf_info+=" 0x"+chrhex(tmp[i]);
}
err.err("lexer",line,column,1,"invalid utf-8 <"+utf_info+">");
err.fatal("lexer","fatal error occurred, stop");
}
str+=tmp;
column+=2; // may have some problems because not all the unicode takes 2 space
} else {
++ptr; ++ptr;
++column; ++column;
continue;
} }
tmp+=res[ptr++];
for(u32 i=0;i<nbytes;++i,++ptr) {
if (ptr<res.size() && (res[ptr]&0xc0)==0x80) {
tmp+=res[ptr];
}
}
// utf8 character's total length is 1+nbytes
if (tmp.length()!=1+nbytes) {
++column;
string utf_info="0x"+chrhex(tmp[0]);
for(u32 i=1;i<tmp.size();++i) {
utf_info+=" 0x"+chrhex(tmp[i]);
}
err.err("lexer",line,column,1,"invalid utf-8 <"+utf_info+">");
err.fatal("lexer","fatal error occurred, stop");
}
str+=tmp;
column+=2; // may have some problems because not all the unicode takes 2 space
} }
return str; return str;
} }

View File

@ -313,12 +313,18 @@ void vm::die(const string& str) {
std::cout<<"[vm] error: "<<str<<"\n"; std::cout<<"[vm] error: "<<str<<"\n";
traceback(); traceback();
stackinfo(); stackinfo();
// show verbose crash info
if (verbose) { if (verbose) {
detail(); detail();
} }
if (ngc.stack==stack) { if (ngc.stack==stack) {
// in main context, exit directly
std::exit(1); std::exit(1);
} else { } else {
// in coroutine, shut down the coroutine
// and return to main context
pc=0; // mark coroutine 'dead' pc=0; // mark coroutine 'dead'
ngc.ctxreserve(); ngc.ctxreserve();
top[0]=nil; top[0]=nil;
@ -330,48 +336,48 @@ inline bool vm::cond(var& val) {
return val.num(); return val.num();
} else if (val.type==vm_str) { } else if (val.type==vm_str) {
const f64 num=str2num(val.str().c_str()); const f64 num=str2num(val.str().c_str());
return std::isnan(num)?!val.str().empty():num; return std::isnan(num)? !val.str().empty():num;
} }
return false; return false;
} }
inline void vm::o_intg() { void vm::o_intg() {
// global values store on stack // global values store on stack
top+=imm[pc]; top+=imm[pc];
--top;// point to the top --top;// point to the top
} }
inline void vm::o_intl() { void vm::o_intl() {
top[0].func().local.resize(imm[pc],nil); top[0].func().local.resize(imm[pc],nil);
top[0].func().lsize=imm[pc]; top[0].func().lsize=imm[pc];
} }
inline void vm::o_loadg() { void vm::o_loadg() {
stack[imm[pc]]=(top--)[0]; stack[imm[pc]]=(top--)[0];
} }
inline void vm::o_loadl() { void vm::o_loadl() {
localr[imm[pc]]=(top--)[0]; localr[imm[pc]]=(top--)[0];
} }
inline void vm::o_loadu() { void vm::o_loadu() {
funcr.func().upval[(imm[pc]>>16)&0xffff] funcr.func().upval[(imm[pc]>>16)&0xffff]
.upval()[imm[pc]&0xffff]=(top--)[0]; .upval()[imm[pc]&0xffff]=(top--)[0];
} }
inline void vm::o_pnum() { void vm::o_pnum() {
(++top)[0]={vm_num,cnum[imm[pc]]}; (++top)[0]={vm_num,cnum[imm[pc]]};
} }
inline void vm::o_pnil() { void vm::o_pnil() {
(++top)[0]=nil; (++top)[0]=nil;
} }
inline void vm::o_pstr() { void vm::o_pstr() {
(++top)[0]=ngc.strs[imm[pc]]; (++top)[0]=ngc.strs[imm[pc]];
} }
inline void vm::o_newv() { void vm::o_newv() {
var newv=ngc.alloc(vm_vec); var newv=ngc.alloc(vm_vec);
auto& vec=newv.vec().elems; auto& vec=newv.vec().elems;
vec.resize(imm[pc]); vec.resize(imm[pc]);
@ -383,11 +389,11 @@ inline void vm::o_newv() {
top[0]=newv; top[0]=newv;
} }
inline void vm::o_newh() { void vm::o_newh() {
(++top)[0]=ngc.alloc(vm_hash); (++top)[0]=ngc.alloc(vm_hash);
} }
inline void vm::o_newf() { void vm::o_newf() {
(++top)[0]=ngc.alloc(vm_func); (++top)[0]=ngc.alloc(vm_func);
nas_func& func=top[0].func(); nas_func& func=top[0].func();
func.entry=imm[pc]; func.entry=imm[pc];
@ -406,19 +412,19 @@ inline void vm::o_newf() {
} }
} }
inline void vm::o_happ() { void vm::o_happ() {
top[-1].hash().elems[cstr[imm[pc]]]=top[0]; top[-1].hash().elems[cstr[imm[pc]]]=top[0];
--top; --top;
} }
inline void vm::o_para() { void vm::o_para() {
nas_func& func=top[0].func(); nas_func& func=top[0].func();
// func->size has 1 place reserved for "me" // func->size has 1 place reserved for "me"
func.keys[imm[pc]]=func.psize; func.keys[imm[pc]]=func.psize;
func.local[func.psize++]={vm_none}; func.local[func.psize++]={vm_none};
} }
inline void vm::o_deft() { void vm::o_deft() {
var val=top[0]; var val=top[0];
nas_func& func=(--top)[0].func(); nas_func& func=(--top)[0].func();
// func->size has 1 place reserved for "me" // func->size has 1 place reserved for "me"
@ -426,11 +432,11 @@ inline void vm::o_deft() {
func.local[func.psize++]=val; func.local[func.psize++]=val;
} }
inline void vm::o_dyn() { void vm::o_dyn() {
top[0].func().dpara=imm[pc]; top[0].func().dpara=imm[pc];
} }
inline void vm::o_unot() { void vm::o_unot() {
var val=top[0]; var val=top[0];
switch(val.type) { switch(val.type) {
case vm_nil:top[0]=one;break; case vm_nil:top[0]=one;break;
@ -450,7 +456,7 @@ inline void vm::o_unot() {
} }
} }
inline void vm::o_usub() { void vm::o_usub() {
top[0]={vm_num,-top[0].tonum()}; top[0]={vm_num,-top[0].tonum()};
} }
@ -458,11 +464,11 @@ inline void vm::o_usub() {
top[-1]={vm_num,top[-1].tonum() type top[0].tonum()};\ top[-1]={vm_num,top[-1].tonum() type top[0].tonum()};\
--top; --top;
inline void vm::o_add() {op_calc(+);} void vm::o_add() {op_calc(+);}
inline void vm::o_sub() {op_calc(-);} void vm::o_sub() {op_calc(-);}
inline void vm::o_mul() {op_calc(*);} void vm::o_mul() {op_calc(*);}
inline void vm::o_div() {op_calc(/);} void vm::o_div() {op_calc(/);}
inline void vm::o_lnk() { void vm::o_lnk() {
top[-1]=ngc.newstr(top[-1].tostr()+top[0].tostr()); top[-1]=ngc.newstr(top[-1].tostr()+top[0].tostr());
--top; --top;
} }
@ -470,11 +476,11 @@ inline void vm::o_lnk() {
#define op_calc_const(type)\ #define op_calc_const(type)\
top[0]={vm_num,top[0].tonum() type cnum[imm[pc]]}; top[0]={vm_num,top[0].tonum() type cnum[imm[pc]]};
inline void vm::o_addc() {op_calc_const(+);} void vm::o_addc() {op_calc_const(+);}
inline void vm::o_subc() {op_calc_const(-);} void vm::o_subc() {op_calc_const(-);}
inline void vm::o_mulc() {op_calc_const(*);} void vm::o_mulc() {op_calc_const(*);}
inline void vm::o_divc() {op_calc_const(/);} void vm::o_divc() {op_calc_const(/);}
inline void vm::o_lnkc() { void vm::o_lnkc() {
top[0]=ngc.newstr(top[0].tostr()+cstr[imm[pc]]); top[0]=ngc.newstr(top[0].tostr()+cstr[imm[pc]]);
} }
@ -483,11 +489,11 @@ inline void vm::o_lnkc() {
memr=nullptr;\ memr=nullptr;\
top-=imm[pc]+1; top-=imm[pc]+1;
inline void vm::o_addeq() {op_calc_eq(+);} void vm::o_addeq() {op_calc_eq(+);}
inline void vm::o_subeq() {op_calc_eq(-);} void vm::o_subeq() {op_calc_eq(-);}
inline void vm::o_muleq() {op_calc_eq(*);} void vm::o_muleq() {op_calc_eq(*);}
inline void vm::o_diveq() {op_calc_eq(/);} void vm::o_diveq() {op_calc_eq(/);}
inline void vm::o_lnkeq() { void vm::o_lnkeq() {
top[-1]=memr[0]=ngc.newstr(memr[0].tostr()+top[-1].tostr()); top[-1]=memr[0]=ngc.newstr(memr[0].tostr()+top[-1].tostr());
memr=nullptr; memr=nullptr;
top-=imm[pc]+1; top-=imm[pc]+1;
@ -498,17 +504,17 @@ inline void vm::o_lnkeq() {
memr=nullptr;\ memr=nullptr;\
top-=(imm[pc]>>31); top-=(imm[pc]>>31);
inline void vm::o_addeqc() {op_calc_eq_const(+);} void vm::o_addeqc() {op_calc_eq_const(+);}
inline void vm::o_subeqc() {op_calc_eq_const(-);} void vm::o_subeqc() {op_calc_eq_const(-);}
inline void vm::o_muleqc() {op_calc_eq_const(*);} void vm::o_muleqc() {op_calc_eq_const(*);}
inline void vm::o_diveqc() {op_calc_eq_const(/);} void vm::o_diveqc() {op_calc_eq_const(/);}
inline void vm::o_lnkeqc() { void vm::o_lnkeqc() {
top[0]=memr[0]=ngc.newstr(memr[0].tostr()+cstr[imm[pc]&0x7fffffff]); top[0]=memr[0]=ngc.newstr(memr[0].tostr()+cstr[imm[pc]&0x7fffffff]);
memr=nullptr; memr=nullptr;
top-=(imm[pc]>>31); top-=(imm[pc]>>31);
} }
inline void vm::o_meq() { void vm::o_meq() {
// pop old memr[0] and replace it // pop old memr[0] and replace it
// the reason why we should get memr and push the old value on stack // the reason why we should get memr and push the old value on stack
// is that when lnkeq/lnkeqc is called, there will be // is that when lnkeq/lnkeqc is called, there will be
@ -519,7 +525,7 @@ inline void vm::o_meq() {
top-=imm[pc]+1; top-=imm[pc]+1;
} }
inline void vm::o_eq() { void vm::o_eq() {
var val2=top[0]; var val2=top[0];
var val1=(--top)[0]; var val1=(--top)[0];
if (val1.type==vm_nil && val2.type==vm_nil) { if (val1.type==vm_nil && val2.type==vm_nil) {
@ -534,7 +540,7 @@ inline void vm::o_eq() {
} }
} }
inline void vm::o_neq() { void vm::o_neq() {
var val2=top[0]; var val2=top[0];
var val1=(--top)[0]; var val1=(--top)[0];
if (val1.type==vm_nil && val2.type==vm_nil) { if (val1.type==vm_nil && val2.type==vm_nil) {
@ -553,28 +559,28 @@ inline void vm::o_neq() {
--top;\ --top;\
top[0]=(top[0].tonum() type top[1].tonum())?one:zero; top[0]=(top[0].tonum() type top[1].tonum())?one:zero;
inline void vm::o_less() {op_cmp(<);} void vm::o_less() {op_cmp(<);}
inline void vm::o_leq() {op_cmp(<=);} void vm::o_leq() {op_cmp(<=);}
inline void vm::o_grt() {op_cmp(>);} void vm::o_grt() {op_cmp(>);}
inline void vm::o_geq() {op_cmp(>=);} void vm::o_geq() {op_cmp(>=);}
#define op_cmp_const(type)\ #define op_cmp_const(type)\
top[0]=(top[0].tonum() type cnum[imm[pc]])?one:zero; top[0]=(top[0].tonum() type cnum[imm[pc]])?one:zero;
inline void vm::o_lessc() {op_cmp_const(<);} void vm::o_lessc() {op_cmp_const(<);}
inline void vm::o_leqc() {op_cmp_const(<=);} void vm::o_leqc() {op_cmp_const(<=);}
inline void vm::o_grtc() {op_cmp_const(>);} void vm::o_grtc() {op_cmp_const(>);}
inline void vm::o_geqc() {op_cmp_const(>=);} void vm::o_geqc() {op_cmp_const(>=);}
inline void vm::o_pop() { void vm::o_pop() {
--top; --top;
} }
inline void vm::o_jmp() { void vm::o_jmp() {
pc=imm[pc]-1; pc=imm[pc]-1;
} }
inline void vm::o_jt() { void vm::o_jt() {
// jump true needs to reserve the result on stack // jump true needs to reserve the result on stack
// because conditional expression in nasal has return value // because conditional expression in nasal has return value
if (cond(top[0])) { if (cond(top[0])) {
@ -582,7 +588,7 @@ inline void vm::o_jt() {
} }
} }
inline void vm::o_jf() { void vm::o_jf() {
// jump false doesn't need to reserve result // jump false doesn't need to reserve result
if (!cond(top[0])) { if (!cond(top[0])) {
pc=imm[pc]-1; pc=imm[pc]-1;
@ -590,7 +596,7 @@ inline void vm::o_jf() {
--top; --top;
} }
inline void vm::o_cnt() { void vm::o_cnt() {
if (top[0].type!=vm_vec) { if (top[0].type!=vm_vec) {
die("must use vector in forindex/foreach"); die("must use vector in forindex/foreach");
return; return;
@ -598,7 +604,7 @@ inline void vm::o_cnt() {
(++top)[0]={vm_cnt,(i64)-1}; (++top)[0]={vm_cnt,(i64)-1};
} }
inline void vm::o_findex() { void vm::o_findex() {
if ((usize)(++top[0].cnt())>=top[-1].vec().size()) { if ((usize)(++top[0].cnt())>=top[-1].vec().size()) {
pc=imm[pc]-1; pc=imm[pc]-1;
return; return;
@ -607,7 +613,7 @@ inline void vm::o_findex() {
++top; ++top;
} }
inline void vm::o_feach() { void vm::o_feach() {
auto& ref=top[-1].vec().elems; auto& ref=top[-1].vec().elems;
if ((usize)(++top[0].cnt())>=ref.size()) { if ((usize)(++top[0].cnt())>=ref.size()) {
pc=imm[pc]-1; pc=imm[pc]-1;
@ -617,20 +623,20 @@ inline void vm::o_feach() {
++top; ++top;
} }
inline void vm::o_callg() { void vm::o_callg() {
(++top)[0]=stack[imm[pc]]; (++top)[0]=stack[imm[pc]];
} }
inline void vm::o_calll() { void vm::o_calll() {
(++top)[0]=localr[imm[pc]]; (++top)[0]=localr[imm[pc]];
} }
inline void vm::o_upval() { void vm::o_upval() {
(++top)[0]=funcr.func().upval[(imm[pc]>>16)&0xffff] (++top)[0]=funcr.func().upval[(imm[pc]>>16)&0xffff]
.upval()[imm[pc]&0xffff]; .upval()[imm[pc]&0xffff];
} }
inline void vm::o_callv() { void vm::o_callv() {
var val=top[0]; var val=top[0];
var vec=(--top)[0]; var vec=(--top)[0];
if (vec.type==vm_vec) { if (vec.type==vm_vec) {
@ -666,7 +672,7 @@ inline void vm::o_callv() {
} }
} }
inline void vm::o_callvi() { void vm::o_callvi() {
var val=top[0]; var val=top[0];
if (val.type!=vm_vec) { if (val.type!=vm_vec) {
die("must use a vector"); die("must use a vector");
@ -680,7 +686,7 @@ inline void vm::o_callvi() {
} }
} }
inline void vm::o_callh() { void vm::o_callh() {
var val=top[0]; var val=top[0];
if (val.type!=vm_hash) { if (val.type!=vm_hash) {
die("must call a hash"); die("must call a hash");
@ -695,7 +701,7 @@ inline void vm::o_callh() {
} }
} }
inline void vm::o_callfv() { void vm::o_callfv() {
u32 argc=imm[pc]; // arguments counter u32 argc=imm[pc]; // arguments counter
var* local=top-argc+1; // arguments begin address var* local=top-argc+1; // arguments begin address
if (local[-1].type!=vm_func) { if (local[-1].type!=vm_func) {
@ -753,7 +759,7 @@ inline void vm::o_callfv() {
upvalr=nil; upvalr=nil;
} }
inline void vm::o_callfh() { void vm::o_callfh() {
auto& hash=top[0].hash().elems; auto& hash=top[0].hash().elems;
if (top[-1].type!=vm_func) { if (top[-1].type!=vm_func) {
die("must call a function"); die("must call a function");
@ -797,7 +803,7 @@ inline void vm::o_callfh() {
upvalr=nil; upvalr=nil;
} }
inline void vm::o_callb() { void vm::o_callb() {
// reserve place for builtin function return, // reserve place for builtin function return,
// in fact this code is changed because of coroutine // in fact this code is changed because of coroutine
(++top)[0]=nil; (++top)[0]=nil;
@ -811,7 +817,7 @@ inline void vm::o_callb() {
} }
} }
inline void vm::o_slcbeg() { void vm::o_slcbeg() {
// +--------------+ // +--------------+
// | slice_vector | <-- top[0] // | slice_vector | <-- top[0]
// +--------------+ // +--------------+
@ -824,12 +830,12 @@ inline void vm::o_slcbeg() {
} }
} }
inline void vm::o_slcend() { void vm::o_slcend() {
top[-1]=top[0]; top[-1]=top[0];
--top; --top;
} }
inline void vm::o_slc() { void vm::o_slc() {
var val=(top--)[0]; var val=(top--)[0];
var res=top[-1].vec().get_val(val.tonum()); var res=top[-1].vec().get_val(val.tonum());
if (res.type==vm_none) { if (res.type==vm_none) {
@ -839,7 +845,7 @@ inline void vm::o_slc() {
top[0].vec().elems.push_back(res); top[0].vec().elems.push_back(res);
} }
inline void vm::o_slc2() { void vm::o_slc2() {
var val2=(top--)[0]; var val2=(top--)[0];
var val1=(top--)[0]; var val1=(top--)[0];
auto& ref=top[-1].vec().elems; auto& ref=top[-1].vec().elems;
@ -868,28 +874,28 @@ inline void vm::o_slc2() {
} }
} }
inline void vm::o_mcallg() { void vm::o_mcallg() {
memr=stack+imm[pc]; memr=stack+imm[pc];
(++top)[0]=memr[0]; (++top)[0]=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
} }
inline void vm::o_mcalll() { void vm::o_mcalll() {
memr=localr+imm[pc]; memr=localr+imm[pc];
(++top)[0]=memr[0]; (++top)[0]=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
} }
inline void vm::o_mupval() { void vm::o_mupval() {
memr=&(funcr.func().upval[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]); memr=&(funcr.func().upval[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]);
(++top)[0]=memr[0]; (++top)[0]=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
} }
inline void vm::o_mcallv() { void vm::o_mcallv() {
var val=top[0]; // index var val=top[0]; // index
var vec=(--top)[0]; // mcall vector, reserved on stack to avoid gc var vec=(--top)[0]; // mcall vector, reserved on stack to avoid gc
if (vec.type==vm_vec) { if (vec.type==vm_vec) {
@ -916,7 +922,7 @@ inline void vm::o_mcallv() {
} }
} }
inline void vm::o_mcallh() { void vm::o_mcallh() {
var hash=top[0]; // mcall hash, reserved on stack to avoid gc var hash=top[0]; // mcall hash, reserved on stack to avoid gc
if (hash.type!=vm_hash) { if (hash.type!=vm_hash) {
die("must call a hash"); die("must call a hash");
@ -931,7 +937,7 @@ inline void vm::o_mcallh() {
} }
} }
inline void vm::o_ret() { void vm::o_ret() {
/* +-------------+ /* +-------------+
* | return value| <- top[0] * | return value| <- top[0]
* +-------------+ * +-------------+
@ -974,6 +980,7 @@ inline void vm::o_ret() {
ngc.ctxreserve(); ngc.ctxreserve();
} }
} }
void vm::run( void vm::run(
const codegen& gen, const codegen& gen,
const linker& linker, const linker& linker,

View File

@ -28,6 +28,7 @@ var run=func(width,height){
if(_width>=width) _width=0; if(_width>=width) _width=0;
return map[_height][_width]=='O'; return map[_height][_width]=='O';
} }
# enable ANSI escape sequence # enable ANSI escape sequence
if(os.platform()=="windows") if(os.platform()=="windows")
system("color"); system("color");
@ -55,43 +56,48 @@ var run=func(width,height){
}; };
var ppm_gen=func(width,height){ var ppm_gen=func(width,height){
var pixels=width*height;
var new_map=func(){
var tmp=[];
setsize(tmp,pixels);
return tmp;
}
# iteration counter and trigger for ppm/data generator # iteration counter and trigger for ppm/data generator
var iter_to_print=0; var iter_to_print=0;
var init=func(){ var init=func(){
var res=new_map(width,height); var res=new_map();
if(io.exists(".life_data")) { if(io.exists(".life_data")) {
var vec=split("\n",io.fin(".life_data")); var vec=split("\n",io.fin(".life_data"));
if (num(vec[0])!=width or num(vec[1])!=height) { if (num(vec[0])!=width or num(vec[1])!=height) {
die("incorrect width or height: "~vec[0]~":"~str(width)~" / "~vec[1]~":"~str(height)) die("incorrect width or height: "~vec[0]~":"~str(width)~" / "~vec[1]~":"~str(height))
} }
iter_to_print=num(vec[2]); iter_to_print=num(vec[2]);
var data=split("",vec[3]); var data=vec[3];
for(var i=0;i<height;i+=1) var n="1"[0];
for(var j=0;j<width;j+=1) for(var i=0;i<pixels;i+=1){
res[i][j]=num(data[i*width+j]); res[i]=data[i]==n?1:0;
}
return res; return res;
} }
rand(time(0)); rand(time(0));
for(var i=0;i<height;i+=1) for(var i=0;i<pixels;i+=1)
for(var j=0;j<width;j+=1) res[i]=0;
res[i][j]=0;
for(var i=int(height/5*2);i<int(height/5*3);i+=1) for(var i=int(height/5*2);i<int(height/5*3);i+=1)
forindex(var j;res[i]) forindex(var j;res[i])
res[i][j]=rand()<0.5?1:0; res[i*width+j]=rand()<0.5?1:0;
return res; return res;
} }
var store=func(){ var store=func(){
var fd=io.open(".life_data","w"); var fd=io.open(".life_data","w");
io.write(fd,str(width)~"\n"~str(height)~"\n"~str(iter_to_print)~"\n"); io.write(fd,str(width)~"\n"~str(height)~"\n"~str(iter_to_print)~"\n");
for(var i=0;i<height;i+=1){ for(var i=0;i<pixels;i+=1){
for(var j=0;j<width;j+=1){ io.write(fd,map[i]==1?"1":"0");
io.write(fd,map[i][j]==1?"1":"0");
}
} }
io.close(fd); io.close(fd);
} }
@ -103,24 +109,21 @@ var ppm_gen=func(width,height){
io.write(fd,"P6\n"~width~" "~height~"\n255\n"); io.write(fd,"P6\n"~width~" "~height~"\n255\n");
var white=char(255)~char(255)~char(255); var white=char(255)~char(255)~char(255);
var black=char(0)~char(0)~char(0); var black=char(0)~char(0)~char(0);
for(var i=0;i<height;i+=1){ for(var i=0;i<pixels;i+=1){
for(var j=0;j<width;j+=1){ io.write(fd,map[i]==1?white:black);
var s=map[i][j]==1?white:black;
io.write(fd,s);
}
} }
io.close(fd); io.close(fd);
} }
var ts=maketimestamp(); var ts=maketimestamp();
var bar=process_bar.high_resolution_bar(80); var bar=process_bar.high_resolution_bar(50);
var map=init(); var map=init();
var tmp=new_map(width,height); var tmp=new_map();
var check=func(_width,_height){ var check=func(_width,_height){
if(_height>=height) _height=0; if(_height>=height) _height=0;
if(_width>=width) _width=0; if(_width>=width) _width=0;
return map[_height][_width]==1; return map[_height*width+_width]==1;
} }
for(var r=0;r<1001;r+=1){ for(var r=0;r<1001;r+=1){
@ -128,9 +131,9 @@ var ppm_gen=func(width,height){
for(var i=0;i<height;i+=1){ for(var i=0;i<height;i+=1){
for(var j=0;j<width;j+=1){ for(var j=0;j<width;j+=1){
var cnt=check(j,i+1)+check(j+1,i)+check(j,i-1)+check(j-1,i)+check(j+1,i+1)+check(j-1,i-1)+check(j+1,i-1)+check(j-1,i+1); var cnt=check(j,i+1)+check(j+1,i)+check(j,i-1)+check(j-1,i)+check(j+1,i+1)+check(j-1,i-1)+check(j+1,i-1)+check(j-1,i+1);
if(cnt==2) tmp[i][j]=map[i][j]; if(cnt==2) tmp[i*width+j]=map[i*width+j];
elsif(cnt==3) tmp[i][j]=1; elsif(cnt==3) tmp[i*width+j]=1;
else tmp[i][j]=0; else tmp[i*width+j]=0;
} }
} }
(map,tmp)=(tmp,map); (map,tmp)=(tmp,map);

View File

@ -12,19 +12,19 @@ var unicode测试=func(){
var emoji测试=func(){ var emoji测试=func(){
var 💻=print; var 💻=print;
var 🎤="\n"; var 🎤="\n";
var 🤣="🤣笑嘻了"; var 🤣="🤣 笑嘻了";
var 😅="😅差不多得了"; var 😅="😅 差不多得了";
var 🤤="🤤收收味"; var 🤤="🤤 收收味";
var 🥵="🥵太烧啦"; var 🥵="🥵 太烧啦";
var 🥶="🥶捏麻麻滴冷死了"; var 🥶="🥶 我草!冰!";
var 🤢="🤢老八秘制小汉堡🍔"; var 🤢="🤢 老八秘制小汉堡 🍔";
var 🤓="🤓我是傻逼"; var 🤓="🤓 我是傻逼";
var 😭="😭你带我走吧😭😭😭"; var 😭="😭 你带我走吧 😭😭😭";
var 👿="👿密麻麻石蜡"; var 👿="👿 密麻麻石蜡";
var 🤡="🤡居然就是你"; var 🤡="🤡 居然就是你";
var 💩="💩奥利给干了兄弟们"; var 💩="💩 奥利给干了兄弟们";
var 🍾="🍾好似,开🍾咯"; var 🍾="🍾 好似,开 🍾 咯";
var 🐘="🐘太🚬🐘了兄弟们"; var 🐘="🐘 🚬🐘 了兄弟们";
var 📁=[🤣,😅,🤤,🥵,🥶,🤢,🤓,😭,👿,🤡,💩,🍾,🐘]; var 📁=[🤣,😅,🤤,🥵,🥶,🤢,🤓,😭,👿,🤡,💩,🍾,🐘];
var 🗄️={ var 🗄️={
🤣:🤣, 🤣:🤣,