diff --git a/main.cpp b/main.cpp index f4bb8a4..3820220 100644 --- a/main.cpp +++ b/main.cpp @@ -13,6 +13,8 @@ #include +using ch_clk=std::chrono::high_resolution_clock; + const u32 VM_TOKEN =0x01; const u32 VM_AST =0x02; const u32 VM_CODE =0x04; @@ -114,10 +116,10 @@ void execute(const string& file,const std::vector& argv,const u32 cmd) debugger(err).run(gen,ld,argv); else if(cmd&VM_TIME) { - auto start=std::chrono::high_resolution_clock::now(); + auto start=ch_clk::now(); ctx.run(gen,ld,argv,cmd&VM_DETAIL); - auto end=std::chrono::high_resolution_clock::now(); - std::clog<<"process exited after "<<(end-start).count()*1.0/std::chrono::high_resolution_clock::duration::period::den<<"s.\n"; + auto end=ch_clk::now(); + std::clog<<"process exited after "<<(end-start).count()*1.0/ch_clk::duration::period::den<<"s.\n"; } else if(cmd&VM_EXEC) ctx.run(gen,ld,argv,cmd&VM_DETAIL); diff --git a/nasal.h b/nasal.h index b4e800a..90d2103 100644 --- a/nasal.h +++ b/nasal.h @@ -1,6 +1,8 @@ -#ifndef __NASAL_H__ -#define __NASAL_H__ +#pragma once + +#ifndef __nasver #define __nasver "10.1" +#endif #include #include @@ -151,5 +153,3 @@ string rawstr(const string& str,const usize maxlen=0) } #include "nasal_gc.h" // declarations of var and nasal_gc - -#endif diff --git a/nasal_ast.h b/nasal_ast.h index 2283c36..7b089ec 100644 --- a/nasal_ast.h +++ b/nasal_ast.h @@ -1,5 +1,4 @@ -#ifndef __NASAL_AST_H__ -#define __NASAL_AST_H__ +#pragma once #include #include @@ -53,12 +52,12 @@ enum ast_node:u32 ast_foreach, // foreach keyword ast_while, // while ast_iter, // iterator, used in forindex/foreach - ast_conditional, // mark a sub-tree of conditional expression + ast_cond, // mark a sub-tree of conditional expression ast_if, // if keyword ast_elsif, // elsif keyword ast_else, // else keyword ast_multi_id, // multi identifiers sub-tree - ast_multi_scalar,// multi value sub-tree + ast_tuple, // tuple, only used in multiple assignment ast_def, // definition ast_multi_assign,// multi assignment sub-tree ast_continue, // continue keyword, only used in loop @@ -107,20 +106,20 @@ const char* ast_name[]= "*", "/", "~", - "unary-", - "unary!", + "neg", + "!", "trino", "for", "forindex", "foreach", "while", "iter", - "conditional", + "cond", "if", "elsif", "else", "multi-id", - "multi-scalar", + "tuple", "def", "multi-assign", "continue", @@ -131,15 +130,15 @@ const char* ast_name[]= class ast { private: - u32 node_line; - u32 node_col; - u32 node_type; - f64 node_num; - string node_str; - std::vector node_child; + u32 nd_line; + u32 nd_col; + u32 nd_type; + f64 nd_num; + string nd_str; + std::vector nd_child; public: ast(const u32 l,const u32 c,const u32 t): - node_line(l),node_col(c),node_type(t),node_num(0){} + nd_line(l),nd_col(c),nd_type(t),nd_num(0){} ast(const ast&); ast(ast&&); void print_tree(); @@ -148,74 +147,74 @@ public: ast& operator=(const ast&); ast& operator=(ast&&); - ast& operator[](usize n){return node_child[n];} - const ast& operator[](usize n) const {return node_child[n];} - usize size() const {return node_child.size();} + ast& operator[](usize n){return nd_child[n];} + const ast& operator[](usize n) const {return nd_child[n];} + usize size() const {return nd_child.size();} - void add(ast&& node){node_child.push_back(std::move(node));} - void add(const ast& node){node_child.push_back(node);} - void set_line(const u32 l){node_line=l;} - void set_type(const u32 t){node_type=t;} - void set_str(const string& s){node_str=s;} - void set_num(const f64 n){node_num=n;} + void add(ast&& node){nd_child.push_back(std::move(node));} + void add(const ast& node){nd_child.push_back(node);} + void set_line(const u32 l){nd_line=l;} + void set_type(const u32 t){nd_type=t;} + void set_str(const string& s){nd_str=s;} + void set_num(const f64 n){nd_num=n;} - inline u32 line() const {return node_line;} - inline u32 col() const {return node_col;} - inline u32 type() const {return node_type;} - inline f64 num() const {return node_num;} - inline const string& str() const {return node_str;} - inline const std::vector& child() const {return node_child;} - inline std::vector& child(){return node_child;} + inline u32 line() const {return nd_line;} + inline u32 col() const {return nd_col;} + inline u32 type() const {return nd_type;} + inline f64 num() const {return nd_num;} + inline const string& str() const {return nd_str;} + inline const std::vector& child() const {return nd_child;} + inline std::vector& child(){return nd_child;} }; ast::ast(const ast& tmp): - node_str(tmp.node_str),node_child(tmp.node_child) + nd_str(tmp.nd_str),nd_child(tmp.nd_child) { - node_line=tmp.node_line; - node_col=tmp.node_col; - node_type=tmp.node_type; - node_num =tmp.node_num; + nd_line=tmp.nd_line; + nd_col=tmp.nd_col; + nd_type=tmp.nd_type; + nd_num =tmp.nd_num; } ast::ast(ast&& tmp) { - node_line=tmp.node_line; - node_col=tmp.node_col; - node_type=tmp.node_type; - node_num =tmp.node_num; - node_str.swap(tmp.node_str); - node_child.swap(tmp.node_child); + nd_line=tmp.nd_line; + nd_col=tmp.nd_col; + nd_type=tmp.nd_type; + nd_num =tmp.nd_num; + nd_str.swap(tmp.nd_str); + nd_child.swap(tmp.nd_child); } ast& ast::operator=(const ast& tmp) { - node_line=tmp.node_line; - node_col=tmp.node_col; - node_type=tmp.node_type; - node_num=tmp.node_num; - node_str=tmp.node_str; - node_child=tmp.node_child; + nd_line=tmp.nd_line; + nd_col=tmp.nd_col; + nd_type=tmp.nd_type; + nd_num=tmp.nd_num; + nd_str=tmp.nd_str; + nd_child=tmp.nd_child; return *this; } ast& ast::operator=(ast&& tmp) { - node_line=tmp.node_line; - node_col=tmp.node_col; - node_type=tmp.node_type; - node_num=tmp.node_num; - node_str.swap(tmp.node_str); - node_child.swap(tmp.node_child); + nd_line=tmp.nd_line; + nd_col=tmp.nd_col; + nd_type=tmp.nd_type; + nd_num=tmp.nd_num; + nd_str.swap(tmp.nd_str); + nd_child.swap(tmp.nd_child); return *this; } void ast::clear() { - node_line=node_col=0; - node_num=0; - node_str.clear(); - node_type=ast_null; - node_child.clear(); + nd_line=nd_col=0; + nd_num=0; + nd_str.clear(); + nd_type=ast_null; + nd_child.clear(); } void ast::print_tree() @@ -228,15 +227,13 @@ void ast::print(u32 depth,bool last,std::vector& indent) { for(auto& i:indent) std::cout<& indent) #else indent.back()="│ "; #endif - for(u32 i=0;i @@ -248,7 +247,7 @@ private: void single_def(const ast&); void def_gen(const ast&); void multi_assign_gen(const ast&); - void conditional_gen(const ast&); + void cond_gen(const ast&); void loop_gen(const ast&); void load_continue_break(i32,i32); void while_gen(const ast&); @@ -649,7 +648,7 @@ void codegen::multi_def(const ast& node) { auto& ids=node[0].child(); usize size=ids.size(); - if(node[1].type()==ast_multi_scalar) // (var a,b,c)=(c,b,a); + if(node[1].type()==ast_tuple) // (var a,b,c)=(c,b,a); { auto& vals=node[1].child(); for(usize i=0;i=0;--i) calc_gen(node[1][i]); @@ -725,7 +724,7 @@ void codegen::multi_assign_gen(const ast& node) } } -void codegen::conditional_gen(const ast& node) +void codegen::cond_gen(const ast& node) { std::vector jmp_label; for(auto& tmp:node.child()) @@ -1146,7 +1145,7 @@ void codegen::block_gen(const ast& node) case ast_file:fileindex=tmp.num();break; // special node type in main block case ast_def:def_gen(tmp);break; case ast_multi_assign:multi_assign_gen(tmp);break; - case ast_conditional:conditional_gen(tmp);break; + case ast_cond:cond_gen(tmp);break; case ast_continue: continue_ptr.front().push_back(code.size()); gen(op_jmp,0,tmp.line()); @@ -1288,5 +1287,3 @@ void codegen::print() for(u32 i=0;i ":" ") - < #include @@ -159,5 +158,3 @@ public: } void chkerr(){if(cnt)std::exit(1);} }; - -#endif \ No newline at end of file diff --git a/nasal_gc.h b/nasal_gc.h index 8caa574..577499b 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -1,5 +1,4 @@ -#ifndef __NASAL_GC_H__ -#define __NASAL_GC_H__ +#pragma once #include #include @@ -725,5 +724,3 @@ var nas_err(const string& err_f,const string& info) typedef var (*mod)(var*,usize,gc*); // module function type typedef mod (*getptr)(const char*); // module function "get" type - -#endif \ No newline at end of file diff --git a/nasal_import.h b/nasal_import.h index 0cdf0d8..031f64c 100644 --- a/nasal_import.h +++ b/nasal_import.h @@ -1,5 +1,4 @@ -#ifndef __NASAL_IMPORT_H__ -#define __NASAL_IMPORT_H__ +#pragma once #ifndef _MSC_VER #include @@ -224,5 +223,3 @@ void linker::link(parse& parse,const string& self,bool spath=false) parse.tree()=load(parse.tree(),0); err.chkerr(); } - -#endif \ No newline at end of file diff --git a/nasal_lexer.h b/nasal_lexer.h index 9ee3432..af77c7b 100644 --- a/nasal_lexer.h +++ b/nasal_lexer.h @@ -1,5 +1,4 @@ -#ifndef __NASAL_LEXER_H__ -#define __NASAL_LEXER_H__ +#pragma once #include #include @@ -8,18 +7,6 @@ #define S_ISREG(m) (((m)&0xF000)==0x8000) #endif -#define ID(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||(c<0)) -#define HEX(c) (('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F')) -#define OCT(c) ('0'<=c&&c<='7') -#define DIGIT(c) ('0'<=c&&c<='9') -#define STR(c) (c=='\''||c=='\"'||c=='`') -// single operators have only one character -#define SINGLE_OPERATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\ - c=='?'||c=='`'||c=='&'||c=='@'||c=='%'||c=='$'||c=='^'||c=='\\') -// calculation operators may have two chars, for example: += -= *= /= ~= != == >= <= -#define CALC_OPERATOR(c) (c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~') -#define NOTE(c) (c=='#') - enum tok:u32{ tok_null=0, // null token (default token type) tok_num, // number literal @@ -38,15 +25,39 @@ enum tok:u32{ tok_elsif, // condition expression keyword elsif tok_else, // condition expression keyword else tok_nil, // nil literal - tok_lcurve,tok_rcurve, - tok_lbracket,tok_rbracket, - tok_lbrace,tok_rbrace, - tok_semi,tok_and,tok_or,tok_comma,tok_dot,tok_ellipsis,tok_quesmark, - tok_colon,tok_add,tok_sub,tok_mult,tok_div,tok_link,tok_not, - tok_eq, - tok_addeq,tok_subeq,tok_multeq,tok_diveq,tok_lnkeq, - tok_cmpeq,tok_neq,tok_less,tok_leq,tok_grt,tok_geq, - tok_eof // end of token list + tok_lcurve, // ( + tok_rcurve, // ) + tok_lbracket,// [ + tok_rbracket,// ] + tok_lbrace, // { + tok_rbrace, // } + tok_semi, // ; + tok_and, // operator and + tok_or, // operator or + tok_comma, // , + tok_dot, // . + tok_ellipsis,// ... + tok_quesmark,// ? + tok_colon, // : + tok_add, // operator + + tok_sub, // operator - + tok_mult, // operator * + tok_div, // operator / + tok_link, // operator ~ + tok_not, // operator ! + tok_eq, // operator = + tok_addeq, // operator += + tok_subeq, // operator -= + tok_multeq, // operator *= + tok_diveq, // operator /= + tok_lnkeq, // operator ~= + tok_cmpeq, // operator == + tok_neq, // operator != + tok_less, // operator < + tok_leq, // operator <= + tok_grt, // operator > + tok_geq, // operator >= + tok_eof // end of token list }; struct{ @@ -126,6 +137,13 @@ private: std::vector tokens; u32 get_type(const string&); + bool is_id(char); + bool is_hex(char); + bool is_oct(char); + bool is_dec(char); + bool is_str(char); + bool is_single_opr(char); + bool is_calc_opr(char); void die(const string& info){err.err("lexer",line,column,info);} void open(const string&); string utf8_gen(); @@ -142,6 +160,47 @@ public: const std::vector& result() const {return tokens;} }; +bool lexer::is_id(char c) +{ + return (c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||(c<0); +} + +bool lexer::is_hex(char c) +{ + return ('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F'); +} + +bool lexer::is_oct(char c) +{ + return '0'<=c&&c<='7'; +} + +bool lexer::is_dec(char c) +{ + return '0'<=c&&c<='9'; +} + +bool lexer::is_str(char c) +{ + return c=='\''||c=='\"'||c=='`'; +} + +bool lexer::is_single_opr(char c) +{ + return ( + c=='('||c==')'||c=='['||c==']'|| + c=='{'||c=='}'||c==','||c==';'|| + c=='|'||c==':'||c=='?'||c=='`'|| + c=='&'||c=='@'||c=='%'||c=='$'|| + c=='^'||c=='\\' + ); +} + +bool lexer::is_calc_opr(char c) +{ + return c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~'; +} + void lexer::open(const string& file) { struct stat buffer; @@ -205,7 +264,7 @@ string lexer::utf8_gen() string lexer::id_gen() { string str=""; - while(ptr [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*) string str=""; - while(ptr=res.size()) break; - if(ID(res[ptr])) + if(is_id(res[ptr])) { str=id_gen(); u32 type=get_type(str); tokens.push_back({line,column,type?type:tok_id,str}); } - else if(DIGIT(res[ptr])) + else if(is_dec(res[ptr])) { str=num_gen(); // make sure column is correct tokens.push_back({line,column,tok_num,str}); } - else if(STR(res[ptr])) + else if(is_str(res[ptr])) { str=str_gen(); // make sure column is correct tokens.push_back({line,column,tok_str,str}); } - else if(SINGLE_OPERATOR(res[ptr])) + else if(is_single_opr(res[ptr])) { str=res[ptr]; ++column; @@ -387,7 +446,7 @@ void lexer::scan(const string& file) column+=str.length(); tokens.push_back({line,column,get_type(str),str}); } - else if(CALC_OPERATOR(res[ptr])) + else if(is_calc_opr(res[ptr])) { // get calculation operator str=res[ptr++]; @@ -396,7 +455,7 @@ void lexer::scan(const string& file) column+=str.length(); tokens.push_back({line,column,get_type(str),str}); } - else if(NOTE(res[ptr]))// avoid note, after this process ptr will point to a '\n', so next loop line counter+1 + else if(res[ptr]=='#')// avoid note, after this process ptr will point to a '\n', so next loop line counter+1 while(++ptr"}); res=""; err.chkerr(); } @@ -415,5 +474,3 @@ void lexer::print() for(auto& tok:tokens) std::cout<<"("< @@ -67,4 +66,3 @@ void optimize(ast& root) for(auto& i:root.child()) calc_const(i); } -#endif \ No newline at end of file diff --git a/nasal_parse.h b/nasal_parse.h index d1fb0fe..2aa90a9 100644 --- a/nasal_parse.h +++ b/nasal_parse.h @@ -1,5 +1,4 @@ -#ifndef __NASAL_PARSE_H__ -#define __NASAL_PARSE_H__ +#pragma once #include @@ -96,7 +95,7 @@ private: ast for_loop(); ast forei_loop(); ast iter_gen(); - ast conditional(); + ast cond(); ast continue_expr(); ast break_expr(); ast ret_expr(); @@ -244,7 +243,7 @@ bool parse::check_special_call() bool parse::need_semi_check(const ast& node) { u32 type=node.type(); - if(type==ast_for || type==ast_foreach || type==ast_forindex || type==ast_while || type==ast_conditional) + if(type==ast_for || type==ast_foreach || type==ast_forindex || type==ast_while || type==ast_cond) return false; return !check_func_end(node); } @@ -466,7 +465,7 @@ ast parse::expr() case tok_forindex: case tok_foreach: case tok_while: return loop(); break; - case tok_if: return conditional(); break; + case tok_if: return cond(); break; case tok_continue: return continue_expr(); break; case tok_break: return break_expr(); break; case tok_ret: return ret_expr(); break; @@ -765,9 +764,9 @@ ast parse::definition() node.add(check_multi_scalar()?multi_scalar(false):calc()); else node.add(calc()); - if(node[0].type()==ast_id && node[1].type()==ast_multi_scalar) + if(node[0].type()==ast_id && node[1].type()==ast_tuple) die(node[1].line(),"one variable cannot accept too many values"); - else if(node[0].type()==ast_multi_id && node[1].type()==ast_multi_scalar && node[0].size()!=node[1].size()) + else if(node[0].type()==ast_multi_id && node[1].type()==ast_tuple && node[0].size()!=node[1].size()) die(node[0].line(),"too much or lack values in multi-definition"); return node; } @@ -815,7 +814,7 @@ ast parse::multi_scalar(bool check_call_memory) tok_func,tok_var,tok_lcurve, tok_lbrace,tok_lbracket,tok_null }; - ast node(tokens[ptr].line,tokens[ptr].col,ast_multi_scalar); + ast node(tokens[ptr].line,tokens[ptr].col,ast_tuple); match(tok_lcurve); while(!lookahead(tok_rcurve)) { @@ -846,7 +845,7 @@ ast parse::multi_assgin() node.add(check_multi_scalar()?multi_scalar(false):calc()); else node.add(calc()); - if(node[1].type()==ast_multi_scalar + if(node[1].type()==ast_tuple && node[0].size()!=node[1].size()) die(node[0].line(),"too much or lack values in multi-assignment"); return node; @@ -952,9 +951,9 @@ ast parse::iter_gen() } return node; } -ast parse::conditional() +ast parse::cond() { - ast node(tokens[ptr].line,tokens[ptr].col,ast_conditional); + ast node(tokens[ptr].line,tokens[ptr].col,ast_cond); ast ifnode(tokens[ptr].line,tokens[ptr].col,ast_if); match(tok_if); match(tok_lcurve); @@ -1006,4 +1005,3 @@ ast parse::ret_expr() node.add(calc()); return node; } -#endif diff --git a/nasal_vm.h b/nasal_vm.h index 03038d1..dfd0549 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -1,5 +1,4 @@ -#ifndef __NASAL_VM_H__ -#define __NASAL_VM_H__ +#pragma once #include #include @@ -16,9 +15,11 @@ protected: var upvalr; // upvalue register var* canary; // avoid stackoverflow var* top; // stack top - const f64* num_table;// const numbers, ref from codegen - const string* str_table;// const symbols, ref from codegen - std::vector imm; // immediate number + + /* constants */ + const f64* cnum; // const numbers + const string* cstr; // const symbols + std::vector imm; // immediate number /* garbage collector */ gc ngc; @@ -26,8 +27,8 @@ protected: var stack[STACK_DEPTH]; /* values used for debugger */ - const string* files; // ref from linker - const opcode* bytecode; // ref from codegen + const string* files; + const opcode* bytecode; void init( const std::vector&, @@ -128,7 +129,7 @@ public: vm(): pc(0),localr(nullptr),memr(nullptr),funcr(nil), upvalr(nil),canary(nullptr),top(stack), - num_table(nullptr),str_table(nullptr), + cnum(nullptr),cstr(nullptr), ngc(pc,localr,memr,funcr,upvalr,canary,top,stack), files(nullptr),bytecode(nullptr),detail_info(false){} void run( @@ -146,8 +147,8 @@ void vm::init( const std::vector& argv) { ngc.init(strs,argv); - num_table=nums.data(); - str_table=strs.data(); + cnum=nums.data(); + cstr=strs.data(); bytecode=code.data(); files=filenames.data(); @@ -223,7 +224,7 @@ void vm::traceback() <<" 0x"<>31); @@ -503,7 +506,7 @@ inline void vm::o_muleqc(){op_calc_eq_const(*);} inline void vm::o_diveqc(){op_calc_eq_const(/);} inline void vm::o_lnkeqc() { - top[0]=memr[0]=ngc.newstr(memr[0].tostr()+str_table[imm[pc]&0x7fffffff]); + top[0]=memr[0]=ngc.newstr(memr[0].tostr()+cstr[imm[pc]&0x7fffffff]); memr=nullptr; top-=(imm[pc]>>31); } @@ -558,7 +561,7 @@ inline void vm::o_grt(){op_cmp(>);} inline void vm::o_geq(){op_cmp(>=);} #define op_cmp_const(type)\ - top[0]=(top[0].tonum() type num_table[imm[pc]])?one:zero; + top[0]=(top[0].tonum() type cnum[imm[pc]])?one:zero; inline void vm::o_lessc(){op_cmp_const(<);} inline void vm::o_leqc(){op_cmp_const(<=);} @@ -671,9 +674,9 @@ inline void vm::o_callh() var val=top[0]; if(val.type!=vm_hash) vm_error("must call a hash"); - top[0]=val.hash().get_val(str_table[imm[pc]]); + top[0]=val.hash().get_val(cstr[imm[pc]]); if(top[0].type==vm_none) - vm_error("member \""+str_table[imm[pc]]+"\" does not exist"); + vm_error("member \""+cstr[imm[pc]]+"\" does not exist"); if(top[0].type==vm_func) top[0].func().local[0]=val;// 'me' } @@ -746,7 +749,7 @@ inline void vm::o_callfh() for(auto& i:func.keys) { - const string& key=str_table[i.first]; + auto& key=cstr[i.first]; if(hash.count(key)) local[i.second]=hash[key]; else if(local[i.second].type==vm_none) @@ -874,8 +877,8 @@ inline void vm::o_mcallh() var hash=top[0]; // mcall hash, reserved on stack to avoid gc if(hash.type!=vm_hash) vm_error("must call a hash"); - nas_hash& ref=hash.hash(); - const string& str=str_table[imm[pc]]; + auto& ref=hash.hash(); + auto& str=cstr[imm[pc]]; memr=ref.get_mem(str); if(!memr) // create a new key { @@ -1117,4 +1120,3 @@ mcallh: exec_nodie(o_mcallh); // -0 ret: exec_nodie(o_ret ); // -2 #endif } -#endif \ No newline at end of file diff --git a/test/wavecollapse.nas b/test/wavecollapse.nas index d667919..3adfb7a 100644 --- a/test/wavecollapse.nas +++ b/test/wavecollapse.nas @@ -1,7 +1,7 @@ # wave collapse function 2022/4/10 # by ValKmjolnir srand(); -var interval=1/60; +var interval=1/120; var table=[ # c ,w,a,s,d ["═",0,1,0,1],