⚡ optimize code & add comments
This commit is contained in:
parent
9d7f799ad3
commit
e6e89039b8
6
nasal.h
6
nasal.h
|
@ -23,7 +23,7 @@ using std::string;
|
|||
|
||||
const u32 STACK_DEPTH=1024;
|
||||
|
||||
inline f64 hex2f(const char* str) {
|
||||
f64 hex2f(const char* str) {
|
||||
f64 ret=0;
|
||||
for(;*str;++str) {
|
||||
if ('0'<=*str && *str<='9') {
|
||||
|
@ -39,7 +39,7 @@ inline f64 hex2f(const char* str) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
inline f64 oct2f(const char* str) {
|
||||
f64 oct2f(const char* str) {
|
||||
f64 ret=0;
|
||||
while('0'<=*str && *str<'8') {
|
||||
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.
|
||||
// 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.
|
||||
inline f64 dec2f(const char* str) {
|
||||
f64 dec2f(const char* str) {
|
||||
f64 ret=0,negative=1,num_pow=0;
|
||||
while('0'<=*str && *str<='9') {
|
||||
ret=ret*10+(*str++-'0');
|
||||
|
|
14
nasal_ast.h
14
nasal_ast.h
|
@ -157,13 +157,13 @@ public:
|
|||
void set_str(const string& s) {nd_str=s;}
|
||||
void set_num(const f64 n) {nd_num=n;}
|
||||
|
||||
inline u32 line() const {return nd_line;}
|
||||
inline u32 col() const {return nd_col;}
|
||||
inline u32 type() const {return nd_type;}
|
||||
inline f64 num() const {return nd_num;}
|
||||
inline const string& str() const {return nd_str;}
|
||||
inline const std::vector<ast>& child() const {return nd_child;}
|
||||
inline std::vector<ast>& child() {return nd_child;}
|
||||
u32 line() const {return nd_line;}
|
||||
u32 col() const {return nd_col;}
|
||||
u32 type() const {return nd_type;}
|
||||
f64 num() const {return nd_num;}
|
||||
const string& str() const {return nd_str;}
|
||||
const std::vector<ast>& child() const {return nd_child;}
|
||||
std::vector<ast>& child() {return nd_child;}
|
||||
};
|
||||
|
||||
ast::ast(const ast& tmp):
|
||||
|
|
|
@ -1151,13 +1151,20 @@ var builtin_coresume(var* local,gc& ngc) {
|
|||
return nas_err("coroutine::resume","cannot start another coroutine when one is running");
|
||||
}
|
||||
var co=local[1];
|
||||
// return nil if is not a coroutine object
|
||||
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) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
// change to coroutine context
|
||||
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];
|
||||
}
|
||||
|
||||
|
@ -1165,16 +1172,21 @@ var builtin_coyield(var* local,gc& ngc) {
|
|||
if (!ngc.cort) {
|
||||
return nas_err("coroutine::yield","no coroutine is running");
|
||||
}
|
||||
ngc.ctxreserve();
|
||||
|
||||
// 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];
|
||||
}
|
||||
|
||||
var builtin_costatus(var* local,gc& ngc) {
|
||||
var co=local[1];
|
||||
if (co.type!=vm_co) {
|
||||
return nas_err("coroutine::status","must use a coroutine object");
|
||||
return ngc.newstr("error");
|
||||
}
|
||||
switch(co.co().status) {
|
||||
case nas_co::suspended: return ngc.newstr("suspended");break;
|
||||
|
|
44
nasal_gc.h
44
nasal_gc.h
|
@ -80,17 +80,17 @@ struct var {
|
|||
string tostr();
|
||||
friend std::ostream& operator<<(std::ostream&,var&);
|
||||
bool objchk(u32);
|
||||
inline var* addr();
|
||||
inline u32 ret ();
|
||||
inline i64& cnt ();
|
||||
inline f64 num ();
|
||||
inline string& str ();
|
||||
inline nas_vec& vec ();
|
||||
inline nas_hash& hash();
|
||||
inline nas_func& func();
|
||||
inline nas_upval& upval();
|
||||
inline nas_obj& obj ();
|
||||
inline nas_co& co ();
|
||||
var* addr();
|
||||
u32 ret ();
|
||||
i64& cnt ();
|
||||
f64 num ();
|
||||
string& str ();
|
||||
nas_vec& vec ();
|
||||
nas_hash& hash();
|
||||
nas_func& func();
|
||||
nas_upval& upval();
|
||||
nas_obj& obj ();
|
||||
nas_co& co ();
|
||||
};
|
||||
|
||||
struct nas_vec {
|
||||
|
@ -412,17 +412,17 @@ bool var::objchk(u32 objtype) {
|
|||
return type==vm_obj && obj().type==objtype && obj().ptr;
|
||||
}
|
||||
|
||||
inline var* var::addr () {return val.addr; }
|
||||
inline u32 var::ret () {return val.ret; }
|
||||
inline i64& var::cnt () {return val.cnt; }
|
||||
inline f64 var::num () {return val.num; }
|
||||
inline string& var::str () {return *val.gcobj->ptr.str; }
|
||||
inline nas_vec& var::vec () {return *val.gcobj->ptr.vec; }
|
||||
inline nas_hash& var::hash () {return *val.gcobj->ptr.hash; }
|
||||
inline nas_func& var::func () {return *val.gcobj->ptr.func; }
|
||||
inline nas_upval& var::upval() {return *val.gcobj->ptr.upval;}
|
||||
inline nas_obj& var::obj () {return *val.gcobj->ptr.obj; }
|
||||
inline nas_co& var::co () {return *val.gcobj->ptr.co; }
|
||||
var* var::addr () {return val.addr; }
|
||||
u32 var::ret () {return val.ret; }
|
||||
i64& var::cnt () {return val.cnt; }
|
||||
f64 var::num () {return val.num; }
|
||||
string& var::str () {return *val.gcobj->ptr.str; }
|
||||
nas_vec& var::vec () {return *val.gcobj->ptr.vec; }
|
||||
nas_hash& var::hash () {return *val.gcobj->ptr.hash; }
|
||||
nas_func& var::func () {return *val.gcobj->ptr.func; }
|
||||
nas_upval& var::upval() {return *val.gcobj->ptr.upval;}
|
||||
nas_obj& var::obj () {return *val.gcobj->ptr.obj; }
|
||||
nas_co& var::co () {return *val.gcobj->ptr.co; }
|
||||
|
||||
const var zero={vm_num,(f64)0};
|
||||
const var one ={vm_num,(f64)1};
|
||||
|
|
|
@ -238,28 +238,31 @@ string lexer::utf8_gen() {
|
|||
while(ptr<res.size() && res[ptr]<0) {
|
||||
string tmp="";
|
||||
u32 nbytes=utf8_hdchk(res[ptr]);
|
||||
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 {
|
||||
if (!nbytes) {
|
||||
++ptr;
|
||||
++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;
|
||||
}
|
||||
|
|
157
nasal_vm.h
157
nasal_vm.h
|
@ -313,12 +313,18 @@ void vm::die(const string& str) {
|
|||
std::cout<<"[vm] error: "<<str<<"\n";
|
||||
traceback();
|
||||
stackinfo();
|
||||
|
||||
// show verbose crash info
|
||||
if (verbose) {
|
||||
detail();
|
||||
}
|
||||
|
||||
if (ngc.stack==stack) {
|
||||
// in main context, exit directly
|
||||
std::exit(1);
|
||||
} else {
|
||||
// in coroutine, shut down the coroutine
|
||||
// and return to main context
|
||||
pc=0; // mark coroutine 'dead'
|
||||
ngc.ctxreserve();
|
||||
top[0]=nil;
|
||||
|
@ -330,48 +336,48 @@ inline bool vm::cond(var& val) {
|
|||
return val.num();
|
||||
} else if (val.type==vm_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;
|
||||
}
|
||||
|
||||
inline void vm::o_intg() {
|
||||
void vm::o_intg() {
|
||||
// global values store on stack
|
||||
top+=imm[pc];
|
||||
--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().lsize=imm[pc];
|
||||
}
|
||||
|
||||
inline void vm::o_loadg() {
|
||||
void vm::o_loadg() {
|
||||
stack[imm[pc]]=(top--)[0];
|
||||
}
|
||||
|
||||
inline void vm::o_loadl() {
|
||||
void vm::o_loadl() {
|
||||
localr[imm[pc]]=(top--)[0];
|
||||
}
|
||||
|
||||
inline void vm::o_loadu() {
|
||||
void vm::o_loadu() {
|
||||
funcr.func().upval[(imm[pc]>>16)&0xffff]
|
||||
.upval()[imm[pc]&0xffff]=(top--)[0];
|
||||
}
|
||||
|
||||
inline void vm::o_pnum() {
|
||||
void vm::o_pnum() {
|
||||
(++top)[0]={vm_num,cnum[imm[pc]]};
|
||||
}
|
||||
|
||||
inline void vm::o_pnil() {
|
||||
void vm::o_pnil() {
|
||||
(++top)[0]=nil;
|
||||
}
|
||||
|
||||
inline void vm::o_pstr() {
|
||||
void vm::o_pstr() {
|
||||
(++top)[0]=ngc.strs[imm[pc]];
|
||||
}
|
||||
|
||||
inline void vm::o_newv() {
|
||||
void vm::o_newv() {
|
||||
var newv=ngc.alloc(vm_vec);
|
||||
auto& vec=newv.vec().elems;
|
||||
vec.resize(imm[pc]);
|
||||
|
@ -383,11 +389,11 @@ inline void vm::o_newv() {
|
|||
top[0]=newv;
|
||||
}
|
||||
|
||||
inline void vm::o_newh() {
|
||||
void vm::o_newh() {
|
||||
(++top)[0]=ngc.alloc(vm_hash);
|
||||
}
|
||||
|
||||
inline void vm::o_newf() {
|
||||
void vm::o_newf() {
|
||||
(++top)[0]=ngc.alloc(vm_func);
|
||||
nas_func& func=top[0].func();
|
||||
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;
|
||||
}
|
||||
|
||||
inline void vm::o_para() {
|
||||
void vm::o_para() {
|
||||
nas_func& func=top[0].func();
|
||||
// func->size has 1 place reserved for "me"
|
||||
func.keys[imm[pc]]=func.psize;
|
||||
func.local[func.psize++]={vm_none};
|
||||
}
|
||||
|
||||
inline void vm::o_deft() {
|
||||
void vm::o_deft() {
|
||||
var val=top[0];
|
||||
nas_func& func=(--top)[0].func();
|
||||
// func->size has 1 place reserved for "me"
|
||||
|
@ -426,11 +432,11 @@ inline void vm::o_deft() {
|
|||
func.local[func.psize++]=val;
|
||||
}
|
||||
|
||||
inline void vm::o_dyn() {
|
||||
void vm::o_dyn() {
|
||||
top[0].func().dpara=imm[pc];
|
||||
}
|
||||
|
||||
inline void vm::o_unot() {
|
||||
void vm::o_unot() {
|
||||
var val=top[0];
|
||||
switch(val.type) {
|
||||
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()};
|
||||
}
|
||||
|
||||
|
@ -458,11 +464,11 @@ inline void vm::o_usub() {
|
|||
top[-1]={vm_num,top[-1].tonum() type top[0].tonum()};\
|
||||
--top;
|
||||
|
||||
inline void vm::o_add() {op_calc(+);}
|
||||
inline void vm::o_sub() {op_calc(-);}
|
||||
inline void vm::o_mul() {op_calc(*);}
|
||||
inline void vm::o_div() {op_calc(/);}
|
||||
inline void vm::o_lnk() {
|
||||
void vm::o_add() {op_calc(+);}
|
||||
void vm::o_sub() {op_calc(-);}
|
||||
void vm::o_mul() {op_calc(*);}
|
||||
void vm::o_div() {op_calc(/);}
|
||||
void vm::o_lnk() {
|
||||
top[-1]=ngc.newstr(top[-1].tostr()+top[0].tostr());
|
||||
--top;
|
||||
}
|
||||
|
@ -470,11 +476,11 @@ inline void vm::o_lnk() {
|
|||
#define op_calc_const(type)\
|
||||
top[0]={vm_num,top[0].tonum() type cnum[imm[pc]]};
|
||||
|
||||
inline void vm::o_addc() {op_calc_const(+);}
|
||||
inline void vm::o_subc() {op_calc_const(-);}
|
||||
inline void vm::o_mulc() {op_calc_const(*);}
|
||||
inline void vm::o_divc() {op_calc_const(/);}
|
||||
inline void vm::o_lnkc() {
|
||||
void vm::o_addc() {op_calc_const(+);}
|
||||
void vm::o_subc() {op_calc_const(-);}
|
||||
void vm::o_mulc() {op_calc_const(*);}
|
||||
void vm::o_divc() {op_calc_const(/);}
|
||||
void vm::o_lnkc() {
|
||||
top[0]=ngc.newstr(top[0].tostr()+cstr[imm[pc]]);
|
||||
}
|
||||
|
||||
|
@ -483,11 +489,11 @@ inline void vm::o_lnkc() {
|
|||
memr=nullptr;\
|
||||
top-=imm[pc]+1;
|
||||
|
||||
inline void vm::o_addeq() {op_calc_eq(+);}
|
||||
inline void vm::o_subeq() {op_calc_eq(-);}
|
||||
inline void vm::o_muleq() {op_calc_eq(*);}
|
||||
inline void vm::o_diveq() {op_calc_eq(/);}
|
||||
inline void vm::o_lnkeq() {
|
||||
void vm::o_addeq() {op_calc_eq(+);}
|
||||
void vm::o_subeq() {op_calc_eq(-);}
|
||||
void vm::o_muleq() {op_calc_eq(*);}
|
||||
void vm::o_diveq() {op_calc_eq(/);}
|
||||
void vm::o_lnkeq() {
|
||||
top[-1]=memr[0]=ngc.newstr(memr[0].tostr()+top[-1].tostr());
|
||||
memr=nullptr;
|
||||
top-=imm[pc]+1;
|
||||
|
@ -498,17 +504,17 @@ inline void vm::o_lnkeq() {
|
|||
memr=nullptr;\
|
||||
top-=(imm[pc]>>31);
|
||||
|
||||
inline void vm::o_addeqc() {op_calc_eq_const(+);}
|
||||
inline void vm::o_subeqc() {op_calc_eq_const(-);}
|
||||
inline void vm::o_muleqc() {op_calc_eq_const(*);}
|
||||
inline void vm::o_diveqc() {op_calc_eq_const(/);}
|
||||
inline void vm::o_lnkeqc() {
|
||||
void vm::o_addeqc() {op_calc_eq_const(+);}
|
||||
void vm::o_subeqc() {op_calc_eq_const(-);}
|
||||
void vm::o_muleqc() {op_calc_eq_const(*);}
|
||||
void vm::o_diveqc() {op_calc_eq_const(/);}
|
||||
void vm::o_lnkeqc() {
|
||||
top[0]=memr[0]=ngc.newstr(memr[0].tostr()+cstr[imm[pc]&0x7fffffff]);
|
||||
memr=nullptr;
|
||||
top-=(imm[pc]>>31);
|
||||
}
|
||||
|
||||
inline void vm::o_meq() {
|
||||
void vm::o_meq() {
|
||||
// pop old memr[0] and replace it
|
||||
// the reason why we should get memr and push the old value on stack
|
||||
// is that when lnkeq/lnkeqc is called, there will be
|
||||
|
@ -519,7 +525,7 @@ inline void vm::o_meq() {
|
|||
top-=imm[pc]+1;
|
||||
}
|
||||
|
||||
inline void vm::o_eq() {
|
||||
void vm::o_eq() {
|
||||
var val2=top[0];
|
||||
var val1=(--top)[0];
|
||||
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 val1=(--top)[0];
|
||||
if (val1.type==vm_nil && val2.type==vm_nil) {
|
||||
|
@ -553,28 +559,28 @@ inline void vm::o_neq() {
|
|||
--top;\
|
||||
top[0]=(top[0].tonum() type top[1].tonum())?one:zero;
|
||||
|
||||
inline void vm::o_less() {op_cmp(<);}
|
||||
inline void vm::o_leq() {op_cmp(<=);}
|
||||
inline void vm::o_grt() {op_cmp(>);}
|
||||
inline void vm::o_geq() {op_cmp(>=);}
|
||||
void vm::o_less() {op_cmp(<);}
|
||||
void vm::o_leq() {op_cmp(<=);}
|
||||
void vm::o_grt() {op_cmp(>);}
|
||||
void vm::o_geq() {op_cmp(>=);}
|
||||
|
||||
#define op_cmp_const(type)\
|
||||
top[0]=(top[0].tonum() type cnum[imm[pc]])?one:zero;
|
||||
|
||||
inline void vm::o_lessc() {op_cmp_const(<);}
|
||||
inline void vm::o_leqc() {op_cmp_const(<=);}
|
||||
inline void vm::o_grtc() {op_cmp_const(>);}
|
||||
inline void vm::o_geqc() {op_cmp_const(>=);}
|
||||
void vm::o_lessc() {op_cmp_const(<);}
|
||||
void vm::o_leqc() {op_cmp_const(<=);}
|
||||
void vm::o_grtc() {op_cmp_const(>);}
|
||||
void vm::o_geqc() {op_cmp_const(>=);}
|
||||
|
||||
inline void vm::o_pop() {
|
||||
void vm::o_pop() {
|
||||
--top;
|
||||
}
|
||||
|
||||
inline void vm::o_jmp() {
|
||||
void vm::o_jmp() {
|
||||
pc=imm[pc]-1;
|
||||
}
|
||||
|
||||
inline void vm::o_jt() {
|
||||
void vm::o_jt() {
|
||||
// jump true needs to reserve the result on stack
|
||||
// because conditional expression in nasal has return value
|
||||
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
|
||||
if (!cond(top[0])) {
|
||||
pc=imm[pc]-1;
|
||||
|
@ -590,7 +596,7 @@ inline void vm::o_jf() {
|
|||
--top;
|
||||
}
|
||||
|
||||
inline void vm::o_cnt() {
|
||||
void vm::o_cnt() {
|
||||
if (top[0].type!=vm_vec) {
|
||||
die("must use vector in forindex/foreach");
|
||||
return;
|
||||
|
@ -598,7 +604,7 @@ inline void vm::o_cnt() {
|
|||
(++top)[0]={vm_cnt,(i64)-1};
|
||||
}
|
||||
|
||||
inline void vm::o_findex() {
|
||||
void vm::o_findex() {
|
||||
if ((usize)(++top[0].cnt())>=top[-1].vec().size()) {
|
||||
pc=imm[pc]-1;
|
||||
return;
|
||||
|
@ -607,7 +613,7 @@ inline void vm::o_findex() {
|
|||
++top;
|
||||
}
|
||||
|
||||
inline void vm::o_feach() {
|
||||
void vm::o_feach() {
|
||||
auto& ref=top[-1].vec().elems;
|
||||
if ((usize)(++top[0].cnt())>=ref.size()) {
|
||||
pc=imm[pc]-1;
|
||||
|
@ -617,20 +623,20 @@ inline void vm::o_feach() {
|
|||
++top;
|
||||
}
|
||||
|
||||
inline void vm::o_callg() {
|
||||
void vm::o_callg() {
|
||||
(++top)[0]=stack[imm[pc]];
|
||||
}
|
||||
|
||||
inline void vm::o_calll() {
|
||||
void vm::o_calll() {
|
||||
(++top)[0]=localr[imm[pc]];
|
||||
}
|
||||
|
||||
inline void vm::o_upval() {
|
||||
void vm::o_upval() {
|
||||
(++top)[0]=funcr.func().upval[(imm[pc]>>16)&0xffff]
|
||||
.upval()[imm[pc]&0xffff];
|
||||
}
|
||||
|
||||
inline void vm::o_callv() {
|
||||
void vm::o_callv() {
|
||||
var val=top[0];
|
||||
var vec=(--top)[0];
|
||||
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];
|
||||
if (val.type!=vm_vec) {
|
||||
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];
|
||||
if (val.type!=vm_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
|
||||
var* local=top-argc+1; // arguments begin address
|
||||
if (local[-1].type!=vm_func) {
|
||||
|
@ -753,7 +759,7 @@ inline void vm::o_callfv() {
|
|||
upvalr=nil;
|
||||
}
|
||||
|
||||
inline void vm::o_callfh() {
|
||||
void vm::o_callfh() {
|
||||
auto& hash=top[0].hash().elems;
|
||||
if (top[-1].type!=vm_func) {
|
||||
die("must call a function");
|
||||
|
@ -797,7 +803,7 @@ inline void vm::o_callfh() {
|
|||
upvalr=nil;
|
||||
}
|
||||
|
||||
inline void vm::o_callb() {
|
||||
void vm::o_callb() {
|
||||
// reserve place for builtin function return,
|
||||
// in fact this code is changed because of coroutine
|
||||
(++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]
|
||||
// +--------------+
|
||||
|
@ -824,12 +830,12 @@ inline void vm::o_slcbeg() {
|
|||
}
|
||||
}
|
||||
|
||||
inline void vm::o_slcend() {
|
||||
void vm::o_slcend() {
|
||||
top[-1]=top[0];
|
||||
--top;
|
||||
}
|
||||
|
||||
inline void vm::o_slc() {
|
||||
void vm::o_slc() {
|
||||
var val=(top--)[0];
|
||||
var res=top[-1].vec().get_val(val.tonum());
|
||||
if (res.type==vm_none) {
|
||||
|
@ -839,7 +845,7 @@ inline void vm::o_slc() {
|
|||
top[0].vec().elems.push_back(res);
|
||||
}
|
||||
|
||||
inline void vm::o_slc2() {
|
||||
void vm::o_slc2() {
|
||||
var val2=(top--)[0];
|
||||
var val1=(top--)[0];
|
||||
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];
|
||||
(++top)[0]=memr[0];
|
||||
// push value in this memory space on stack
|
||||
// to avoid being garbage collected
|
||||
}
|
||||
|
||||
inline void vm::o_mcalll() {
|
||||
void vm::o_mcalll() {
|
||||
memr=localr+imm[pc];
|
||||
(++top)[0]=memr[0];
|
||||
// push value in this memory space on stack
|
||||
// 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]);
|
||||
(++top)[0]=memr[0];
|
||||
// push value in this memory space on stack
|
||||
// to avoid being garbage collected
|
||||
}
|
||||
|
||||
inline void vm::o_mcallv() {
|
||||
void vm::o_mcallv() {
|
||||
var val=top[0]; // index
|
||||
var vec=(--top)[0]; // mcall vector, reserved on stack to avoid gc
|
||||
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
|
||||
if (hash.type!=vm_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]
|
||||
* +-------------+
|
||||
|
@ -974,6 +980,7 @@ inline void vm::o_ret() {
|
|||
ngc.ctxreserve();
|
||||
}
|
||||
}
|
||||
|
||||
void vm::run(
|
||||
const codegen& gen,
|
||||
const linker& linker,
|
||||
|
|
|
@ -28,6 +28,7 @@ var run=func(width,height){
|
|||
if(_width>=width) _width=0;
|
||||
return map[_height][_width]=='O';
|
||||
}
|
||||
|
||||
# enable ANSI escape sequence
|
||||
if(os.platform()=="windows")
|
||||
system("color");
|
||||
|
@ -55,43 +56,48 @@ var run=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
|
||||
var iter_to_print=0;
|
||||
|
||||
var init=func(){
|
||||
var res=new_map(width,height);
|
||||
var res=new_map();
|
||||
if(io.exists(".life_data")) {
|
||||
var vec=split("\n",io.fin(".life_data"));
|
||||
if (num(vec[0])!=width or num(vec[1])!=height) {
|
||||
die("incorrect width or height: "~vec[0]~":"~str(width)~" / "~vec[1]~":"~str(height))
|
||||
}
|
||||
iter_to_print=num(vec[2]);
|
||||
var data=split("",vec[3]);
|
||||
for(var i=0;i<height;i+=1)
|
||||
for(var j=0;j<width;j+=1)
|
||||
res[i][j]=num(data[i*width+j]);
|
||||
var data=vec[3];
|
||||
var n="1"[0];
|
||||
for(var i=0;i<pixels;i+=1){
|
||||
res[i]=data[i]==n?1:0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
rand(time(0));
|
||||
for(var i=0;i<height;i+=1)
|
||||
for(var j=0;j<width;j+=1)
|
||||
res[i][j]=0;
|
||||
for(var i=0;i<pixels;i+=1)
|
||||
res[i]=0;
|
||||
|
||||
for(var i=int(height/5*2);i<int(height/5*3);i+=1)
|
||||
forindex(var j;res[i])
|
||||
res[i][j]=rand()<0.5?1:0;
|
||||
res[i*width+j]=rand()<0.5?1:0;
|
||||
return res;
|
||||
}
|
||||
|
||||
var store=func(){
|
||||
var fd=io.open(".life_data","w");
|
||||
io.write(fd,str(width)~"\n"~str(height)~"\n"~str(iter_to_print)~"\n");
|
||||
for(var i=0;i<height;i+=1){
|
||||
for(var j=0;j<width;j+=1){
|
||||
io.write(fd,map[i][j]==1?"1":"0");
|
||||
}
|
||||
for(var i=0;i<pixels;i+=1){
|
||||
io.write(fd,map[i]==1?"1":"0");
|
||||
}
|
||||
io.close(fd);
|
||||
}
|
||||
|
@ -103,24 +109,21 @@ var ppm_gen=func(width,height){
|
|||
io.write(fd,"P6\n"~width~" "~height~"\n255\n");
|
||||
var white=char(255)~char(255)~char(255);
|
||||
var black=char(0)~char(0)~char(0);
|
||||
for(var i=0;i<height;i+=1){
|
||||
for(var j=0;j<width;j+=1){
|
||||
var s=map[i][j]==1?white:black;
|
||||
io.write(fd,s);
|
||||
}
|
||||
for(var i=0;i<pixels;i+=1){
|
||||
io.write(fd,map[i]==1?white:black);
|
||||
}
|
||||
io.close(fd);
|
||||
}
|
||||
|
||||
var ts=maketimestamp();
|
||||
var bar=process_bar.high_resolution_bar(80);
|
||||
var bar=process_bar.high_resolution_bar(50);
|
||||
var map=init();
|
||||
var tmp=new_map(width,height);
|
||||
var tmp=new_map();
|
||||
|
||||
var check=func(_width,_height){
|
||||
if(_height>=height) _height=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){
|
||||
|
@ -128,9 +131,9 @@ var ppm_gen=func(width,height){
|
|||
for(var i=0;i<height;i+=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);
|
||||
if(cnt==2) tmp[i][j]=map[i][j];
|
||||
elsif(cnt==3) tmp[i][j]=1;
|
||||
else tmp[i][j]=0;
|
||||
if(cnt==2) tmp[i*width+j]=map[i*width+j];
|
||||
elsif(cnt==3) tmp[i*width+j]=1;
|
||||
else tmp[i*width+j]=0;
|
||||
}
|
||||
}
|
||||
(map,tmp)=(tmp,map);
|
||||
|
|
|
@ -12,19 +12,19 @@ var unicode测试=func(){
|
|||
var emoji测试=func(){
|
||||
var 💻=print;
|
||||
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 🗄️={
|
||||
🤣:🤣,
|
||||
|
|
Loading…
Reference in New Issue