optimize nasal_ast and fix bug in opr_slc2
This commit is contained in:
parent
4f0acc4d63
commit
540aeb73f4
25
makefile
25
makefile
|
@ -1,14 +1,31 @@
|
||||||
.PHONY=test
|
.PHONY=test
|
||||||
nasal:main.cpp nasal_ast.h nasal_builtin.h nasal_codegen.h nasal_gc.h nasal_import.h nasal_lexer.h nasal_parse.h nasal_vm.h nasal.h
|
nasal:main.cpp nasal_ast.h nasal_builtin.h nasal_codegen.h nasal_gc.h nasal_import.h nasal_lexer.h nasal_parse.h nasal_vm.h nasal.h
|
||||||
clang++ -std=c++11 -O3 main.cpp -o nasal -fno-exceptions
|
clang++ -std=c++11 -O3 main.cpp -o nasal -fno-exceptions -Wshadow
|
||||||
test:nasal
|
test:nasal
|
||||||
./nasal test/ascii-art.nas
|
./nasal test/ascii-art.nas
|
||||||
./nasal test/bp.nas
|
./nasal -c test/bf.nas
|
||||||
|
./nasal -c test/bfconvertor.nas
|
||||||
|
./nasal test/bfs.nas
|
||||||
./nasal -t test/bigloop.nas
|
./nasal -t test/bigloop.nas
|
||||||
./nasal -t test/fib.nas
|
./nasal test/bp.nas
|
||||||
|
./nasal test/calc.nas
|
||||||
|
./nasal test/choice.nas
|
||||||
./nasal test/class.nas
|
./nasal test/class.nas
|
||||||
|
# ./nasal test/exception.nas
|
||||||
|
./nasal -t test/fib.nas
|
||||||
|
./nasal test/hexdump.nas
|
||||||
|
./nasal test/json.nas
|
||||||
|
./nasal test/leetcode1319.nas
|
||||||
./nasal test/lexer.nas
|
./nasal test/lexer.nas
|
||||||
|
./nasal -c test/life.nas
|
||||||
|
./nasal -t test/loop.nas
|
||||||
|
./nasal -c test/mandel.nas
|
||||||
./nasal -t test/mandelbrot.nas
|
./nasal -t test/mandelbrot.nas
|
||||||
|
./nasal test/nasal_test.nas
|
||||||
./nasal -t test/pi.nas
|
./nasal -t test/pi.nas
|
||||||
|
./nasal -t test/prime.nas
|
||||||
|
./nasal -t test/quick_sort.nas
|
||||||
|
./nasal test/scalar.nas
|
||||||
|
./nasal test/trait.nas
|
||||||
./nasal -t test/ycombinator.nas
|
./nasal -t test/ycombinator.nas
|
||||||
./nasal test/exception.nas
|
|
51
nasal_ast.h
51
nasal_ast.h
|
@ -4,17 +4,25 @@
|
||||||
enum ast_node
|
enum ast_node
|
||||||
{
|
{
|
||||||
ast_null=0,
|
ast_null=0,
|
||||||
ast_root,ast_block,
|
ast_root,
|
||||||
|
ast_block,
|
||||||
ast_file, // ast_file is only used to store which file the subtree is on,codegen will generate nothing
|
ast_file, // ast_file is only used to store which file the subtree is on,codegen will generate nothing
|
||||||
ast_nil,ast_num,ast_str,ast_id,ast_func,ast_hash,ast_vec,
|
ast_nil,ast_num,ast_str,ast_id,ast_func,ast_hash,ast_vec,
|
||||||
ast_hashmember,ast_call,ast_callh,ast_callv,ast_callf,ast_subvec,
|
ast_hashmember,
|
||||||
ast_args,ast_default_arg,ast_dynamic_id,
|
ast_call,ast_callh,ast_callv,ast_callf,
|
||||||
|
ast_subvec,
|
||||||
|
ast_args,ast_default,ast_dynamic,
|
||||||
ast_and,ast_or,
|
ast_and,ast_or,
|
||||||
ast_equal,ast_addeq,ast_subeq,ast_multeq,ast_diveq,ast_lnkeq,
|
ast_equal,
|
||||||
|
ast_addeq,ast_subeq,
|
||||||
|
ast_multeq,ast_diveq,
|
||||||
|
ast_lnkeq,
|
||||||
ast_cmpeq,ast_neq,
|
ast_cmpeq,ast_neq,
|
||||||
ast_less,ast_leq,
|
ast_less,ast_leq,
|
||||||
ast_grt,ast_geq,
|
ast_grt,ast_geq,
|
||||||
ast_add,ast_sub,ast_mult,ast_div,ast_link,
|
ast_add,ast_sub,
|
||||||
|
ast_mult,ast_div,
|
||||||
|
ast_link,
|
||||||
ast_neg,ast_not,
|
ast_neg,ast_not,
|
||||||
ast_trino,
|
ast_trino,
|
||||||
ast_for,ast_forindex,ast_foreach,ast_while,ast_new_iter,
|
ast_for,ast_forindex,ast_foreach,ast_while,ast_new_iter,
|
||||||
|
@ -27,17 +35,25 @@ enum ast_node
|
||||||
const char* ast_name[]=
|
const char* ast_name[]=
|
||||||
{
|
{
|
||||||
"null",
|
"null",
|
||||||
"root","block",
|
"root",
|
||||||
|
"block",
|
||||||
"file",
|
"file",
|
||||||
"nil","node_num","node_str","id","func","hash","vec",
|
"nil","num","str","id","func","hash","vec",
|
||||||
"hashmember","call","callh","callv","callf","subvec",
|
"hashmember",
|
||||||
"args","deflt_arg","dyn_id",
|
"call","callh","callv","callf",
|
||||||
|
"subvec",
|
||||||
|
"args","default","dynamic",
|
||||||
"and","or",
|
"and","or",
|
||||||
"=","+=","-=","*=","/=","~=",
|
"=",
|
||||||
|
"+=","-=",
|
||||||
|
"*=","/=",
|
||||||
|
"~=",
|
||||||
"==","!=",
|
"==","!=",
|
||||||
"<","<=",
|
"<","<=",
|
||||||
">",">=",
|
">",">=",
|
||||||
"+","-","*","/","~",
|
"+","-",
|
||||||
|
"*","/",
|
||||||
|
"~",
|
||||||
"unary-","unary!",
|
"unary-","unary!",
|
||||||
"trino",
|
"trino",
|
||||||
"for","forindex","foreach","while","iter",
|
"for","forindex","foreach","while","iter",
|
||||||
|
@ -59,10 +75,15 @@ public:
|
||||||
nasal_ast(const uint32_t l=0,const uint32_t t=ast_null):text_line(l),node_type(t){}
|
nasal_ast(const uint32_t l=0,const uint32_t t=ast_null):text_line(l),node_type(t){}
|
||||||
nasal_ast(const nasal_ast&);
|
nasal_ast(const nasal_ast&);
|
||||||
nasal_ast(nasal_ast&&);
|
nasal_ast(nasal_ast&&);
|
||||||
nasal_ast& operator=(const nasal_ast&);
|
|
||||||
nasal_ast& operator=(nasal_ast&&);
|
|
||||||
void print(const int);
|
void print(const int);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
nasal_ast& operator=(const nasal_ast&);
|
||||||
|
nasal_ast& operator=(nasal_ast&&);
|
||||||
|
nasal_ast& operator[](const int index){return node_child[index];}
|
||||||
|
const nasal_ast& operator[](const int index) const {return node_child[index];}
|
||||||
|
size_t size() const {return node_child.size();}
|
||||||
|
|
||||||
void add(nasal_ast&& ast){node_child.push_back(std::move(ast));}
|
void add(nasal_ast&& ast){node_child.push_back(std::move(ast));}
|
||||||
void add(const nasal_ast& ast){node_child.push_back(ast);}
|
void add(const nasal_ast& ast){node_child.push_back(ast);}
|
||||||
void set_line(const uint32_t l){text_line=l;}
|
void set_line(const uint32_t l){text_line=l;}
|
||||||
|
@ -133,8 +154,8 @@ void nasal_ast::print(const int depth)
|
||||||
if(
|
if(
|
||||||
node_type==ast_str ||
|
node_type==ast_str ||
|
||||||
node_type==ast_id ||
|
node_type==ast_id ||
|
||||||
node_type==ast_default_arg ||
|
node_type==ast_default ||
|
||||||
node_type==ast_dynamic_id ||
|
node_type==ast_dynamic ||
|
||||||
node_type==ast_callh)
|
node_type==ast_callh)
|
||||||
std::cout<<":"<<raw_string(node_str);
|
std::cout<<":"<<raw_string(node_str);
|
||||||
else if(node_type==ast_num || node_type==ast_file)
|
else if(node_type==ast_num || node_type==ast_file)
|
||||||
|
|
|
@ -63,11 +63,11 @@ nasal_ref builtin_err(const char* func_name,std::string info)
|
||||||
|
|
||||||
// register builtin function's name and it's address here in this table below
|
// register builtin function's name and it's address here in this table below
|
||||||
// this table must end with {nullptr,nullptr}
|
// this table must end with {nullptr,nullptr}
|
||||||
struct func
|
struct
|
||||||
{
|
{
|
||||||
const char* name;
|
const char* name;
|
||||||
nasal_ref (*func)(std::vector<nasal_ref>&,nasal_gc&);
|
nasal_ref (*func)(std::vector<nasal_ref>&,nasal_gc&);
|
||||||
} builtin_func[]=
|
} builtin[]=
|
||||||
{
|
{
|
||||||
{"__builtin_print", builtin_print },
|
{"__builtin_print", builtin_print },
|
||||||
{"__builtin_append", builtin_append },
|
{"__builtin_append", builtin_append },
|
||||||
|
|
523
nasal_codegen.h
523
nasal_codegen.h
File diff suppressed because it is too large
Load Diff
|
@ -116,11 +116,11 @@ struct nasal_func// 112 bytes
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr uint8_t GC_UNCOLLECTED=0;
|
||||||
|
constexpr uint8_t GC_COLLECTED =1;
|
||||||
|
constexpr uint8_t GC_FOUND =2;
|
||||||
struct nasal_val// 16 bytes
|
struct nasal_val// 16 bytes
|
||||||
{
|
{
|
||||||
#define GC_UNCOLLECTED 0
|
|
||||||
#define GC_COLLECTED 1
|
|
||||||
#define GC_FOUND 2
|
|
||||||
uint8_t mark;
|
uint8_t mark;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
union
|
union
|
||||||
|
|
|
@ -37,14 +37,13 @@ only this kind of node can be recognized as 'import':
|
||||||
*/
|
*/
|
||||||
if(node.type()!=ast_call)
|
if(node.type()!=ast_call)
|
||||||
return false;
|
return false;
|
||||||
const std::vector<nasal_ast>& vec=node.child();
|
if(node.size()!=2)
|
||||||
if(vec.size()!=2)
|
|
||||||
return false;
|
return false;
|
||||||
if(vec[0].str()!="import")
|
if(node[0].str()!="import")
|
||||||
return false;
|
return false;
|
||||||
if(vec[1].type()!=ast_callf)
|
if(node[1].type()!=ast_callf)
|
||||||
return false;
|
return false;
|
||||||
if(vec[1].child().size()!=1 || vec[1].child()[0].type()!=ast_str)
|
if(node[1].size()!=1 || node[1][0].type()!=ast_str)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +68,7 @@ void nasal_import::linker(nasal_ast& root,nasal_ast&& add_root)
|
||||||
nasal_ast nasal_import::file_import(nasal_ast& node)
|
nasal_ast nasal_import::file_import(nasal_ast& node)
|
||||||
{
|
{
|
||||||
// get filename and set node to ast_null
|
// get filename and set node to ast_null
|
||||||
std::string filename=node.child()[1].child()[0].str();
|
std::string filename=node[1][0].str();
|
||||||
node.clear();
|
node.clear();
|
||||||
|
|
||||||
// avoid infinite loading loop
|
// avoid infinite loading loop
|
||||||
|
|
115
nasal_parse.h
115
nasal_parse.h
|
@ -43,8 +43,8 @@ class nasal_parse
|
||||||
private:
|
private:
|
||||||
uint32_t ptr;
|
uint32_t ptr;
|
||||||
uint32_t error;
|
uint32_t error;
|
||||||
uint32_t in_func; // count when generating function block,used to check return-expression
|
uint32_t in_func; // count when generating function block
|
||||||
uint32_t in_loop; // count when generating loop block,used to check break/continue-expression
|
uint32_t in_loop; // count when generating loop block
|
||||||
nasal_ast root;
|
nasal_ast root;
|
||||||
std::vector<token> tokens;
|
std::vector<token> tokens;
|
||||||
std::vector<token> error_token;
|
std::vector<token> error_token;
|
||||||
|
@ -53,7 +53,7 @@ private:
|
||||||
void match(uint32_t type,const char* info=nullptr);
|
void match(uint32_t type,const char* info=nullptr);
|
||||||
bool check_comma(const uint32_t*);
|
bool check_comma(const uint32_t*);
|
||||||
bool check_multi_scalar();
|
bool check_multi_scalar();
|
||||||
bool check_function_end(const nasal_ast&);
|
bool check_func_end(const nasal_ast&);
|
||||||
bool check_special_call();
|
bool check_special_call();
|
||||||
bool need_semi_check(const nasal_ast&);
|
bool need_semi_check(const nasal_ast&);
|
||||||
void check_memory_reachable(const nasal_ast&);
|
void check_memory_reachable(const nasal_ast&);
|
||||||
|
@ -93,7 +93,7 @@ private:
|
||||||
nasal_ast while_loop();
|
nasal_ast while_loop();
|
||||||
nasal_ast for_loop();
|
nasal_ast for_loop();
|
||||||
nasal_ast forei_loop();
|
nasal_ast forei_loop();
|
||||||
nasal_ast new_iter_gen();
|
nasal_ast iter_gen();
|
||||||
nasal_ast conditional();
|
nasal_ast conditional();
|
||||||
nasal_ast continue_expr();
|
nasal_ast continue_expr();
|
||||||
nasal_ast break_expr();
|
nasal_ast break_expr();
|
||||||
|
@ -197,7 +197,7 @@ bool nasal_parse::check_multi_scalar()
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool nasal_parse::check_function_end(const nasal_ast& node)
|
bool nasal_parse::check_func_end(const nasal_ast& node)
|
||||||
{
|
{
|
||||||
uint32_t type=node.type();
|
uint32_t type=node.type();
|
||||||
if(type==ast_func)
|
if(type==ast_func)
|
||||||
|
@ -218,7 +218,7 @@ bool nasal_parse::check_function_end(const nasal_ast& node)
|
||||||
)
|
)
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
return check_function_end(node.child().back());
|
return check_func_end(node.child().back());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool nasal_parse::check_special_call()
|
bool nasal_parse::check_special_call()
|
||||||
|
@ -250,7 +250,7 @@ bool nasal_parse::need_semi_check(const nasal_ast& node)
|
||||||
uint32_t type=node.type();
|
uint32_t 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_conditional)
|
||||||
return false;
|
return false;
|
||||||
return !check_function_end(node);
|
return !check_func_end(node);
|
||||||
}
|
}
|
||||||
void nasal_parse::check_memory_reachable(const nasal_ast& node)
|
void nasal_parse::check_memory_reachable(const nasal_ast& node)
|
||||||
{
|
{
|
||||||
|
@ -259,7 +259,7 @@ void nasal_parse::check_memory_reachable(const nasal_ast& node)
|
||||||
const nasal_ast& tmp=node.child().back();
|
const nasal_ast& tmp=node.child().back();
|
||||||
if(tmp.type()==ast_callf)
|
if(tmp.type()==ast_callf)
|
||||||
die(tmp.line(),"bad left-value");
|
die(tmp.line(),"bad left-value");
|
||||||
if(tmp.type()==ast_callv && (tmp.child().size()>1 || tmp.child()[0].type()==ast_subvec))
|
if(tmp.type()==ast_callv && (tmp.size()>1 || tmp[0].type()==ast_subvec))
|
||||||
die(tmp.line(),"bad left-value");
|
die(tmp.line(),"bad left-value");
|
||||||
}
|
}
|
||||||
else if(node.type()!=ast_id)
|
else if(node.type()!=ast_id)
|
||||||
|
@ -380,14 +380,14 @@ nasal_ast nasal_parse::args()
|
||||||
{
|
{
|
||||||
match(tok_eq);
|
match(tok_eq);
|
||||||
special_arg=std::move(tmp);
|
special_arg=std::move(tmp);
|
||||||
special_arg.set_type(ast_default_arg);
|
special_arg.set_type(ast_default);
|
||||||
special_arg.add(calc());
|
special_arg.add(calc());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
match(tok_ellipsis);
|
match(tok_ellipsis);
|
||||||
special_arg=std::move(tmp);
|
special_arg=std::move(tmp);
|
||||||
special_arg.set_type(ast_dynamic_id);
|
special_arg.set_type(ast_dynamic);
|
||||||
}
|
}
|
||||||
node.add(std::move(special_arg));
|
node.add(std::move(special_arg));
|
||||||
}
|
}
|
||||||
|
@ -405,40 +405,41 @@ nasal_ast nasal_parse::args()
|
||||||
std::string format="func(";
|
std::string format="func(";
|
||||||
for(auto& tmp:node.child())
|
for(auto& tmp:node.child())
|
||||||
{
|
{
|
||||||
|
format+=tmp.str();
|
||||||
switch(tmp.type())
|
switch(tmp.type())
|
||||||
{
|
{
|
||||||
case ast_id: format+=tmp.str();break;
|
case ast_id: break;
|
||||||
case ast_default_arg: format+=tmp.str()+"=val";break;
|
case ast_default: format+="=val";break;
|
||||||
case ast_dynamic_id: format+=tmp.str()+"...";break;
|
case ast_dynamic: format+="..."; break;
|
||||||
}
|
}
|
||||||
format+=",)"[&tmp==&node.child().back()];
|
format+=",)"[&tmp==&node.child().back()];
|
||||||
}
|
}
|
||||||
bool checked_default_val=false,checked_dynamic_ids=false;
|
bool checked_default=false,checked_dynamic=false;
|
||||||
for(auto& tmp:node.child())
|
for(auto& tmp:node.child())
|
||||||
{
|
{
|
||||||
if(tmp.type()==ast_default_arg)
|
if(tmp.type()==ast_default)
|
||||||
checked_default_val=true;
|
checked_default=true;
|
||||||
else if(tmp.type()==ast_dynamic_id)
|
else if(tmp.type()==ast_dynamic)
|
||||||
checked_dynamic_ids=true;
|
checked_dynamic=true;
|
||||||
if(checked_default_val && tmp.type()!=ast_default_arg)
|
if(checked_default && tmp.type()!=ast_default)
|
||||||
die(tmp.line(),"must use default paras after using it once: "+format);
|
die(tmp.line(),"must use default paras after using once: "+format);
|
||||||
if(checked_dynamic_ids && &tmp!=&node.child().back())
|
if(checked_dynamic && &tmp!=&node.child().back())
|
||||||
die(tmp.line(),"dynamic para must be the end: "+format);
|
die(tmp.line(),"dynamic para must be the end: "+format);
|
||||||
}
|
}
|
||||||
std::unordered_map<std::string,bool> argname_table;
|
std::unordered_map<std::string,bool> argname;
|
||||||
for(auto& tmp:node.child())
|
for(auto& tmp:node.child())
|
||||||
{
|
{
|
||||||
std::string new_name;
|
std::string name;
|
||||||
switch(tmp.type())
|
switch(tmp.type())
|
||||||
{
|
{
|
||||||
case ast_dynamic_id:
|
case ast_dynamic:
|
||||||
case ast_id: new_name=tmp.str();break;
|
case ast_id: name=tmp.str();break;
|
||||||
case ast_default_arg:new_name=tmp.str();break;
|
case ast_default:name=tmp.str();break;
|
||||||
}
|
}
|
||||||
if(argname_table.count(new_name))
|
if(argname.count(name))
|
||||||
die(tmp.line(),"parameter's name repeats: "+new_name);
|
die(tmp.line(),"parameter's name repeats: "+name);
|
||||||
else
|
else
|
||||||
argname_table[new_name]=true;
|
argname[name]=true;
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -778,11 +779,11 @@ nasal_ast nasal_parse::definition()
|
||||||
node.add(check_multi_scalar()?multi_scalar(false):calc());
|
node.add(check_multi_scalar()?multi_scalar(false):calc());
|
||||||
else
|
else
|
||||||
node.add(calc());
|
node.add(calc());
|
||||||
if(node.child()[0].type()==ast_id && node.child()[1].type()==ast_multi_scalar)
|
if(node[0].type()==ast_id && node[1].type()==ast_multi_scalar)
|
||||||
die(node.child()[1].line(),"one identifier cannot accept too many values");
|
die(node[1].line(),"one identifier cannot accept too many values");
|
||||||
else if(node.child()[0].type()==ast_multi_id && node.child()[1].type()==ast_multi_scalar)
|
else if(node[0].type()==ast_multi_id && node[1].type()==ast_multi_scalar)
|
||||||
if(node.child()[0].child().size()!=node.child()[1].child().size())
|
if(node[0].size()!=node[1].size())
|
||||||
die(node.child()[0].line(),"too much or lack values in multi-definition");
|
die(node[0].line(),"too much or lack values in multi-definition");
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
nasal_ast nasal_parse::var_incurve_def()
|
nasal_ast nasal_parse::var_incurve_def()
|
||||||
|
@ -861,9 +862,9 @@ nasal_ast nasal_parse::multi_assgin()
|
||||||
node.add(check_multi_scalar()?multi_scalar(false):calc());
|
node.add(check_multi_scalar()?multi_scalar(false):calc());
|
||||||
else
|
else
|
||||||
node.add(calc());
|
node.add(calc());
|
||||||
if(node.child()[1].type()==ast_multi_scalar
|
if(node[1].type()==ast_multi_scalar
|
||||||
&& node.child()[0].child().size()!=node.child()[1].child().size())
|
&& node[0].size()!=node[1].size())
|
||||||
die(node.child()[0].line(),"too much or lack values in multi-assignment");
|
die(node[0].line(),"too much or lack values in multi-assignment");
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
nasal_ast nasal_parse::loop()
|
nasal_ast nasal_parse::loop()
|
||||||
|
@ -941,7 +942,7 @@ nasal_ast nasal_parse::forei_loop()
|
||||||
// foreach/forindex must have an iterator to loop through
|
// foreach/forindex must have an iterator to loop through
|
||||||
if(tokens[ptr].type!=tok_var && tokens[ptr].type!=tok_id)
|
if(tokens[ptr].type!=tok_var && tokens[ptr].type!=tok_id)
|
||||||
die(error_line,"expected iterator");
|
die(error_line,"expected iterator");
|
||||||
node.add(new_iter_gen());
|
node.add(iter_gen());
|
||||||
// check semi
|
// check semi
|
||||||
match(tok_semi,"expected \';\' in foreach/forindex(iter;vector)");
|
match(tok_semi,"expected \';\' in foreach/forindex(iter;vector)");
|
||||||
// check vector
|
// check vector
|
||||||
|
@ -952,7 +953,7 @@ nasal_ast nasal_parse::forei_loop()
|
||||||
node.add(exprs());
|
node.add(exprs());
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
nasal_ast nasal_parse::new_iter_gen()
|
nasal_ast nasal_parse::iter_gen()
|
||||||
{
|
{
|
||||||
nasal_ast node(tokens[ptr].line,ast_null);
|
nasal_ast node(tokens[ptr].line,ast_null);
|
||||||
if(tokens[ptr].type==tok_var)
|
if(tokens[ptr].type==tok_var)
|
||||||
|
@ -975,30 +976,29 @@ nasal_ast nasal_parse::new_iter_gen()
|
||||||
nasal_ast nasal_parse::conditional()
|
nasal_ast nasal_parse::conditional()
|
||||||
{
|
{
|
||||||
nasal_ast node(tokens[ptr].line,ast_conditional);
|
nasal_ast node(tokens[ptr].line,ast_conditional);
|
||||||
nasal_ast tmp(tokens[ptr].line,ast_if);
|
nasal_ast ifnode(tokens[ptr].line,ast_if);
|
||||||
match(tok_if);
|
match(tok_if);
|
||||||
match(tok_lcurve);
|
match(tok_lcurve);
|
||||||
tmp.add(calc());
|
ifnode.add(calc());
|
||||||
match(tok_rcurve);
|
match(tok_rcurve);
|
||||||
tmp.add(exprs());
|
ifnode.add(exprs());
|
||||||
node.add(std::move(tmp));
|
node.add(std::move(ifnode));
|
||||||
// end of if-expression
|
|
||||||
while(tokens[ptr].type==tok_elsif)
|
while(tokens[ptr].type==tok_elsif)
|
||||||
{
|
{
|
||||||
nasal_ast tmp(tokens[ptr].line,ast_elsif);
|
nasal_ast elsifnode(tokens[ptr].line,ast_elsif);
|
||||||
match(tok_elsif);
|
match(tok_elsif);
|
||||||
match(tok_lcurve);
|
match(tok_lcurve);
|
||||||
tmp.add(calc());
|
elsifnode.add(calc());
|
||||||
match(tok_rcurve);
|
match(tok_rcurve);
|
||||||
tmp.add(exprs());
|
elsifnode.add(exprs());
|
||||||
node.add(std::move(tmp));
|
node.add(std::move(elsifnode));
|
||||||
}
|
}
|
||||||
if(tokens[ptr].type==tok_else)
|
if(tokens[ptr].type==tok_else)
|
||||||
{
|
{
|
||||||
nasal_ast tmp(tokens[ptr].line,ast_else);
|
nasal_ast elsenode(tokens[ptr].line,ast_else);
|
||||||
match(tok_else);
|
match(tok_else);
|
||||||
tmp.add(exprs());
|
elsenode.add(exprs());
|
||||||
node.add(std::move(tmp));
|
node.add(std::move(elsenode));
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -1019,8 +1019,17 @@ nasal_ast nasal_parse::ret_expr()
|
||||||
nasal_ast node(tokens[ptr].line,ast_ret);
|
nasal_ast node(tokens[ptr].line,ast_ret);
|
||||||
match(tok_ret);
|
match(tok_ret);
|
||||||
uint32_t type=tokens[ptr].type;
|
uint32_t type=tokens[ptr].type;
|
||||||
if(type==tok_nil || type==tok_num || type==tok_str || type==tok_id || type==tok_func ||
|
if(
|
||||||
type==tok_sub || type==tok_not || type==tok_lcurve || type==tok_lbracket || type==tok_lbrace)
|
type==tok_nil ||
|
||||||
|
type==tok_num ||
|
||||||
|
type==tok_str ||
|
||||||
|
type==tok_id ||
|
||||||
|
type==tok_func ||
|
||||||
|
type==tok_sub ||
|
||||||
|
type==tok_not ||
|
||||||
|
type==tok_lcurve ||
|
||||||
|
type==tok_lbracket ||
|
||||||
|
type==tok_lbrace)
|
||||||
node.add(calc());
|
node.add(calc());
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
23
nasal_vm.h
23
nasal_vm.h
|
@ -165,7 +165,7 @@ void nasal_vm::bytecodeinfo(const uint32_t p)
|
||||||
const opcode& code=bytecode[p];
|
const opcode& code=bytecode[p];
|
||||||
printf("\t0x%.8x: %s 0x%x",p,code_table[code.op].name,code.num);
|
printf("\t0x%.8x: %s 0x%x",p,code_table[code.op].name,code.num);
|
||||||
if(code.op==op_callb)
|
if(code.op==op_callb)
|
||||||
printf(" <%s>",builtin_func[code.num].name);
|
printf(" <%s>",builtin[code.num].name);
|
||||||
printf(" (<%s> line %d)\n",files[code.fidx].c_str(),code.line);
|
printf(" (<%s> line %d)\n",files[code.fidx].c_str(),code.line);
|
||||||
}
|
}
|
||||||
void nasal_vm::traceback()
|
void nasal_vm::traceback()
|
||||||
|
@ -286,10 +286,9 @@ inline bool nasal_vm::condition(nasal_ref val)
|
||||||
return val.value.num;
|
return val.value.num;
|
||||||
else if(val.type==vm_str)
|
else if(val.type==vm_str)
|
||||||
{
|
{
|
||||||
const std::string& str=*val.str();
|
double num=str2num(val.str()->c_str());
|
||||||
double num=str2num(str.c_str());
|
|
||||||
if(std::isnan(num))
|
if(std::isnan(num))
|
||||||
return str.empty();
|
return val.str()->empty();
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -560,7 +559,7 @@ inline void nasal_vm::opr_findex()
|
||||||
pc=imm[pc]-1;
|
pc=imm[pc]-1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(++top)[0]={vm_num,static_cast<double>(counter.top())};
|
(++top)[0]={vm_num,(double)counter.top()};
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_feach()
|
inline void nasal_vm::opr_feach()
|
||||||
{
|
{
|
||||||
|
@ -642,7 +641,7 @@ inline void nasal_vm::opr_callh()
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_callfv()
|
inline void nasal_vm::opr_callfv()
|
||||||
{
|
{
|
||||||
size_t args_size=imm[pc];
|
uint32_t args_size=imm[pc];
|
||||||
nasal_ref* args=top-args_size+1;
|
nasal_ref* args=top-args_size+1;
|
||||||
if(args[-1].type!=vm_func)
|
if(args[-1].type!=vm_func)
|
||||||
die("callfv: must call a function");
|
die("callfv: must call a function");
|
||||||
|
@ -655,13 +654,13 @@ inline void nasal_vm::opr_callfv()
|
||||||
// load parameters
|
// load parameters
|
||||||
auto& closure=gc.local.back().vec()->elems;
|
auto& closure=gc.local.back().vec()->elems;
|
||||||
|
|
||||||
size_t para_size=func.keys.size();
|
uint32_t para_size=func.keys.size();
|
||||||
// load arguments
|
// load arguments
|
||||||
// if the first default value is not vm_none,then values after it are not nullptr
|
// if the first default value is not vm_none,then values after it are not nullptr
|
||||||
if(args_size<para_size && func.local[args_size+1/*1 is reserved for 'me'*/].type==vm_none)
|
if(args_size<para_size && func.local[args_size+1/*1 is reserved for 'me'*/].type==vm_none)
|
||||||
die("callfv: lack argument(s)");
|
die("callfv: lack argument(s)");
|
||||||
// if args_size>para_size,for 0 to args_size will cause corruption
|
// if args_size>para_size,for 0 to args_size will cause corruption
|
||||||
size_t min_size=std::min(para_size,args_size);
|
uint32_t min_size=std::min(para_size,args_size);
|
||||||
for(uint32_t i=0;i<min_size;++i)
|
for(uint32_t i=0;i<min_size;++i)
|
||||||
closure[i+1]=args[i];
|
closure[i+1]=args[i];
|
||||||
// load dynamic argument if args_size>=para_size
|
// load dynamic argument if args_size>=para_size
|
||||||
|
@ -707,7 +706,7 @@ inline void nasal_vm::opr_callfh()
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_callb()
|
inline void nasal_vm::opr_callb()
|
||||||
{
|
{
|
||||||
(++top)[0]=(*builtin_func[imm[pc]].func)(gc.local.back().vec()->elems,gc);
|
(++top)[0]=(*builtin[imm[pc]].func)(gc.local.back().vec()->elems,gc);
|
||||||
if(top[0].type==vm_none)
|
if(top[0].type==vm_none)
|
||||||
die("native function error.");
|
die("native function error.");
|
||||||
}
|
}
|
||||||
|
@ -744,7 +743,7 @@ inline void nasal_vm::opr_slc2()
|
||||||
uint8_t type1=val1.type,type2=val2.type;
|
uint8_t type1=val1.type,type2=val2.type;
|
||||||
int num1=val1.to_number();
|
int num1=val1.to_number();
|
||||||
int num2=val2.to_number();
|
int num2=val2.to_number();
|
||||||
size_t size=ref.size();
|
int size=ref.size();
|
||||||
if(type1==vm_nil && type2==vm_nil)
|
if(type1==vm_nil && type2==vm_nil)
|
||||||
{
|
{
|
||||||
num1=0;
|
num1=0;
|
||||||
|
@ -799,7 +798,7 @@ inline void nasal_vm::opr_mcallv()
|
||||||
mem_addr=ref.get_mem(str);
|
mem_addr=ref.get_mem(str);
|
||||||
if(!mem_addr)
|
if(!mem_addr)
|
||||||
{
|
{
|
||||||
ref.elems[str]=gc.nil;
|
ref.elems[str]={vm_nil};
|
||||||
mem_addr=ref.get_mem(str);
|
mem_addr=ref.get_mem(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -816,7 +815,7 @@ inline void nasal_vm::opr_mcallh()
|
||||||
mem_addr=ref.get_mem(str);
|
mem_addr=ref.get_mem(str);
|
||||||
if(!mem_addr) // create a new key
|
if(!mem_addr) // create a new key
|
||||||
{
|
{
|
||||||
ref.elems[str]=gc.nil;
|
ref.elems[str]={vm_nil};
|
||||||
mem_addr=ref.get_mem(str);
|
mem_addr=ref.get_mem(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue