optimize code structure
This commit is contained in:
parent
1b240b293e
commit
d4a9412947
|
@ -465,7 +465,7 @@ a=b=0;
|
|||
2021/10/8 update:
|
||||
|
||||
In this version vm_nil and vm_num now is not managed by nasal_gc,
|
||||
this will decrease the usage of gc_alloc and increase the efficiency of execution.
|
||||
this will decrease the usage of gc::alloc and increase the efficiency of execution.
|
||||
|
||||
New value type is added: vm_obj.
|
||||
This type is reserved for user to define their own value types.
|
||||
|
@ -897,7 +897,7 @@ nasal_ref builtin_print(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
case vm_obj: std::cout<<"<object>"; break;
|
||||
}
|
||||
std::cout<<std::flush;
|
||||
// generate return value,use gc::gc_alloc(type) to make a new value
|
||||
// generate return value,use gc::alloc(type) to make a new value
|
||||
// or use reserved reference gc.nil/gc.one/gc.zero
|
||||
return gc.nil;
|
||||
}
|
||||
|
@ -943,7 +943,7 @@ version 6.5 update:
|
|||
Use nasal_gc::builtin_alloc in builtin function if this function uses alloc more than one time.
|
||||
|
||||
When running a builtin function,alloc will run more than one time,
|
||||
this may cause mark-sweep in gc_alloc.
|
||||
this may cause mark-sweep in gc::alloc.
|
||||
|
||||
The value got before will be collected,but stil in use in this builtin function,
|
||||
this is a fatal error.
|
||||
|
@ -961,7 +961,7 @@ nasal_ref builtin_keys(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
}
|
||||
|
||||
// push vector into local scope to avoid being sweeped
|
||||
local.push_back(gc.gc_alloc(vm_vec));
|
||||
local.push_back(gc.alloc(vm_vec));
|
||||
std::vector<nasal_ref>& vec=local.back().vec()->elems;
|
||||
for(auto& iter:hash.hash()->elems)
|
||||
{
|
||||
|
|
76
main.cpp
76
main.cpp
|
@ -1,11 +1,11 @@
|
|||
#include "nasal.h"
|
||||
#define VM_LEXINFO 1
|
||||
#define VM_ASTINFO 2
|
||||
#define VM_CODEINFO 4
|
||||
#define VM_EXECTIME 8
|
||||
#define VM_OPCALLNUM 16
|
||||
#define VM_EXEC 32
|
||||
void help_cmd()
|
||||
constexpr uint32_t VM_LEXINFO =1;
|
||||
constexpr uint32_t VM_ASTINFO =2;
|
||||
constexpr uint32_t VM_CODEINFO =4;
|
||||
constexpr uint32_t VM_EXECTIME =8;
|
||||
constexpr uint32_t VM_OPCALLNUM=16;
|
||||
constexpr uint32_t VM_EXEC =32;
|
||||
void help()
|
||||
{
|
||||
std::cout
|
||||
#ifdef _WIN32
|
||||
|
@ -27,7 +27,6 @@ void help_cmd()
|
|||
<<" -o, --opcnt | count operands while running.\n"
|
||||
<<"file:\n"
|
||||
<<" input file name to execute script file.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void logo()
|
||||
|
@ -43,8 +42,7 @@ void logo()
|
|||
<<"code repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n"
|
||||
<<"code repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
|
||||
<<"lang info : http://wiki.flightgear.org/Nasal_scripting_language\n"
|
||||
<<"input \"nasal -h\" to get help .\n";
|
||||
return;
|
||||
<<"input <nasal -h> to get help .\n";
|
||||
}
|
||||
|
||||
void die(const char* stage,const std::string& filename)
|
||||
|
@ -53,11 +51,11 @@ void die(const char* stage,const std::string& filename)
|
|||
std::exit(1);
|
||||
}
|
||||
|
||||
void cmderr()
|
||||
void err()
|
||||
{
|
||||
std::cout
|
||||
<<"invalid argument(s).\n"
|
||||
<<"use nasal -h to get help.\n";
|
||||
<<"use <nasal -h> to get help.\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
|
@ -65,44 +63,44 @@ void execute(const std::string& file,const uint16_t cmd)
|
|||
{
|
||||
nasal_lexer lexer;
|
||||
nasal_parse parse;
|
||||
nasal_import import;
|
||||
nasal_codegen codegen;
|
||||
nasal_import linker;
|
||||
nasal_codegen gen;
|
||||
nasal_vm vm;
|
||||
lexer.open(file);
|
||||
lexer.scan();
|
||||
|
||||
// lexer scans file to get tokens
|
||||
lexer.scan(file);
|
||||
if(lexer.err())
|
||||
die("lexer",file);
|
||||
if(cmd&VM_LEXINFO)
|
||||
lexer.print();
|
||||
parse.compile(lexer.get_tokens());
|
||||
|
||||
// parser gets lexer's token list to compile
|
||||
parse.compile(lexer);
|
||||
if(parse.err())
|
||||
die("parse",file);
|
||||
|
||||
// linker gets parser's ast and load import files to this ast
|
||||
linker.link(parse,file);
|
||||
if(linker.err())
|
||||
die("import",file);
|
||||
|
||||
// code generator gets parser's ast and linker's import file list to generate code
|
||||
gen.compile(parse,linker);
|
||||
if(gen.err())
|
||||
die("code",file);
|
||||
|
||||
if(cmd&VM_LEXINFO)
|
||||
lexer.print();
|
||||
if(cmd&VM_ASTINFO)
|
||||
parse.ast().print(0);
|
||||
// first used file is itself
|
||||
import.link(parse.ast(),file);
|
||||
if(import.err())
|
||||
die("import",file);
|
||||
codegen.compile(import.ast(),import.get_file());
|
||||
if(codegen.err())
|
||||
die("code",file);
|
||||
if(cmd&VM_CODEINFO)
|
||||
codegen.print();
|
||||
vm.init(
|
||||
codegen.get_strs(),
|
||||
codegen.get_nums(),
|
||||
import.get_file()
|
||||
);
|
||||
gen.print();
|
||||
if(cmd&VM_EXECTIME)
|
||||
{
|
||||
clock_t t=clock();
|
||||
vm.run(codegen.get_code(),cmd&VM_OPCALLNUM);
|
||||
vm.run(gen,linker,cmd&VM_OPCALLNUM);
|
||||
std::cout<<"process exited after "<<((double)(clock()-t))/CLOCKS_PER_SEC<<"s.\n";
|
||||
}
|
||||
else if(cmd&VM_EXEC)
|
||||
vm.run(codegen.get_code(),cmd&VM_OPCALLNUM);
|
||||
vm.clear();
|
||||
return;
|
||||
vm.run(gen,linker,cmd&VM_OPCALLNUM);
|
||||
}
|
||||
|
||||
int main(int argc,const char* argv[])
|
||||
|
@ -110,7 +108,7 @@ int main(int argc,const char* argv[])
|
|||
if(argc==2 && (!strcmp(argv[1],"-v") || !strcmp(argv[1],"--version")))
|
||||
logo();
|
||||
else if(argc==2 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help")))
|
||||
help_cmd();
|
||||
help();
|
||||
else if(argc==2 && argv[1][0]!='-')
|
||||
execute(argv[1],VM_EXEC);
|
||||
else if(argc>=3)
|
||||
|
@ -130,11 +128,11 @@ int main(int argc,const char* argv[])
|
|||
else if(s=="--time" || s=="-t")
|
||||
cmd|=VM_EXECTIME;
|
||||
else
|
||||
cmderr();
|
||||
err();
|
||||
}
|
||||
execute(argv[argc-1],cmd);
|
||||
}
|
||||
else
|
||||
cmderr();
|
||||
err();
|
||||
return 0;
|
||||
}
|
19
nasal.h
19
nasal.h
|
@ -20,6 +20,25 @@
|
|||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
class nasal_err
|
||||
{
|
||||
private:
|
||||
uint32_t error;
|
||||
std::string stage;
|
||||
public:
|
||||
nasal_err(
|
||||
const uint32_t _error,
|
||||
const std::string _stage
|
||||
):error(_error),stage(_stage){}
|
||||
void unwarp(const std::string& error_file)
|
||||
{
|
||||
if(!error)
|
||||
return;
|
||||
std::cout<<"["<<stage<<"] in <"<<error_file<<">: error(s) occurred,stop.\n";
|
||||
std::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
check if a string can be converted to a number
|
||||
if this string cannot be converted to a number,it will return nan
|
||||
|
|
119
nasal_ast.h
119
nasal_ast.h
|
@ -29,7 +29,7 @@ const char* ast_name[]=
|
|||
"null",
|
||||
"root","block",
|
||||
"file",
|
||||
"nil","num","str","id","func","hash","vec",
|
||||
"nil","node_num","node_str","id","func","hash","vec",
|
||||
"hashmember","call","callh","callv","callf","subvec",
|
||||
"args","deflt_arg","dyn_id",
|
||||
"and","or",
|
||||
|
@ -50,103 +50,98 @@ const char* ast_name[]=
|
|||
class nasal_ast
|
||||
{
|
||||
private:
|
||||
uint32_t line;
|
||||
uint32_t type;
|
||||
double num;
|
||||
std::string str;
|
||||
std::vector<nasal_ast> children;
|
||||
uint32_t text_line;
|
||||
uint32_t node_type;
|
||||
double node_num;
|
||||
std::string node_str;
|
||||
std::vector<nasal_ast> node_child;
|
||||
public:
|
||||
nasal_ast(){line=0;type=ast_null;}
|
||||
nasal_ast(const uint32_t l,const uint32_t t){line=l;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(nasal_ast&&);
|
||||
nasal_ast& operator=(const nasal_ast&);
|
||||
nasal_ast& operator=(nasal_ast&&);
|
||||
void print(const int);
|
||||
void clear();
|
||||
void add_child(nasal_ast&& ast){children.push_back(std::move(ast));}
|
||||
void add_child(const nasal_ast& ast){children.push_back(ast);}
|
||||
void set_line(const uint32_t l){line=l;}
|
||||
void set_type(const uint32_t t){type=t;}
|
||||
void set_str(const std::string& s){str=s;}
|
||||
void set_num(const double n){num=n;}
|
||||
void print(const int);
|
||||
void clear();
|
||||
void add(nasal_ast&& ast){node_child.push_back(std::move(ast));}
|
||||
void add(const nasal_ast& ast){node_child.push_back(ast);}
|
||||
void set_line(const uint32_t l){text_line=l;}
|
||||
void set_type(const uint32_t t){node_type=t;}
|
||||
void set_str(const std::string& s){node_str=s;}
|
||||
void set_num(const double n){node_num=n;}
|
||||
|
||||
uint32_t get_line(){return line;}
|
||||
uint32_t get_type(){return type;}
|
||||
double get_num() {return num;}
|
||||
std::string& get_str() {return str;}
|
||||
std::vector<nasal_ast>& get_children(){return children;}
|
||||
|
||||
uint32_t get_line() const {return line;}
|
||||
uint32_t get_type() const {return type;}
|
||||
double get_num() const {return num;}
|
||||
const std::string& get_str() const {return str;}
|
||||
const std::vector<nasal_ast>& get_children() const {return children;}
|
||||
inline const uint32_t line() const {return text_line;}
|
||||
inline const uint32_t type() const {return node_type;}
|
||||
inline const double num() const {return node_num;}
|
||||
inline const std::string& str() const {return node_str;}
|
||||
inline const std::vector<nasal_ast>& child() const {return node_child;}
|
||||
inline std::vector<nasal_ast>& child(){return node_child;}
|
||||
};
|
||||
|
||||
nasal_ast::nasal_ast(const nasal_ast& tmp)
|
||||
{
|
||||
line=tmp.line;
|
||||
type=tmp.type;
|
||||
num =tmp.num;
|
||||
str =tmp.str;
|
||||
children=tmp.children;
|
||||
return;
|
||||
text_line=tmp.text_line;
|
||||
node_type=tmp.node_type;
|
||||
node_num =tmp.node_num;
|
||||
node_str =tmp.node_str;
|
||||
node_child=tmp.node_child;
|
||||
}
|
||||
|
||||
nasal_ast::nasal_ast(nasal_ast&& tmp)
|
||||
{
|
||||
line=tmp.line;
|
||||
type=tmp.type;
|
||||
num =tmp.num;
|
||||
str.swap(tmp.str);
|
||||
children.swap(tmp.children);
|
||||
return;
|
||||
text_line=tmp.text_line;
|
||||
node_type=tmp.node_type;
|
||||
node_num =tmp.node_num;
|
||||
node_str.swap(tmp.node_str);
|
||||
node_child.swap(tmp.node_child);
|
||||
}
|
||||
|
||||
nasal_ast& nasal_ast::operator=(const nasal_ast& tmp)
|
||||
{
|
||||
line=tmp.line;
|
||||
type=tmp.type;
|
||||
num=tmp.num;
|
||||
str=tmp.str;
|
||||
children=tmp.children;
|
||||
text_line=tmp.text_line;
|
||||
node_type=tmp.node_type;
|
||||
node_num=tmp.node_num;
|
||||
node_str=tmp.node_str;
|
||||
node_child=tmp.node_child;
|
||||
return *this;
|
||||
}
|
||||
|
||||
nasal_ast& nasal_ast::operator=(nasal_ast&& tmp)
|
||||
{
|
||||
line=tmp.line;
|
||||
type=tmp.type;
|
||||
num=tmp.num;
|
||||
str.swap(tmp.str);
|
||||
children.swap(tmp.children);
|
||||
text_line=tmp.text_line;
|
||||
node_type=tmp.node_type;
|
||||
node_num=tmp.node_num;
|
||||
node_str.swap(tmp.node_str);
|
||||
node_child.swap(tmp.node_child);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void nasal_ast::clear()
|
||||
{
|
||||
line=0;
|
||||
num=0;
|
||||
str="";
|
||||
type=ast_null;
|
||||
children.clear();
|
||||
return;
|
||||
text_line=0;
|
||||
node_num=0;
|
||||
node_str="";
|
||||
node_type=ast_null;
|
||||
node_child.clear();
|
||||
}
|
||||
|
||||
void nasal_ast::print(const int depth)
|
||||
{
|
||||
for(int i=0;i<depth;++i)
|
||||
std::cout<<"| ";
|
||||
std::cout<<ast_name[type];
|
||||
if(type==ast_str || type==ast_id || type==ast_default_arg || type==ast_dynamic_id || type==ast_callh)
|
||||
std::cout<<":"<<raw_string(str);
|
||||
else if(type==ast_num || type==ast_file)
|
||||
std::cout<<":"<<num;
|
||||
std::cout<<ast_name[node_type];
|
||||
if(
|
||||
node_type==ast_str ||
|
||||
node_type==ast_id ||
|
||||
node_type==ast_default_arg ||
|
||||
node_type==ast_dynamic_id ||
|
||||
node_type==ast_callh)
|
||||
std::cout<<":"<<raw_string(node_str);
|
||||
else if(node_type==ast_num || node_type==ast_file)
|
||||
std::cout<<":"<<node_num;
|
||||
std::cout<<'\n';
|
||||
for(auto& i:children)
|
||||
for(auto& i:node_child)
|
||||
i.print(depth+1);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -120,7 +120,7 @@ nasal_ref builtin_print(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
// local[0] is reserved for 'me'
|
||||
nasal_ref vec=local[1];
|
||||
// main process
|
||||
for(auto i:vec.vec()->elems)
|
||||
for(auto& i:vec.vec()->elems)
|
||||
switch(i.type)
|
||||
{
|
||||
case vm_none: std::cout<<"null"; break;
|
||||
|
@ -143,7 +143,7 @@ nasal_ref builtin_append(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
if(vec.type!=vm_vec)
|
||||
return builtin_err("append","\"vector\" must be vector");
|
||||
auto& ref_vec=vec.vec()->elems;
|
||||
for(auto i:elem.vec()->elems)
|
||||
for(auto& i:elem.vec()->elems)
|
||||
ref_vec.push_back(i);
|
||||
return gc.nil;
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ nasal_ref builtin_system(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
}
|
||||
nasal_ref builtin_input(std::vector<nasal_ref>& local,nasal_gc& gc)
|
||||
{
|
||||
nasal_ref ret=gc.gc_alloc(vm_str);
|
||||
nasal_ref ret=gc.alloc(vm_str);
|
||||
std::cin>>*ret.str();
|
||||
return ret;
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ nasal_ref builtin_fin(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
std::ifstream fin(filename);
|
||||
if(!fin.fail())
|
||||
{
|
||||
nasal_ref ret=gc.gc_alloc(vm_str);
|
||||
nasal_ref ret=gc.alloc(vm_str);
|
||||
std::stringstream rd;
|
||||
rd<<fin.rdbuf();
|
||||
*ret.str()=rd.str();
|
||||
|
@ -228,14 +228,14 @@ nasal_ref builtin_split(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
size_t source_len=source.length();
|
||||
|
||||
// push it to local scope to avoid being sweeped
|
||||
local.push_back(gc.gc_alloc(vm_vec));
|
||||
local.push_back(gc.alloc(vm_vec));
|
||||
|
||||
std::vector<nasal_ref>& vec=local.back().vec()->elems;
|
||||
if(!delimeter_len)
|
||||
{
|
||||
for(int i=0;i<source_len;++i)
|
||||
{
|
||||
vec.push_back(gc.gc_alloc(vm_str));
|
||||
vec.push_back(gc.alloc(vm_str));
|
||||
*vec.back().str()=source[i];
|
||||
}
|
||||
return local.back();
|
||||
|
@ -257,7 +257,7 @@ nasal_ref builtin_split(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
{
|
||||
if(tmp.length())
|
||||
{
|
||||
vec.push_back(gc.gc_alloc(vm_str));
|
||||
vec.push_back(gc.alloc(vm_str));
|
||||
*vec.back().str()=tmp;
|
||||
tmp="";
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ nasal_ref builtin_split(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
}
|
||||
if(tmp.length())
|
||||
{
|
||||
vec.push_back(gc.gc_alloc(vm_str));
|
||||
vec.push_back(gc.alloc(vm_str));
|
||||
*vec.back().str()=tmp;
|
||||
tmp="";
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ nasal_ref builtin_rand(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
nasal_ref builtin_id(std::vector<nasal_ref>& local,nasal_gc& gc)
|
||||
{
|
||||
nasal_ref val=local[1];
|
||||
nasal_ref ret=gc.gc_alloc(vm_str);
|
||||
nasal_ref ret=gc.alloc(vm_str);
|
||||
char buf[32];
|
||||
if(val.type>vm_num)
|
||||
sprintf(buf,"%p",val.value.gcobj);
|
||||
|
@ -334,7 +334,7 @@ nasal_ref builtin_str(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
nasal_ref val=local[1];
|
||||
if(val.type!=vm_num)
|
||||
return builtin_err("str","\"number\" must be number");
|
||||
nasal_ref ret=gc.gc_alloc(vm_str);
|
||||
nasal_ref ret=gc.alloc(vm_str);
|
||||
*ret.str()=std::to_string(val.num());
|
||||
return ret;
|
||||
}
|
||||
|
@ -500,11 +500,11 @@ nasal_ref builtin_keys(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
if(hash.type!=vm_hash)
|
||||
return builtin_err("keys","\"hash\" must be hash");
|
||||
// push vector into local scope to avoid being sweeped
|
||||
local.push_back(gc.gc_alloc(vm_vec));
|
||||
local.push_back(gc.alloc(vm_vec));
|
||||
auto& vec=local.back().vec()->elems;
|
||||
for(auto& iter:hash.hash()->elems)
|
||||
{
|
||||
nasal_ref str=gc.gc_alloc(vm_str);
|
||||
nasal_ref str=gc.alloc(vm_str);
|
||||
*str.str()=iter.first;
|
||||
vec.push_back(str);
|
||||
}
|
||||
|
@ -527,7 +527,7 @@ nasal_ref builtin_die(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
nasal_ref builtin_type(std::vector<nasal_ref>& local,nasal_gc& gc)
|
||||
{
|
||||
nasal_ref val=local[1];
|
||||
nasal_ref ret=gc.gc_alloc(vm_str);
|
||||
nasal_ref ret=gc.alloc(vm_str);
|
||||
switch(val.type)
|
||||
{
|
||||
case vm_none: *ret.str()="undefined";break;
|
||||
|
@ -558,7 +558,7 @@ nasal_ref builtin_substr(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
return builtin_err("susbtr","index out of range");
|
||||
if(length<0)
|
||||
length=0;
|
||||
nasal_ref ret=gc.gc_alloc(vm_str);
|
||||
nasal_ref ret=gc.alloc(vm_str);
|
||||
*ret.str()=str.str()->substr(begin,length);
|
||||
return ret;
|
||||
}
|
||||
|
@ -579,7 +579,7 @@ nasal_ref builtin_left(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
int length=(int)len.num();
|
||||
if(length<0)
|
||||
length=0;
|
||||
nasal_ref ret=gc.gc_alloc(vm_str);
|
||||
nasal_ref ret=gc.alloc(vm_str);
|
||||
*ret.str()=str.str()->substr(0,length);
|
||||
return ret;
|
||||
}
|
||||
|
@ -597,7 +597,7 @@ nasal_ref builtin_right(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
length=srclen;
|
||||
if(length<0)
|
||||
length=0;
|
||||
nasal_ref ret=gc.gc_alloc(vm_str);
|
||||
nasal_ref ret=gc.alloc(vm_str);
|
||||
*ret.str()=str.str()->substr(srclen-length, srclen);
|
||||
return ret;
|
||||
}
|
||||
|
@ -634,7 +634,7 @@ nasal_ref builtin_chr(std::vector<nasal_ref>& local,nasal_gc& gc)
|
|||
nasal_ref code=local[1];
|
||||
if(code.type!=vm_num)
|
||||
return builtin_err("chr","\"code\" must be number");
|
||||
nasal_ref ret=gc.gc_alloc(vm_str);
|
||||
nasal_ref ret=gc.alloc(vm_str);
|
||||
int num=code.num();
|
||||
if(0<=num && num<128)
|
||||
*ret.str()=(char)num;
|
||||
|
|
511
nasal_codegen.h
511
nasal_codegen.h
File diff suppressed because it is too large
Load Diff
16
nasal_gc.h
16
nasal_gc.h
|
@ -340,9 +340,9 @@ struct nasal_gc
|
|||
std::vector<nasal_ref> local;
|
||||
void mark();
|
||||
void sweep();
|
||||
void gc_init(const std::vector<std::string>&);
|
||||
void gc_clear();
|
||||
nasal_ref gc_alloc(const uint8_t);
|
||||
void init(const std::vector<std::string>&);
|
||||
void clear();
|
||||
nasal_ref alloc(const uint8_t);
|
||||
nasal_ref builtin_alloc(const uint8_t);
|
||||
};
|
||||
|
||||
|
@ -350,7 +350,7 @@ struct nasal_gc
|
|||
void nasal_gc::mark()
|
||||
{
|
||||
std::queue<nasal_ref> bfs;
|
||||
for(auto i:local)
|
||||
for(auto& i:local)
|
||||
bfs.push(i);
|
||||
for(nasal_ref* i=val_stack;i<=stack_top;++i)
|
||||
bfs.push(*i);
|
||||
|
@ -406,7 +406,7 @@ void nasal_gc::sweep()
|
|||
}
|
||||
return;
|
||||
}
|
||||
void nasal_gc::gc_init(const std::vector<std::string>& strs)
|
||||
void nasal_gc::init(const std::vector<std::string>& strs)
|
||||
{
|
||||
for(uint8_t i=vm_str;i<vm_type_size;++i)
|
||||
for(uint32_t j=0;j<increment[i];++j)
|
||||
|
@ -431,7 +431,7 @@ void nasal_gc::gc_init(const std::vector<std::string>& strs)
|
|||
}
|
||||
return;
|
||||
}
|
||||
void nasal_gc::gc_clear()
|
||||
void nasal_gc::clear()
|
||||
{
|
||||
for(auto i:memory)
|
||||
delete i;
|
||||
|
@ -445,7 +445,7 @@ void nasal_gc::gc_clear()
|
|||
str_addrs.clear();
|
||||
return;
|
||||
}
|
||||
nasal_ref nasal_gc::gc_alloc(uint8_t type)
|
||||
nasal_ref nasal_gc::alloc(uint8_t type)
|
||||
{
|
||||
if(free_list[type].empty())
|
||||
{
|
||||
|
@ -467,7 +467,7 @@ nasal_ref nasal_gc::gc_alloc(uint8_t type)
|
|||
nasal_ref nasal_gc::builtin_alloc(uint8_t type)
|
||||
{
|
||||
// when running a builtin function,alloc will run more than one time
|
||||
// this may cause mark-sweep in gc_alloc
|
||||
// this may cause mark-sweep in gc::alloc
|
||||
// and the value got before will be collected,this is a fatal error
|
||||
// so use builtin_alloc in builtin functions if this function uses alloc more then one time
|
||||
if(free_list[type].empty())
|
||||
|
|
|
@ -8,7 +8,7 @@ private:
|
|||
nasal_lexer import_lex;
|
||||
nasal_parse import_par;
|
||||
nasal_ast import_ast;
|
||||
std::vector<std::string> filename_table;
|
||||
std::vector<std::string> file_table;
|
||||
void die(const std::string&,const char*);
|
||||
bool check_import(const nasal_ast&);
|
||||
bool check_exist(const std::string&);
|
||||
|
@ -17,9 +17,8 @@ private:
|
|||
nasal_ast load(nasal_ast&,uint16_t);
|
||||
public:
|
||||
uint32_t err(){return error;}
|
||||
void link(nasal_ast&,const std::string&);
|
||||
const nasal_ast& ast(){return import_ast;}
|
||||
const std::vector<std::string>& get_file(){return filename_table;}
|
||||
void link(nasal_parse&,const std::string&);
|
||||
const std::vector<std::string>& get_file() const {return file_table;}
|
||||
};
|
||||
|
||||
void nasal_import::die(const std::string& file,const char* stage)
|
||||
|
@ -37,16 +36,16 @@ only this kind of node can be recognized as 'import':
|
|||
call_func
|
||||
string:'filename'
|
||||
*/
|
||||
if(node.get_type()!=ast_call)
|
||||
if(node.type()!=ast_call)
|
||||
return false;
|
||||
const std::vector<nasal_ast>& ref_vec=node.get_children();
|
||||
const std::vector<nasal_ast>& ref_vec=node.child();
|
||||
if(ref_vec.size()!=2)
|
||||
return false;
|
||||
if(ref_vec[0].get_str()!="import")
|
||||
if(ref_vec[0].str()!="import")
|
||||
return false;
|
||||
if(ref_vec[1].get_type()!=ast_callf)
|
||||
if(ref_vec[1].type()!=ast_callf)
|
||||
return false;
|
||||
if(ref_vec[1].get_children().size()!=1 || ref_vec[1].get_children()[0].get_type()!=ast_str)
|
||||
if(ref_vec[1].child().size()!=1 || ref_vec[1].child()[0].type()!=ast_str)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -54,76 +53,70 @@ only this kind of node can be recognized as 'import':
|
|||
bool nasal_import::check_exist(const std::string& file)
|
||||
{
|
||||
// avoid importing the same file
|
||||
for(auto& fname:filename_table)
|
||||
for(auto& fname:file_table)
|
||||
if(file==fname)
|
||||
return true;
|
||||
filename_table.push_back(file);
|
||||
file_table.push_back(file);
|
||||
return false;
|
||||
}
|
||||
|
||||
void nasal_import::linker(nasal_ast& root,nasal_ast&& add_root)
|
||||
{
|
||||
// add children of add_root to the back of root
|
||||
for(auto& i:add_root.get_children())
|
||||
root.add_child(std::move(i));
|
||||
for(auto& i:add_root.child())
|
||||
root.add(std::move(i));
|
||||
}
|
||||
|
||||
nasal_ast nasal_import::file_import(nasal_ast& node)
|
||||
{
|
||||
// initializing
|
||||
nasal_ast tmp(0,ast_root);
|
||||
|
||||
// get filename and set node to ast_null
|
||||
std::string filename=node.get_children()[1].get_children()[0].get_str();
|
||||
std::string filename=node.child()[1].child()[0].str();
|
||||
node.clear();
|
||||
|
||||
// avoid infinite loading loop
|
||||
if(check_exist(filename))
|
||||
return tmp;
|
||||
return {0,ast_root};
|
||||
|
||||
// start importing...
|
||||
import_lex.open(filename);
|
||||
import_lex.scan();
|
||||
import_lex.scan(filename);
|
||||
if(import_lex.err())
|
||||
{
|
||||
die(filename,"lexer");
|
||||
return tmp;
|
||||
return {0,ast_root};
|
||||
}
|
||||
import_par.compile(import_lex.get_tokens());
|
||||
import_par.compile(import_lex);
|
||||
if(import_par.err())
|
||||
{
|
||||
die(filename,"parser");
|
||||
return tmp;
|
||||
return {0,ast_root};
|
||||
}
|
||||
tmp=std::move(import_par.ast());
|
||||
nasal_ast tmp=std::move(import_par.ast());
|
||||
// check if tmp has 'import'
|
||||
return load(tmp,filename_table.size()-1);
|
||||
return load(tmp,file_table.size()-1);
|
||||
}
|
||||
|
||||
nasal_ast nasal_import::load(nasal_ast& root,uint16_t fileindex)
|
||||
{
|
||||
nasal_ast new_root(0,ast_root);
|
||||
for(auto& i:root.get_children())
|
||||
for(auto& i:root.child())
|
||||
if(check_import(i))
|
||||
linker(new_root,file_import(i));
|
||||
// add root to the back of new_root
|
||||
nasal_ast file_head(0,ast_file);
|
||||
file_head.set_num(fileindex);
|
||||
new_root.add_child(std::move(file_head));
|
||||
new_root.add(std::move(file_head));
|
||||
linker(new_root,std::move(root));
|
||||
return new_root;
|
||||
}
|
||||
|
||||
void nasal_import::link(nasal_ast& root,const std::string& self)
|
||||
void nasal_import::link(nasal_parse& parse,const std::string& self)
|
||||
{
|
||||
// initializing
|
||||
error=0;
|
||||
filename_table.clear();
|
||||
filename_table.push_back(self);
|
||||
import_ast.clear();
|
||||
file_table={self};
|
||||
// scan root and import files,then generate a new ast and return to import_ast
|
||||
// the main file's index is 0
|
||||
import_ast=load(root,0);
|
||||
parse.ast()=load(parse.ast(),0);
|
||||
}
|
||||
|
||||
#endif
|
101
nasal_lexer.h
101
nasal_lexer.h
|
@ -1,22 +1,24 @@
|
|||
#ifndef __NASAL_LEXER_H__
|
||||
#define __NASAL_LEXER_H__
|
||||
|
||||
#define IS_ID(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z'))
|
||||
#define IS_HEX(c) (('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F'))
|
||||
#define IS_OCT(c) ('0'<=c&&c<='7')
|
||||
#define IS_DIGIT(c) ('0'<=c&&c<='9')
|
||||
#define IS_STR(c) (c=='\''||c=='\"'||c=='`')
|
||||
#define ID(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z'))
|
||||
#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 IS_SINGLE_OPERATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\
|
||||
#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 IS_CALC_OPERATOR(c) (c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~')
|
||||
#define IS_NOTE(c) (c=='#')
|
||||
#define CALC_OPERATOR(c) (c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~')
|
||||
#define NOTE(c) (c=='#')
|
||||
|
||||
enum token_type
|
||||
{
|
||||
tok_null=0,
|
||||
tok_num,tok_str,tok_id,
|
||||
tok_null=0,// null token default token type
|
||||
tok_num, // number basic token type
|
||||
tok_str, // string basic token type
|
||||
tok_id, // identifier basic token type
|
||||
tok_for,tok_forindex,tok_foreach,tok_while,
|
||||
tok_var,tok_func,tok_break,tok_continue,
|
||||
tok_ret,tok_if,tok_elsif,tok_else,tok_nil,
|
||||
|
@ -28,7 +30,7 @@ enum token_type
|
|||
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
|
||||
tok_eof // end of token list
|
||||
};
|
||||
|
||||
struct
|
||||
|
@ -105,26 +107,25 @@ private:
|
|||
std::vector<token> tokens;
|
||||
uint32_t get_type(const std::string&);
|
||||
void die(const char*);
|
||||
void open(const std::string&);
|
||||
std::string id_gen();
|
||||
std::string num_gen();
|
||||
std::string str_gen();
|
||||
public:
|
||||
void open(const std::string&);
|
||||
void scan();
|
||||
void print();
|
||||
uint32_t err(){return error;}
|
||||
const std::vector<token>& get_tokens(){return tokens;}
|
||||
void scan(const std::string&);
|
||||
void print();
|
||||
const std::vector<token>& get_tokens() const {return tokens;}
|
||||
};
|
||||
|
||||
void nasal_lexer::open(const std::string& filename)
|
||||
void nasal_lexer::open(const std::string& file)
|
||||
{
|
||||
error=0;
|
||||
res.clear();
|
||||
std::ifstream fin(filename,std::ios::binary);
|
||||
std::ifstream fin(file,std::ios::binary);
|
||||
if(fin.fail())
|
||||
{
|
||||
++error;
|
||||
std::cout<<"[lexer] cannot open file <"<<filename<<">.\n";
|
||||
std::cout<<"[lexer] cannot open file <"<<file<<">.\n";
|
||||
}
|
||||
std::stringstream ss;
|
||||
ss<<fin.rdbuf();
|
||||
|
@ -143,19 +144,18 @@ void nasal_lexer::die(const char* info)
|
|||
{
|
||||
++error;
|
||||
std::cout<<"[lexer] line "<<line<<" column "<<code.length()<<": \n"<<code<<'\n';
|
||||
for(auto i:code)
|
||||
std::cout<<char(" \t"[i=='\t']);
|
||||
for(uint32_t i=0;i<code.size()-1;++i)
|
||||
std::cout<<char(" \t"[code[i]=='\t']);
|
||||
std::cout<<'^'<<info<<'\n';
|
||||
}
|
||||
|
||||
std::string nasal_lexer::id_gen()
|
||||
{
|
||||
std::string str="";
|
||||
while(ptr<size && (IS_ID(res[ptr])||IS_DIGIT(res[ptr])))
|
||||
while(ptr<size && (ID(res[ptr])||DIGIT(res[ptr])))
|
||||
str+=res[ptr++];
|
||||
code+=str;
|
||||
return str;
|
||||
// after running this process, ptr will point to the next token's beginning character
|
||||
}
|
||||
|
||||
std::string nasal_lexer::num_gen()
|
||||
|
@ -165,7 +165,7 @@ std::string nasal_lexer::num_gen()
|
|||
{
|
||||
std::string str="0x";
|
||||
ptr+=2;
|
||||
while(ptr<size && IS_HEX(res[ptr]))
|
||||
while(ptr<size && HEX(res[ptr]))
|
||||
str+=res[ptr++];
|
||||
code+=str;
|
||||
if(str.length()<3)// "0x"
|
||||
|
@ -177,7 +177,7 @@ std::string nasal_lexer::num_gen()
|
|||
{
|
||||
std::string str="0o";
|
||||
ptr+=2;
|
||||
while(ptr<size && IS_OCT(res[ptr]))
|
||||
while(ptr<size && OCT(res[ptr]))
|
||||
str+=res[ptr++];
|
||||
code+=str;
|
||||
if(str.length()<3)// "0o"
|
||||
|
@ -187,12 +187,12 @@ std::string nasal_lexer::num_gen()
|
|||
// generate dec number
|
||||
// dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
|
||||
std::string str="";
|
||||
while(ptr<size && IS_DIGIT(res[ptr]))
|
||||
while(ptr<size && DIGIT(res[ptr]))
|
||||
str+=res[ptr++];
|
||||
if(ptr<size && res[ptr]=='.')
|
||||
{
|
||||
str+=res[ptr++];
|
||||
while(ptr<size && IS_DIGIT(res[ptr]))
|
||||
while(ptr<size && DIGIT(res[ptr]))
|
||||
str+=res[ptr++];
|
||||
// "xxxx." is not a correct number
|
||||
if(str.back()=='.')
|
||||
|
@ -207,7 +207,7 @@ std::string nasal_lexer::num_gen()
|
|||
str+=res[ptr++];
|
||||
if(ptr<size && (res[ptr]=='-' || res[ptr]=='+'))
|
||||
str+=res[ptr++];
|
||||
while(ptr<size && IS_DIGIT(res[ptr]))
|
||||
while(ptr<size && DIGIT(res[ptr]))
|
||||
str+=res[ptr++];
|
||||
// "xxxe(-|+)" is not a correct number
|
||||
if(str.back()=='e' || str.back()=='E' || str.back()=='-' || str.back()=='+')
|
||||
|
@ -239,15 +239,15 @@ std::string nasal_lexer::str_gen()
|
|||
code+=res[++ptr];
|
||||
switch(res[ptr])
|
||||
{
|
||||
case '0': str+='\0'; break;
|
||||
case 'a': str+='\a'; break;
|
||||
case 'b': str+='\b'; break;
|
||||
case 'f': str+='\f'; break;
|
||||
case 'n': str+='\n'; break;
|
||||
case 'r': str+='\r'; break;
|
||||
case 't': str+='\t'; break;
|
||||
case 'n': str+='\n'; break;
|
||||
case 'v': str+='\v'; break;
|
||||
case 'f': str+='\f'; break;
|
||||
case 'r': str+='\r'; break;
|
||||
case '?': str+='\?'; break;
|
||||
case '0': str+='\0'; break;
|
||||
case '\\':str+='\\'; break;
|
||||
case '\'':str+='\''; break;
|
||||
case '\"':str+='\"'; break;
|
||||
|
@ -266,8 +266,9 @@ std::string nasal_lexer::str_gen()
|
|||
return str;
|
||||
}
|
||||
|
||||
void nasal_lexer::scan()
|
||||
void nasal_lexer::scan(const std::string& file)
|
||||
{
|
||||
open(file);
|
||||
tokens.clear();
|
||||
line=1;
|
||||
ptr=0;
|
||||
|
@ -288,18 +289,17 @@ void nasal_lexer::scan()
|
|||
}
|
||||
}
|
||||
if(ptr>=size) break;
|
||||
if(IS_ID(res[ptr]))
|
||||
if(ID(res[ptr]))
|
||||
{
|
||||
str=id_gen();
|
||||
tokens.push_back({line,get_type(str),str});
|
||||
if(!tokens.back().type)
|
||||
tokens.back().type=tok_id;
|
||||
uint32_t type=get_type(str);
|
||||
tokens.push_back({line,type?type:tok_id,str});
|
||||
}
|
||||
else if(IS_DIGIT(res[ptr]))
|
||||
else if(DIGIT(res[ptr]))
|
||||
tokens.push_back({line,tok_num,num_gen()});
|
||||
else if(IS_STR(res[ptr]))
|
||||
else if(STR(res[ptr]))
|
||||
tokens.push_back({line,tok_str,str_gen()});
|
||||
else if(IS_SINGLE_OPERATOR(res[ptr]))
|
||||
else if(SINGLE_OPERATOR(res[ptr]))
|
||||
{
|
||||
str=res[ptr];
|
||||
code+=res[ptr];
|
||||
|
@ -311,20 +311,14 @@ void nasal_lexer::scan()
|
|||
}
|
||||
else if(res[ptr]=='.')
|
||||
{
|
||||
str=".";
|
||||
if(ptr+2<size && res[ptr+1]=='.' && res[ptr+2]=='.')
|
||||
{
|
||||
str="...";
|
||||
ptr+=3;
|
||||
}
|
||||
else
|
||||
{
|
||||
str=".";
|
||||
++ptr;
|
||||
}
|
||||
str+="..";
|
||||
ptr+=str.length();
|
||||
code+=str;
|
||||
tokens.push_back({line,get_type(str),str});
|
||||
}
|
||||
else if(IS_CALC_OPERATOR(res[ptr]))
|
||||
else if(CALC_OPERATOR(res[ptr]))
|
||||
{
|
||||
// get calculation operator
|
||||
str=res[ptr++];
|
||||
|
@ -333,7 +327,7 @@ void nasal_lexer::scan()
|
|||
code+=str;
|
||||
tokens.push_back({line,get_type(str),str});
|
||||
}
|
||||
else if(IS_NOTE(res[ptr]))// avoid note, after this process ptr will point to a '\n', so next loop line counter+1
|
||||
else if(NOTE(res[ptr]))// avoid note, after this process ptr will point to a '\n', so next loop line counter+1
|
||||
while(++ptr<size && res[ptr]!='\n');
|
||||
else
|
||||
{
|
||||
|
@ -341,15 +335,14 @@ void nasal_lexer::scan()
|
|||
die("unknown character.");
|
||||
}
|
||||
}
|
||||
tokens.push_back({line,tok_eof,""});
|
||||
tokens.push_back({line,tok_eof,"eof"});
|
||||
res.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_lexer::print()
|
||||
{
|
||||
for(auto& tok:tokens)
|
||||
std::cout<<"("<<tok.line<<" | "<<tok.str<<")\n";
|
||||
std::cout<<"("<<tok.line<<" | "<<raw_string(tok.str)<<")\n";
|
||||
}
|
||||
|
||||
#endif
|
718
nasal_parse.h
718
nasal_parse.h
File diff suppressed because it is too large
Load Diff
131
nasal_vm.h
131
nasal_vm.h
|
@ -12,14 +12,20 @@ private:
|
|||
std::stack<uint32_t> ret; // ptr stack stores address for function to return
|
||||
std::stack<nasal_func*> func_stk; // stack to store function,this is used when getting upvalues
|
||||
std::stack<int> counter; // iterator stack for forindex/foreach
|
||||
std::vector<double> num_table;// numbers used in process(const calculation)
|
||||
const double* num_table;// numbers used in process(const calculation)
|
||||
std::vector<std::string> str_table;// symbols used in process
|
||||
std::vector<uint32_t> imm; // immediate number
|
||||
const uint32_t* imm; // immediate number
|
||||
nasal_ref* mem_addr; // used for mem_call
|
||||
nasal_gc gc; // garbage collector
|
||||
/* values used for debug */
|
||||
std::vector<opcode> bytecode; // bytecode
|
||||
std::vector<std::string> files; // files
|
||||
|
||||
void init(
|
||||
const std::vector<std::string>&,
|
||||
const std::vector<double>&,
|
||||
const std::vector<std::string>&);
|
||||
void clear();
|
||||
/* debug functions */
|
||||
void bytecodeinfo(const uint32_t);
|
||||
void traceback();
|
||||
|
@ -107,15 +113,9 @@ private:
|
|||
void opr_mcallh();
|
||||
void opr_ret();
|
||||
public:
|
||||
nasal_vm():stack_top(gc.stack_top){};
|
||||
void init(
|
||||
const std::vector<std::string>&,
|
||||
const std::vector<double>&,
|
||||
const std::vector<std::string>&);
|
||||
void clear();
|
||||
void run(
|
||||
const std::vector<opcode>&,
|
||||
const bool);
|
||||
nasal_vm():stack_top(gc.stack_top){}
|
||||
~nasal_vm(){clear();}
|
||||
void run(const nasal_codegen&,const nasal_import&,const bool);
|
||||
};
|
||||
|
||||
void nasal_vm::init(
|
||||
|
@ -123,24 +123,20 @@ void nasal_vm::init(
|
|||
const std::vector<double>& nums,
|
||||
const std::vector<std::string>& filenames)
|
||||
{
|
||||
gc.gc_init(strs);
|
||||
gc.init(strs);
|
||||
gc.val_stack[STACK_MAX_DEPTH-1].value.gcobj=nullptr;
|
||||
num_table=nums; // get constant numbers
|
||||
num_table=nums.data(); // get constant numbers
|
||||
str_table=strs; // get constant strings & symbols
|
||||
files=filenames;// get filenames for debugger
|
||||
return;
|
||||
}
|
||||
void nasal_vm::clear()
|
||||
{
|
||||
gc.gc_clear();
|
||||
gc.clear();
|
||||
while(!ret.empty())
|
||||
ret.pop();
|
||||
while(!counter.empty())
|
||||
counter.pop();
|
||||
num_table.clear();
|
||||
str_table.clear();
|
||||
imm.clear();
|
||||
return;
|
||||
}
|
||||
void nasal_vm::bytecodeinfo(const uint32_t p)
|
||||
{
|
||||
|
@ -149,7 +145,6 @@ void nasal_vm::bytecodeinfo(const uint32_t p)
|
|||
if(code.op==op_callb)
|
||||
printf(" <%s>",builtin_func[code.num].name);
|
||||
printf(" (%s line %d)\n",files[code.fidx].c_str(),code.line);
|
||||
return;
|
||||
}
|
||||
void nasal_vm::traceback()
|
||||
{
|
||||
|
@ -172,7 +167,6 @@ void nasal_vm::traceback()
|
|||
}
|
||||
if(same_cnt)
|
||||
printf("\t0x%.8x: %d same call(s) ...\n",last_point,same_cnt);
|
||||
return;
|
||||
}
|
||||
void nasal_vm::stackinfo(const uint32_t limit)
|
||||
{
|
||||
|
@ -207,7 +201,6 @@ void nasal_vm::stackinfo(const uint32_t limit)
|
|||
}
|
||||
if(same_cnt)
|
||||
printf("\t... | %d same value(s)\n",same_cnt);
|
||||
return;
|
||||
}
|
||||
void nasal_vm::die(std::string str)
|
||||
{
|
||||
|
@ -246,56 +239,46 @@ inline void nasal_vm::opr_intg()
|
|||
for(uint32_t i=0;i<imm[pc];++i)
|
||||
(stack_top++)[0].type=vm_nil;
|
||||
--stack_top;// point to the top
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_intl()
|
||||
{
|
||||
stack_top[0].func()->local.resize(imm[pc],gc.nil);
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_loadg()
|
||||
{
|
||||
gc.val_stack[imm[pc]]=(stack_top--)[0];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_loadl()
|
||||
{
|
||||
gc.local.back().vec()->elems[imm[pc]]=(stack_top--)[0];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_loadu()
|
||||
{
|
||||
func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]=(stack_top--)[0];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_pnum()
|
||||
{
|
||||
(++stack_top)[0]={vm_num,num_table[imm[pc]]};
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_pone()
|
||||
{
|
||||
(++stack_top)[0]={vm_num,(double)1};
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_pzero()
|
||||
{
|
||||
(++stack_top)[0]={vm_num,(double)0};
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_pnil()
|
||||
{
|
||||
(++stack_top)[0].type=vm_nil;
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_pstr()
|
||||
{
|
||||
(++stack_top)[0]=gc.str_addrs[imm[pc]];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_newv()
|
||||
{
|
||||
nasal_ref vec_addr=gc.gc_alloc(vm_vec);
|
||||
nasal_ref vec_addr=gc.alloc(vm_vec);
|
||||
nasal_ref* begin=stack_top-imm[pc]+1;
|
||||
auto& vec=vec_addr.vec()->elems;// stack_top-imm[pc] stores the vector
|
||||
vec.resize(imm[pc]);
|
||||
|
@ -303,30 +286,26 @@ inline void nasal_vm::opr_newv()
|
|||
vec[i]=begin[i];
|
||||
begin[0]=vec_addr;
|
||||
stack_top=begin;
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_newh()
|
||||
{
|
||||
(++stack_top)[0]=gc.gc_alloc(vm_hash);
|
||||
return;
|
||||
(++stack_top)[0]=gc.alloc(vm_hash);
|
||||
}
|
||||
inline void nasal_vm::opr_newf()
|
||||
{
|
||||
newf_off=1;
|
||||
(++stack_top)[0]=gc.gc_alloc(vm_func);
|
||||
(++stack_top)[0]=gc.alloc(vm_func);
|
||||
stack_top[0].func()->entry=imm[pc];
|
||||
if(!gc.local.empty())
|
||||
{
|
||||
stack_top[0].func()->upvalue=func_stk.top()->upvalue;
|
||||
stack_top[0].func()->upvalue.push_back(gc.local.back());
|
||||
}
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_happ()
|
||||
{
|
||||
stack_top[-1].hash()->elems[str_table[imm[pc]]]=stack_top[0];
|
||||
--stack_top;
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_para()
|
||||
{
|
||||
|
@ -335,7 +314,6 @@ inline void nasal_vm::opr_para()
|
|||
func->key_table[str_table[imm[pc]]]=size;
|
||||
func->local[newf_off]={vm_none};
|
||||
++newf_off;
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_defpara()
|
||||
{
|
||||
|
@ -345,12 +323,10 @@ inline void nasal_vm::opr_defpara()
|
|||
func->key_table[str_table[imm[pc]]]=size;
|
||||
func->local[newf_off]=def_val;
|
||||
++newf_off;
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_dynpara()
|
||||
{
|
||||
stack_top[0].func()->dynpara=imm[pc];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_unot()
|
||||
{
|
||||
|
@ -370,12 +346,10 @@ inline void nasal_vm::opr_unot()
|
|||
break;
|
||||
default:die("unot: incorrect value type");break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_usub()
|
||||
{
|
||||
stack_top[0]={vm_num,-stack_top[0].to_number()};
|
||||
return;
|
||||
}
|
||||
|
||||
#define op_calc(type)\
|
||||
|
@ -388,10 +362,9 @@ inline void nasal_vm::opr_mul(){op_calc(*);}
|
|||
inline void nasal_vm::opr_div(){op_calc(/);}
|
||||
inline void nasal_vm::opr_lnk()
|
||||
{
|
||||
nasal_ref new_val=gc.gc_alloc(vm_str);
|
||||
nasal_ref new_val=gc.alloc(vm_str);
|
||||
*new_val.str()=stack_top[-1].to_string()+stack_top[0].to_string();
|
||||
(--stack_top)[0]=new_val;
|
||||
return;
|
||||
}
|
||||
|
||||
#define op_calc_const(type)\
|
||||
|
@ -404,10 +377,9 @@ inline void nasal_vm::opr_mulc(){op_calc_const(*);}
|
|||
inline void nasal_vm::opr_divc(){op_calc_const(/);}
|
||||
inline void nasal_vm::opr_lnkc()
|
||||
{
|
||||
nasal_ref new_val=gc.gc_alloc(vm_str);
|
||||
nasal_ref new_val=gc.alloc(vm_str);
|
||||
*new_val.str()=stack_top[0].to_string()+str_table[imm[pc]];
|
||||
stack_top[0]=new_val;
|
||||
return;
|
||||
}
|
||||
|
||||
#define op_calc_eq(type)\
|
||||
|
@ -420,10 +392,9 @@ inline void nasal_vm::opr_muleq(){op_calc_eq(*);}
|
|||
inline void nasal_vm::opr_diveq(){op_calc_eq(/);}
|
||||
inline void nasal_vm::opr_lnkeq()
|
||||
{
|
||||
nasal_ref new_val=gc.gc_alloc(vm_str);
|
||||
nasal_ref new_val=gc.alloc(vm_str);
|
||||
*new_val.str()=mem_addr[0].to_string()+stack_top[-1].to_string();
|
||||
(--stack_top)[0]=mem_addr[0]=new_val;
|
||||
return;
|
||||
}
|
||||
|
||||
#define op_calc_eq_const(type)\
|
||||
|
@ -436,16 +407,14 @@ inline void nasal_vm::opr_muleqc(){op_calc_eq_const(*);}
|
|||
inline void nasal_vm::opr_diveqc(){op_calc_eq_const(/);}
|
||||
inline void nasal_vm::opr_lnkeqc()
|
||||
{
|
||||
nasal_ref new_val=gc.gc_alloc(vm_str);
|
||||
nasal_ref new_val=gc.alloc(vm_str);
|
||||
*new_val.str()=mem_addr[0].to_string()+str_table[imm[pc]];
|
||||
stack_top[0]=mem_addr[0]=new_val;
|
||||
return;
|
||||
}
|
||||
|
||||
inline void nasal_vm::opr_meq()
|
||||
{
|
||||
mem_addr[0]=(--stack_top)[0];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_eq()
|
||||
{
|
||||
|
@ -461,7 +430,6 @@ inline void nasal_vm::opr_eq()
|
|||
stack_top[0]=(val1.to_number()==val2.to_number())?gc.one:gc.zero;
|
||||
else
|
||||
stack_top[0]=(val1==val2)?gc.one:gc.zero;
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_neq()
|
||||
{
|
||||
|
@ -477,7 +445,6 @@ inline void nasal_vm::opr_neq()
|
|||
stack_top[0]=(val1.to_number()!=val2.to_number())?gc.one:gc.zero;
|
||||
else
|
||||
stack_top[0]=(val1!=val2)?gc.one:gc.zero;
|
||||
return;
|
||||
}
|
||||
|
||||
#define op_cmp(type)\
|
||||
|
@ -500,37 +467,31 @@ inline void nasal_vm::opr_geqc(){op_cmp_const(>=);}
|
|||
inline void nasal_vm::opr_pop()
|
||||
{
|
||||
--stack_top;
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_jmp()
|
||||
{
|
||||
pc=imm[pc]-1;
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_jt()
|
||||
{
|
||||
if(condition(stack_top[0]))
|
||||
pc=imm[pc]-1;
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_jf()
|
||||
{
|
||||
if(!condition(stack_top[0]))
|
||||
pc=imm[pc]-1;
|
||||
--stack_top;
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_counter()
|
||||
{
|
||||
counter.push(-1);
|
||||
if(stack_top[0].type!=vm_vec)
|
||||
die("cnt: must use vector in forindex/foreach");
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_cntpop()
|
||||
{
|
||||
counter.pop();
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_findex()
|
||||
{
|
||||
|
@ -540,7 +501,6 @@ inline void nasal_vm::opr_findex()
|
|||
return;
|
||||
}
|
||||
(++stack_top)[0]={vm_num,static_cast<double>(counter.top())};
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_feach()
|
||||
{
|
||||
|
@ -551,22 +511,18 @@ inline void nasal_vm::opr_feach()
|
|||
return;
|
||||
}
|
||||
(++stack_top)[0]=ref[counter.top()];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_callg()
|
||||
{
|
||||
(++stack_top)[0]=gc.val_stack[imm[pc]];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_calll()
|
||||
{
|
||||
(++stack_top)[0]=gc.local.back().vec()->elems[imm[pc]];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_upval()
|
||||
{
|
||||
(++stack_top)[0]=func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_callv()
|
||||
{
|
||||
|
@ -599,7 +555,6 @@ inline void nasal_vm::opr_callv()
|
|||
}
|
||||
else
|
||||
die("callv: must call a vector/hash/string");
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_callvi()
|
||||
{
|
||||
|
@ -611,7 +566,6 @@ inline void nasal_vm::opr_callvi()
|
|||
(++stack_top)[0]=val.vec()->get_val(imm[pc]);
|
||||
if(stack_top[0].type==vm_none)
|
||||
die("callvi: index out of range:"+std::to_string(imm[pc]));
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_callh()
|
||||
{
|
||||
|
@ -625,7 +579,6 @@ inline void nasal_vm::opr_callh()
|
|||
|
||||
if(stack_top[0].type==vm_func)
|
||||
stack_top[0].func()->local[0]=val;// me
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_callfv()
|
||||
{
|
||||
|
@ -639,7 +592,7 @@ inline void nasal_vm::opr_callfv()
|
|||
func_stk.push(func_addr.func());
|
||||
auto& ref_func=*func_addr.func();
|
||||
|
||||
gc.local.push_back(gc.gc_alloc(vm_vec));
|
||||
gc.local.push_back(gc.alloc(vm_vec));
|
||||
gc.local.back().vec()->elems=ref_func.local;
|
||||
// load parameters
|
||||
auto& ref_closure=gc.local.back().vec()->elems;
|
||||
|
@ -656,7 +609,7 @@ inline void nasal_vm::opr_callfv()
|
|||
// load dynamic argument if args_size>=para_size
|
||||
if(ref_func.dynpara>=0)
|
||||
{
|
||||
nasal_ref vec_addr=gc.gc_alloc(vm_vec);
|
||||
nasal_ref vec_addr=gc.alloc(vm_vec);
|
||||
for(uint32_t i=para_size;i<args_size;++i)
|
||||
vec_addr.vec()->elems.push_back(vec[i]);
|
||||
ref_closure.back()=vec_addr;
|
||||
|
@ -665,7 +618,6 @@ inline void nasal_vm::opr_callfv()
|
|||
stack_top-=args_size;// pop arguments
|
||||
ret.push(pc);
|
||||
pc=ref_func.entry-1;
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_callfh()
|
||||
{
|
||||
|
@ -677,7 +629,7 @@ inline void nasal_vm::opr_callfh()
|
|||
// push new local scope
|
||||
func_stk.push(func_addr.func());
|
||||
auto& ref_func=*func_addr.func();
|
||||
gc.local.push_back(gc.gc_alloc(vm_vec));
|
||||
gc.local.push_back(gc.alloc(vm_vec));
|
||||
gc.local.back().vec()->elems=ref_func.local;
|
||||
// load parameters
|
||||
|
||||
|
@ -696,14 +648,12 @@ inline void nasal_vm::opr_callfh()
|
|||
--stack_top;// pop hash
|
||||
ret.push(pc);
|
||||
pc=ref_func.entry-1;
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_callb()
|
||||
{
|
||||
(++stack_top)[0]=(*builtin_func[imm[pc]].func)(gc.local.back().vec()->elems,gc);
|
||||
if(stack_top[0].type==vm_none)
|
||||
die("native function error.");
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_slcbegin()
|
||||
{
|
||||
|
@ -711,16 +661,14 @@ inline void nasal_vm::opr_slcbegin()
|
|||
// ----------------
|
||||
// | resource_vec | <-- stack_top[-1]
|
||||
// ----------------
|
||||
(++stack_top)[0]=gc.gc_alloc(vm_vec);
|
||||
(++stack_top)[0]=gc.alloc(vm_vec);
|
||||
if(stack_top[-1].type!=vm_vec)
|
||||
die("slcbegin: must slice a vector");
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_slcend()
|
||||
{
|
||||
stack_top[-1]=stack_top[0];
|
||||
--stack_top;
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_slc()
|
||||
{
|
||||
|
@ -729,7 +677,6 @@ inline void nasal_vm::opr_slc()
|
|||
if(res.type==vm_none)
|
||||
die("slc: index out of range:"+std::to_string(val.to_number()));
|
||||
stack_top[0].vec()->elems.push_back(res);
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_slc2()
|
||||
{
|
||||
|
@ -761,25 +708,21 @@ inline void nasal_vm::opr_slc2()
|
|||
else
|
||||
for(int i=num1;i<=num2;++i)
|
||||
aim.push_back(i>=0?ref[i]:ref[i+ref_size]);
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_mcallg()
|
||||
{
|
||||
mem_addr=gc.val_stack+imm[pc];
|
||||
(++stack_top)[0]=mem_addr[0];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_mcalll()
|
||||
{
|
||||
mem_addr=&(gc.local.back().vec()->elems[imm[pc]]);
|
||||
(++stack_top)[0]=mem_addr[0];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_mupval()
|
||||
{
|
||||
mem_addr=&func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff];
|
||||
(++stack_top)[0]=mem_addr[0];
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_mcallv()
|
||||
{
|
||||
|
@ -806,7 +749,6 @@ inline void nasal_vm::opr_mcallv()
|
|||
}
|
||||
else
|
||||
die("mcallv: cannot get memory space in other types");
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_mcallh()
|
||||
{
|
||||
|
@ -821,7 +763,6 @@ inline void nasal_vm::opr_mcallh()
|
|||
ref.elems[str]=gc.nil;
|
||||
mem_addr=ref.get_mem(str);
|
||||
}
|
||||
return;
|
||||
}
|
||||
inline void nasal_vm::opr_ret()
|
||||
{
|
||||
|
@ -834,12 +775,10 @@ inline void nasal_vm::opr_ret()
|
|||
func_stk.pop(); // pop function stack
|
||||
gc.local.pop_back(); // pop local scope
|
||||
pc=ret.top();ret.pop(); // fetch pc
|
||||
return;
|
||||
}
|
||||
void nasal_vm::run(
|
||||
const std::vector<opcode>& exec,
|
||||
const bool op_cnt)
|
||||
void nasal_vm::run(const nasal_codegen& gen,const nasal_import& linker,const bool opcnt)
|
||||
{
|
||||
init(gen.get_strs(),gen.get_nums(),linker.get_file());
|
||||
uint64_t count[op_exit+1]={0};
|
||||
const void* opr_table[]=
|
||||
{
|
||||
|
@ -864,13 +803,16 @@ void nasal_vm::run(
|
|||
&&mcallg, &&mcalll, &&mupval, &&mcallv,
|
||||
&&mcallh, &&ret, &&vmexit
|
||||
};
|
||||
bytecode=exec;
|
||||
std::vector<const void*> code;
|
||||
for(auto& i:exec)
|
||||
bytecode=gen.get_code();
|
||||
std::vector<const void*> codes;
|
||||
std::vector<uint32_t> imms;
|
||||
for(auto& i:bytecode)
|
||||
{
|
||||
code.push_back(opr_table[i.op]);
|
||||
imm.push_back(i.num);
|
||||
codes.push_back(opr_table[i.op]);
|
||||
imms.push_back(i.num);
|
||||
}
|
||||
auto code=codes.data();
|
||||
imm=imms.data();
|
||||
|
||||
// set canary and program counter
|
||||
auto& canary=gc.val_stack[STACK_MAX_DEPTH-1];
|
||||
|
@ -881,7 +823,7 @@ void nasal_vm::run(
|
|||
vmexit:
|
||||
if(canary.value.gcobj)
|
||||
stackoverflow();
|
||||
if(op_cnt)
|
||||
if(opcnt)
|
||||
{
|
||||
std::cout<<std::endl;
|
||||
for(int i=0;i<15;++i)
|
||||
|
@ -897,6 +839,7 @@ vmexit:
|
|||
count[index]=0;
|
||||
}
|
||||
}
|
||||
clear();
|
||||
return;
|
||||
// may cause stackoverflow
|
||||
#define exec_operand(op,num) {op();++count[num];if(!canary.value.gcobj)goto *code[++pc];goto vmexit;}
|
||||
|
|
|
@ -32,7 +32,7 @@ var a=func(){
|
|||
}
|
||||
|
||||
var b=func(){
|
||||
return Result().Err("unknown");
|
||||
return Result().Err("exception test");
|
||||
}
|
||||
|
||||
println(a().unwrap());
|
||||
|
|
|
@ -161,7 +161,7 @@ var lexer=func(file)
|
|||
ptr+=1;
|
||||
return;
|
||||
},
|
||||
main:func()
|
||||
compile:func()
|
||||
{
|
||||
while(ptr<len)
|
||||
{
|
||||
|
@ -185,9 +185,8 @@ var lexer=func(file)
|
|||
};
|
||||
}
|
||||
|
||||
var nasal_lexer=lexer("test/lexer.nas");
|
||||
nasal_lexer.main();
|
||||
var info="";
|
||||
foreach(var tok;nasal_lexer.get_token())
|
||||
info~=tok~' ';
|
||||
println(info);
|
||||
var lex=lexer("test/props.nas");
|
||||
lex.compile();
|
||||
foreach(var tok;lex.get_token())
|
||||
print(tok,' ');
|
||||
print('\n');
|
Loading…
Reference in New Issue