🐛 fix ast print bug & delete some macros
This commit is contained in:
parent
0c216e5f16
commit
aaccfbda11
9
main.cpp
9
main.cpp
|
@ -90,12 +90,11 @@ void execute(const string& file,const std::vector<string>& argv,const u32 cmd)
|
||||||
vm ctx;
|
vm ctx;
|
||||||
|
|
||||||
// lexer scans file to get tokens
|
// lexer scans file to get tokens
|
||||||
lex.scan(file);
|
lex.scan(file).chkerr();
|
||||||
|
|
||||||
// parser gets lexer's token list to compile
|
// parser gets lexer's token list to compile
|
||||||
parse.compile(lex);
|
parse.compile(lex).chkerr();
|
||||||
// linker gets parser's ast and load import files to this ast
|
// linker gets parser's ast and load import files to this ast
|
||||||
ld.link(parse,file,cmd&VM_DETAIL);
|
ld.link(parse,file,cmd&VM_DETAIL).chkerr();
|
||||||
// optimizer does simple optimization on ast
|
// optimizer does simple optimization on ast
|
||||||
if(cmd&VM_OPT)
|
if(cmd&VM_OPT)
|
||||||
optimize(parse.tree());
|
optimize(parse.tree());
|
||||||
|
@ -103,7 +102,7 @@ void execute(const string& file,const std::vector<string>& argv,const u32 cmd)
|
||||||
parse.print();
|
parse.print();
|
||||||
|
|
||||||
// code generator gets parser's ast and linker's import file list to generate code
|
// code generator gets parser's ast and linker's import file list to generate code
|
||||||
gen.compile(parse,ld);
|
gen.compile(parse,ld).chkerr();
|
||||||
if(cmd&VM_CODE)
|
if(cmd&VM_CODE)
|
||||||
gen.print();
|
gen.print();
|
||||||
|
|
||||||
|
|
28
nasal_ast.h
28
nasal_ast.h
|
@ -67,20 +67,20 @@ enum ast_node:u32
|
||||||
|
|
||||||
const char* ast_name[]=
|
const char* ast_name[]=
|
||||||
{
|
{
|
||||||
"null", "root", "block", "file",
|
"null", "root", "block", "file",
|
||||||
"nil", "num", "str", "id",
|
"nil", "num", "str", "id",
|
||||||
"func", "hash", "vec", "pair",
|
"func", "hash", "vec", "pair",
|
||||||
"call", "callh", "callv", "callf",
|
"call", "callh", "callv", "callf",
|
||||||
"subvec", "args", "default", "dynamic",
|
"subvec", "args", "default", "dynamic",
|
||||||
"and", "or", "=", "+=",
|
"and", "or", "=", "+=",
|
||||||
"-=", "*=", "/=" "~=",
|
"-=", "*=", "/=", "~=",
|
||||||
"==", "!=", "<", "<=",
|
"==", "!=", "<", "<=",
|
||||||
">", ">=", "+", "-",
|
">", ">=", "+", "-",
|
||||||
"*", "/", "~", "neg",
|
"*", "/", "~", "neg",
|
||||||
"!", "trino", "for", "forindex",
|
"!", "trino", "for", "forindex",
|
||||||
"foreach", "while", "iter", "cond",
|
"foreach", "while", "iter", "cond",
|
||||||
"if", "elsif", "else", "multi-id",
|
"if", "elsif", "else", "ltuple",
|
||||||
"tuple", "def", "multi-assign", "continue",
|
"tuple", "def", "massign", "continue",
|
||||||
"break", "return"
|
"break", "return"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -98,10 +98,10 @@ var builtin_fin(var* local,gc& ngc)
|
||||||
var val=local[1];
|
var val=local[1];
|
||||||
if(val.type!=vm_str)
|
if(val.type!=vm_str)
|
||||||
return nas_err("io::fin","\"filename\" must be string");
|
return nas_err("io::fin","\"filename\" must be string");
|
||||||
std::ifstream fin(val.str(),std::ios::binary);
|
std::ifstream in(val.str(),std::ios::binary);
|
||||||
std::stringstream rd;
|
std::stringstream rd;
|
||||||
if(!fin.fail())
|
if(!in.fail())
|
||||||
rd<<fin.rdbuf();
|
rd<<in.rdbuf();
|
||||||
return ngc.newstr(rd.str());
|
return ngc.newstr(rd.str());
|
||||||
}
|
}
|
||||||
var builtin_fout(var* local,gc& ngc)
|
var builtin_fout(var* local,gc& ngc)
|
||||||
|
@ -110,10 +110,10 @@ var builtin_fout(var* local,gc& ngc)
|
||||||
var str=local[2];
|
var str=local[2];
|
||||||
if(val.type!=vm_str)
|
if(val.type!=vm_str)
|
||||||
return nas_err("io::fout","\"filename\" must be string");
|
return nas_err("io::fout","\"filename\" must be string");
|
||||||
std::ofstream fout(val.str());
|
std::ofstream out(val.str());
|
||||||
if(fout.fail())
|
if(out.fail())
|
||||||
return nas_err("io::fout","cannot open <"+val.str()+">");
|
return nas_err("io::fout","cannot open <"+val.str()+">");
|
||||||
fout<<str;
|
out<<str;
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
var builtin_split(var* local,gc& ngc)
|
var builtin_split(var* local,gc& ngc)
|
||||||
|
@ -330,17 +330,15 @@ var builtin_time(var* local,gc& ngc)
|
||||||
{
|
{
|
||||||
var val=local[1];
|
var val=local[1];
|
||||||
if(val.type!=vm_num)
|
if(val.type!=vm_num)
|
||||||
return nas_err("time","\"begin_time\" must be number");
|
return nas_err("time","\"begin\" must be number");
|
||||||
time_t begin_time=(time_t)val.num();
|
time_t begin=(time_t)val.num();
|
||||||
return {vm_num,(f64)time(&begin_time)};
|
return {vm_num,(f64)time(&begin)};
|
||||||
}
|
}
|
||||||
var builtin_contains(var* local,gc& ngc)
|
var builtin_contains(var* local,gc& ngc)
|
||||||
{
|
{
|
||||||
var hash=local[1];
|
var hash=local[1];
|
||||||
var key=local[2];
|
var key=local[2];
|
||||||
if(hash.type!=vm_hash)
|
if(hash.type!=vm_hash || key.type!=vm_str)
|
||||||
return nas_err("contains","\"hash\" must be hash");
|
|
||||||
if(key.type!=vm_str)
|
|
||||||
return zero;
|
return zero;
|
||||||
return hash.hash().elems.count(key.str())?one:zero;
|
return hash.hash().elems.count(key.str())?one:zero;
|
||||||
}
|
}
|
||||||
|
@ -734,7 +732,7 @@ var builtin_pipe(var* local,gc& ngc)
|
||||||
res.vec().elems.push_back({vm_num,(f64)fd[1]});
|
res.vec().elems.push_back({vm_num,(f64)fd[1]});
|
||||||
return res;
|
return res;
|
||||||
#endif
|
#endif
|
||||||
return nas_err("pipe","not supported for windows");
|
return nas_err("pipe","not supported");
|
||||||
}
|
}
|
||||||
var builtin_fork(var* local,gc& ngc)
|
var builtin_fork(var* local,gc& ngc)
|
||||||
{
|
{
|
||||||
|
@ -744,7 +742,7 @@ var builtin_fork(var* local,gc& ngc)
|
||||||
return nas_err("fork","failed to fork a process");
|
return nas_err("fork","failed to fork a process");
|
||||||
return {vm_num,(f64)res};
|
return {vm_num,(f64)res};
|
||||||
#endif
|
#endif
|
||||||
return nas_err("fork","not supported for windows");
|
return nas_err("fork","not supported");
|
||||||
}
|
}
|
||||||
var builtin_waitpid(var* local,gc& ngc)
|
var builtin_waitpid(var* local,gc& ngc)
|
||||||
{
|
{
|
||||||
|
@ -760,7 +758,7 @@ var builtin_waitpid(var* local,gc& ngc)
|
||||||
vec.vec().elems.push_back({vm_num,(f64)status});
|
vec.vec().elems.push_back({vm_num,(f64)status});
|
||||||
return vec;
|
return vec;
|
||||||
#endif
|
#endif
|
||||||
return nas_err("waitpid","not supported for windows");
|
return nas_err("waitpid","not supported");
|
||||||
}
|
}
|
||||||
void obj_dir_dtor(void* ptr)
|
void obj_dir_dtor(void* ptr)
|
||||||
{
|
{
|
||||||
|
@ -1032,18 +1030,18 @@ var builtin_md5(var* local,gc& ngc)
|
||||||
|
|
||||||
var builtin_cocreate(var* local,gc& ngc)
|
var builtin_cocreate(var* local,gc& ngc)
|
||||||
{
|
{
|
||||||
// +-----------------+
|
// +-------------+
|
||||||
// | old pc | <- top[0]
|
// | old pc | <- top[0]
|
||||||
// +-----------------+
|
// +-------------+
|
||||||
// | old localr | <- top[-1]
|
// | old localr | <- top[-1]
|
||||||
// +-----------------+
|
// +-------------+
|
||||||
// | old upvalr | <- top[-2]
|
// | old upvalr | <- top[-2]
|
||||||
// +-----------------+
|
// +-------------+
|
||||||
// | local scope |
|
// | local scope |
|
||||||
// | ... |
|
// | ... |
|
||||||
// +-----------------+ <- local pointer stored in localr
|
// +-------------+ <- local pointer stored in localr
|
||||||
// | old funcr | <- old function stored in funcr
|
// | old funcr | <- old function stored in funcr
|
||||||
// +-----------------+
|
// +-------------+
|
||||||
var func=local[1];
|
var func=local[1];
|
||||||
if(func.type!=vm_func)
|
if(func.type!=vm_func)
|
||||||
return nas_err("coroutine::create","must use a function to create coroutine");
|
return nas_err("coroutine::create","must use a function to create coroutine");
|
||||||
|
@ -1124,7 +1122,15 @@ var builtin_logtime(var* local,gc& ngc)
|
||||||
time_t t=time(nullptr);
|
time_t t=time(nullptr);
|
||||||
tm* tm_t=localtime(&t);
|
tm* tm_t=localtime(&t);
|
||||||
char s[128];
|
char s[128];
|
||||||
sprintf(s,"%d-%.2d-%.2d %.2d:%.2d:%.2d",tm_t->tm_year+1900,tm_t->tm_mon+1,tm_t->tm_mday,tm_t->tm_hour,tm_t->tm_min,tm_t->tm_sec);
|
sprintf(
|
||||||
|
s,"%d-%.2d-%.2d %.2d:%.2d:%.2d",
|
||||||
|
tm_t->tm_year+1900,
|
||||||
|
tm_t->tm_mon+1,
|
||||||
|
tm_t->tm_mday,
|
||||||
|
tm_t->tm_hour,
|
||||||
|
tm_t->tm_min,
|
||||||
|
tm_t->tm_sec
|
||||||
|
);
|
||||||
return ngc.newstr(s);
|
return ngc.newstr(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -264,7 +264,7 @@ private:
|
||||||
void singleop(const u32);
|
void singleop(const u32);
|
||||||
public:
|
public:
|
||||||
codegen(error& e):fileindex(0),err(e),file(nullptr){}
|
codegen(error& e):fileindex(0),err(e),file(nullptr){}
|
||||||
void compile(const parse&,const linker&);
|
const error& compile(const parse&,const linker&);
|
||||||
void print();
|
void print();
|
||||||
const std::vector<string>& strs() const {return str_res;}
|
const std::vector<string>& strs() const {return str_res;}
|
||||||
const std::vector<f64>& nums() const {return num_res;}
|
const std::vector<f64>& nums() const {return num_res;}
|
||||||
|
@ -1235,7 +1235,7 @@ void codegen::ret_gen(const ast& node)
|
||||||
gen(op_ret,0,node.line());
|
gen(op_ret,0,node.line());
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::compile(const parse& parse,const linker& import)
|
const error& codegen::compile(const parse& parse,const linker& import)
|
||||||
{
|
{
|
||||||
fileindex=0;
|
fileindex=0;
|
||||||
file=import.filelist().data();
|
file=import.filelist().data();
|
||||||
|
@ -1248,7 +1248,7 @@ void codegen::compile(const parse& parse,const linker& import)
|
||||||
die("too many global variants: "+std::to_string(global.size()),0,0);
|
die("too many global variants: "+std::to_string(global.size()),0,0);
|
||||||
if(code.size()>0xffffffff)
|
if(code.size()>0xffffffff)
|
||||||
die("too large generated bytecode file: "+std::to_string(code.size()),0,0);
|
die("too large generated bytecode file: "+std::to_string(code.size()),0,0);
|
||||||
err.chkerr();
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void codegen::singleop(const u32 index)
|
void codegen::singleop(const u32 index)
|
||||||
|
|
41
nasal_err.h
41
nasal_err.h
|
@ -71,7 +71,7 @@ std::ostream& reset(std::ostream& s)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
class fstreamline
|
class flstream
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
string file;
|
string file;
|
||||||
|
@ -100,7 +100,7 @@ public:
|
||||||
usize size(){return res.size();}
|
usize size(){return res.size();}
|
||||||
};
|
};
|
||||||
|
|
||||||
class error:public fstreamline
|
class error:public flstream
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
u32 cnt;
|
u32 cnt;
|
||||||
|
@ -115,26 +115,29 @@ public:
|
||||||
void err(const string& stage,const string& info)
|
void err(const string& stage,const string& info)
|
||||||
{
|
{
|
||||||
++cnt;
|
++cnt;
|
||||||
std::cerr<<red<<stage<<": "
|
std::cerr
|
||||||
<<white<<info<<reset<<"\n\n";
|
<<red<<stage<<": "
|
||||||
|
<<white<<info<<reset<<"\n\n";
|
||||||
}
|
}
|
||||||
void err(const string& stage,u32 line,u32 col,const string& info)
|
void err(const string& stage,u32 line,u32 col,const string& info)
|
||||||
{
|
{
|
||||||
++cnt;
|
++cnt;
|
||||||
const string& code=res[line-1];
|
const string& code=res[line-1];
|
||||||
const string iden=identation(std::to_string(line).length());
|
const string iden=identation(std::to_string(line).length());
|
||||||
std::cerr<<red<<stage<<": "
|
std::cerr
|
||||||
<<white<<info<<reset<<"\n"
|
<<red<<stage<<": "
|
||||||
<<cyan<<" --> "<<reset
|
<<white<<info<<reset<<"\n"
|
||||||
<<orange<<file<<":"<<line<<":"<<col<<"\n";
|
<<cyan<<" --> "<<reset
|
||||||
|
<<orange<<file<<":"<<line<<":"<<col<<"\n";
|
||||||
if(!line)
|
if(!line)
|
||||||
{
|
{
|
||||||
std::cerr<<"\n";
|
std::cerr<<"\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::cerr<<cyan<<iden<<" | "<<reset<<"\n"
|
std::cerr
|
||||||
<<cyan<<line<<" | "<<reset<<code<<"\n"
|
<<cyan<<iden<<" | "<<reset<<"\n"
|
||||||
<<cyan<<iden<<" | "<<reset;
|
<<cyan<<line<<" | "<<reset<<code<<"\n"
|
||||||
|
<<cyan<<iden<<" | "<<reset;
|
||||||
for(i32 i=0;i<(i32)col-1;++i)
|
for(i32 i=0;i<(i32)col-1;++i)
|
||||||
std::cerr<<char(" \t"[code[i]=='\t']);
|
std::cerr<<char(" \t"[code[i]=='\t']);
|
||||||
std::cerr<<red<<"^ "<<info<<reset<<"\n\n";
|
std::cerr<<red<<"^ "<<info<<reset<<"\n\n";
|
||||||
|
@ -143,18 +146,20 @@ public:
|
||||||
{
|
{
|
||||||
++cnt;
|
++cnt;
|
||||||
const string iden=identation(std::to_string(line).length());
|
const string iden=identation(std::to_string(line).length());
|
||||||
std::cerr<<red<<stage<<": "
|
std::cerr
|
||||||
<<white<<info<<reset<<"\n"
|
<<red<<stage<<": "
|
||||||
<<cyan<<" --> "<<reset
|
<<white<<info<<reset<<"\n"
|
||||||
<<orange<<file<<":"<<line<<"\n";
|
<<cyan<<" --> "<<reset
|
||||||
|
<<orange<<file<<":"<<line<<"\n";
|
||||||
if(!line)
|
if(!line)
|
||||||
{
|
{
|
||||||
std::cerr<<"\n";
|
std::cerr<<"\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::cerr<<cyan<<iden<<" | "<<reset<<"\n"
|
std::cerr
|
||||||
<<cyan<<line<<" | "<<reset<<res[line-1]<<"\n"
|
<<cyan<<iden<<" | "<<reset<<"\n"
|
||||||
<<cyan<<iden<<" | "<<reset<<"\n\n";
|
<<cyan<<line<<" | "<<reset<<res[line-1]<<"\n"
|
||||||
|
<<cyan<<iden<<" | "<<reset<<"\n\n";
|
||||||
}
|
}
|
||||||
void chkerr() const {if(cnt)std::exit(1);}
|
void chkerr() const {if(cnt)std::exit(1);}
|
||||||
};
|
};
|
||||||
|
|
12
nasal_gc.h
12
nasal_gc.h
|
@ -108,9 +108,9 @@ struct nas_vec
|
||||||
|
|
||||||
nas_vec():printed(false){}
|
nas_vec():printed(false){}
|
||||||
friend std::ostream& operator<<(std::ostream&,nas_vec&);
|
friend std::ostream& operator<<(std::ostream&,nas_vec&);
|
||||||
usize size(){return elems.size();}
|
usize size(){return elems.size();}
|
||||||
var get_val(const i32);
|
var get_val(const i32);
|
||||||
var* get_mem(const i32);
|
var* get_mem(const i32);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_hash
|
struct nas_hash
|
||||||
|
@ -120,9 +120,9 @@ struct nas_hash
|
||||||
|
|
||||||
nas_hash():printed(false){}
|
nas_hash():printed(false){}
|
||||||
friend std::ostream& operator<<(std::ostream&,nas_hash&);
|
friend std::ostream& operator<<(std::ostream&,nas_hash&);
|
||||||
usize size(){return elems.size();}
|
usize size(){return elems.size();}
|
||||||
var get_val(const string&);
|
var get_val(const string&);
|
||||||
var* get_mem(const string&);
|
var* get_mem(const string&);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_func
|
struct nas_func
|
||||||
|
|
|
@ -30,7 +30,7 @@ private:
|
||||||
ast load(ast&,u16);
|
ast load(ast&,u16);
|
||||||
public:
|
public:
|
||||||
linker(error&);
|
linker(error&);
|
||||||
void link(parse&,const string&,bool);
|
const error& link(parse&,const string&,bool);
|
||||||
const std::vector<string>& filelist() const {return files;}
|
const std::vector<string>& filelist() const {return files;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@ ast linker::load(ast& root,u16 fileindex)
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
void linker::link(parse& parse,const string& self,bool spath=false)
|
const error& linker::link(parse& parse,const string& self,bool spath=false)
|
||||||
{
|
{
|
||||||
show_path=spath;
|
show_path=spath;
|
||||||
// initializing
|
// initializing
|
||||||
|
@ -221,5 +221,5 @@ void linker::link(parse& parse,const string& self,bool spath=false)
|
||||||
// scan root and import files,then generate a new ast and return to import_ast
|
// scan root and import files,then generate a new ast and return to import_ast
|
||||||
// the main file's index is 0
|
// the main file's index is 0
|
||||||
parse.tree()=load(parse.tree(),0);
|
parse.tree()=load(parse.tree(),0);
|
||||||
err.chkerr();
|
return err;
|
||||||
}
|
}
|
||||||
|
|
150
nasal_lexer.h
150
nasal_lexer.h
|
@ -67,12 +67,8 @@ struct token
|
||||||
u32 col;
|
u32 col;
|
||||||
u32 type;
|
u32 type;
|
||||||
string str;
|
string str;
|
||||||
token(u32 l=0,u32 c=0,u32 t=tok_null,const string& s=""):str(s)
|
token(u32 l=0,u32 c=0,u32 t=tok_null,const string& s="")
|
||||||
{
|
:line(l),col(c),type(t),str(s){}
|
||||||
line=l;
|
|
||||||
col=c;
|
|
||||||
type=t;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class lexer
|
class lexer
|
||||||
|
@ -85,54 +81,55 @@ private:
|
||||||
error& err;
|
error& err;
|
||||||
std::vector<token> toks;
|
std::vector<token> toks;
|
||||||
std::unordered_map<string,u32> typetbl {
|
std::unordered_map<string,u32> typetbl {
|
||||||
{"for" ,tok_for },
|
{"for" ,tok_for },
|
||||||
{"forindex",tok_forindex },
|
{"forindex",tok_forindex},
|
||||||
{"foreach" ,tok_foreach },
|
{"foreach" ,tok_foreach },
|
||||||
{"while" ,tok_while },
|
{"while" ,tok_while },
|
||||||
{"var" ,tok_var },
|
{"var" ,tok_var },
|
||||||
{"func" ,tok_func },
|
{"func" ,tok_func },
|
||||||
{"break" ,tok_break },
|
{"break" ,tok_break },
|
||||||
{"continue",tok_continue },
|
{"continue",tok_continue},
|
||||||
{"return" ,tok_ret },
|
{"return" ,tok_ret },
|
||||||
{"if" ,tok_if },
|
{"if" ,tok_if },
|
||||||
{"elsif" ,tok_elsif },
|
{"elsif" ,tok_elsif },
|
||||||
{"else" ,tok_else },
|
{"else" ,tok_else },
|
||||||
{"nil" ,tok_nil },
|
{"nil" ,tok_nil },
|
||||||
{"(" ,tok_lcurve },
|
{"(" ,tok_lcurve },
|
||||||
{")" ,tok_rcurve },
|
{")" ,tok_rcurve },
|
||||||
{"[" ,tok_lbracket },
|
{"[" ,tok_lbracket},
|
||||||
{"]" ,tok_rbracket },
|
{"]" ,tok_rbracket},
|
||||||
{"{" ,tok_lbrace },
|
{"{" ,tok_lbrace },
|
||||||
{"}" ,tok_rbrace },
|
{"}" ,tok_rbrace },
|
||||||
{";" ,tok_semi },
|
{";" ,tok_semi },
|
||||||
{"and" ,tok_and },
|
{"and" ,tok_and },
|
||||||
{"or" ,tok_or },
|
{"or" ,tok_or },
|
||||||
{"," ,tok_comma },
|
{"," ,tok_comma },
|
||||||
{"." ,tok_dot },
|
{"." ,tok_dot },
|
||||||
{"..." ,tok_ellipsis },
|
{"..." ,tok_ellipsis},
|
||||||
{"?" ,tok_quesmark },
|
{"?" ,tok_quesmark},
|
||||||
{":" ,tok_colon },
|
{":" ,tok_colon },
|
||||||
{"+" ,tok_add },
|
{"+" ,tok_add },
|
||||||
{"-" ,tok_sub },
|
{"-" ,tok_sub },
|
||||||
{"*" ,tok_mult },
|
{"*" ,tok_mult },
|
||||||
{"/" ,tok_div },
|
{"/" ,tok_div },
|
||||||
{"~" ,tok_link },
|
{"~" ,tok_link },
|
||||||
{"!" ,tok_not },
|
{"!" ,tok_not },
|
||||||
{"=" ,tok_eq },
|
{"=" ,tok_eq },
|
||||||
{"+=" ,tok_addeq },
|
{"+=" ,tok_addeq },
|
||||||
{"-=" ,tok_subeq },
|
{"-=" ,tok_subeq },
|
||||||
{"*=" ,tok_multeq },
|
{"*=" ,tok_multeq },
|
||||||
{"/=" ,tok_diveq },
|
{"/=" ,tok_diveq },
|
||||||
{"~=" ,tok_lnkeq },
|
{"~=" ,tok_lnkeq },
|
||||||
{"==" ,tok_cmpeq },
|
{"==" ,tok_cmpeq },
|
||||||
{"!=" ,tok_neq },
|
{"!=" ,tok_neq },
|
||||||
{"<" ,tok_less },
|
{"<" ,tok_less },
|
||||||
{"<=" ,tok_leq },
|
{"<=" ,tok_leq },
|
||||||
{">" ,tok_grt },
|
{">" ,tok_grt },
|
||||||
{">=" ,tok_geq }
|
{">=" ,tok_geq }
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 get_type(const string&);
|
u32 get_type(const string&);
|
||||||
|
bool skip(char);
|
||||||
bool is_id(char);
|
bool is_id(char);
|
||||||
bool is_hex(char);
|
bool is_hex(char);
|
||||||
bool is_oct(char);
|
bool is_oct(char);
|
||||||
|
@ -140,22 +137,23 @@ private:
|
||||||
bool is_str(char);
|
bool is_str(char);
|
||||||
bool is_single_opr(char);
|
bool is_single_opr(char);
|
||||||
bool is_calc_opr(char);
|
bool is_calc_opr(char);
|
||||||
void die(const string& info){err.err("lexer",line,column,info);}
|
void die(const string&);
|
||||||
void open(const string&);
|
void open(const string&);
|
||||||
string utf8_gen();
|
string utf8_gen();
|
||||||
string id_gen();
|
string id_gen();
|
||||||
string num_gen();
|
string num_gen();
|
||||||
string str_gen();
|
string str_gen();
|
||||||
public:
|
public:
|
||||||
lexer(error& e):
|
lexer(error& e):line(1),column(0),ptr(0),res(""),err(e){}
|
||||||
line(1),column(0),
|
const error& scan(const string&);
|
||||||
ptr(0),res(""),
|
|
||||||
err(e){}
|
|
||||||
void scan(const string&);
|
|
||||||
void print();
|
|
||||||
const std::vector<token>& result() const {return toks;}
|
const std::vector<token>& result() const {return toks;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool lexer::skip(char c)
|
||||||
|
{
|
||||||
|
return c==' '||c=='\n'||c=='\t'||c=='\r'||c==0;
|
||||||
|
}
|
||||||
|
|
||||||
bool lexer::is_id(char c)
|
bool lexer::is_id(char c)
|
||||||
{
|
{
|
||||||
return (c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||(c<0);
|
return (c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||(c<0);
|
||||||
|
@ -194,7 +192,16 @@ bool lexer::is_single_opr(char c)
|
||||||
|
|
||||||
bool lexer::is_calc_opr(char c)
|
bool lexer::is_calc_opr(char c)
|
||||||
{
|
{
|
||||||
return c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~';
|
return (
|
||||||
|
c=='='||c=='+'||c=='-'||c=='*'||
|
||||||
|
c=='!'||c=='/'||c=='<'||c=='>'||
|
||||||
|
c=='~'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lexer::die(const string& info)
|
||||||
|
{
|
||||||
|
err.err("lexer",line,column,info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lexer::open(const string& file)
|
void lexer::open(const string& file)
|
||||||
|
@ -205,21 +212,19 @@ void lexer::open(const string& file)
|
||||||
err.err("lexer","<"+file+"> is not a regular file");
|
err.err("lexer","<"+file+"> is not a regular file");
|
||||||
err.chkerr();
|
err.chkerr();
|
||||||
}
|
}
|
||||||
std::ifstream fin(file,std::ios::binary);
|
std::ifstream in(file,std::ios::binary);
|
||||||
if(fin.fail())
|
if(in.fail())
|
||||||
err.err("lexer","failed to open <"+file+">");
|
err.err("lexer","failed to open <"+file+">");
|
||||||
else
|
else
|
||||||
err.load(file);
|
err.load(file);
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss<<fin.rdbuf();
|
ss<<in.rdbuf();
|
||||||
res=ss.str();
|
res=ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 lexer::get_type(const string& str)
|
u32 lexer::get_type(const string& str)
|
||||||
{
|
{
|
||||||
if(typetbl.count(str))
|
return typetbl.count(str)?typetbl.at(str):tok_null;
|
||||||
return typetbl.at(str);
|
|
||||||
return tok_null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string lexer::utf8_gen()
|
string lexer::utf8_gen()
|
||||||
|
@ -241,7 +246,8 @@ string lexer::utf8_gen()
|
||||||
string utf_info="0x"+chrhex(tmp[0]);
|
string utf_info="0x"+chrhex(tmp[0]);
|
||||||
for(u32 i=1;i<tmp.size();++i)
|
for(u32 i=1;i<tmp.size();++i)
|
||||||
utf_info+=" 0x"+chrhex(tmp[i]);
|
utf_info+=" 0x"+chrhex(tmp[i]);
|
||||||
die("invalid utf-8 character `"+utf_info+"`, make sure it is utf8-text file");
|
die("invalid utf-8 <"+utf_info+">");
|
||||||
|
err.err("lexer","fatal error occurred, stop");
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
str+=tmp;
|
str+=tmp;
|
||||||
|
@ -385,7 +391,7 @@ string lexer::str_gen()
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lexer::scan(const string& file)
|
const error& lexer::scan(const string& file)
|
||||||
{
|
{
|
||||||
line=1;
|
line=1;
|
||||||
column=0;
|
column=0;
|
||||||
|
@ -395,7 +401,7 @@ void lexer::scan(const string& file)
|
||||||
string str;
|
string str;
|
||||||
while(ptr<res.size())
|
while(ptr<res.size())
|
||||||
{
|
{
|
||||||
while(ptr<res.size() && (res[ptr]==' ' || res[ptr]=='\n' || res[ptr]=='\t' || res[ptr]=='\r' || res[ptr]==0))
|
while(ptr<res.size() && skip(res[ptr]))
|
||||||
{
|
{
|
||||||
// these characters will be ignored, and '\n' will cause ++line
|
// these characters will be ignored, and '\n' will cause ++line
|
||||||
++column;
|
++column;
|
||||||
|
@ -461,11 +467,5 @@ void lexer::scan(const string& file)
|
||||||
}
|
}
|
||||||
toks.push_back({line,column,tok_eof,"<eof>"});
|
toks.push_back({line,column,tok_eof,"<eof>"});
|
||||||
res="";
|
res="";
|
||||||
err.chkerr();
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
void lexer::print()
|
|
||||||
{
|
|
||||||
for(auto& tok:toks)
|
|
||||||
std::cout<<"("<<tok.line<<" | "<<rawstr(tok.str,32)<<")\n";
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
class parse
|
class parse
|
||||||
{
|
{
|
||||||
#define err_line (toks[ptr].line)
|
#define err_line (toks[ptr].line)
|
||||||
#define is_call(type) ((type)==tok_lcurve || (type)==tok_lbracket || (type)==tok_dot)
|
|
||||||
private:
|
private:
|
||||||
u32 ptr;
|
u32 ptr;
|
||||||
u32 in_func; // count function block
|
u32 in_func; // count function block
|
||||||
|
@ -97,10 +96,12 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
void die(u32,string,bool);
|
void die(u32,string,bool);
|
||||||
|
void next() {++ptr;};
|
||||||
void match(u32 type,const char* info=nullptr);
|
void match(u32 type,const char* info=nullptr);
|
||||||
bool lookahead(u32 type);
|
bool lookahead(u32);
|
||||||
|
bool is_call(u32);
|
||||||
bool check_comma(const u32*);
|
bool check_comma(const u32*);
|
||||||
bool check_multi_scalar();
|
bool check_tuple();
|
||||||
bool check_func_end(const ast&);
|
bool check_func_end(const ast&);
|
||||||
bool check_special_call();
|
bool check_special_call();
|
||||||
bool need_semi_check(const ast&);
|
bool need_semi_check(const ast&);
|
||||||
|
@ -152,11 +153,11 @@ public:
|
||||||
toks(nullptr),root(0,0,ast_root),
|
toks(nullptr),root(0,0,ast_root),
|
||||||
err(e){}
|
err(e){}
|
||||||
void print(){root.print_tree();}
|
void print(){root.print_tree();}
|
||||||
void compile(const lexer&);
|
const error& compile(const lexer&);
|
||||||
ast& tree(){return root;}
|
ast& tree(){return root;}
|
||||||
const ast& tree() const {return root;}
|
const ast& tree() const {return root;}
|
||||||
};
|
};
|
||||||
void parse::compile(const lexer& lexer)
|
const error& parse::compile(const lexer& lexer)
|
||||||
{
|
{
|
||||||
toks=lexer.result().data();
|
toks=lexer.result().data();
|
||||||
ptr=in_func=in_loop=0;
|
ptr=in_func=in_loop=0;
|
||||||
|
@ -171,7 +172,7 @@ void parse::compile(const lexer& lexer)
|
||||||
else if(need_semi_check(root.child().back()) && !lookahead(tok_eof))
|
else if(need_semi_check(root.child().back()) && !lookahead(tok_eof))
|
||||||
die(err_line,"expected \";\"",true);
|
die(err_line,"expected \";\"",true);
|
||||||
}
|
}
|
||||||
err.chkerr();
|
return err;
|
||||||
}
|
}
|
||||||
void parse::die(u32 line,string info,bool report_prev=false)
|
void parse::die(u32 line,string info,bool report_prev=false)
|
||||||
{
|
{
|
||||||
|
@ -205,12 +206,16 @@ void parse::match(u32 type,const char* info)
|
||||||
}
|
}
|
||||||
if(lookahead(tok_eof))
|
if(lookahead(tok_eof))
|
||||||
return;
|
return;
|
||||||
++ptr;
|
next();
|
||||||
}
|
}
|
||||||
bool parse::lookahead(u32 type)
|
bool parse::lookahead(u32 type)
|
||||||
{
|
{
|
||||||
return toks[ptr].type==type;
|
return toks[ptr].type==type;
|
||||||
}
|
}
|
||||||
|
bool parse::is_call(u32 type)
|
||||||
|
{
|
||||||
|
return type==tok_lcurve || type==tok_lbracket || type==tok_dot;
|
||||||
|
}
|
||||||
bool parse::check_comma(const u32* panic_set)
|
bool parse::check_comma(const u32* panic_set)
|
||||||
{
|
{
|
||||||
for(u32 i=0;panic_set[i];++i)
|
for(u32 i=0;panic_set[i];++i)
|
||||||
|
@ -221,7 +226,7 @@ bool parse::check_comma(const u32* panic_set)
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool parse::check_multi_scalar()
|
bool parse::check_tuple()
|
||||||
{
|
{
|
||||||
u32 check_ptr=ptr,curve=1,bracket=0,brace=0;
|
u32 check_ptr=ptr,curve=1,bracket=0,brace=0;
|
||||||
while(toks[++check_ptr].type!=tok_eof && curve)
|
while(toks[++check_ptr].type!=tok_eof && curve)
|
||||||
|
@ -486,7 +491,7 @@ ast parse::lcurve_expr()
|
||||||
{
|
{
|
||||||
if(toks[ptr+1].type==tok_var)
|
if(toks[ptr+1].type==tok_var)
|
||||||
return definition();
|
return definition();
|
||||||
return check_multi_scalar()?multi_assgin():calc();
|
return check_tuple()?multi_assgin():calc();
|
||||||
}
|
}
|
||||||
ast parse::expr()
|
ast parse::expr()
|
||||||
{
|
{
|
||||||
|
@ -519,7 +524,7 @@ ast parse::expr()
|
||||||
case tok_semi: break;
|
case tok_semi: break;
|
||||||
default:
|
default:
|
||||||
die(err_line,"incorrect token <"+toks[ptr].str+">");
|
die(err_line,"incorrect token <"+toks[ptr].str+">");
|
||||||
++ptr;
|
next();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return {toks[ptr].line,toks[ptr].col,ast_null};
|
return {toks[ptr].line,toks[ptr].col,ast_null};
|
||||||
|
@ -808,7 +813,7 @@ ast parse::definition()
|
||||||
node.add(incurve_def());
|
node.add(incurve_def());
|
||||||
match(tok_eq);
|
match(tok_eq);
|
||||||
if(lookahead(tok_lcurve))
|
if(lookahead(tok_lcurve))
|
||||||
node.add(check_multi_scalar()?multi_scalar(false):calc());
|
node.add(check_tuple()?multi_scalar(false):calc());
|
||||||
else
|
else
|
||||||
node.add(calc());
|
node.add(calc());
|
||||||
if(node[0].type()==ast_id && node[1].type()==ast_tuple)
|
if(node[0].type()==ast_id && node[1].type()==ast_tuple)
|
||||||
|
@ -889,7 +894,7 @@ ast parse::multi_assgin()
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if(lookahead(tok_lcurve))
|
if(lookahead(tok_lcurve))
|
||||||
node.add(check_multi_scalar()?multi_scalar(false):calc());
|
node.add(check_tuple()?multi_scalar(false):calc());
|
||||||
else
|
else
|
||||||
node.add(calc());
|
node.add(calc());
|
||||||
if(node[1].type()==ast_tuple
|
if(node[1].type()==ast_tuple
|
||||||
|
|
22
nasal_vm.h
22
nasal_vm.h
|
@ -49,7 +49,7 @@ protected:
|
||||||
void die(const string&);
|
void die(const string&);
|
||||||
#define vm_error(info) {die(info);return;}
|
#define vm_error(info) {die(info);return;}
|
||||||
/* vm calculation functions*/
|
/* vm calculation functions*/
|
||||||
bool condition(var);
|
bool cond(var&);
|
||||||
/* vm operands */
|
/* vm operands */
|
||||||
void o_intg();
|
void o_intg();
|
||||||
void o_intl();
|
void o_intl();
|
||||||
|
@ -232,8 +232,8 @@ void vm::stackinfo(const u32 limit=10)
|
||||||
{
|
{
|
||||||
/* bytecode[0].num is the global size */
|
/* bytecode[0].num is the global size */
|
||||||
const u32 gsize=ngc.stack==stack?bytecode[0].num:0;
|
const u32 gsize=ngc.stack==stack?bytecode[0].num:0;
|
||||||
var* t=top;
|
var* t=top;
|
||||||
var* bottom=ngc.stack+gsize;
|
var* bottom=ngc.stack+gsize;
|
||||||
std::cout<<"vm stack (0x"<<std::hex<<(u64)bottom<<std::dec
|
std::cout<<"vm stack (0x"<<std::hex<<(u64)bottom<<std::dec
|
||||||
<<" <sp+"<<gsize<<">, limit "<<limit<<", total "
|
<<" <sp+"<<gsize<<">, limit "<<limit<<", total "
|
||||||
<<(t<bottom? 0:(i64)(t-bottom+1))<<")\n";
|
<<(t<bottom? 0:(i64)(t-bottom+1))<<")\n";
|
||||||
|
@ -324,7 +324,7 @@ void vm::die(const string& str)
|
||||||
top[0]=nil;
|
top[0]=nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline bool vm::condition(var val)
|
inline bool vm::cond(var& val)
|
||||||
{
|
{
|
||||||
if(val.type==vm_num)
|
if(val.type==vm_num)
|
||||||
return val.num();
|
return val.num();
|
||||||
|
@ -578,12 +578,12 @@ inline void vm::o_jmp()
|
||||||
}
|
}
|
||||||
inline void vm::o_jt()
|
inline void vm::o_jt()
|
||||||
{
|
{
|
||||||
if(condition(top[0]))
|
if(cond(top[0]))
|
||||||
pc=imm[pc]-1;
|
pc=imm[pc]-1;
|
||||||
}
|
}
|
||||||
inline void vm::o_jf()
|
inline void vm::o_jf()
|
||||||
{
|
{
|
||||||
if(!condition(top[0]))
|
if(!cond(top[0]))
|
||||||
pc=imm[pc]-1;
|
pc=imm[pc]-1;
|
||||||
--top;
|
--top;
|
||||||
}
|
}
|
||||||
|
@ -635,7 +635,7 @@ inline void vm::o_callv()
|
||||||
{
|
{
|
||||||
top[0]=vec.vec().get_val(val.tonum());
|
top[0]=vec.vec().get_val(val.tonum());
|
||||||
if(top[0].type==vm_none)
|
if(top[0].type==vm_none)
|
||||||
vm_error("index out of range:"+std::to_string(val.tonum()));
|
vm_error("out of range:"+std::to_string(val.tonum()));
|
||||||
}
|
}
|
||||||
else if(vec.type==vm_hash)
|
else if(vec.type==vm_hash)
|
||||||
{
|
{
|
||||||
|
@ -653,7 +653,7 @@ inline void vm::o_callv()
|
||||||
i32 num=val.tonum();
|
i32 num=val.tonum();
|
||||||
i32 len=str.length();
|
i32 len=str.length();
|
||||||
if(num<-len || num>=len)
|
if(num<-len || num>=len)
|
||||||
vm_error("index out of range:"+std::to_string(val.tonum()));
|
vm_error("out of range:"+std::to_string(val.tonum()));
|
||||||
top[0]={vm_num,f64((u8)str[num>=0? num:num+len])};
|
top[0]={vm_num,f64((u8)str[num>=0? num:num+len])};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -667,7 +667,7 @@ inline void vm::o_callvi()
|
||||||
// cannot use operator[],because this may cause overflow
|
// cannot use operator[],because this may cause overflow
|
||||||
(++top)[0]=val.vec().get_val(imm[pc]);
|
(++top)[0]=val.vec().get_val(imm[pc]);
|
||||||
if(top[0].type==vm_none)
|
if(top[0].type==vm_none)
|
||||||
vm_error("index out of range:"+std::to_string(imm[pc]));
|
vm_error("out of range:"+std::to_string(imm[pc]));
|
||||||
}
|
}
|
||||||
inline void vm::o_callh()
|
inline void vm::o_callh()
|
||||||
{
|
{
|
||||||
|
@ -796,7 +796,7 @@ inline void vm::o_slc()
|
||||||
var val=(top--)[0];
|
var val=(top--)[0];
|
||||||
var res=top[-1].vec().get_val(val.tonum());
|
var res=top[-1].vec().get_val(val.tonum());
|
||||||
if(res.type==vm_none)
|
if(res.type==vm_none)
|
||||||
vm_error("index out of range:"+std::to_string(val.tonum()));
|
vm_error("out of range:"+std::to_string(val.tonum()));
|
||||||
top[0].vec().elems.push_back(res);
|
top[0].vec().elems.push_back(res);
|
||||||
}
|
}
|
||||||
inline void vm::o_slc2()
|
inline void vm::o_slc2()
|
||||||
|
@ -856,7 +856,7 @@ inline void vm::o_mcallv()
|
||||||
{
|
{
|
||||||
memr=vec.vec().get_mem(val.tonum());
|
memr=vec.vec().get_mem(val.tonum());
|
||||||
if(!memr)
|
if(!memr)
|
||||||
vm_error("index out of range:"+std::to_string(val.tonum()));
|
vm_error("out of range:"+std::to_string(val.tonum()));
|
||||||
}else if(vec.type==vm_hash) // do mcallh but use the mcallv way
|
}else if(vec.type==vm_hash) // do mcallh but use the mcallv way
|
||||||
{
|
{
|
||||||
if(val.type!=vm_str)
|
if(val.type!=vm_str)
|
||||||
|
|
|
@ -19,7 +19,7 @@ var prt=func(){
|
||||||
}
|
}
|
||||||
s~='+--------------------+\n';
|
s~='+--------------------+\n';
|
||||||
print(s);
|
print(s);
|
||||||
unix.sleep(1/144);
|
unix.sleep(1/200);
|
||||||
}
|
}
|
||||||
|
|
||||||
var bfs=func(begin,end){
|
var bfs=func(begin,end){
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
# 2022/5/19
|
# 2022/5/19
|
||||||
import.stl.process_bar;
|
import.stl.process_bar;
|
||||||
|
|
||||||
|
if(os.platform()=="windows"){
|
||||||
|
system("chcp 65001");
|
||||||
|
system("color");
|
||||||
|
}
|
||||||
|
|
||||||
var fib=func(){
|
var fib=func(){
|
||||||
var (a,b)=(1,1);
|
var (a,b)=(1,1);
|
||||||
coroutine.yield(a);
|
coroutine.yield(a);
|
||||||
|
@ -76,10 +81,6 @@ var total=1000; # ms
|
||||||
var co=coroutine.create(productor);
|
var co=coroutine.create(productor);
|
||||||
var tm=maketimestamp();
|
var tm=maketimestamp();
|
||||||
|
|
||||||
if(os.platform()=="windows"){
|
|
||||||
system("chcp 65001");
|
|
||||||
system("color");
|
|
||||||
}
|
|
||||||
var counter=0;
|
var counter=0;
|
||||||
var bar=process_bar.high_resolution_bar(40);
|
var bar=process_bar.high_resolution_bar(40);
|
||||||
var consumer=func(){
|
var consumer=func(){
|
||||||
|
|
|
@ -25,7 +25,7 @@ var prt=func()
|
||||||
s~='\n';
|
s~='\n';
|
||||||
}
|
}
|
||||||
print(s);
|
print(s);
|
||||||
unix.sleep(1/144);
|
unix.sleep(1/160);
|
||||||
}
|
}
|
||||||
|
|
||||||
func(){
|
func(){
|
||||||
|
|
Loading…
Reference in New Issue