optimize code structure

This commit is contained in:
ValKmjolnir 2021-10-16 21:08:57 +08:00
parent 1b240b293e
commit d4a9412947
13 changed files with 882 additions and 923 deletions

View File

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

View File

@ -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
View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -32,7 +32,7 @@ var a=func(){
}
var b=func(){
return Result().Err("unknown");
return Result().Err("exception test");
}
println(a().unwrap());

View File

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