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;
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');

View File

@ -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):

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");
}
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;

View File

@ -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};

View File

@ -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;
}

View File

@ -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,

View File

@ -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);

View File

@ -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 🗄️={
🤣:🤣,