From 2c851613ce36cfaf5f68e73149f9b0cd5b21d793 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Fri, 17 May 2024 00:10:24 +0800 Subject: [PATCH 01/21] :memo: update docs --- README.md | 50 +++-- doc/README_zh.md | 50 +++-- std/runtime.nas | 42 ++-- test/console3D.nas | 500 ++++++++++++++++++++++----------------------- 4 files changed, 326 insertions(+), 316 deletions(-) diff --git a/README.md b/README.md index f5a72e8..5fd0fd0 100644 --- a/README.md +++ b/README.md @@ -337,9 +337,8 @@ and the debugger will print this: ```javascript source code: ---> var fib=func(x) - { - if(x<2) return x; +--> var fib = func(x) { + if (x<2) return x; return fib(x-1)+fib(x-2); } for(var i=0;i<31;i+=1) @@ -347,16 +346,16 @@ source code: next bytecode: - 0x000848 4a 00 00 01 callfv 0x1(std/lib.nas:427) - 0x000849 3d 00 00 00 pop 0x0(std/lib.nas:427) - 0x00084a 07 00 00 00 pnil 0x0(std/lib.nas:423) - 0x00084b 56 00 00 00 ret 0x0(std/lib.nas:423) - 0x00084c 03 00 00 5e loadg 0x5e(std/lib.nas:423) ---> 0x00084d 0b 00 08 51 newf 0x851(test/fib.nas:1) - 0x00084e 02 00 00 03 intl 0x3(test/fib.nas:1) - 0x00084f 0d 00 00 08 para 0x8 (x)(test/fib.nas:1) + 0x0003a8 07:00 00 00 00 00 00 00 00 pnil 0x0 (std/lib.nas:413) + 0x0003a9 56:00 00 00 00 00 00 00 00 ret 0x0 (std/lib.nas:413) + 0x0003aa 03:00 00 00 00 00 00 00 56 loadg 0x56 (std/lib.nas:413) +--> 0x0003ab 0b:00 00 00 00 00 00 03 af newf 0x3af (test/fib.nas:1) + 0x0003ac 02:00 00 00 00 00 00 00 03 intl 0x3 (test/fib.nas:1) + 0x0003ad 0d:00 00 00 00 00 00 00 22 para 0x22 (x) (test/fib.nas:1) + 0x0003ae 3e:00 00 00 00 00 00 03 be jmp 0x3be (test/fib.nas:1) + 0x0003af 45:00 00 00 00 00 00 00 01 calll 0x1 (test/fib.nas:2) -stack (0x55ccd0a1b9d0, limit 10, total 0) +vm stack (0x7fca7e9f1010, limit 16, total 0) >> ``` @@ -371,9 +370,8 @@ This will help you debugging or learning how the vm works: ```javascript source code: - var fib=func(x) - { ---> if(x<2) return x; + var fib = func(x) { +--> if (x<2) return x; return fib(x-1)+fib(x-2); } for(var i=0;i<31;i+=1) @@ -381,24 +379,24 @@ source code: next bytecode: - 0x000850 3e 00 08 60 jmp 0x860(test/fib.nas:1) ---> 0x000851 45 00 00 01 calll 0x1(test/fib.nas:3) - 0x000852 39 00 00 07 lessc 0x7 (2)(test/fib.nas:3) - 0x000853 40 00 08 56 jf 0x856(test/fib.nas:3) - 0x000854 45 00 00 01 calll 0x1(test/fib.nas:3) - 0x000855 56 00 00 00 ret 0x0(test/fib.nas:3) - 0x000856 44 00 00 5f callg 0x5f(test/fib.nas:4) - 0x000857 45 00 00 01 calll 0x1(test/fib.nas:4) + 0x0003a8 07:00 00 00 00 00 00 00 00 pnil 0x0 (std/lib.nas:413) + 0x0003a9 56:00 00 00 00 00 00 00 00 ret 0x0 (std/lib.nas:413) + 0x0003aa 03:00 00 00 00 00 00 00 56 loadg 0x56 (std/lib.nas:413) + 0x0003ab 0b:00 00 00 00 00 00 03 af newf 0x3af (test/fib.nas:1) + 0x0003ac 02:00 00 00 00 00 00 00 03 intl 0x3 (test/fib.nas:1) + 0x0003ad 0d:00 00 00 00 00 00 00 22 para 0x22 (x) (test/fib.nas:1) + 0x0003ae 3e:00 00 00 00 00 00 03 be jmp 0x3be (test/fib.nas:1) +--> 0x0003af 45:00 00 00 00 00 00 00 01 calll 0x1 (test/fib.nas:2) -stack (0x55ccd0a1b9d0, limit 10, total 8) - 0x000007 | pc | 0x869 +vm stack (0x7fca7e9f1010, limit 16, total 8) + 0x000007 | pc | 0x3c7 0x000006 | addr | 0x0 0x000005 | nil | 0x000004 | nil | 0x000003 | num | 0 0x000002 | nil | 0x000001 | nil | - 0x000000 | func | <0x55ccd0a58fa0> entry:0x487 + 0x000000 | func | <0x5573f66ef5f0> func(elems...) {..} >> ``` diff --git a/doc/README_zh.md b/doc/README_zh.md index 2f655e9..77f6480 100644 --- a/doc/README_zh.md +++ b/doc/README_zh.md @@ -322,9 +322,8 @@ local (0x55dcb5b43190 <+7>) ```javascript source code: ---> var fib=func(x) - { - if(x<2) return x; +--> var fib = func(x) { + if (x<2) return x; return fib(x-1)+fib(x-2); } for(var i=0;i<31;i+=1) @@ -332,16 +331,16 @@ source code: next bytecode: - 0x000848 4a 00 00 01 callfv 0x1(std/lib.nas:427) - 0x000849 3d 00 00 00 pop 0x0(std/lib.nas:427) - 0x00084a 07 00 00 00 pnil 0x0(std/lib.nas:423) - 0x00084b 56 00 00 00 ret 0x0(std/lib.nas:423) - 0x00084c 03 00 00 5e loadg 0x5e(std/lib.nas:423) ---> 0x00084d 0b 00 08 51 newf 0x851(test/fib.nas:1) - 0x00084e 02 00 00 03 intl 0x3(test/fib.nas:1) - 0x00084f 0d 00 00 08 para 0x8 (x)(test/fib.nas:1) + 0x0003a8 07:00 00 00 00 00 00 00 00 pnil 0x0 (std/lib.nas:413) + 0x0003a9 56:00 00 00 00 00 00 00 00 ret 0x0 (std/lib.nas:413) + 0x0003aa 03:00 00 00 00 00 00 00 56 loadg 0x56 (std/lib.nas:413) +--> 0x0003ab 0b:00 00 00 00 00 00 03 af newf 0x3af (test/fib.nas:1) + 0x0003ac 02:00 00 00 00 00 00 00 03 intl 0x3 (test/fib.nas:1) + 0x0003ad 0d:00 00 00 00 00 00 00 22 para 0x22 (x) (test/fib.nas:1) + 0x0003ae 3e:00 00 00 00 00 00 03 be jmp 0x3be (test/fib.nas:1) + 0x0003af 45:00 00 00 00 00 00 00 01 calll 0x1 (test/fib.nas:2) -stack (0x55ccd0a1b9d0, limit 10, total 0) +vm stack (0x7fca7e9f1010, limit 16, total 0) >> ``` @@ -356,9 +355,8 @@ stack (0x55ccd0a1b9d0, limit 10, total 0) ```javascript source code: - var fib=func(x) - { ---> if(x<2) return x; + var fib = func(x) { +--> if (x<2) return x; return fib(x-1)+fib(x-2); } for(var i=0;i<31;i+=1) @@ -366,24 +364,24 @@ source code: next bytecode: - 0x000850 3e 00 08 60 jmp 0x860(test/fib.nas:1) ---> 0x000851 45 00 00 01 calll 0x1(test/fib.nas:3) - 0x000852 39 00 00 07 lessc 0x7 (2)(test/fib.nas:3) - 0x000853 40 00 08 56 jf 0x856(test/fib.nas:3) - 0x000854 45 00 00 01 calll 0x1(test/fib.nas:3) - 0x000855 56 00 00 00 ret 0x0(test/fib.nas:3) - 0x000856 44 00 00 5f callg 0x5f(test/fib.nas:4) - 0x000857 45 00 00 01 calll 0x1(test/fib.nas:4) + 0x0003a8 07:00 00 00 00 00 00 00 00 pnil 0x0 (std/lib.nas:413) + 0x0003a9 56:00 00 00 00 00 00 00 00 ret 0x0 (std/lib.nas:413) + 0x0003aa 03:00 00 00 00 00 00 00 56 loadg 0x56 (std/lib.nas:413) + 0x0003ab 0b:00 00 00 00 00 00 03 af newf 0x3af (test/fib.nas:1) + 0x0003ac 02:00 00 00 00 00 00 00 03 intl 0x3 (test/fib.nas:1) + 0x0003ad 0d:00 00 00 00 00 00 00 22 para 0x22 (x) (test/fib.nas:1) + 0x0003ae 3e:00 00 00 00 00 00 03 be jmp 0x3be (test/fib.nas:1) +--> 0x0003af 45:00 00 00 00 00 00 00 01 calll 0x1 (test/fib.nas:2) -stack (0x55ccd0a1b9d0, limit 10, total 8) - 0x000007 | pc | 0x869 +vm stack (0x7fca7e9f1010, limit 16, total 8) + 0x000007 | pc | 0x3c7 0x000006 | addr | 0x0 0x000005 | nil | 0x000004 | nil | 0x000003 | num | 0 0x000002 | nil | 0x000001 | nil | - 0x000000 | func | <0x55ccd0a58fa0> entry:0x487 + 0x000000 | func | <0x5573f66ef5f0> func(elems...) {..} >> ``` diff --git a/std/runtime.nas b/std/runtime.nas index b6edeaf..bad3203 100644 --- a/std/runtime.nas +++ b/std/runtime.nas @@ -1,13 +1,29 @@ -# runtime.nas -# 2023 by ValKmjolnir -# runtime gives us some functions that we could manage it manually. - -# command line arguments -var argv = func() { - return globals.arg; -} - -var gc = { - extend: func(type) {return __gcextd;}, - info: func() {return __gcinfo;} -}; +# runtime.nas +# 2023 by ValKmjolnir +# runtime gives us some functions that we could manage it manually. + +# command line arguments +var argv = func() { + return globals.arg; +} + +var _gc_extend = func(type) { + return __gcextd; +} + +var gc = { + extend: func(type, times = 1) { + if (times<=0) { + return nil; + } + if (times>16) { + times = 16; + } + + for(var i = 0; iedge; -} - -var vec3abs = func(v) { - return [abs(v[0]),abs(v[1]),abs(v[2])]; -} -var vec3sign = func(v) { - return [sign(v[0]),sign(v[1]),sign(v[2])]; -} -var vec3step = func(edge,v) { - return [step(edge[0],v[0]),step(edge[1],v[1]),step(edge[2],v[2])]; -} -var vec3reflect = func(rd,n) { - var d=vec3dot(n,rd); - return vec3sub(rd,vec3mul(n,vec3mul([2,2,2],[d,d,d]))); -} - -var sphere = func(ro,rd,r) { - var b=vec3dot(ro,rd); - var c=vec3dot(ro,ro)-r*r; - var h=b*b-c; - if (h<0.0) return [-1.0,-1.0]; - h=sqrt(h); - return [-b-h,-b+h]; -} - -var box = func(ro,rd,boxSize,outNormal) { - var m=vec3div([1.0,1.0,1.0],rd); - var n=vec3mul(m,ro); - var k=vec3mul(vec3abs(m),boxSize); - var t1=vec3sub(vec3neg(n),k); - var t2=vec3add(vec3neg(n),k); - var tN=max(max(t1[0],t1[1]),t1[2]); - var tF=min(min(t2[0],t2[1]),t2[2]); - if (tN>tF or tF<0.0) return [-1.0,-1.0]; - var yzx=[t1[1],t1[2],t1[0]]; - var zxy=[t1[2],t1[0],t1[1]]; - var tmp=vec3mul(vec3mul(vec3neg(vec3sign(rd)), vec3step(yzx,t1)),vec3step(zxy,t1)); - outNormal[0]=tmp[0]; - outNormal[1]=tmp[1]; - outNormal[2]=tmp[2]; - return [tN, tF]; -} - -var plane = func(ro,rd,p,w) { - return -(vec3dot(ro,p)+w)/vec3dot(rd,p); -} - -var main = func(frame) { - - var height=15*2; - var width=int(height*1/0.618)*2; - - var aspect=width/height; - var pixelAspect=11.0/24.0; - - var gradient=split(""," .:!/r(l1Z4H9W8$"); - var gradientSize=size(gradient)-1; - - var screen=[]; - setsize(screen,width*height); - - var light=vec3norm([-0.5,0.5,-1.0]); - var spherePos=[0,3,0]; - var vec2_2_2=[2,2]; - var vec2_1_1=[1,1]; - var vec3_000=[0,0,0]; - var vec3_00n1=[0,0,-1]; - var vec3_111=[1,1,1]; - - print("\e[2J"); - var stamp=maketimestamp(); - for(var t=0;t0) { - var itPoint=vec3add(vec3sub(ro,spherePos),vec3mul(rd,[intersection[0],intersection[0],intersection[0]])); - minIt=intersection[0]; - n=vec3norm(itPoint); - } - var boxN=[0,0,0]; - intersection=box(ro,rd,vec3_111,boxN); - if (intersection[0]>0 and intersection[0]0 and intersection[0]edge; +} + +var vec3abs = func(v) { + return [abs(v[0]),abs(v[1]),abs(v[2])]; +} +var vec3sign = func(v) { + return [sign(v[0]),sign(v[1]),sign(v[2])]; +} +var vec3step = func(edge,v) { + return [step(edge[0],v[0]),step(edge[1],v[1]),step(edge[2],v[2])]; +} +var vec3reflect = func(rd,n) { + var d=vec3dot(n,rd); + return vec3sub(rd,vec3mul(n,vec3mul([2,2,2],[d,d,d]))); +} + +var sphere = func(ro,rd,r) { + var b=vec3dot(ro,rd); + var c=vec3dot(ro,ro)-r*r; + var h=b*b-c; + if (h<0.0) return [-1.0,-1.0]; + h=sqrt(h); + return [-b-h,-b+h]; +} + +var box = func(ro,rd,boxSize,outNormal) { + var m=vec3div([1.0,1.0,1.0],rd); + var n=vec3mul(m,ro); + var k=vec3mul(vec3abs(m),boxSize); + var t1=vec3sub(vec3neg(n),k); + var t2=vec3add(vec3neg(n),k); + var tN=max(max(t1[0],t1[1]),t1[2]); + var tF=min(min(t2[0],t2[1]),t2[2]); + if (tN>tF or tF<0.0) return [-1.0,-1.0]; + var yzx=[t1[1],t1[2],t1[0]]; + var zxy=[t1[2],t1[0],t1[1]]; + var tmp=vec3mul(vec3mul(vec3neg(vec3sign(rd)), vec3step(yzx,t1)),vec3step(zxy,t1)); + outNormal[0]=tmp[0]; + outNormal[1]=tmp[1]; + outNormal[2]=tmp[2]; + return [tN, tF]; +} + +var plane = func(ro,rd,p,w) { + return -(vec3dot(ro,p)+w)/vec3dot(rd,p); +} + +var main = func(frame) { + + var height=15*2; + var width=int(height*1/0.618)*2; + + var aspect=width/height; + var pixelAspect=11.0/24.0; + + var gradient=split(""," .:!/r(l1Z4H9W8$"); + var gradientSize=size(gradient)-1; + + var screen=[]; + setsize(screen,width*height); + + var light=vec3norm([-0.5,0.5,-1.0]); + var spherePos=[0,3,0]; + var vec2_2_2=[2,2]; + var vec2_1_1=[1,1]; + var vec3_000=[0,0,0]; + var vec3_00n1=[0,0,-1]; + var vec3_111=[1,1,1]; + + print("\e[2J"); + var stamp=maketimestamp(); + for(var t=0;t0) { + var itPoint=vec3add(vec3sub(ro,spherePos),vec3mul(rd,[intersection[0],intersection[0],intersection[0]])); + minIt=intersection[0]; + n=vec3norm(itPoint); + } + var boxN=[0,0,0]; + intersection=box(ro,rd,vec3_111,boxN); + if (intersection[0]>0 and intersection[0]0 and intersection[0] Date: Tue, 21 May 2024 23:31:21 +0800 Subject: [PATCH 02/21] :memo: rename lexical tokens --- module/keyboard.cpp | 3 +- src/nasal_codegen.cpp | 4 +- src/nasal_gc.cpp | 2 +- src/nasal_lexer.cpp | 57 +++- src/nasal_lexer.h | 228 ++++++++-------- src/nasal_parse.cpp | 611 ++++++++++++++++++++++-------------------- src/nasal_parse.h | 115 ++++---- src/nasal_vm.h | 21 +- src/repl.cpp | 12 +- 9 files changed, 564 insertions(+), 489 deletions(-) diff --git a/module/keyboard.cpp b/module/keyboard.cpp index 6fbf05b..875ed9a 100644 --- a/module/keyboard.cpp +++ b/module/keyboard.cpp @@ -34,7 +34,8 @@ public: tcgetattr(0, &init_termios); new_termios = init_termios; new_termios.c_lflag &= ~(ICANON|ECHO|ECHONL|ECHOE); - // vmin=0 is nonblock input, but in wsl there is a bug that will block input + // vmin = 0 is nonblock input, + // but in wsl1 there is a bug that will block input // so we use fcntl to write the nonblock input new_termios.c_cc[VMIN] = 1; new_termios.c_cc[VTIME] = 0; diff --git a/src/nasal_codegen.cpp b/src/nasal_codegen.cpp index ab5e42e..06f7ea9 100644 --- a/src/nasal_codegen.cpp +++ b/src/nasal_codegen.cpp @@ -239,9 +239,9 @@ void codegen::func_gen(function* node) { } } - usize newf=code.size(); + const auto newf = code.size(); emit(op_newf, 0, node->get_location()); - usize lsize=code.size(); + const auto lsize = code.size(); emit(op_intl, 0, node->get_location()); // add special keyword 'me' into symbol table diff --git a/src/nasal_gc.cpp b/src/nasal_gc.cpp index 8d874b8..dea4acf 100644 --- a/src/nasal_gc.cpp +++ b/src/nasal_gc.cpp @@ -380,7 +380,7 @@ void gc::context_change(nas_co* co) { } void gc::context_reserve() { - // pc=0 means this coroutine is finished + // pc = 0 means this coroutine is finished cort->status = running_context->pc? nas_co::status::suspended: nas_co::status::dead; diff --git a/src/nasal_lexer.cpp b/src/nasal_lexer.cpp index 8e9da33..c066ee8 100644 --- a/src/nasal_lexer.cpp +++ b/src/nasal_lexer.cpp @@ -96,7 +96,7 @@ void lexer::open(const std::string& file) { } tok lexer::get_type(const std::string& str) { - return token_mapper.count(str)? token_mapper.at(str):tok::null; + return token_mapper.count(str)? token_mapper.at(str):tok::tk_null; } std::string lexer::utf8_gen() { @@ -152,7 +152,8 @@ token lexer::id_gen() { tok type = get_type(str); return { {begin_line, begin_column, line, column, filename}, - (type!=tok::null)? type:tok::id, str + (type!=tok::tk_null)? type:tok::tk_id, + str }; } @@ -174,7 +175,11 @@ token lexer::num_gen() { "invalid number `"+str+"`" ); } - return {{begin_line, begin_column, line, column, filename}, tok::num, str}; + return { + {begin_line, begin_column, line, column, filename}, + tok::tk_num, + str + }; } else if (ptr+1 [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*) @@ -213,7 +222,11 @@ token lexer::num_gen() { {begin_line, begin_column, line, column, filename}, "invalid number `"+str+"`" ); - return {{begin_line, begin_column, line, column, filename}, tok::num, "0"}; + return { + {begin_line, begin_column, line, column, filename}, + tok::tk_num, + "0" + }; } } if (ptr"}); + toks.push_back({toks.back().loc, tok::tk_eof, ""}); } else { // if token sequence is empty, generate a default location - toks.push_back({{line, column, line, column, filename}, tok::eof, ""}); + toks.push_back({ + {line, column, line, column, filename}, + tok::tk_eof, + "" + }); } res = ""; return err; diff --git a/src/nasal_lexer.h b/src/nasal_lexer.h index 461b03d..3a00f2b 100644 --- a/src/nasal_lexer.h +++ b/src/nasal_lexer.h @@ -16,66 +16,66 @@ namespace nasal { -enum class tok:u32 { - null=0, // null token (default token type) - num, // number literal - str, // string literal - id, // identifier - tktrue, // keyword true - tkfalse, // keyword false - use, // keyword use - rfor, // loop keyword for - forindex, // loop keyword forindex - foreach, // loop keyword foreach - rwhile, // loop keyword while - var, // keyword for definition - func, // keyword for definition of function - brk, // loop keyword break - cont, // loop keyword continue - ret, // function keyword return - rif, // condition expression keyword if - elsif, // condition expression keyword elsif - relse, // condition expression keyword else - nil, // nil literal - lcurve, // ( - rcurve, // ) - lbracket, // [ - rbracket, // ] - lbrace, // { - rbrace, // } - semi, // ; - opand, // operator and - opor, // operator or - comma, // , - dot, // . - ellipsis, // ... - quesmark, // ? - colon, // : - add, // operator + - sub, // operator - - mult, // operator * - div, // operator / - floater, // operator ~ and binary operator ~ - btand, // bitwise operator & - btor, // bitwise operator | - btxor, // bitwise operator ^ - opnot, // operator ! - eq, // operator = - addeq, // operator += - subeq, // operator -= - multeq, // operator *= - diveq, // operator /= - lnkeq, // operator ~= - btandeq, // operator &= - btoreq, // operator |= - btxoreq, // operator ^= - cmpeq, // operator == - neq, // operator != - less, // operator < - leq, // operator <= - grt, // operator > - geq, // operator >= - eof // end of token list +enum class tok { + tk_null = 0, // null token (default token type) + tk_num, // number literal + tk_str, // string literal + tk_id, // identifier + tk_true, // keyword true + tk_false, // keyword false + tk_use, // keyword use + tk_for, // loop keyword for + tk_forindex, // loop keyword forindex + tk_foreach, // loop keyword foreach + tk_while, // loop keyword while + tk_var, // keyword for definition + tk_func, // keyword for definition of function + tk_brk, // loop keyword break + tk_cont, // loop keyword continue + tk_ret, // function keyword return + tk_if, // condition expression keyword if + tk_elsif, // condition expression keyword elsif + tk_else, // condition expression keyword else + tk_nil, // nil literal + tk_lcurve, // ( + tk_rcurve, // ) + tk_lbracket, // [ + tk_rbracket, // ] + tk_lbrace, // { + tk_rbrace, // } + tk_semi, // ; + tk_and, // operator and + tk_or, // operator or + tk_comma, // , + tk_dot, // . + tk_ellipsis, // ... + tk_quesmark, // ? + tk_colon, // : + tk_add, // operator + + tk_sub, // operator - + tk_mult, // operator * + tk_div, // operator / + tk_floater, // operator ~ and binary operator ~ + tk_btand, // bitwise operator & + tk_btor, // bitwise operator | + tk_btxor, // bitwise operator ^ + tk_not, // operator ! + tk_eq, // operator = + tk_addeq, // operator += + tk_subeq, // operator -= + tk_multeq, // operator *= + tk_diveq, // operator /= + tk_lnkeq, // operator ~= + tk_btandeq, // operator &= + tk_btoreq, // operator |= + tk_btxoreq, // operator ^= + tk_cmpeq, // operator == + tk_neq, // operator != + tk_less, // operator < + tk_leq, // operator <= + tk_grt, // operator > + tk_geq, // operator >= + tk_eof // end of token list }; struct token { @@ -99,60 +99,60 @@ private: std::vector toks; const std::unordered_map token_mapper = { - {"use" ,tok::use }, - {"true" ,tok::tktrue }, - {"false" ,tok::tkfalse }, - {"for" ,tok::rfor }, - {"forindex",tok::forindex}, - {"foreach" ,tok::foreach }, - {"while" ,tok::rwhile }, - {"var" ,tok::var }, - {"func" ,tok::func }, - {"break" ,tok::brk }, - {"continue",tok::cont }, - {"return" ,tok::ret }, - {"if" ,tok::rif }, - {"elsif" ,tok::elsif }, - {"else" ,tok::relse }, - {"nil" ,tok::nil }, - {"(" ,tok::lcurve }, - {")" ,tok::rcurve }, - {"[" ,tok::lbracket}, - {"]" ,tok::rbracket}, - {"{" ,tok::lbrace }, - {"}" ,tok::rbrace }, - {";" ,tok::semi }, - {"and" ,tok::opand }, - {"or" ,tok::opor }, - {"," ,tok::comma }, - {"." ,tok::dot }, - {"..." ,tok::ellipsis}, - {"?" ,tok::quesmark}, - {":" ,tok::colon }, - {"+" ,tok::add }, - {"-" ,tok::sub }, - {"*" ,tok::mult }, - {"/" ,tok::div }, - {"~" ,tok::floater }, - {"&" ,tok::btand }, - {"|" ,tok::btor }, - {"^" ,tok::btxor }, - {"!" ,tok::opnot }, - {"=" ,tok::eq }, - {"+=" ,tok::addeq }, - {"-=" ,tok::subeq }, - {"*=" ,tok::multeq }, - {"/=" ,tok::diveq }, - {"~=" ,tok::lnkeq }, - {"&=" ,tok::btandeq }, - {"|=" ,tok::btoreq }, - {"^=" ,tok::btxoreq }, - {"==" ,tok::cmpeq }, - {"!=" ,tok::neq }, - {"<" ,tok::less }, - {"<=" ,tok::leq }, - {">" ,tok::grt }, - {">=" ,tok::geq } + {"use" , tok::tk_use }, + {"true" , tok::tk_true }, + {"false" , tok::tk_false }, + {"for" , tok::tk_for }, + {"forindex", tok::tk_forindex}, + {"foreach" , tok::tk_foreach }, + {"while" , tok::tk_while }, + {"var" , tok::tk_var }, + {"func" , tok::tk_func }, + {"break" , tok::tk_brk }, + {"continue", tok::tk_cont }, + {"return" , tok::tk_ret }, + {"if" , tok::tk_if }, + {"elsif" , tok::tk_elsif }, + {"else" , tok::tk_else }, + {"nil" , tok::tk_nil }, + {"(" , tok::tk_lcurve }, + {")" , tok::tk_rcurve }, + {"[" , tok::tk_lbracket}, + {"]" , tok::tk_rbracket}, + {"{" , tok::tk_lbrace }, + {"}" , tok::tk_rbrace }, + {";" , tok::tk_semi }, + {"and" , tok::tk_and }, + {"or" , tok::tk_or }, + {"," , tok::tk_comma }, + {"." , tok::tk_dot }, + {"..." , tok::tk_ellipsis}, + {"?" , tok::tk_quesmark}, + {":" , tok::tk_colon }, + {"+" , tok::tk_add }, + {"-" , tok::tk_sub }, + {"*" , tok::tk_mult }, + {"/" , tok::tk_div }, + {"~" , tok::tk_floater }, + {"&" , tok::tk_btand }, + {"|" , tok::tk_btor }, + {"^" , tok::tk_btxor }, + {"!" , tok::tk_not }, + {"=" , tok::tk_eq }, + {"+=" , tok::tk_addeq }, + {"-=" , tok::tk_subeq }, + {"*=" , tok::tk_multeq }, + {"/=" , tok::tk_diveq }, + {"~=" , tok::tk_lnkeq }, + {"&=" , tok::tk_btandeq }, + {"|=" , tok::tk_btoreq }, + {"^=" , tok::tk_btxoreq }, + {"==" , tok::tk_cmpeq }, + {"!=" , tok::tk_neq }, + {"<" , tok::tk_less }, + {"<=" , tok::tk_leq }, + {">" , tok::tk_grt }, + {">=" , tok::tk_geq } }; tok get_type(const std::string&); diff --git a/src/nasal_parse.cpp b/src/nasal_parse.cpp index 163c9bb..e3628e6 100644 --- a/src/nasal_parse.cpp +++ b/src/nasal_parse.cpp @@ -4,16 +4,17 @@ namespace nasal { const error& parse::compile(const lexer& lexer) { - toks=lexer.result().data(); - ptr=in_func=in_loop=0; + toks = lexer.result().data(); + ptr = in_func_depth = in_loop_depth = 0; root = new code_block(toks[0].loc); - while(!lookahead(tok::eof)) { + while(!lookahead(tok::tk_eof)) { root->add_expression(expression()); - if (lookahead(tok::semi)) { - match(tok::semi); - } else if (need_semi_check(root->get_expressions().back()) && !lookahead(tok::eof)) { + if (lookahead(tok::tk_semi)) { + match(tok::tk_semi); + } else if (need_semi_check(root->get_expressions().back()) && + !lookahead(tok::tk_eof)) { // the last expression can be recognized without semi die(prevspan, "expected \";\" after this token"); } @@ -23,6 +24,7 @@ const error& parse::compile(const lexer& lexer) { } void parse::easter_egg() { + // do you remember this text drawing in old versions? std::clog << " _,,,_ \n" << " .' `'. \n" @@ -63,7 +65,7 @@ void parse::die(const span& loc, const std::string& info) { } void parse::next() { - if (lookahead(tok::eof)) { + if (lookahead(tok::tk_eof)) { return; } ++ptr; @@ -76,10 +78,10 @@ void parse::match(tok type, const char* info) { return; } switch(type) { - case tok::num:die(thisspan, "expected number"); break; - case tok::str:die(thisspan, "expected string"); break; - case tok::id: die(thisspan, "expected identifier");break; - default: die(thisspan, "expected \""+tokname.at(type)+"\""); break; + case tok::tk_num: die(thisspan, "expected number"); break; + case tok::tk_str: die(thisspan, "expected string"); break; + case tok::tk_id: die(thisspan, "expected identifier"); break; + default: die(thisspan, "expected \""+tokname.at(type)+"\""); break; } return; } @@ -91,11 +93,11 @@ bool parse::lookahead(tok type) { } bool parse::is_call(tok type) { - return type==tok::lcurve || type==tok::lbracket || type==tok::dot; + return type==tok::tk_lcurve || type==tok::tk_lbracket || type==tok::tk_dot; } bool parse::check_comma(const tok* panic_set) { - for(u32 i=0;panic_set[i]!=tok::null;++i) { + for(u32 i = 0; panic_set[i]!=tok::tk_null; ++i) { if (lookahead(panic_set[i])) { die(prevspan, "expected \",\" between scalars"); return true; @@ -106,17 +108,18 @@ bool parse::check_comma(const tok* panic_set) { bool parse::check_tuple() { u64 check_ptr = ptr, curve = 1, bracket = 0, brace = 0; - while(toks[++check_ptr].type!=tok::eof && curve) { + while(toks[++check_ptr].type!=tok::tk_eof && curve) { switch(toks[check_ptr].type) { - case tok::lcurve: ++curve; break; - case tok::lbracket: ++bracket; break; - case tok::lbrace: ++brace; break; - case tok::rcurve: --curve; break; - case tok::rbracket: --bracket; break; - case tok::rbrace: --brace; break; + case tok::tk_lcurve: ++curve; break; + case tok::tk_lbracket: ++bracket; break; + case tok::tk_lbrace: ++brace; break; + case tok::tk_rcurve: --curve; break; + case tok::tk_rbracket: --bracket; break; + case tok::tk_rbrace: --brace; break; default: break; } - if (curve==1 && !bracket && !brace && toks[check_ptr].type==tok::comma) { + if (curve==1 && !bracket && !brace && + toks[check_ptr].type==tok::tk_comma) { return true; } } @@ -128,7 +131,7 @@ bool parse::check_func_end(expr* node) { if (!node) { return true; } - auto type = node->get_type(); + const auto type = node->get_type(); if (type==expr_type::ast_func) { return true; } else if (type==expr_type::ast_def) { @@ -149,30 +152,32 @@ bool parse::check_in_curve_multi_definition() { // but we still allow syntax like: // func {}(var a = 1) // in fact, this syntax is not recommended - if (!lookahead(tok::lcurve) || toks[ptr+1].type!=tok::var) { + if (!lookahead(tok::tk_lcurve) || toks[ptr+1].type!=tok::tk_var) { return false; } - return toks[ptr+2].type==tok::id && toks[ptr+3].type==tok::comma; + return toks[ptr+2].type==tok::tk_id && toks[ptr+3].type==tok::tk_comma; } bool parse::check_special_call() { // special call means like this: function_name(a:1, b:2, c:3); u64 check_ptr = ptr, curve = 1, bracket = 0, brace = 0; - while(toks[++check_ptr].type!=tok::eof && curve) { + while(toks[++check_ptr].type!=tok::tk_eof && curve) { switch(toks[check_ptr].type) { - case tok::lcurve: ++curve; break; - case tok::lbracket: ++bracket;break; - case tok::lbrace: ++brace; break; - case tok::rcurve: --curve; break; - case tok::rbracket: --bracket;break; - case tok::rbrace: --brace; break; + case tok::tk_lcurve: ++curve; break; + case tok::tk_lbracket: ++bracket;break; + case tok::tk_lbrace: ++brace; break; + case tok::tk_rcurve: --curve; break; + case tok::tk_rbracket: --bracket;break; + case tok::tk_rbrace: --brace; break; default: break; } // m?1:0 will be recognized as normal parameter - if (curve==1 && !bracket && !brace && toks[check_ptr].type==tok::quesmark) { + if (curve==1 && !bracket && !brace && + toks[check_ptr].type==tok::tk_quesmark) { return false; } - if (curve==1 && !bracket && !brace && toks[check_ptr].type==tok::colon) { + if (curve==1 && !bracket && !brace && + toks[check_ptr].type==tok::tk_colon) { return true; } } @@ -203,10 +208,10 @@ void parse::update_location(expr* node) { use_stmt* parse::use_stmt_gen() { auto node = new use_stmt(toks[ptr].loc); - match(tok::use); + match(tok::tk_use); node->add_path(id()); - while(lookahead(tok::dot)) { - match(tok::dot); + while(lookahead(tok::tk_dot)) { + match(tok::tk_dot); node->add_path(id()); } update_location(node); @@ -224,28 +229,28 @@ nil_expr* parse::nil() { number_literal* parse::num() { auto node = new number_literal(toks[ptr].loc, str_to_num(toks[ptr].str.c_str())); - match(tok::num); + match(tok::tk_num); return node; } string_literal* parse::str() { auto node = new string_literal(toks[ptr].loc, toks[ptr].str); - match(tok::str); + match(tok::tk_str); return node; } identifier* parse::id() { auto node = new identifier(toks[ptr].loc, toks[ptr].str); - match(tok::id); + match(tok::tk_id); return node; } bool_literal* parse::bools() { auto node = new bool_literal(toks[ptr].loc, toks[ptr].str=="true"); - if (lookahead(tok::tktrue)) { - match(tok::tktrue); + if (lookahead(tok::tk_true)) { + match(tok::tk_true); } else { - match(tok::tkfalse); + match(tok::tk_false); } return node; } @@ -253,148 +258,149 @@ bool_literal* parse::bools() { vector_expr* parse::vec() { // panic set for this token is not ',' // this is the FIRST set of calculation - // array end with tok::null=0 + // array end with tok::tk_null = 0 const tok panic[] = { - tok::id, tok::str, tok::num, tok::tktrue, - tok::tkfalse, tok::opnot, tok::sub, tok::nil, - tok::func, tok::var, tok::lcurve, tok::floater, - tok::lbrace, tok::lbracket, tok::null + tok::tk_id, tok::tk_str, tok::tk_num, tok::tk_true, + tok::tk_false, tok::tk_not, tok::tk_sub, tok::tk_nil, + tok::tk_func, tok::tk_var, tok::tk_lcurve, tok::tk_floater, + tok::tk_lbrace, tok::tk_lbracket, tok::tk_null }; auto node = new vector_expr(toks[ptr].loc); - match(tok::lbracket); - while(!lookahead(tok::rbracket)) { + match(tok::tk_lbracket); + while(!lookahead(tok::tk_rbracket)) { node->add_element(calc()); - if (lookahead(tok::comma)) { - match(tok::comma); - } else if (lookahead(tok::eof)) { + if (lookahead(tok::tk_comma)) { + match(tok::tk_comma); + } else if (lookahead(tok::tk_eof)) { break; - } else if (!lookahead(tok::rbracket) && !check_comma(panic)) { + } else if (!lookahead(tok::tk_rbracket) && !check_comma(panic)) { break; } } update_location(node); - match(tok::rbracket, "expected \"]\" when generating vector"); + match(tok::tk_rbracket, "expected \"]\" when generating vector"); return node; } hash_expr* parse::hash() { auto node = new hash_expr(toks[ptr].loc); - match(tok::lbrace); - while(!lookahead(tok::rbrace)) { + match(tok::tk_lbrace); + while(!lookahead(tok::tk_rbrace)) { node->add_member(pair()); - if (lookahead(tok::comma)) { - match(tok::comma); - } else if (lookahead(tok::id) || lookahead(tok::str)) { // first set of hashmember + if (lookahead(tok::tk_comma)) { + match(tok::tk_comma); + } else if (lookahead(tok::tk_id) || lookahead(tok::tk_str)) { + // first set of hashmember die(prevspan, "expected \",\" between hash members"); } else { break; } } update_location(node); - match(tok::rbrace, "expected \"}\" when generating hash"); + match(tok::tk_rbrace, "expected \"}\" when generating hash"); return node; } hash_pair* parse::pair() { auto node = new hash_pair(toks[ptr].loc); - if (lookahead(tok::id)) { + if (lookahead(tok::tk_id)) { node->set_name(toks[ptr].str); - match(tok::id); - } else if (lookahead(tok::str)) { + match(tok::tk_id); + } else if (lookahead(tok::tk_str)) { node->set_name(toks[ptr].str); - match(tok::str); + match(tok::tk_str); } else { - match(tok::id, "expected hashmap key"); + match(tok::tk_id, "expected hashmap key"); } - match(tok::colon); + match(tok::tk_colon); node->set_value(calc()); update_location(node); return node; } function* parse::func() { - ++in_func; + ++in_func_depth; auto node = new function(toks[ptr].loc); - match(tok::func); - if (lookahead(tok::lcurve)) { + match(tok::tk_func); + if (lookahead(tok::tk_lcurve)) { params(node); } node->set_code_block(expression_block()); - --in_func; + --in_func_depth; update_location(node); return node; } void parse::params(function* func_node) { - match(tok::lcurve); - while(!lookahead(tok::rcurve)) { + match(tok::tk_lcurve); + while(!lookahead(tok::tk_rcurve)) { auto param = new parameter(toks[ptr].loc); param->set_parameter_name(toks[ptr].str); - match(tok::id); - if (lookahead(tok::eq)) { - match(tok::eq); + match(tok::tk_id); + if (lookahead(tok::tk_eq)) { + match(tok::tk_eq); param->set_parameter_type(parameter::param_type::default_parameter); param->set_default_value(calc()); - } else if (lookahead(tok::ellipsis)) { - match(tok::ellipsis); + } else if (lookahead(tok::tk_ellipsis)) { + match(tok::tk_ellipsis); param->set_parameter_type(parameter::param_type::dynamic_parameter); } else { param->set_parameter_type(parameter::param_type::normal_parameter); } update_location(param); func_node->add_parameter(param); - if (lookahead(tok::comma)) { - match(tok::comma); - } else if (lookahead(tok::id)) { // first set of identifier + if (lookahead(tok::tk_comma)) { + match(tok::tk_comma); + } else if (lookahead(tok::tk_id)) { // first set of identifier die(prevspan, "expected \",\" between identifiers"); } else { break; } } update_location(func_node); - match(tok::rcurve, "expected \")\" after parameter list"); + match(tok::tk_rcurve, "expected \")\" after parameter list"); return; } expr* parse::lcurve_expr() { - if (toks[ptr+1].type==tok::var) + if (toks[ptr+1].type==tok::tk_var) return definition(); return check_tuple()? multi_assignment():calc(); } expr* parse::expression() { tok type=toks[ptr].type; - if ((type==tok::brk || type==tok::cont) && !in_loop) { + if ((type==tok::tk_brk || type==tok::tk_cont) && !in_loop_depth) { die(thisspan, "must use break/continue in loops"); } - if (type==tok::ret && !in_func) { + if (type==tok::tk_ret && !in_func_depth) { die(thisspan, "must use return in functions"); } switch(type) { - case tok::use: return use_stmt_gen(); - case tok::nil: - case tok::num: - case tok::str: - case tok::id: - case tok::tktrue: - case tok::tkfalse: - case tok::func: - case tok::lbracket: - case tok::lbrace: - case tok::sub: - case tok::floater: - case tok::opnot: return calc(); - case tok::var: return definition(); - case tok::lcurve: return lcurve_expr(); - case tok::rfor: - case tok::forindex: - case tok::foreach: - case tok::rwhile: return loop(); - case tok::rif: return cond(); - case tok::cont: return continue_expression(); - case tok::brk: return break_expression(); - case tok::ret: return return_expression(); - case tok::semi: break; + case tok::tk_use: return use_stmt_gen(); + case tok::tk_nil: + case tok::tk_num: + case tok::tk_str: + case tok::tk_id: + case tok::tk_true: + case tok::tk_false: + case tok::tk_func: + case tok::tk_lbracket: + case tok::tk_lbrace: + case tok::tk_sub: + case tok::tk_floater: + case tok::tk_not: return calc(); + case tok::tk_var: return definition(); + case tok::tk_lcurve: return lcurve_expr(); + case tok::tk_for: + case tok::tk_forindex: + case tok::tk_foreach: + case tok::tk_while: return loop(); + case tok::tk_if: return cond(); + case tok::tk_cont: return continue_expression(); + case tok::tk_brk: return break_expression(); + case tok::tk_ret: return return_expression(); + case tok::tk_semi: break; default: die(thisspan, "incorrect token <"+toks[ptr].str+">"); next(); @@ -406,27 +412,28 @@ expr* parse::expression() { } code_block* parse::expression_block() { - if (lookahead(tok::eof)) { + if (lookahead(tok::tk_eof)) { die(thisspan, "expected expression block"); return new code_block(toks[ptr].loc); } auto node = new code_block(toks[ptr].loc); - if (lookahead(tok::lbrace)) { - match(tok::lbrace); - while(!lookahead(tok::rbrace) && !lookahead(tok::eof)) { + if (lookahead(tok::tk_lbrace)) { + match(tok::tk_lbrace); + while(!lookahead(tok::tk_rbrace) && !lookahead(tok::tk_eof)) { node->add_expression(expression()); - if (lookahead(tok::semi)) { - match(tok::semi); - } else if (need_semi_check(node->get_expressions().back()) && !lookahead(tok::rbrace)) { + if (lookahead(tok::tk_semi)) { + match(tok::tk_semi); + } else if (need_semi_check(node->get_expressions().back()) && + !lookahead(tok::tk_rbrace)) { // the last expression can be recognized without semi die(prevspan, "expected \";\" after this token"); } } - match(tok::rbrace, "expected \"}\" when generating expressions"); + match(tok::tk_rbrace, "expected \"}\" when generating expressions"); } else { node->add_expression(expression()); - if (lookahead(tok::semi)) { - match(tok::semi); + if (lookahead(tok::tk_semi)) { + match(tok::tk_semi); } } update_location(node); @@ -435,36 +442,38 @@ code_block* parse::expression_block() { expr* parse::calc() { auto node = bitwise_or(); - if (lookahead(tok::quesmark)) { + if (lookahead(tok::tk_quesmark)) { // trinocular calculation auto tmp = new ternary_operator(toks[ptr].loc); - match(tok::quesmark); + match(tok::tk_quesmark); tmp->set_condition(node); tmp->set_left(calc()); - match(tok::colon); + match(tok::tk_colon); tmp->set_right(calc()); node = tmp; - } else if (tok::eq<=toks[ptr].type && toks[ptr].type<=tok::lnkeq) { + } else if (tok::tk_eq<=toks[ptr].type && toks[ptr].type<=tok::tk_lnkeq) { auto tmp = new assignment_expr(toks[ptr].loc); switch(toks[ptr].type) { - case tok::eq: tmp->set_assignment_type(assignment_expr::assign_type::equal); break; - case tok::addeq: tmp->set_assignment_type(assignment_expr::assign_type::add_equal); break; - case tok::subeq: tmp->set_assignment_type(assignment_expr::assign_type::sub_equal); break; - case tok::multeq: tmp->set_assignment_type(assignment_expr::assign_type::mult_equal); break; - case tok::diveq: tmp->set_assignment_type(assignment_expr::assign_type::div_equal); break; - case tok::lnkeq: tmp->set_assignment_type(assignment_expr::assign_type::concat_equal); break; + case tok::tk_eq: tmp->set_assignment_type(assignment_expr::assign_type::equal); break; + case tok::tk_addeq: tmp->set_assignment_type(assignment_expr::assign_type::add_equal); break; + case tok::tk_subeq: tmp->set_assignment_type(assignment_expr::assign_type::sub_equal); break; + case tok::tk_multeq: tmp->set_assignment_type(assignment_expr::assign_type::mult_equal); break; + case tok::tk_diveq: tmp->set_assignment_type(assignment_expr::assign_type::div_equal); break; + case tok::tk_lnkeq: tmp->set_assignment_type(assignment_expr::assign_type::concat_equal); break; default: break; } tmp->set_left(node); match(toks[ptr].type); tmp->set_right(calc()); node = tmp; - } else if (toks[ptr].type==tok::btandeq || toks[ptr].type==tok::btoreq || toks[ptr].type==tok::btxoreq) { + } else if (toks[ptr].type==tok::tk_btandeq || + toks[ptr].type==tok::tk_btoreq || + toks[ptr].type==tok::tk_btxoreq) { auto tmp = new assignment_expr(toks[ptr].loc); switch(toks[ptr].type) { - case tok::btandeq: tmp->set_assignment_type(assignment_expr::assign_type::bitwise_and_equal); break; - case tok::btoreq: tmp->set_assignment_type(assignment_expr::assign_type::bitwise_or_equal); break; - case tok::btxoreq: tmp->set_assignment_type(assignment_expr::assign_type::bitwise_xor_equal); break; + case tok::tk_btandeq: tmp->set_assignment_type(assignment_expr::assign_type::bitwise_and_equal); break; + case tok::tk_btoreq: tmp->set_assignment_type(assignment_expr::assign_type::bitwise_or_equal); break; + case tok::tk_btxoreq: tmp->set_assignment_type(assignment_expr::assign_type::bitwise_xor_equal); break; default: break; } tmp->set_left(node); @@ -478,11 +487,11 @@ expr* parse::calc() { expr* parse::bitwise_or() { auto node = bitwise_xor(); - while(lookahead(tok::btor)) { + while(lookahead(tok::tk_btor)) { auto tmp = new binary_operator(toks[ptr].loc); tmp->set_operator_type(binary_operator::binary_type::bitwise_or); tmp->set_left(node); - match(tok::btor); + match(tok::tk_btor); tmp->set_right(bitwise_xor()); update_location(tmp); node = tmp; @@ -493,11 +502,11 @@ expr* parse::bitwise_or() { expr* parse::bitwise_xor() { auto node = bitwise_and(); - while(lookahead(tok::btxor)) { + while(lookahead(tok::tk_btxor)) { auto tmp = new binary_operator(toks[ptr].loc); tmp->set_operator_type(binary_operator::binary_type::bitwise_xor); tmp->set_left(node); - match(tok::btxor); + match(tok::tk_btxor); tmp->set_right(bitwise_and()); update_location(tmp); node = tmp; @@ -508,11 +517,11 @@ expr* parse::bitwise_xor() { expr* parse::bitwise_and() { auto node = or_expr(); - while(lookahead(tok::btand)) { + while(lookahead(tok::tk_btand)) { auto tmp = new binary_operator(toks[ptr].loc); tmp->set_operator_type(binary_operator::binary_type::bitwise_and); tmp->set_left(node); - match(tok::btand); + match(tok::tk_btand); tmp->set_right(or_expr()); update_location(tmp); node = tmp; @@ -523,11 +532,11 @@ expr* parse::bitwise_and() { expr* parse::or_expr() { auto node = and_expr(); - while(lookahead(tok::opor)) { + while(lookahead(tok::tk_or)) { auto tmp = new binary_operator(toks[ptr].loc); tmp->set_operator_type(binary_operator::binary_type::condition_or); tmp->set_left(node); - match(tok::opor); + match(tok::tk_or); tmp->set_right(and_expr()); update_location(tmp); node = tmp; @@ -538,11 +547,11 @@ expr* parse::or_expr() { expr* parse::and_expr() { auto node = cmp_expr(); - while(lookahead(tok::opand)) { + while(lookahead(tok::tk_and)) { auto tmp = new binary_operator(toks[ptr].loc); tmp->set_operator_type(binary_operator::binary_type::condition_and); tmp->set_left(node); - match(tok::opand); + match(tok::tk_and); tmp->set_right(cmp_expr()); update_location(tmp); node = tmp; @@ -553,15 +562,15 @@ expr* parse::and_expr() { expr* parse::cmp_expr() { auto node = additive_expr(); - while(tok::cmpeq<=toks[ptr].type && toks[ptr].type<=tok::geq) { + while(tok::tk_cmpeq<=toks[ptr].type && toks[ptr].type<=tok::tk_geq) { auto tmp = new binary_operator(toks[ptr].loc); switch(toks[ptr].type) { - case tok::cmpeq: tmp->set_operator_type(binary_operator::binary_type::cmpeq); break; - case tok::neq: tmp->set_operator_type(binary_operator::binary_type::cmpneq); break; - case tok::less: tmp->set_operator_type(binary_operator::binary_type::less); break; - case tok::leq: tmp->set_operator_type(binary_operator::binary_type::leq); break; - case tok::grt: tmp->set_operator_type(binary_operator::binary_type::grt); break; - case tok::geq: tmp->set_operator_type(binary_operator::binary_type::geq); break; + case tok::tk_cmpeq: tmp->set_operator_type(binary_operator::binary_type::cmpeq); break; + case tok::tk_neq: tmp->set_operator_type(binary_operator::binary_type::cmpneq); break; + case tok::tk_less: tmp->set_operator_type(binary_operator::binary_type::less); break; + case tok::tk_leq: tmp->set_operator_type(binary_operator::binary_type::leq); break; + case tok::tk_grt: tmp->set_operator_type(binary_operator::binary_type::grt); break; + case tok::tk_geq: tmp->set_operator_type(binary_operator::binary_type::geq); break; default: break; } tmp->set_left(node); @@ -576,12 +585,14 @@ expr* parse::cmp_expr() { expr* parse::additive_expr() { auto node = multive_expr(); - while(lookahead(tok::add) || lookahead(tok::sub) || lookahead(tok::floater)) { + while(lookahead(tok::tk_add) || + lookahead(tok::tk_sub) || + lookahead(tok::tk_floater)) { auto tmp = new binary_operator(toks[ptr].loc); switch(toks[ptr].type) { - case tok::add: tmp->set_operator_type(binary_operator::binary_type::add); break; - case tok::sub: tmp->set_operator_type(binary_operator::binary_type::sub); break; - case tok::floater: tmp->set_operator_type(binary_operator::binary_type::concat); break; + case tok::tk_add: tmp->set_operator_type(binary_operator::binary_type::add); break; + case tok::tk_sub: tmp->set_operator_type(binary_operator::binary_type::sub); break; + case tok::tk_floater: tmp->set_operator_type(binary_operator::binary_type::concat); break; default: break; } tmp->set_left(node); @@ -595,17 +606,23 @@ expr* parse::additive_expr() { } expr* parse::multive_expr() { - expr* node=(lookahead(tok::sub) || lookahead(tok::opnot) || lookahead(tok::floater))?unary():scalar(); - while(lookahead(tok::mult) || lookahead(tok::div)) { + expr* node=(lookahead(tok::tk_sub) || + lookahead(tok::tk_not) || + lookahead(tok::tk_floater))? unary():scalar(); + while(lookahead(tok::tk_mult) || lookahead(tok::tk_div)) { auto tmp = new binary_operator(toks[ptr].loc); - if (lookahead(tok::mult)) { + if (lookahead(tok::tk_mult)) { tmp->set_operator_type(binary_operator::binary_type::mult); } else { tmp->set_operator_type(binary_operator::binary_type::div); } tmp->set_left(node); match(toks[ptr].type); - tmp->set_right((lookahead(tok::sub) || lookahead(tok::opnot) || lookahead(tok::floater))?unary():scalar()); + tmp->set_right( + (lookahead(tok::tk_sub) || + lookahead(tok::tk_not) || + lookahead(tok::tk_floater))? unary():scalar() + ); update_location(tmp); node = tmp; } @@ -616,56 +633,60 @@ expr* parse::multive_expr() { unary_operator* parse::unary() { auto node = new unary_operator(toks[ptr].loc); switch(toks[ptr].type) { - case tok::sub: + case tok::tk_sub: node->set_operator_type(unary_operator::unary_type::negative); - match(tok::sub); + match(tok::tk_sub); break; - case tok::opnot: + case tok::tk_not: node->set_operator_type(unary_operator::unary_type::logical_not); - match(tok::opnot); + match(tok::tk_not); break; - case tok::floater: + case tok::tk_floater: node->set_operator_type(unary_operator::unary_type::bitwise_not); - match(tok::floater); + match(tok::tk_floater); break; default: break; } - node->set_value((lookahead(tok::sub) || lookahead(tok::opnot) || lookahead(tok::floater))?unary():scalar()); + node->set_value( + (lookahead(tok::tk_sub) || + lookahead(tok::tk_not) || + lookahead(tok::tk_floater))? unary():scalar() + ); update_location(node); return node; } expr* parse::scalar() { expr* node = nullptr; - if (lookahead(tok::nil)) { + if (lookahead(tok::tk_nil)) { node = nil(); - match(tok::nil); - } else if (lookahead(tok::num)) { + match(tok::tk_nil); + } else if (lookahead(tok::tk_num)) { node = num(); - } else if (lookahead(tok::str)) { + } else if (lookahead(tok::tk_str)) { node = str(); - } else if (lookahead(tok::id)) { + } else if (lookahead(tok::tk_id)) { node = id(); - } else if (lookahead(tok::tktrue) || lookahead(tok::tkfalse)) { + } else if (lookahead(tok::tk_true) || lookahead(tok::tk_false)) { node = bools(); - } else if (lookahead(tok::func)) { + } else if (lookahead(tok::tk_func)) { node = func(); - } else if (lookahead(tok::lbracket)) { + } else if (lookahead(tok::tk_lbracket)) { node = vec(); - } else if (lookahead(tok::lbrace)) { + } else if (lookahead(tok::tk_lbrace)) { node = hash(); - } else if (lookahead(tok::lcurve)) { + } else if (lookahead(tok::tk_lcurve)) { const auto& loc = toks[ptr].loc; - match(tok::lcurve); + match(tok::tk_lcurve); node = calc(); node->set_begin(loc.begin_line, loc.begin_column); update_location(node); - match(tok::rcurve); - } else if (lookahead(tok::var)) { - match(tok::var); + match(tok::tk_rcurve); + } else if (lookahead(tok::tk_var)) { + match(tok::tk_var); auto def_node = new definition_expr(toks[ptr].loc); def_node->set_identifier(id()); - match(tok::eq); + match(tok::tk_eq); def_node->set_value(calc()); node = def_node; } else { @@ -691,9 +712,9 @@ expr* parse::scalar() { call* parse::call_scalar() { switch(toks[ptr].type) { - case tok::lcurve: return callf(); break; - case tok::lbracket: return callv(); break; - case tok::dot: return callh(); break; + case tok::tk_lcurve: return callf(); break; + case tok::tk_lbracket: return callv(); break; + case tok::tk_dot: return callh(); break; default: break; } // unreachable @@ -702,32 +723,32 @@ call* parse::call_scalar() { call_hash* parse::callh() { const auto& begin_loc = toks[ptr].loc; - match(tok::dot); + match(tok::tk_dot); auto node = new call_hash(begin_loc, toks[ptr].str); update_location(node); - match(tok::id, "expected hashmap key"); // get key + match(tok::tk_id, "expected hashmap key"); // get key return node; } call_vector* parse::callv() { // panic set for this token is not ',' // this is the FIRST set of subvec - // array end with tok::null=0 + // array end with tok::tk_null = 0 const tok panic[] = { - tok::id, tok::str, tok::num, tok::tktrue, - tok::tkfalse, tok::opnot, tok::sub, tok::nil, - tok::func, tok::var, tok::lcurve, tok::floater, - tok::lbrace, tok::lbracket, tok::colon, tok::null + tok::tk_id, tok::tk_str, tok::tk_num, tok::tk_true, + tok::tk_false, tok::tk_not, tok::tk_sub, tok::tk_nil, + tok::tk_func, tok::tk_var, tok::tk_lcurve, tok::tk_floater, + tok::tk_lbrace, tok::tk_lbracket, tok::tk_colon, tok::tk_null }; auto node = new call_vector(toks[ptr].loc); - match(tok::lbracket); - while(!lookahead(tok::rbracket)) { + match(tok::tk_lbracket); + while(!lookahead(tok::tk_rbracket)) { node->add_slice(subvec()); - if (lookahead(tok::comma)) { - match(tok::comma); - } else if (lookahead(tok::eof)) { + if (lookahead(tok::tk_comma)) { + match(tok::tk_comma); + } else if (lookahead(tok::tk_eof)) { break; - } else if (!lookahead(tok::rbracket) && !check_comma(panic)) { + } else if (!lookahead(tok::tk_rbracket) && !check_comma(panic)) { break; } } @@ -735,43 +756,47 @@ call_vector* parse::callv() { die(thisspan, "expected index value"); } update_location(node); - match(tok::rbracket, "expected \"]\" when calling vector"); + match(tok::tk_rbracket, "expected \"]\" when calling vector"); return node; } call_function* parse::callf() { // panic set for this token is not ',' // this is the FIRST set of calculation/hashmember - // array end with tok::null=0 + // array end with tok::tk_null = 0 const tok panic[] = { - tok::id, tok::str, tok::num, tok::tktrue, - tok::tkfalse, tok::opnot, tok::sub, tok::nil, - tok::func, tok::var, tok::lcurve, tok::floater, - tok::lbrace, tok::lbracket, tok::null + tok::tk_id, tok::tk_str, tok::tk_num, tok::tk_true, + tok::tk_false, tok::tk_not, tok::tk_sub, tok::tk_nil, + tok::tk_func, tok::tk_var, tok::tk_lcurve, tok::tk_floater, + tok::tk_lbrace, tok::tk_lbracket, tok::tk_null }; auto node = new call_function(toks[ptr].loc); bool special_call=check_special_call(); - match(tok::lcurve); - while(!lookahead(tok::rcurve)) { + match(tok::tk_lcurve); + while(!lookahead(tok::tk_rcurve)) { node->add_argument(special_call?pair():calc()); - if (lookahead(tok::comma)) - match(tok::comma); - else if (lookahead(tok::eof)) + if (lookahead(tok::tk_comma)) + match(tok::tk_comma); + else if (lookahead(tok::tk_eof)) break; - else if (!lookahead(tok::rcurve) && !check_comma(panic)) + else if (!lookahead(tok::tk_rcurve) && !check_comma(panic)) break; } update_location(node); - match(tok::rcurve, "expected \")\" when calling function"); + match(tok::tk_rcurve, "expected \")\" when calling function"); return node; } slice_vector* parse::subvec() { auto node = new slice_vector(toks[ptr].loc); - node->set_begin(lookahead(tok::colon)?nil():calc()); - if (lookahead(tok::colon)) { - match(tok::colon); - node->set_end((lookahead(tok::comma) || lookahead(tok::rbracket))?nil():calc()); + node->set_begin(lookahead(tok::tk_colon)?nil():calc()); + if (lookahead(tok::tk_colon)) { + match(tok::tk_colon); + node->set_end( + (lookahead(tok::tk_comma) || lookahead(tok::tk_rbracket))? + nil(): + calc() + ); } update_location(node); return node; @@ -779,18 +804,18 @@ slice_vector* parse::subvec() { expr* parse::definition() { auto node = new definition_expr(toks[ptr].loc); - if (lookahead(tok::var)) { - match(tok::var); + if (lookahead(tok::tk_var)) { + match(tok::tk_var); switch(toks[ptr].type) { - case tok::id: node->set_identifier(id());break; - case tok::lcurve: node->set_multi_define(outcurve_def());break; + case tok::tk_id: node->set_identifier(id());break; + case tok::tk_lcurve: node->set_multi_define(outcurve_def());break; default: die(thisspan, "expected identifier");break; } - } else if (lookahead(tok::lcurve)) { + } else if (lookahead(tok::tk_lcurve)) { node->set_multi_define(incurve_def()); } - match(tok::eq); - if (lookahead(tok::lcurve)) { + match(tok::tk_eq); + if (lookahead(tok::tk_lcurve)) { check_tuple()? node->set_tuple(multi_scalar()): node->set_value(calc()); @@ -803,33 +828,33 @@ expr* parse::definition() { multi_identifier* parse::incurve_def() { const auto& loc = toks[ptr].loc; - match(tok::lcurve); - match(tok::var); + match(tok::tk_lcurve); + match(tok::tk_var); auto node = multi_id(); update_location(node); - match(tok::rcurve); + match(tok::tk_rcurve); node->set_begin(loc.begin_line, loc.begin_column); return node; } multi_identifier* parse::outcurve_def() { const auto& loc = toks[ptr].loc; - match(tok::lcurve); + match(tok::tk_lcurve); auto node = multi_id(); update_location(node); - match(tok::rcurve); + match(tok::tk_rcurve); node->set_begin(loc.begin_line, loc.begin_column); return node; } multi_identifier* parse::multi_id() { auto node = new multi_identifier(toks[ptr].loc); - while(!lookahead(tok::eof)) { + while(!lookahead(tok::tk_eof)) { // only identifier is allowed here node->add_var(id()); - if (lookahead(tok::comma)) { - match(tok::comma); - } else if (lookahead(tok::id)) { // first set of identifier + if (lookahead(tok::tk_comma)) { + match(tok::tk_comma); + } else if (lookahead(tok::tk_id)) { // first set of identifier die(prevspan, "expected \",\" between identifiers"); } else { break; @@ -843,37 +868,37 @@ tuple_expr* parse::multi_scalar() { // if check_call_memory is true, // we will check if value called here can reach a memory space const tok panic[] = { - tok::id, tok::str, tok::num, tok::tktrue, - tok::tkfalse, tok::opnot, tok::sub, tok::nil, - tok::func, tok::var, tok::lcurve, tok::floater, - tok::lbrace, tok::lbracket, tok::null + tok::tk_id, tok::tk_str, tok::tk_num, tok::tk_true, + tok::tk_false, tok::tk_not, tok::tk_sub, tok::tk_nil, + tok::tk_func, tok::tk_var, tok::tk_lcurve, tok::tk_floater, + tok::tk_lbrace, tok::tk_lbracket, tok::tk_null }; auto node = new tuple_expr(toks[ptr].loc); - match(tok::lcurve); - while(!lookahead(tok::rcurve)) { + match(tok::tk_lcurve); + while(!lookahead(tok::tk_rcurve)) { node->add_element(calc()); - if (lookahead(tok::comma)) { - match(tok::comma); - } else if (lookahead(tok::eof)) { + if (lookahead(tok::tk_comma)) { + match(tok::tk_comma); + } else if (lookahead(tok::tk_eof)) { break; - } else if (!lookahead(tok::rcurve) && !check_comma(panic)) { + } else if (!lookahead(tok::tk_rcurve) && !check_comma(panic)) { break; } } update_location(node); - match(tok::rcurve, "expected \")\" after multi-scalar"); + match(tok::tk_rcurve, "expected \")\" after multi-scalar"); return node; } multi_assign* parse::multi_assignment() { auto node = new multi_assign(toks[ptr].loc); node->set_tuple(multi_scalar()); - match(tok::eq); - if (lookahead(tok::eof)) { + match(tok::tk_eq); + if (lookahead(tok::tk_eof)) { die(thisspan, "expected value list"); return node; } - if (lookahead(tok::lcurve)) { + if (lookahead(tok::tk_lcurve)) { node->set_value(check_tuple()?multi_scalar():calc()); } else { node->set_value(calc()); @@ -883,28 +908,28 @@ multi_assign* parse::multi_assignment() { } expr* parse::loop() { - ++in_loop; + ++in_loop_depth; expr* node = nullptr; switch(toks[ptr].type) { - case tok::rwhile: node = while_loop(); break; - case tok::rfor: node = for_loop(); break; - case tok::forindex: - case tok::foreach: node = forei_loop(); break; + case tok::tk_while: node = while_loop(); break; + case tok::tk_for: node = for_loop(); break; + case tok::tk_forindex: + case tok::tk_foreach: node = forei_loop(); break; default: die(thisspan, "unreachable"); node = null(); break; } - --in_loop; + --in_loop_depth; return node; } while_expr* parse::while_loop() { auto node = new while_expr(toks[ptr].loc); - match(tok::rwhile); - match(tok::lcurve); + match(tok::tk_while); + match(tok::tk_lcurve); node->set_condition(calc()); - match(tok::rcurve); + match(tok::tk_rcurve); node->set_code_block(expression_block()); update_location(node); return node; @@ -912,45 +937,45 @@ while_expr* parse::while_loop() { for_expr* parse::for_loop() { auto node = new for_expr(toks[ptr].loc); - match(tok::rfor); - match(tok::lcurve); + match(tok::tk_for); + match(tok::tk_lcurve); // first expression - if (lookahead(tok::eof)) { + if (lookahead(tok::tk_eof)) { die(thisspan, "expected definition"); } - if (lookahead(tok::semi)) { + if (lookahead(tok::tk_semi)) { node->set_initial(null()); - } else if (lookahead(tok::var)) { + } else if (lookahead(tok::tk_var)) { node->set_initial(definition()); - } else if (lookahead(tok::lcurve)) { + } else if (lookahead(tok::tk_lcurve)) { node->set_initial(lcurve_expr()); } else { node->set_initial(calc()); } - match(tok::semi, "expected \";\" in for(;;)"); + match(tok::tk_semi, "expected \";\" in for(;;)"); // conditional expression - if (lookahead(tok::eof)) { + if (lookahead(tok::tk_eof)) { die(thisspan, "expected conditional expr"); } - if (lookahead(tok::semi)) { + if (lookahead(tok::tk_semi)) { node->set_condition(null()); } else { node->set_condition(calc()); } - match(tok::semi, "expected \";\" in for(;;)"); + match(tok::tk_semi, "expected \";\" in for(;;)"); //after loop expression - if (lookahead(tok::eof)) { + if (lookahead(tok::tk_eof)) { die(thisspan, "expected calculation"); } - if (lookahead(tok::rcurve)) { + if (lookahead(tok::tk_rcurve)) { node->set_step(null()); } else { node->set_step(calc()); } - match(tok::rcurve); + match(tok::tk_rcurve); node->set_code_block(expression_block()); update_location(node); return node; @@ -959,29 +984,29 @@ for_expr* parse::for_loop() { forei_expr* parse::forei_loop() { auto node = new forei_expr(toks[ptr].loc); switch(toks[ptr].type) { - case tok::forindex: + case tok::tk_forindex: node->set_loop_type(forei_expr::forei_loop_type::forindex); - match(tok::forindex); + match(tok::tk_forindex); break; - case tok::foreach: + case tok::tk_foreach: node->set_loop_type(forei_expr::forei_loop_type::foreach); - match(tok::foreach); + match(tok::tk_foreach); break; default: break; } - match(tok::lcurve); + match(tok::tk_lcurve); // first expression // foreach/forindex must have an iterator to loop through - if (!lookahead(tok::var) && !lookahead(tok::id)) { + if (!lookahead(tok::tk_var) && !lookahead(tok::tk_id)) { die(thisspan, "expected iterator"); } node->set_iterator(iter_gen()); - match(tok::semi, "expected \";\" in foreach/forindex(iter;vector)"); - if (lookahead(tok::eof)) { + match(tok::tk_semi, "expected \";\" in foreach/forindex(iter;vector)"); + if (lookahead(tok::tk_eof)) { die(thisspan, "expected vector"); } node->set_value(calc()); - match(tok::rcurve); + match(tok::tk_rcurve); node->set_code_block(expression_block()); update_location(node); return node; @@ -990,8 +1015,8 @@ forei_expr* parse::forei_loop() { iter_expr* parse::iter_gen() { auto node = new iter_expr(toks[ptr].loc); // definition - if (lookahead(tok::var)) { - match(tok::var); + if (lookahead(tok::tk_var)) { + match(tok::tk_var); node->set_name(id()); node->set_is_definition(true); update_location(node); @@ -1022,30 +1047,30 @@ condition_expr* parse::cond() { // generate if auto ifnode = new if_expr(toks[ptr].loc); - match(tok::rif); - match(tok::lcurve); + match(tok::tk_if); + match(tok::tk_lcurve); ifnode->set_condition(calc()); - match(tok::rcurve); + match(tok::tk_rcurve); ifnode->set_code_block(expression_block()); update_location(ifnode); node->set_if_statement(ifnode); // generate elsif - while(lookahead(tok::elsif)) { + while(lookahead(tok::tk_elsif)) { auto elsifnode = new if_expr(toks[ptr].loc); - match(tok::elsif); - match(tok::lcurve); + match(tok::tk_elsif); + match(tok::tk_lcurve); elsifnode->set_condition(calc()); - match(tok::rcurve); + match(tok::tk_rcurve); elsifnode->set_code_block(expression_block()); update_location(elsifnode); node->add_elsif_statement(elsifnode); } // generate else - if (lookahead(tok::relse)) { + if (lookahead(tok::tk_else)) { auto elsenode = new if_expr(toks[ptr].loc); - match(tok::relse); + match(tok::tk_else); elsenode->set_code_block(expression_block()); update_location(elsenode); node->set_else_statement(elsenode); @@ -1056,26 +1081,26 @@ condition_expr* parse::cond() { continue_expr* parse::continue_expression() { auto node = new continue_expr(toks[ptr].loc); - match(tok::cont); + match(tok::tk_cont); return node; } break_expr* parse::break_expression() { auto node = new break_expr(toks[ptr].loc); - match(tok::brk); + match(tok::tk_brk); return node; } return_expr* parse::return_expression() { auto node = new return_expr(toks[ptr].loc); - match(tok::ret); + match(tok::tk_ret); tok type = toks[ptr].type; - if (type==tok::nil || type==tok::num || - type==tok::str || type==tok::id || - type==tok::func || type==tok::sub || - type==tok::opnot || type==tok::lcurve || - type==tok::lbracket || type==tok::lbrace || - type==tok::tktrue || type==tok::tkfalse) { + if (type==tok::tk_nil || type==tok::tk_num || + type==tok::tk_str || type==tok::tk_id || + type==tok::tk_func || type==tok::tk_sub || + type==tok::tk_not || type==tok::tk_lcurve || + type==tok::tk_lbracket || type==tok::tk_lbrace || + type==tok::tk_true || type==tok::tk_false) { node->set_value(calc()); } else { node->set_value(nil()); diff --git a/src/nasal_parse.h b/src/nasal_parse.h index 85d351c..3cb334f 100644 --- a/src/nasal_parse.h +++ b/src/nasal_parse.h @@ -16,66 +16,68 @@ class parse { private: u64 ptr; - u64 in_func; // count function block - u64 in_loop; // count loop block + u64 in_func_depth; // count function block + u64 in_loop_depth; // count loop block const token* toks; code_block* root; error err; private: - const std::unordered_map tokname { - {tok::use ,"use" }, - {tok::rfor ,"for" }, - {tok::forindex,"forindex"}, - {tok::foreach ,"foreach" }, - {tok::rwhile ,"while" }, - {tok::var ,"var" }, - {tok::func ,"func" }, - {tok::brk ,"break" }, - {tok::cont ,"continue"}, - {tok::ret ,"return" }, - {tok::rif ,"if" }, - {tok::elsif ,"elsif" }, - {tok::relse ,"else" }, - {tok::nil ,"nil" }, - {tok::lcurve ,"(" }, - {tok::rcurve ,")" }, - {tok::lbracket,"[" }, - {tok::rbracket,"]" }, - {tok::lbrace ,"{" }, - {tok::rbrace ,"}" }, - {tok::semi ,";" }, - {tok::opand ,"and" }, - {tok::opor ,"or" }, - {tok::comma ,"," }, - {tok::dot ,"." }, - {tok::ellipsis,"..." }, - {tok::quesmark,"?" }, - {tok::colon ,":" }, - {tok::add ,"+" }, - {tok::sub ,"-" }, - {tok::mult ,"*" }, - {tok::div ,"/" }, - {tok::floater ,"~" }, - {tok::btand ,"&" }, - {tok::btor ,"|" }, - {tok::btxor ,"^" }, - {tok::opnot ,"!" }, - {tok::eq ,"=" }, - {tok::addeq ,"+=" }, - {tok::subeq ,"-=" }, - {tok::multeq ,"*=" }, - {tok::diveq ,"/=" }, - {tok::lnkeq ,"~=" }, - {tok::btandeq ,"&=" }, - {tok::btoreq ,"|=" }, - {tok::btxoreq ,"^=" }, - {tok::cmpeq ,"==" }, - {tok::neq ,"!=" }, - {tok::less ,"<" }, - {tok::leq ,"<=" }, - {tok::grt ,">" }, - {tok::geq ,">=" } + const std::unordered_map tokname = { + {tok::tk_true , "true" }, + {tok::tk_false , "false" }, + {tok::tk_use , "use" }, + {tok::tk_for , "for" }, + {tok::tk_forindex, "forindex"}, + {tok::tk_foreach , "foreach" }, + {tok::tk_while , "while" }, + {tok::tk_var , "var" }, + {tok::tk_func , "func" }, + {tok::tk_brk , "break" }, + {tok::tk_cont , "continue"}, + {tok::tk_ret , "return" }, + {tok::tk_if , "if" }, + {tok::tk_elsif , "elsif" }, + {tok::tk_else , "else" }, + {tok::tk_nil , "nil" }, + {tok::tk_lcurve , "(" }, + {tok::tk_rcurve , ")" }, + {tok::tk_lbracket, "[" }, + {tok::tk_rbracket, "]" }, + {tok::tk_lbrace , "{" }, + {tok::tk_rbrace , "}" }, + {tok::tk_semi , ";" }, + {tok::tk_and , "and" }, + {tok::tk_or , "or" }, + {tok::tk_comma , "," }, + {tok::tk_dot , "." }, + {tok::tk_ellipsis, "..." }, + {tok::tk_quesmark, "?" }, + {tok::tk_colon , ":" }, + {tok::tk_add , "+" }, + {tok::tk_sub , "-" }, + {tok::tk_mult , "*" }, + {tok::tk_div , "/" }, + {tok::tk_floater , "~" }, + {tok::tk_btand , "&" }, + {tok::tk_btor , "|" }, + {tok::tk_btxor , "^" }, + {tok::tk_not , "!" }, + {tok::tk_eq , "=" }, + {tok::tk_addeq , "+=" }, + {tok::tk_subeq , "-=" }, + {tok::tk_multeq , "*=" }, + {tok::tk_diveq , "/=" }, + {tok::tk_lnkeq , "~=" }, + {tok::tk_btandeq , "&=" }, + {tok::tk_btoreq , "|=" }, + {tok::tk_btxoreq , "^=" }, + {tok::tk_cmpeq , "==" }, + {tok::tk_neq , "!=" }, + {tok::tk_less , "<" }, + {tok::tk_leq , "<=" }, + {tok::tk_grt , ">" }, + {tok::tk_geq , ">=" } }; private: @@ -151,7 +153,8 @@ public: } public: - parse(): ptr(0), in_func(0), in_loop(0), toks(nullptr), root(nullptr) {} + parse(): ptr(0), in_func_depth(0), in_loop_depth(0), + toks(nullptr), root(nullptr) {} ~parse() {delete root;} const error& compile(const lexer&); static void easter_egg(); diff --git a/src/nasal_vm.h b/src/nasal_vm.h index 88920b9..2553481 100644 --- a/src/nasal_vm.h +++ b/src/nasal_vm.h @@ -50,6 +50,7 @@ protected: /* limited mode, will not load unsafe system api if switched on */ bool flag_limited_mode = false; +protected: /* vm initializing function */ void vm_init_enrty(const std::vector&, const std::vector&, @@ -60,6 +61,7 @@ protected: const std::vector&); void context_and_global_init(); +protected: /* debug functions */ bool verbose = false; void value_info(var&); @@ -190,13 +192,24 @@ public: const std::vector&); // get command line arguments /* set detail report info flag */ - void set_detail_report_info(bool flag) {verbose = flag;} + void set_detail_report_info(bool flag) { + verbose = flag; + } + /* set repl mode flag */ - void set_repl_mode_flag(bool flag) {is_repl_mode = flag;} + void set_repl_mode_flag(bool flag) { + is_repl_mode = flag; + } + /* set repl output flag */ - void set_allow_repl_output_flag(bool flag) {allow_repl_output = flag;} + void set_allow_repl_output_flag(bool flag) { + allow_repl_output = flag; + } + /* set limit mode flag */ - void set_limit_mode_flag(bool flag) {flag_limited_mode = flag;} + void set_limit_mode_flag(bool flag) { + flag_limited_mode = flag; + } }; inline bool vm::cond(var& val) { diff --git a/src/repl.cpp b/src/repl.cpp index e0118c5..b499d67 100644 --- a/src/repl.cpp +++ b/src/repl.cpp @@ -47,12 +47,12 @@ bool repl::check_need_more_input() { i64 in_brace = 0; for(const auto& t : nasal_lexer->result()) { switch(t.type) { - case tok::lcurve: ++in_curve; break; - case tok::rcurve: --in_curve; break; - case tok::lbracket: ++in_bracket; break; - case tok::rbracket: --in_bracket; break; - case tok::lbrace: ++in_brace; break; - case tok::rbrace: --in_brace; break; + case tok::tk_lcurve: ++in_curve; break; + case tok::tk_rcurve: --in_curve; break; + case tok::tk_lbracket: ++in_bracket; break; + case tok::tk_rbracket: --in_bracket; break; + case tok::tk_lbrace: ++in_brace; break; + case tok::tk_rbrace: --in_brace; break; default: break; } } From 7590a286c3734f415ebbea82d3d430071073ea0a Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Tue, 21 May 2024 23:51:44 +0800 Subject: [PATCH 03/21] :sparkles: more beautiful ast dump --- src/ast_dumper.cpp | 74 +++++++++++++++++++++++----------------------- src/ast_dumper.h | 32 ++++++++++++-------- src/main.cpp | 7 +++-- 3 files changed, 61 insertions(+), 52 deletions(-) diff --git a/src/ast_dumper.cpp b/src/ast_dumper.cpp index 900fdd8..a12a0e7 100644 --- a/src/ast_dumper.cpp +++ b/src/ast_dumper.cpp @@ -6,7 +6,7 @@ namespace nasal { bool ast_dumper::visit_use_stmt(use_stmt* node) { dump_indent(); - std::cout << "use" << format_location(node->get_location()); + std::cout << "use" << format_location(node); push_indent(); for(auto i : node->get_path()) { if (i==node->get_path().back()) { @@ -20,48 +20,48 @@ bool ast_dumper::visit_use_stmt(use_stmt* node) { bool ast_dumper::visit_null_expr(null_expr* node) { dump_indent(); - std::cout << "null" << format_location(node->get_location()); + std::cout << "null" << format_location(node); return true; } bool ast_dumper::visit_nil_expr(nil_expr* node) { dump_indent(); - std::cout << "nil" << format_location(node->get_location()); + std::cout << "nil" << format_location(node); return true; } bool ast_dumper::visit_number_literal(number_literal* node) { dump_indent(); std::cout << "number " << node->get_number(); - std::cout << format_location(node->get_location()); + std::cout << format_location(node); return true; } bool ast_dumper::visit_string_literal(string_literal* node) { dump_indent(); std::cout << "string \"" << rawstr(node->get_content()) << "\""; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); return true; } bool ast_dumper::visit_identifier(identifier* node) { dump_indent(); std::cout << "identifier " << node->get_name(); - std::cout << format_location(node->get_location()); + std::cout << format_location(node); return true; } bool ast_dumper::visit_bool_literal(bool_literal* node) { dump_indent(); std::cout << "bool " << node->get_flag(); - std::cout << format_location(node->get_location()); + std::cout << format_location(node); return true; } bool ast_dumper::visit_vector_expr(vector_expr* node) { dump_indent(); std::cout << "vector"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); for(auto i : node->get_elements()) { if (i==node->get_elements().back()) { @@ -76,7 +76,7 @@ bool ast_dumper::visit_vector_expr(vector_expr* node) { bool ast_dumper::visit_hash_expr(hash_expr* node) { dump_indent(); std::cout << "hash"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); for(auto i : node->get_members()) { if (i==node->get_members().back()) { @@ -91,7 +91,7 @@ bool ast_dumper::visit_hash_expr(hash_expr* node) { bool ast_dumper::visit_hash_pair(hash_pair* node) { dump_indent(); std::cout << "pair " << node->get_name(); - std::cout << format_location(node->get_location()); + std::cout << format_location(node); if (node->get_value()) { push_indent(); set_last(); @@ -104,7 +104,7 @@ bool ast_dumper::visit_hash_pair(hash_pair* node) { bool ast_dumper::visit_function(function* node) { dump_indent(); std::cout << "function"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); for(auto i : node->get_parameter_list()) { i->accept(this); @@ -118,7 +118,7 @@ bool ast_dumper::visit_function(function* node) { bool ast_dumper::visit_code_block(code_block* node) { dump_indent(); std::cout << "block"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); for(auto i : node->get_expressions()) { if (i==node->get_expressions().back()) { @@ -133,7 +133,7 @@ bool ast_dumper::visit_code_block(code_block* node) { bool ast_dumper::visit_parameter(parameter* node) { dump_indent(); std::cout << "parameter " << node->get_parameter_name(); - std::cout << format_location(node->get_location()); + std::cout << format_location(node); if (node->get_default_value()) { push_indent(); set_last(); @@ -146,7 +146,7 @@ bool ast_dumper::visit_parameter(parameter* node) { bool ast_dumper::visit_ternary_operator(ternary_operator* node) { dump_indent(); std::cout << "ternary_operator"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); node->get_condition()->accept(this); node->get_left()->accept(this); @@ -166,7 +166,7 @@ bool ast_dumper::visit_binary_operator(binary_operator* node) { return true; } dump_indent(); - std::cout << "binary_operator "; + std::cout << "binary_operator \""; switch(node->get_operator_type()) { case binary_operator::binary_type::add: std::cout << "+"; break; case binary_operator::binary_type::sub: std::cout << "-"; break; @@ -185,7 +185,7 @@ bool ast_dumper::visit_binary_operator(binary_operator* node) { case binary_operator::binary_type::condition_and: std::cout << "and"; break; case binary_operator::binary_type::condition_or: std::cout << "or"; break; } - std::cout << format_location(node->get_location()); + std::cout << "\"" << format_location(node); push_indent(); node->get_left()->accept(this); set_last(); @@ -200,13 +200,13 @@ bool ast_dumper::visit_unary_operator(unary_operator* node) { return true; } dump_indent(); - std::cout << "unary_operator "; + std::cout << "unary_operator \""; switch(node->get_operator_type()) { case unary_operator::unary_type::negative: std::cout << "-"; break; case unary_operator::unary_type::logical_not: std::cout << "!"; break; case unary_operator::unary_type::bitwise_not: std::cout << "~"; break; } - std::cout << format_location(node->get_location()); + std::cout << "\"" << format_location(node); push_indent(); set_last(); node->get_value()->accept(this); @@ -217,7 +217,7 @@ bool ast_dumper::visit_unary_operator(unary_operator* node) { bool ast_dumper::visit_call_expr(call_expr* node) { dump_indent(); std::cout << "call_expr"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); if (!node->get_calls().size()) { set_last(); @@ -236,14 +236,14 @@ bool ast_dumper::visit_call_expr(call_expr* node) { bool ast_dumper::visit_call_hash(call_hash* node) { dump_indent(); std::cout << "call_hash " << node->get_field(); - std::cout << format_location(node->get_location()); + std::cout << format_location(node); return true; } bool ast_dumper::visit_call_vector(call_vector* node) { dump_indent(); std::cout << "call_vector"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); for(auto i : node->get_slices()) { if (i==node->get_slices().back()) { @@ -258,7 +258,7 @@ bool ast_dumper::visit_call_vector(call_vector* node) { bool ast_dumper::visit_call_function(call_function* node) { dump_indent(); std::cout << "call_function"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); for(auto i : node->get_argument()) { if (i==node->get_argument().back()) { @@ -273,7 +273,7 @@ bool ast_dumper::visit_call_function(call_function* node) { bool ast_dumper::visit_slice_vector(slice_vector* node) { dump_indent(); std::cout << "slice"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); if (!node->get_end()) { set_last(); @@ -290,7 +290,7 @@ bool ast_dumper::visit_slice_vector(slice_vector* node) { bool ast_dumper::visit_definition_expr(definition_expr* node) { dump_indent(); std::cout << "definition"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); if (node->get_variable_name()) { node->get_variable_name()->accept(this); @@ -321,7 +321,7 @@ bool ast_dumper::visit_assignment_expr(assignment_expr* node) { case assignment_expr::assign_type::bitwise_or_equal: std::cout << "|="; break; case assignment_expr::assign_type::bitwise_xor_equal: std::cout << "^="; break; } - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); node->get_left()->accept(this); set_last(); @@ -333,7 +333,7 @@ bool ast_dumper::visit_assignment_expr(assignment_expr* node) { bool ast_dumper::visit_multi_identifier(multi_identifier* node) { dump_indent(); std::cout << "multiple_identifier"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); for(auto i : node->get_variables()) { if (i==node->get_variables().back()) { @@ -348,7 +348,7 @@ bool ast_dumper::visit_multi_identifier(multi_identifier* node) { bool ast_dumper::visit_tuple_expr(tuple_expr* node) { dump_indent(); std::cout << "tuple"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); for(auto i : node->get_elements()) { if (i==node->get_elements().back()) { @@ -363,7 +363,7 @@ bool ast_dumper::visit_tuple_expr(tuple_expr* node) { bool ast_dumper::visit_multi_assign(multi_assign* node) { dump_indent(); std::cout << "multiple_assignment"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); node->get_tuple()->accept(this); set_last(); @@ -375,7 +375,7 @@ bool ast_dumper::visit_multi_assign(multi_assign* node) { bool ast_dumper::visit_while_expr(while_expr* node) { dump_indent(); std::cout << "while"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); node->get_condition()->accept(this); set_last(); @@ -387,7 +387,7 @@ bool ast_dumper::visit_while_expr(while_expr* node) { bool ast_dumper::visit_for_expr(for_expr* node) { dump_indent(); std::cout << "for"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); node->get_initial()->accept(this); node->get_condition()->accept(this); @@ -405,7 +405,7 @@ bool ast_dumper::visit_iter_expr(iter_expr* node) { } else { std::cout << "iterator"; } - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); set_last(); if (node->get_name()) { @@ -424,7 +424,7 @@ bool ast_dumper::visit_forei_expr(forei_expr* node) { } else { std::cout << "forindex"; } - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); node->get_iterator()->accept(this); node->get_value()->accept(this); @@ -437,7 +437,7 @@ bool ast_dumper::visit_forei_expr(forei_expr* node) { bool ast_dumper::visit_condition_expr(condition_expr* node) { dump_indent(); std::cout << "condition"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); if (!node->get_elsif_stataments().size() && !node->get_else_statement()) { @@ -462,7 +462,7 @@ bool ast_dumper::visit_condition_expr(condition_expr* node) { bool ast_dumper::visit_if_expr(if_expr* node) { dump_indent(); std::cout << "if"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); push_indent(); if (node->get_condition()) { node->get_condition()->accept(this); @@ -476,21 +476,21 @@ bool ast_dumper::visit_if_expr(if_expr* node) { bool ast_dumper::visit_continue_expr(continue_expr* node) { dump_indent(); std::cout << "continue"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); return true; } bool ast_dumper::visit_break_expr(break_expr* node) { dump_indent(); std::cout << "break"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); return true; } bool ast_dumper::visit_return_expr(return_expr* node) { dump_indent(); std::cout << "return"; - std::cout << format_location(node->get_location()); + std::cout << format_location(node); if (node->get_value()) { push_indent(); set_last(); diff --git a/src/ast_dumper.h b/src/ast_dumper.h index c762f79..5825ed7 100644 --- a/src/ast_dumper.h +++ b/src/ast_dumper.h @@ -16,29 +16,37 @@ private: private: void push_indent() { if (indent.size()) { - if (indent.back()=="|--") { - indent.back() = "| "; - } else if (indent.back()=="+--") { + if (indent.back()=="├──") { + indent.back() = "│ "; + } else if (indent.back()=="└──") { indent.back() = " "; } } - indent.push_back("|--"); + indent.push_back("├──"); } - void pop_indent() {indent.pop_back();} - void set_last() {indent.back() = "+--";} + + void pop_indent() { + indent.pop_back(); + } + + void set_last() { + indent.back() = "└──"; + } + void dump_indent() { - if (indent.size() && indent.back()=="| ") { - indent.back() = "|--"; + if (indent.size() && indent.back()=="│ ") { + indent.back() = "├──"; } for(const auto& i : indent) { std::cout << i; } } - std::string format_location(const span& location) { + + std::string format_location(expr* node) { std::stringstream ss; - ss << " -> "; - location.dump_begin(ss); - ss << "\n"; + ss << " → ["; + node->get_location().dump_begin(ss); + ss << "]\n"; return ss.str(); } diff --git a/src/main.cpp b/src/main.cpp index 422cd27..2108732 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -45,7 +45,7 @@ std::ostream& help(std::ostream& out) { << "option:\n" << " -h, --help | get help.\n" << " -v, --version | get version.\n" - << " -r, --repl | use repl interpreter(experimental).\n" + << " -r, --repl | use repl interpreter.\n" << "\nnasal [option] [argv]\n" << "option:\n" << " -a, --ast | view ast after link/optimize process.\n" @@ -101,11 +101,12 @@ std::ostream& version(std::ostream& out) { for(u32 i = 0; i<5; ++i) { num = (num+rand())*(1.0/(RAND_MAX+1.0)); } - if (num<0.01) { + // give you 5% to see this easter egg + if (num<0.05) { nasal::parse::easter_egg(); } - out << "nasal interpreter version " << __nasver__; + out << "nasal version " << __nasver__; out << " " << nasal::get_platform() << " " << nasal::get_arch(); out << " (" << __DATE__ << " " << __TIME__ << ")\n"; return out; From b6a7b7f46d3e177e9ac45fd3448d1068d4399221 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Wed, 22 May 2024 00:08:36 +0800 Subject: [PATCH 04/21] :memo: rename flstream => filestream --- src/main.cpp | 4 +++- src/nasal_dbg.cpp | 2 +- src/nasal_err.cpp | 2 +- src/nasal_err.h | 6 +++--- src/nasal_misc.cpp | 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 2108732..aac8a13 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -88,7 +88,9 @@ std::ostream& logo(std::ostream& out) { << "repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n" << "wiki : https://wiki.flightgear.org/Nasal_scripting_language\n" << "\n" - << "presented by fgprc members - http://fgprc.org.cn\n" + << "presented by fgprc members\n" + << " - fgprc : http://fgprc.org\n" + << " - fgprc.cn : http://fgprc.org.cn\n" << "\n" << "input to get help .\n\n"; return out; diff --git a/src/nasal_dbg.cpp b/src/nasal_dbg.cpp index 64d911c..cc1bc9c 100644 --- a/src/nasal_dbg.cpp +++ b/src/nasal_dbg.cpp @@ -13,7 +13,7 @@ void operand_line_counter::load_file_line_counter( file_name_list = file_list; file_line_counter = {}; file_contents = {}; - flstream fs; + filestream fs; for(usize i =0; i res; public: - flstream(): file("") {} + filestream(): file("") {} void load(const std::string&); const std::string& operator[](usize n) const {return res[n];} const auto& name() const {return file;} @@ -43,7 +43,7 @@ public: usize size() const {return res.size();} }; -class error: public flstream { +class error: public filestream { private: u32 cnt; // counter for errors diff --git a/src/nasal_misc.cpp b/src/nasal_misc.cpp index 13f7f30..77da7dc 100644 --- a/src/nasal_misc.cpp +++ b/src/nasal_misc.cpp @@ -105,7 +105,7 @@ const char* get_platform() { } else if (is_macos()) { return "macOS"; } - return "unknown platform"; + return "unknown"; } const char* get_arch() { @@ -126,7 +126,7 @@ const char* get_arch() { } else if (is_superh()) { return "superh"; } - return "unknown arch"; + return "unknown"; } f64 hex_to_f64(const char* str) { From 971583b1c78653fb75085a7fc4d551f95b12e05b Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Wed, 22 May 2024 19:23:09 +0800 Subject: [PATCH 05/21] :sparkles: support utf8 ast dump on windows --- src/ast_dumper.h | 16 ++++++++++++++++ src/natives/nasal_builtin.cpp | 14 ++++++++++++++ src/natives/nasal_builtin.h | 3 +++ std/runtime.nas | 6 ++++++ test/utf8chk.nas | 21 +++++++++++++-------- 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/ast_dumper.h b/src/ast_dumper.h index 5825ed7..f95f6bd 100644 --- a/src/ast_dumper.h +++ b/src/ast_dumper.h @@ -2,6 +2,10 @@ #include "ast_visitor.h" +#ifdef _WIN32 +#include +#endif + #include #include #include @@ -89,7 +93,19 @@ public: public: void dump(code_block* root) { +#ifdef _WIN32 + // store previous code page + auto cp = GetConsoleOutputCP(); + // allow 65001 code page + SetConsoleOutputCP(CP_UTF8); +#endif + root->accept(this); + +#ifdef _WIN32 + // restore previous code page + SetConsoleOutputCP(cp); +#endif } }; diff --git a/src/natives/nasal_builtin.cpp b/src/natives/nasal_builtin.cpp index 628c711..d9beaba 100644 --- a/src/natives/nasal_builtin.cpp +++ b/src/natives/nasal_builtin.cpp @@ -1,6 +1,10 @@ #include "natives/nasal_builtin.h" #include +#ifdef _WIN32 +#include +#endif + namespace nasal { var builtin_unsafe(context* ctx, gc* ngc) { @@ -717,6 +721,15 @@ var builtin_ghosttype(context* ctx, gc* ngc) { return ngc->newstr(name); } +var builtin_set_utf8_output(context* ctx, gc* ngc) { +#ifdef _WIN32 + // allow 65001 code page + SetConsoleOutputCP(CP_UTF8); +#endif + // do nothing on other platforms + return nil; +} + nasal_builtin_table builtin[] = { {"__print", builtin_print}, {"__println", builtin_println}, @@ -763,6 +776,7 @@ nasal_builtin_table builtin[] = { {"__gcinfo", builtin_gcinfo}, {"__logtime", builtin_logtime}, {"__ghosttype", builtin_ghosttype}, + {"__set_utf8_output", builtin_set_utf8_output}, {nullptr, nullptr} }; diff --git a/src/natives/nasal_builtin.h b/src/natives/nasal_builtin.h index 11f096d..2239a17 100644 --- a/src/natives/nasal_builtin.h +++ b/src/natives/nasal_builtin.h @@ -81,6 +81,9 @@ var builtin_gcinfo(context*, gc*); var builtin_logtime(context*, gc*); var builtin_ghosttype(context*, gc*); +// only useful on windows platform +var builtin_set_utf8_output(context*, gc*); + // register builtin function's name and it's address here in this table below // this table must end with {nullptr, nullptr} struct nasal_builtin_table { diff --git a/std/runtime.nas b/std/runtime.nas index bad3203..2cd57a1 100644 --- a/std/runtime.nas +++ b/std/runtime.nas @@ -27,3 +27,9 @@ var gc = { }, info: func() {return __gcinfo;} }; + +var windows = { + set_utf8_output: func() { + return __set_utf8_output; + } +}; diff --git a/test/utf8chk.nas b/test/utf8chk.nas index ff2b445..63c5cfe 100644 --- a/test/utf8chk.nas +++ b/test/utf8chk.nas @@ -1,11 +1,16 @@ +use std.runtime; + +# do nothing if platform is not windows +runtime.windows.set_utf8_output(); + var unicode测试 = func() { var 输出=print; var 测试成功=[ - "unicode: utf-8支持测试成功", - "目前仅支持utf-8以及ascii格式文件", - "注意: windows系统请开启chcp 65001代码页" + "unicode: utf-8 支持测试成功", + "目前仅支持 utf-8 以及 ascii 格式文件", + "注意: windows 系统请开启 chcp 65001 代码页" ]; - foreach(var 内容;测试成功) + foreach(var 内容; 测试成功) 输出(内容~"\n"); } @@ -41,10 +46,10 @@ var emoji测试 = func() { 🍾:🍾, 🐘:🐘 }; - foreach(var 📄;📁) - 💻(📄,🎤); - foreach(var 📄;keys(🗄️)) - 💻(📄,🗄️[📄],🎤); + foreach(var 📄; 📁) + 💻(📄, 🎤); + foreach(var 📄; keys(🗄️)) + 💻(📄, 🗄️[📄], 🎤); } var dotsgen = func() { From 6a155f56e5dc64668d03ea387b86f6cc358b4f10 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Wed, 22 May 2024 20:02:37 +0800 Subject: [PATCH 06/21] :memo: update doc about enabling 65001 code page --- README.md | 8 ++++++++ doc/README_zh.md | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5fd0fd0..e8b5158 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,14 @@ if (os.platform()=="windows") { } ``` +Or use `std.runtime.windows.set_utf8_output()`: + +```javascript +use std.runtime; + +runtime.windows.set_utf8_output(); +``` + ## __Difference Between Andy's and This Interpreter__ ![error](./doc/gif/error.gif) diff --git a/doc/README_zh.md b/doc/README_zh.md index 77f6480..0cdd1da 100644 --- a/doc/README_zh.md +++ b/doc/README_zh.md @@ -103,7 +103,7 @@ Windows 平台的预览版解释器现在还没配置相关流水线, ![usage](../doc/gif/help.gif) -如果你是 `Windows` 用户且想正常输出unicode,在nasal代码里写这个来开启unicode代码页: +如果你是 `Windows` 用户且想正常输出 unicode,可以这样开启 unicode 代码页: ```javascript if (os.platform()=="windows") { @@ -111,6 +111,14 @@ if (os.platform()=="windows") { } ``` +或者使用 `std.runtime.windows.set_utf8_output()`: + +```javascript +use std.runtime; + +runtime.windows.set_utf8_output(); +``` + ## __与andy解释器的不同之处__ ![error](../doc/gif/error.gif) From f9f2cf6d47fe820bc4af1f40a9fffc4da1b123e2 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Wed, 22 May 2024 20:29:13 +0800 Subject: [PATCH 07/21] :memo: change eol to lf --- src/ast_dumper.h | 224 +++++++++++++++++++++++------------------------ 1 file changed, 112 insertions(+), 112 deletions(-) diff --git a/src/ast_dumper.h b/src/ast_dumper.h index f95f6bd..cfbd1d0 100644 --- a/src/ast_dumper.h +++ b/src/ast_dumper.h @@ -1,112 +1,112 @@ -#pragma once - -#include "ast_visitor.h" - -#ifdef _WIN32 -#include -#endif - -#include -#include -#include -#include - -namespace nasal { - -class ast_dumper: public ast_visitor { -private: - std::vector indent; - -private: - void push_indent() { - if (indent.size()) { - if (indent.back()=="├──") { - indent.back() = "│ "; - } else if (indent.back()=="└──") { - indent.back() = " "; - } - } - indent.push_back("├──"); - } - - void pop_indent() { - indent.pop_back(); - } - - void set_last() { - indent.back() = "└──"; - } - - void dump_indent() { - if (indent.size() && indent.back()=="│ ") { - indent.back() = "├──"; - } - for(const auto& i : indent) { - std::cout << i; - } - } - - std::string format_location(expr* node) { - std::stringstream ss; - ss << " → ["; - node->get_location().dump_begin(ss); - ss << "]\n"; - return ss.str(); - } - -public: - bool visit_use_stmt(use_stmt*) override; - bool visit_null_expr(null_expr*) override; - bool visit_nil_expr(nil_expr*) override; - bool visit_number_literal(number_literal*) override; - bool visit_string_literal(string_literal*) override; - bool visit_identifier(identifier*) override; - bool visit_bool_literal(bool_literal*) override; - bool visit_vector_expr(vector_expr*) override; - bool visit_hash_expr(hash_expr*) override; - bool visit_hash_pair(hash_pair*) override; - bool visit_function(function*) override; - bool visit_code_block(code_block*) override; - bool visit_parameter(parameter*) override; - bool visit_ternary_operator(ternary_operator*) override; - bool visit_binary_operator(binary_operator*) override; - bool visit_unary_operator(unary_operator*) override; - bool visit_call_expr(call_expr*) override; - bool visit_call_hash(call_hash*) override; - bool visit_call_vector(call_vector*) override; - bool visit_call_function(call_function*) override; - bool visit_slice_vector(slice_vector*) override; - bool visit_definition_expr(definition_expr*) override; - bool visit_assignment_expr(assignment_expr*) override; - bool visit_multi_identifier(multi_identifier*) override; - bool visit_tuple_expr(tuple_expr*) override; - bool visit_multi_assign(multi_assign*) override; - bool visit_while_expr(while_expr*) override; - bool visit_for_expr(for_expr*) override; - bool visit_iter_expr(iter_expr*) override; - bool visit_forei_expr(forei_expr*) override; - bool visit_condition_expr(condition_expr*) override; - bool visit_if_expr(if_expr*) override; - bool visit_continue_expr(continue_expr*) override; - bool visit_break_expr(break_expr*) override; - bool visit_return_expr(return_expr*) override; - -public: - void dump(code_block* root) { -#ifdef _WIN32 - // store previous code page - auto cp = GetConsoleOutputCP(); - // allow 65001 code page - SetConsoleOutputCP(CP_UTF8); -#endif - - root->accept(this); - -#ifdef _WIN32 - // restore previous code page - SetConsoleOutputCP(cp); -#endif - } -}; - -} +#pragma once + +#include "ast_visitor.h" + +#ifdef _WIN32 +#include +#endif + +#include +#include +#include +#include + +namespace nasal { + +class ast_dumper: public ast_visitor { +private: + std::vector indent; + +private: + void push_indent() { + if (indent.size()) { + if (indent.back()=="├──") { + indent.back() = "│ "; + } else if (indent.back()=="└──") { + indent.back() = " "; + } + } + indent.push_back("├──"); + } + + void pop_indent() { + indent.pop_back(); + } + + void set_last() { + indent.back() = "└──"; + } + + void dump_indent() { + if (indent.size() && indent.back()=="│ ") { + indent.back() = "├──"; + } + for(const auto& i : indent) { + std::cout << i; + } + } + + std::string format_location(expr* node) { + std::stringstream ss; + ss << " → ["; + node->get_location().dump_begin(ss); + ss << "]\n"; + return ss.str(); + } + +public: + bool visit_use_stmt(use_stmt*) override; + bool visit_null_expr(null_expr*) override; + bool visit_nil_expr(nil_expr*) override; + bool visit_number_literal(number_literal*) override; + bool visit_string_literal(string_literal*) override; + bool visit_identifier(identifier*) override; + bool visit_bool_literal(bool_literal*) override; + bool visit_vector_expr(vector_expr*) override; + bool visit_hash_expr(hash_expr*) override; + bool visit_hash_pair(hash_pair*) override; + bool visit_function(function*) override; + bool visit_code_block(code_block*) override; + bool visit_parameter(parameter*) override; + bool visit_ternary_operator(ternary_operator*) override; + bool visit_binary_operator(binary_operator*) override; + bool visit_unary_operator(unary_operator*) override; + bool visit_call_expr(call_expr*) override; + bool visit_call_hash(call_hash*) override; + bool visit_call_vector(call_vector*) override; + bool visit_call_function(call_function*) override; + bool visit_slice_vector(slice_vector*) override; + bool visit_definition_expr(definition_expr*) override; + bool visit_assignment_expr(assignment_expr*) override; + bool visit_multi_identifier(multi_identifier*) override; + bool visit_tuple_expr(tuple_expr*) override; + bool visit_multi_assign(multi_assign*) override; + bool visit_while_expr(while_expr*) override; + bool visit_for_expr(for_expr*) override; + bool visit_iter_expr(iter_expr*) override; + bool visit_forei_expr(forei_expr*) override; + bool visit_condition_expr(condition_expr*) override; + bool visit_if_expr(if_expr*) override; + bool visit_continue_expr(continue_expr*) override; + bool visit_break_expr(break_expr*) override; + bool visit_return_expr(return_expr*) override; + +public: + void dump(code_block* root) { +#ifdef _WIN32 + // store previous code page + auto cp = GetConsoleOutputCP(); + // allow 65001 code page + SetConsoleOutputCP(CP_UTF8); +#endif + + root->accept(this); + +#ifdef _WIN32 + // restore previous code page + SetConsoleOutputCP(cp); +#endif + } +}; + +} From b02168fc55b29c3ac18d731aae4cf7ffafadcc5e Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Wed, 22 May 2024 23:41:14 +0800 Subject: [PATCH 08/21] :memo: delete system call in test files --- src/main.cpp | 3 --- test/ascii-art.nas | 6 ++---- test/coroutine.nas | 3 ++- test/filesystem.nas | 6 +++--- test/md5compare.nas | 6 ++---- test/occupation.nas | 2 +- test/qrcode.nas | 6 +++--- test/snake.nas | 4 +--- test/tetris.nas | 7 +++---- test/wavecollapse.nas | 5 ++--- 10 files changed, 19 insertions(+), 29 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index aac8a13..f2a107f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,9 +38,6 @@ std::ostream& help(std::ostream& out) { << " ,--#-,\n" << "<3 / \\____\\ <3\n" << " |_|__A_|\n" -#ifdef _WIN32 - << "use command to use unicode.\n" -#endif << "\nnasal