🎨 improve format of code

This commit is contained in:
ValKmjolnir 2022-10-28 23:28:15 +08:00
parent c705b75513
commit d121dcd630
14 changed files with 223 additions and 188 deletions

View File

@ -13,6 +13,8 @@
#include <unordered_map> #include <unordered_map>
using ch_clk=std::chrono::high_resolution_clock;
const u32 VM_TOKEN =0x01; const u32 VM_TOKEN =0x01;
const u32 VM_AST =0x02; const u32 VM_AST =0x02;
const u32 VM_CODE =0x04; const u32 VM_CODE =0x04;
@ -114,10 +116,10 @@ void execute(const string& file,const std::vector<string>& argv,const u32 cmd)
debugger(err).run(gen,ld,argv); debugger(err).run(gen,ld,argv);
else if(cmd&VM_TIME) else if(cmd&VM_TIME)
{ {
auto start=std::chrono::high_resolution_clock::now(); auto start=ch_clk::now();
ctx.run(gen,ld,argv,cmd&VM_DETAIL); ctx.run(gen,ld,argv,cmd&VM_DETAIL);
auto end=std::chrono::high_resolution_clock::now(); auto end=ch_clk::now();
std::clog<<"process exited after "<<(end-start).count()*1.0/std::chrono::high_resolution_clock::duration::period::den<<"s.\n"; std::clog<<"process exited after "<<(end-start).count()*1.0/ch_clk::duration::period::den<<"s.\n";
} }
else if(cmd&VM_EXEC) else if(cmd&VM_EXEC)
ctx.run(gen,ld,argv,cmd&VM_DETAIL); ctx.run(gen,ld,argv,cmd&VM_DETAIL);

View File

@ -1,6 +1,8 @@
#ifndef __NASAL_H__ #pragma once
#define __NASAL_H__
#ifndef __nasver
#define __nasver "10.1" #define __nasver "10.1"
#endif
#include <cstdint> #include <cstdint>
#include <iostream> #include <iostream>
@ -151,5 +153,3 @@ string rawstr(const string& str,const usize maxlen=0)
} }
#include "nasal_gc.h" // declarations of var and nasal_gc #include "nasal_gc.h" // declarations of var and nasal_gc
#endif

View File

@ -1,5 +1,4 @@
#ifndef __NASAL_AST_H__ #pragma once
#define __NASAL_AST_H__
#include <vector> #include <vector>
#include <cstring> #include <cstring>
@ -53,12 +52,12 @@ enum ast_node:u32
ast_foreach, // foreach keyword ast_foreach, // foreach keyword
ast_while, // while ast_while, // while
ast_iter, // iterator, used in forindex/foreach ast_iter, // iterator, used in forindex/foreach
ast_conditional, // mark a sub-tree of conditional expression ast_cond, // mark a sub-tree of conditional expression
ast_if, // if keyword ast_if, // if keyword
ast_elsif, // elsif keyword ast_elsif, // elsif keyword
ast_else, // else keyword ast_else, // else keyword
ast_multi_id, // multi identifiers sub-tree ast_multi_id, // multi identifiers sub-tree
ast_multi_scalar,// multi value sub-tree ast_tuple, // tuple, only used in multiple assignment
ast_def, // definition ast_def, // definition
ast_multi_assign,// multi assignment sub-tree ast_multi_assign,// multi assignment sub-tree
ast_continue, // continue keyword, only used in loop ast_continue, // continue keyword, only used in loop
@ -107,20 +106,20 @@ const char* ast_name[]=
"*", "*",
"/", "/",
"~", "~",
"unary-", "neg",
"unary!", "!",
"trino", "trino",
"for", "for",
"forindex", "forindex",
"foreach", "foreach",
"while", "while",
"iter", "iter",
"conditional", "cond",
"if", "if",
"elsif", "elsif",
"else", "else",
"multi-id", "multi-id",
"multi-scalar", "tuple",
"def", "def",
"multi-assign", "multi-assign",
"continue", "continue",
@ -131,15 +130,15 @@ const char* ast_name[]=
class ast class ast
{ {
private: private:
u32 node_line; u32 nd_line;
u32 node_col; u32 nd_col;
u32 node_type; u32 nd_type;
f64 node_num; f64 nd_num;
string node_str; string nd_str;
std::vector<ast> node_child; std::vector<ast> nd_child;
public: public:
ast(const u32 l,const u32 c,const u32 t): ast(const u32 l,const u32 c,const u32 t):
node_line(l),node_col(c),node_type(t),node_num(0){} nd_line(l),nd_col(c),nd_type(t),nd_num(0){}
ast(const ast&); ast(const ast&);
ast(ast&&); ast(ast&&);
void print_tree(); void print_tree();
@ -148,74 +147,74 @@ public:
ast& operator=(const ast&); ast& operator=(const ast&);
ast& operator=(ast&&); ast& operator=(ast&&);
ast& operator[](usize n){return node_child[n];} ast& operator[](usize n){return nd_child[n];}
const ast& operator[](usize n) const {return node_child[n];} const ast& operator[](usize n) const {return nd_child[n];}
usize size() const {return node_child.size();} usize size() const {return nd_child.size();}
void add(ast&& node){node_child.push_back(std::move(node));} void add(ast&& node){nd_child.push_back(std::move(node));}
void add(const ast& node){node_child.push_back(node);} void add(const ast& node){nd_child.push_back(node);}
void set_line(const u32 l){node_line=l;} void set_line(const u32 l){nd_line=l;}
void set_type(const u32 t){node_type=t;} void set_type(const u32 t){nd_type=t;}
void set_str(const string& s){node_str=s;} void set_str(const string& s){nd_str=s;}
void set_num(const f64 n){node_num=n;} void set_num(const f64 n){nd_num=n;}
inline u32 line() const {return node_line;} inline u32 line() const {return nd_line;}
inline u32 col() const {return node_col;} inline u32 col() const {return nd_col;}
inline u32 type() const {return node_type;} inline u32 type() const {return nd_type;}
inline f64 num() const {return node_num;} inline f64 num() const {return nd_num;}
inline const string& str() const {return node_str;} inline const string& str() const {return nd_str;}
inline const std::vector<ast>& child() const {return node_child;} inline const std::vector<ast>& child() const {return nd_child;}
inline std::vector<ast>& child(){return node_child;} inline std::vector<ast>& child(){return nd_child;}
}; };
ast::ast(const ast& tmp): ast::ast(const ast& tmp):
node_str(tmp.node_str),node_child(tmp.node_child) nd_str(tmp.nd_str),nd_child(tmp.nd_child)
{ {
node_line=tmp.node_line; nd_line=tmp.nd_line;
node_col=tmp.node_col; nd_col=tmp.nd_col;
node_type=tmp.node_type; nd_type=tmp.nd_type;
node_num =tmp.node_num; nd_num =tmp.nd_num;
} }
ast::ast(ast&& tmp) ast::ast(ast&& tmp)
{ {
node_line=tmp.node_line; nd_line=tmp.nd_line;
node_col=tmp.node_col; nd_col=tmp.nd_col;
node_type=tmp.node_type; nd_type=tmp.nd_type;
node_num =tmp.node_num; nd_num =tmp.nd_num;
node_str.swap(tmp.node_str); nd_str.swap(tmp.nd_str);
node_child.swap(tmp.node_child); nd_child.swap(tmp.nd_child);
} }
ast& ast::operator=(const ast& tmp) ast& ast::operator=(const ast& tmp)
{ {
node_line=tmp.node_line; nd_line=tmp.nd_line;
node_col=tmp.node_col; nd_col=tmp.nd_col;
node_type=tmp.node_type; nd_type=tmp.nd_type;
node_num=tmp.node_num; nd_num=tmp.nd_num;
node_str=tmp.node_str; nd_str=tmp.nd_str;
node_child=tmp.node_child; nd_child=tmp.nd_child;
return *this; return *this;
} }
ast& ast::operator=(ast&& tmp) ast& ast::operator=(ast&& tmp)
{ {
node_line=tmp.node_line; nd_line=tmp.nd_line;
node_col=tmp.node_col; nd_col=tmp.nd_col;
node_type=tmp.node_type; nd_type=tmp.nd_type;
node_num=tmp.node_num; nd_num=tmp.nd_num;
node_str.swap(tmp.node_str); nd_str.swap(tmp.nd_str);
node_child.swap(tmp.node_child); nd_child.swap(tmp.nd_child);
return *this; return *this;
} }
void ast::clear() void ast::clear()
{ {
node_line=node_col=0; nd_line=nd_col=0;
node_num=0; nd_num=0;
node_str.clear(); nd_str.clear();
node_type=ast_null; nd_type=ast_null;
node_child.clear(); nd_child.clear();
} }
void ast::print_tree() void ast::print_tree()
@ -228,15 +227,13 @@ void ast::print(u32 depth,bool last,std::vector<string>& indent)
{ {
for(auto& i:indent) for(auto& i:indent)
std::cout<<i; std::cout<<i;
std::cout<<ast_name[node_type]; std::cout<<ast_name[nd_type];
if(node_type==ast_str || if(nd_type==ast_str || nd_type==ast_id ||
node_type==ast_id || nd_type==ast_default || nd_type==ast_dynamic ||
node_type==ast_default || nd_type==ast_callh)
node_type==ast_dynamic || std::cout<<":"<<rawstr(nd_str);
node_type==ast_callh) else if(nd_type==ast_num || nd_type==ast_file)
std::cout<<":"<<rawstr(node_str); std::cout<<":"<<nd_num;
else if(node_type==ast_num || node_type==ast_file)
std::cout<<":"<<node_num;
std::cout<<"\n"; std::cout<<"\n";
if(last && depth) if(last && depth)
indent.back()=" "; indent.back()=" ";
@ -246,16 +243,14 @@ void ast::print(u32 depth,bool last,std::vector<string>& indent)
#else #else
indent.back()=""; indent.back()="";
#endif #endif
for(u32 i=0;i<node_child.size();++i) for(u32 i=0;i<nd_child.size();++i)
{ {
#ifdef _WIN32 #ifdef _WIN32
indent.push_back(i==node_child.size()-1?"+-":"|-"); indent.push_back(i==nd_child.size()-1?"+-":"|-");
#else #else
indent.push_back(i==node_child.size()-1?"└─":"├─"); indent.push_back(i==nd_child.size()-1?"└─":"├─");
#endif #endif
node_child[i].print(depth+1,i==node_child.size()-1,indent); nd_child[i].print(depth+1,i==nd_child.size()-1,indent);
indent.pop_back(); indent.pop_back();
} }
} }
#endif

View File

@ -1,5 +1,4 @@
#ifndef __NASAL_BUILTIN_H__ #pragma once
#define __NASAL_BUILTIN_H__
#include "nasal_gc.h" #include "nasal_gc.h"
@ -1231,4 +1230,3 @@ struct
{"__logtime", builtin_logtime }, {"__logtime", builtin_logtime },
{nullptr, nullptr } {nullptr, nullptr }
}; };
#endif

View File

@ -1,5 +1,4 @@
#ifndef __NASAL_CODEGEN_H__ #pragma once
#define __NASAL_CODEGEN_H__
#include "nasal_err.h" #include "nasal_err.h"
#include <iomanip> #include <iomanip>
@ -248,7 +247,7 @@ private:
void single_def(const ast&); void single_def(const ast&);
void def_gen(const ast&); void def_gen(const ast&);
void multi_assign_gen(const ast&); void multi_assign_gen(const ast&);
void conditional_gen(const ast&); void cond_gen(const ast&);
void loop_gen(const ast&); void loop_gen(const ast&);
void load_continue_break(i32,i32); void load_continue_break(i32,i32);
void while_gen(const ast&); void while_gen(const ast&);
@ -649,7 +648,7 @@ void codegen::multi_def(const ast& node)
{ {
auto& ids=node[0].child(); auto& ids=node[0].child();
usize size=ids.size(); usize size=ids.size();
if(node[1].type()==ast_multi_scalar) // (var a,b,c)=(c,b,a); if(node[1].type()==ast_tuple) // (var a,b,c)=(c,b,a);
{ {
auto& vals=node[1].child(); auto& vals=node[1].child();
for(usize i=0;i<size;++i) for(usize i=0;i<size;++i)
@ -684,7 +683,7 @@ void codegen::def_gen(const ast& node)
void codegen::multi_assign_gen(const ast& node) void codegen::multi_assign_gen(const ast& node)
{ {
i32 size=node[0].size(); i32 size=node[0].size();
if(node[1].type()==ast_multi_scalar) if(node[1].type()==ast_tuple)
{ {
for(i32 i=size-1;i>=0;--i) for(i32 i=size-1;i>=0;--i)
calc_gen(node[1][i]); calc_gen(node[1][i]);
@ -725,7 +724,7 @@ void codegen::multi_assign_gen(const ast& node)
} }
} }
void codegen::conditional_gen(const ast& node) void codegen::cond_gen(const ast& node)
{ {
std::vector<usize> jmp_label; std::vector<usize> jmp_label;
for(auto& tmp:node.child()) for(auto& tmp:node.child())
@ -1146,7 +1145,7 @@ void codegen::block_gen(const ast& node)
case ast_file:fileindex=tmp.num();break; // special node type in main block case ast_file:fileindex=tmp.num();break; // special node type in main block
case ast_def:def_gen(tmp);break; case ast_def:def_gen(tmp);break;
case ast_multi_assign:multi_assign_gen(tmp);break; case ast_multi_assign:multi_assign_gen(tmp);break;
case ast_conditional:conditional_gen(tmp);break; case ast_cond:cond_gen(tmp);break;
case ast_continue: case ast_continue:
continue_ptr.front().push_back(code.size()); continue_ptr.front().push_back(code.size());
gen(op_jmp,0,tmp.line()); gen(op_jmp,0,tmp.line());
@ -1288,5 +1287,3 @@ void codegen::print()
for(u32 i=0;i<code.size();++i) for(u32 i=0;i<code.size();++i)
singleop(i); singleop(i);
} }
#endif

View File

@ -1,5 +1,4 @@
#ifndef __NASAL_DBG_H__ #pragma once
#define __NASAL_DBG_H__
#include "nasal_err.h" #include "nasal_err.h"
#include "nasal_vm.h" #include "nasal_vm.h"
@ -126,7 +125,7 @@ void debugger::stepinfo()
for(u32 i=begin;i<end && bytecode[i].op!=op_exit;++i) for(u32 i=begin;i<end && bytecode[i].op!=op_exit;++i)
std::cout std::cout
<<(i==pc?back_white:reset)<<(i==pc?"--> ":" ") <<(i==pc?back_white:reset)<<(i==pc?"--> ":" ")
<<codestream(bytecode[i],i,num_table,str_table,files) <<codestream(bytecode[i],i,cnum,cstr,files)
<<reset<<"\n"; <<reset<<"\n";
stackinfo(10); stackinfo(10);
} }
@ -399,5 +398,3 @@ mcallh: dbg(o_mcallh,op_mcallh);
ret: dbg(o_ret ,op_ret ); ret: dbg(o_ret ,op_ret );
#endif #endif
} }
#endif

View File

@ -1,5 +1,4 @@
#ifndef __NASAL_ERR_H__ #pragma once
#define __NASAL_ERR_H__
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
@ -159,5 +158,3 @@ public:
} }
void chkerr(){if(cnt)std::exit(1);} void chkerr(){if(cnt)std::exit(1);}
}; };
#endif

View File

@ -1,5 +1,4 @@
#ifndef __NASAL_GC_H__ #pragma once
#define __NASAL_GC_H__
#include <vector> #include <vector>
#include <queue> #include <queue>
@ -725,5 +724,3 @@ var nas_err(const string& err_f,const string& info)
typedef var (*mod)(var*,usize,gc*); // module function type typedef var (*mod)(var*,usize,gc*); // module function type
typedef mod (*getptr)(const char*); // module function "get" type typedef mod (*getptr)(const char*); // module function "get" type
#endif

View File

@ -1,5 +1,4 @@
#ifndef __NASAL_IMPORT_H__ #pragma once
#define __NASAL_IMPORT_H__
#ifndef _MSC_VER #ifndef _MSC_VER
#include <unistd.h> #include <unistd.h>
@ -224,5 +223,3 @@ void linker::link(parse& parse,const string& self,bool spath=false)
parse.tree()=load(parse.tree(),0); parse.tree()=load(parse.tree(),0);
err.chkerr(); err.chkerr();
} }
#endif

View File

@ -1,5 +1,4 @@
#ifndef __NASAL_LEXER_H__ #pragma once
#define __NASAL_LEXER_H__
#include <sstream> #include <sstream>
#include <sys/stat.h> #include <sys/stat.h>
@ -8,18 +7,6 @@
#define S_ISREG(m) (((m)&0xF000)==0x8000) #define S_ISREG(m) (((m)&0xF000)==0x8000)
#endif #endif
#define ID(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||(c<0))
#define HEX(c) (('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F'))
#define OCT(c) ('0'<=c&&c<='7')
#define DIGIT(c) ('0'<=c&&c<='9')
#define STR(c) (c=='\''||c=='\"'||c=='`')
// single operators have only one character
#define SINGLE_OPERATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\
c=='?'||c=='`'||c=='&'||c=='@'||c=='%'||c=='$'||c=='^'||c=='\\')
// calculation operators may have two chars, for example: += -= *= /= ~= != == >= <=
#define CALC_OPERATOR(c) (c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~')
#define NOTE(c) (c=='#')
enum tok:u32{ enum tok:u32{
tok_null=0, // null token (default token type) tok_null=0, // null token (default token type)
tok_num, // number literal tok_num, // number literal
@ -38,15 +25,39 @@ enum tok:u32{
tok_elsif, // condition expression keyword elsif tok_elsif, // condition expression keyword elsif
tok_else, // condition expression keyword else tok_else, // condition expression keyword else
tok_nil, // nil literal tok_nil, // nil literal
tok_lcurve,tok_rcurve, tok_lcurve, // (
tok_lbracket,tok_rbracket, tok_rcurve, // )
tok_lbrace,tok_rbrace, tok_lbracket,// [
tok_semi,tok_and,tok_or,tok_comma,tok_dot,tok_ellipsis,tok_quesmark, tok_rbracket,// ]
tok_colon,tok_add,tok_sub,tok_mult,tok_div,tok_link,tok_not, tok_lbrace, // {
tok_eq, tok_rbrace, // }
tok_addeq,tok_subeq,tok_multeq,tok_diveq,tok_lnkeq, tok_semi, // ;
tok_cmpeq,tok_neq,tok_less,tok_leq,tok_grt,tok_geq, tok_and, // operator and
tok_eof // end of token list tok_or, // operator or
tok_comma, // ,
tok_dot, // .
tok_ellipsis,// ...
tok_quesmark,// ?
tok_colon, // :
tok_add, // operator +
tok_sub, // operator -
tok_mult, // operator *
tok_div, // operator /
tok_link, // operator ~
tok_not, // operator !
tok_eq, // operator =
tok_addeq, // operator +=
tok_subeq, // operator -=
tok_multeq, // operator *=
tok_diveq, // operator /=
tok_lnkeq, // operator ~=
tok_cmpeq, // operator ==
tok_neq, // operator !=
tok_less, // operator <
tok_leq, // operator <=
tok_grt, // operator >
tok_geq, // operator >=
tok_eof // <eof> end of token list
}; };
struct{ struct{
@ -126,6 +137,13 @@ private:
std::vector<token> tokens; std::vector<token> tokens;
u32 get_type(const string&); u32 get_type(const string&);
bool is_id(char);
bool is_hex(char);
bool is_oct(char);
bool is_dec(char);
bool is_str(char);
bool is_single_opr(char);
bool is_calc_opr(char);
void die(const string& info){err.err("lexer",line,column,info);} void die(const string& info){err.err("lexer",line,column,info);}
void open(const string&); void open(const string&);
string utf8_gen(); string utf8_gen();
@ -142,6 +160,47 @@ public:
const std::vector<token>& result() const {return tokens;} const std::vector<token>& result() const {return tokens;}
}; };
bool lexer::is_id(char c)
{
return (c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||(c<0);
}
bool lexer::is_hex(char c)
{
return ('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F');
}
bool lexer::is_oct(char c)
{
return '0'<=c&&c<='7';
}
bool lexer::is_dec(char c)
{
return '0'<=c&&c<='9';
}
bool lexer::is_str(char c)
{
return c=='\''||c=='\"'||c=='`';
}
bool lexer::is_single_opr(char c)
{
return (
c=='('||c==')'||c=='['||c==']'||
c=='{'||c=='}'||c==','||c==';'||
c=='|'||c==':'||c=='?'||c=='`'||
c=='&'||c=='@'||c=='%'||c=='$'||
c=='^'||c=='\\'
);
}
bool lexer::is_calc_opr(char c)
{
return c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~';
}
void lexer::open(const string& file) void lexer::open(const string& file)
{ {
struct stat buffer; struct stat buffer;
@ -205,7 +264,7 @@ string lexer::utf8_gen()
string lexer::id_gen() string lexer::id_gen()
{ {
string str=""; string str="";
while(ptr<res.size() && (ID(res[ptr])||DIGIT(res[ptr]))) while(ptr<res.size() && (is_id(res[ptr])||is_dec(res[ptr])))
{ {
if(res[ptr]<0) // utf-8 if(res[ptr]<0) // utf-8
str+=utf8_gen(); str+=utf8_gen();
@ -225,7 +284,7 @@ string lexer::num_gen()
{ {
string str="0x"; string str="0x";
ptr+=2; ptr+=2;
while(ptr<res.size() && HEX(res[ptr])) while(ptr<res.size() && is_hex(res[ptr]))
str+=res[ptr++]; str+=res[ptr++];
column+=str.length(); column+=str.length();
if(str.length()<3)// "0x" if(str.length()<3)// "0x"
@ -237,7 +296,7 @@ string lexer::num_gen()
{ {
string str="0o"; string str="0o";
ptr+=2; ptr+=2;
while(ptr<res.size() && OCT(res[ptr])) while(ptr<res.size() && is_oct(res[ptr]))
str+=res[ptr++]; str+=res[ptr++];
column+=str.length(); column+=str.length();
if(str.length()<3)// "0o" if(str.length()<3)// "0o"
@ -247,12 +306,12 @@ string lexer::num_gen()
// generate dec number // generate dec number
// dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*) // dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
string str=""; string str="";
while(ptr<res.size() && DIGIT(res[ptr])) while(ptr<res.size() && is_dec(res[ptr]))
str+=res[ptr++]; str+=res[ptr++];
if(ptr<res.size() && res[ptr]=='.') if(ptr<res.size() && res[ptr]=='.')
{ {
str+=res[ptr++]; str+=res[ptr++];
while(ptr<res.size() && DIGIT(res[ptr])) while(ptr<res.size() && is_dec(res[ptr]))
str+=res[ptr++]; str+=res[ptr++];
// "xxxx." is not a correct number // "xxxx." is not a correct number
if(str.back()=='.') if(str.back()=='.')
@ -267,7 +326,7 @@ string lexer::num_gen()
str+=res[ptr++]; str+=res[ptr++];
if(ptr<res.size() && (res[ptr]=='-' || res[ptr]=='+')) if(ptr<res.size() && (res[ptr]=='-' || res[ptr]=='+'))
str+=res[ptr++]; str+=res[ptr++];
while(ptr<res.size() && DIGIT(res[ptr])) while(ptr<res.size() && is_dec(res[ptr]))
str+=res[ptr++]; str+=res[ptr++];
// "xxxe(-|+)" is not a correct number // "xxxe(-|+)" is not a correct number
if(str.back()=='e' || str.back()=='E' || str.back()=='-' || str.back()=='+') if(str.back()=='e' || str.back()=='E' || str.back()=='-' || str.back()=='+')
@ -352,23 +411,23 @@ void lexer::scan(const string& file)
} }
} }
if(ptr>=res.size()) break; if(ptr>=res.size()) break;
if(ID(res[ptr])) if(is_id(res[ptr]))
{ {
str=id_gen(); str=id_gen();
u32 type=get_type(str); u32 type=get_type(str);
tokens.push_back({line,column,type?type:tok_id,str}); tokens.push_back({line,column,type?type:tok_id,str});
} }
else if(DIGIT(res[ptr])) else if(is_dec(res[ptr]))
{ {
str=num_gen(); // make sure column is correct str=num_gen(); // make sure column is correct
tokens.push_back({line,column,tok_num,str}); tokens.push_back({line,column,tok_num,str});
} }
else if(STR(res[ptr])) else if(is_str(res[ptr]))
{ {
str=str_gen(); // make sure column is correct str=str_gen(); // make sure column is correct
tokens.push_back({line,column,tok_str,str}); tokens.push_back({line,column,tok_str,str});
} }
else if(SINGLE_OPERATOR(res[ptr])) else if(is_single_opr(res[ptr]))
{ {
str=res[ptr]; str=res[ptr];
++column; ++column;
@ -387,7 +446,7 @@ void lexer::scan(const string& file)
column+=str.length(); column+=str.length();
tokens.push_back({line,column,get_type(str),str}); tokens.push_back({line,column,get_type(str),str});
} }
else if(CALC_OPERATOR(res[ptr])) else if(is_calc_opr(res[ptr]))
{ {
// get calculation operator // get calculation operator
str=res[ptr++]; str=res[ptr++];
@ -396,7 +455,7 @@ void lexer::scan(const string& file)
column+=str.length(); column+=str.length();
tokens.push_back({line,column,get_type(str),str}); tokens.push_back({line,column,get_type(str),str});
} }
else if(NOTE(res[ptr]))// avoid note, after this process ptr will point to a '\n', so next loop line counter+1 else if(res[ptr]=='#')// avoid note, after this process ptr will point to a '\n', so next loop line counter+1
while(++ptr<res.size() && res[ptr]!='\n'); while(++ptr<res.size() && res[ptr]!='\n');
else else
{ {
@ -405,7 +464,7 @@ void lexer::scan(const string& file)
die("invalid character 0x"+chrhex(c)); die("invalid character 0x"+chrhex(c));
} }
} }
tokens.push_back({line,column,tok_eof,"eof"}); tokens.push_back({line,column,tok_eof,"<eof>"});
res=""; res="";
err.chkerr(); err.chkerr();
} }
@ -415,5 +474,3 @@ void lexer::print()
for(auto& tok:tokens) for(auto& tok:tokens)
std::cout<<"("<<tok.line<<" | "<<rawstr(tok.str,128)<<")\n"; std::cout<<"("<<tok.line<<" | "<<rawstr(tok.str,128)<<")\n";
} }
#endif

View File

@ -1,5 +1,4 @@
#ifndef __NASAL_OPT_H__ #pragma once
#define __NASAL_OPT_H__
#include <cmath> #include <cmath>
@ -67,4 +66,3 @@ void optimize(ast& root)
for(auto& i:root.child()) for(auto& i:root.child())
calc_const(i); calc_const(i);
} }
#endif

View File

@ -1,5 +1,4 @@
#ifndef __NASAL_PARSE_H__ #pragma once
#define __NASAL_PARSE_H__
#include <unordered_map> #include <unordered_map>
@ -96,7 +95,7 @@ private:
ast for_loop(); ast for_loop();
ast forei_loop(); ast forei_loop();
ast iter_gen(); ast iter_gen();
ast conditional(); ast cond();
ast continue_expr(); ast continue_expr();
ast break_expr(); ast break_expr();
ast ret_expr(); ast ret_expr();
@ -244,7 +243,7 @@ bool parse::check_special_call()
bool parse::need_semi_check(const ast& node) bool parse::need_semi_check(const ast& node)
{ {
u32 type=node.type(); u32 type=node.type();
if(type==ast_for || type==ast_foreach || type==ast_forindex || type==ast_while || type==ast_conditional) if(type==ast_for || type==ast_foreach || type==ast_forindex || type==ast_while || type==ast_cond)
return false; return false;
return !check_func_end(node); return !check_func_end(node);
} }
@ -466,7 +465,7 @@ ast parse::expr()
case tok_forindex: case tok_forindex:
case tok_foreach: case tok_foreach:
case tok_while: return loop(); break; case tok_while: return loop(); break;
case tok_if: return conditional(); break; case tok_if: return cond(); break;
case tok_continue: return continue_expr(); break; case tok_continue: return continue_expr(); break;
case tok_break: return break_expr(); break; case tok_break: return break_expr(); break;
case tok_ret: return ret_expr(); break; case tok_ret: return ret_expr(); break;
@ -765,9 +764,9 @@ ast parse::definition()
node.add(check_multi_scalar()?multi_scalar(false):calc()); node.add(check_multi_scalar()?multi_scalar(false):calc());
else else
node.add(calc()); node.add(calc());
if(node[0].type()==ast_id && node[1].type()==ast_multi_scalar) if(node[0].type()==ast_id && node[1].type()==ast_tuple)
die(node[1].line(),"one variable cannot accept too many values"); die(node[1].line(),"one variable cannot accept too many values");
else if(node[0].type()==ast_multi_id && node[1].type()==ast_multi_scalar && node[0].size()!=node[1].size()) else if(node[0].type()==ast_multi_id && node[1].type()==ast_tuple && node[0].size()!=node[1].size())
die(node[0].line(),"too much or lack values in multi-definition"); die(node[0].line(),"too much or lack values in multi-definition");
return node; return node;
} }
@ -815,7 +814,7 @@ ast parse::multi_scalar(bool check_call_memory)
tok_func,tok_var,tok_lcurve, tok_func,tok_var,tok_lcurve,
tok_lbrace,tok_lbracket,tok_null tok_lbrace,tok_lbracket,tok_null
}; };
ast node(tokens[ptr].line,tokens[ptr].col,ast_multi_scalar); ast node(tokens[ptr].line,tokens[ptr].col,ast_tuple);
match(tok_lcurve); match(tok_lcurve);
while(!lookahead(tok_rcurve)) while(!lookahead(tok_rcurve))
{ {
@ -846,7 +845,7 @@ ast parse::multi_assgin()
node.add(check_multi_scalar()?multi_scalar(false):calc()); node.add(check_multi_scalar()?multi_scalar(false):calc());
else else
node.add(calc()); node.add(calc());
if(node[1].type()==ast_multi_scalar if(node[1].type()==ast_tuple
&& node[0].size()!=node[1].size()) && node[0].size()!=node[1].size())
die(node[0].line(),"too much or lack values in multi-assignment"); die(node[0].line(),"too much or lack values in multi-assignment");
return node; return node;
@ -952,9 +951,9 @@ ast parse::iter_gen()
} }
return node; return node;
} }
ast parse::conditional() ast parse::cond()
{ {
ast node(tokens[ptr].line,tokens[ptr].col,ast_conditional); ast node(tokens[ptr].line,tokens[ptr].col,ast_cond);
ast ifnode(tokens[ptr].line,tokens[ptr].col,ast_if); ast ifnode(tokens[ptr].line,tokens[ptr].col,ast_if);
match(tok_if); match(tok_if);
match(tok_lcurve); match(tok_lcurve);
@ -1006,4 +1005,3 @@ ast parse::ret_expr()
node.add(calc()); node.add(calc());
return node; return node;
} }
#endif

View File

@ -1,5 +1,4 @@
#ifndef __NASAL_VM_H__ #pragma once
#define __NASAL_VM_H__
#include <iomanip> #include <iomanip>
#include <stack> #include <stack>
@ -16,9 +15,11 @@ protected:
var upvalr; // upvalue register var upvalr; // upvalue register
var* canary; // avoid stackoverflow var* canary; // avoid stackoverflow
var* top; // stack top var* top; // stack top
const f64* num_table;// const numbers, ref from codegen
const string* str_table;// const symbols, ref from codegen /* constants */
std::vector<u32> imm; // immediate number const f64* cnum; // const numbers
const string* cstr; // const symbols
std::vector<u32> imm; // immediate number
/* garbage collector */ /* garbage collector */
gc ngc; gc ngc;
@ -26,8 +27,8 @@ protected:
var stack[STACK_DEPTH]; var stack[STACK_DEPTH];
/* values used for debugger */ /* values used for debugger */
const string* files; // ref from linker const string* files;
const opcode* bytecode; // ref from codegen const opcode* bytecode;
void init( void init(
const std::vector<string>&, const std::vector<string>&,
@ -128,7 +129,7 @@ public:
vm(): vm():
pc(0),localr(nullptr),memr(nullptr),funcr(nil), pc(0),localr(nullptr),memr(nullptr),funcr(nil),
upvalr(nil),canary(nullptr),top(stack), upvalr(nil),canary(nullptr),top(stack),
num_table(nullptr),str_table(nullptr), cnum(nullptr),cstr(nullptr),
ngc(pc,localr,memr,funcr,upvalr,canary,top,stack), ngc(pc,localr,memr,funcr,upvalr,canary,top,stack),
files(nullptr),bytecode(nullptr),detail_info(false){} files(nullptr),bytecode(nullptr),detail_info(false){}
void run( void run(
@ -146,8 +147,8 @@ void vm::init(
const std::vector<string>& argv) const std::vector<string>& argv)
{ {
ngc.init(strs,argv); ngc.init(strs,argv);
num_table=nums.data(); cnum=nums.data();
str_table=strs.data(); cstr=strs.data();
bytecode=code.data(); bytecode=code.data();
files=filenames.data(); files=filenames.data();
@ -223,7 +224,7 @@ void vm::traceback()
<<" 0x"<<std::hex<<std::setw(8)<<std::setfill('0') <<" 0x"<<std::hex<<std::setw(8)<<std::setfill('0')
<<prev<<std::dec<<" "<<same<<" same call(s)\n"; <<prev<<std::dec<<" "<<same<<" same call(s)\n";
same=0; same=0;
std::cout<<" "<<codestream(bytecode[p],p,num_table,str_table,files)<<"\n"; std::cout<<" "<<codestream(bytecode[p],p,cnum,cstr,files)<<"\n";
} }
// the first called place has no same calls // the first called place has no same calls
} }
@ -360,7 +361,7 @@ inline void vm::o_loadu()
} }
inline void vm::o_pnum() inline void vm::o_pnum()
{ {
(++top)[0]={vm_num,num_table[imm[pc]]}; (++top)[0]={vm_num,cnum[imm[pc]]};
} }
inline void vm::o_pnil() inline void vm::o_pnil()
{ {
@ -396,6 +397,8 @@ inline void vm::o_newf()
if(localr) if(localr)
{ {
func.upval=funcr.func().upval; func.upval=funcr.func().upval;
// function created in the same local scope shares one closure
// so this size & stk setting has no problem
var upval=(upvalr.type==vm_nil)?ngc.alloc(vm_upval):upvalr; var upval=(upvalr.type==vm_nil)?ngc.alloc(vm_upval):upvalr;
upval.upval().size=funcr.func().lsize; upval.upval().size=funcr.func().lsize;
upval.upval().stk=localr; upval.upval().stk=localr;
@ -405,7 +408,7 @@ inline void vm::o_newf()
} }
inline void vm::o_happ() inline void vm::o_happ()
{ {
top[-1].hash().elems[str_table[imm[pc]]]=top[0]; top[-1].hash().elems[cstr[imm[pc]]]=top[0];
--top; --top;
} }
inline void vm::o_para() inline void vm::o_para()
@ -465,7 +468,7 @@ inline void vm::o_lnk()
} }
#define op_calc_const(type)\ #define op_calc_const(type)\
top[0]={vm_num,top[0].tonum() type num_table[imm[pc]]}; top[0]={vm_num,top[0].tonum() type cnum[imm[pc]]};
inline void vm::o_addc(){op_calc_const(+);} inline void vm::o_addc(){op_calc_const(+);}
inline void vm::o_subc(){op_calc_const(-);} inline void vm::o_subc(){op_calc_const(-);}
@ -473,7 +476,7 @@ inline void vm::o_mulc(){op_calc_const(*);}
inline void vm::o_divc(){op_calc_const(/);} inline void vm::o_divc(){op_calc_const(/);}
inline void vm::o_lnkc() inline void vm::o_lnkc()
{ {
top[0]=ngc.newstr(top[0].tostr()+str_table[imm[pc]]); top[0]=ngc.newstr(top[0].tostr()+cstr[imm[pc]]);
} }
#define op_calc_eq(type)\ #define op_calc_eq(type)\
@ -493,7 +496,7 @@ inline void vm::o_lnkeq()
} }
#define op_calc_eq_const(type)\ #define op_calc_eq_const(type)\
top[0]=memr[0]={vm_num,memr[0].tonum() type num_table[imm[pc]&0x7fffffff]};\ top[0]=memr[0]={vm_num,memr[0].tonum() type cnum[imm[pc]&0x7fffffff]};\
memr=nullptr;\ memr=nullptr;\
top-=(imm[pc]>>31); top-=(imm[pc]>>31);
@ -503,7 +506,7 @@ inline void vm::o_muleqc(){op_calc_eq_const(*);}
inline void vm::o_diveqc(){op_calc_eq_const(/);} inline void vm::o_diveqc(){op_calc_eq_const(/);}
inline void vm::o_lnkeqc() inline void vm::o_lnkeqc()
{ {
top[0]=memr[0]=ngc.newstr(memr[0].tostr()+str_table[imm[pc]&0x7fffffff]); top[0]=memr[0]=ngc.newstr(memr[0].tostr()+cstr[imm[pc]&0x7fffffff]);
memr=nullptr; memr=nullptr;
top-=(imm[pc]>>31); top-=(imm[pc]>>31);
} }
@ -558,7 +561,7 @@ inline void vm::o_grt(){op_cmp(>);}
inline void vm::o_geq(){op_cmp(>=);} inline void vm::o_geq(){op_cmp(>=);}
#define op_cmp_const(type)\ #define op_cmp_const(type)\
top[0]=(top[0].tonum() type num_table[imm[pc]])?one:zero; top[0]=(top[0].tonum() type cnum[imm[pc]])?one:zero;
inline void vm::o_lessc(){op_cmp_const(<);} inline void vm::o_lessc(){op_cmp_const(<);}
inline void vm::o_leqc(){op_cmp_const(<=);} inline void vm::o_leqc(){op_cmp_const(<=);}
@ -671,9 +674,9 @@ inline void vm::o_callh()
var val=top[0]; var val=top[0];
if(val.type!=vm_hash) if(val.type!=vm_hash)
vm_error("must call a hash"); vm_error("must call a hash");
top[0]=val.hash().get_val(str_table[imm[pc]]); top[0]=val.hash().get_val(cstr[imm[pc]]);
if(top[0].type==vm_none) if(top[0].type==vm_none)
vm_error("member \""+str_table[imm[pc]]+"\" does not exist"); vm_error("member \""+cstr[imm[pc]]+"\" does not exist");
if(top[0].type==vm_func) if(top[0].type==vm_func)
top[0].func().local[0]=val;// 'me' top[0].func().local[0]=val;// 'me'
} }
@ -746,7 +749,7 @@ inline void vm::o_callfh()
for(auto& i:func.keys) for(auto& i:func.keys)
{ {
const string& key=str_table[i.first]; auto& key=cstr[i.first];
if(hash.count(key)) if(hash.count(key))
local[i.second]=hash[key]; local[i.second]=hash[key];
else if(local[i.second].type==vm_none) else if(local[i.second].type==vm_none)
@ -874,8 +877,8 @@ inline void vm::o_mcallh()
var hash=top[0]; // mcall hash, reserved on stack to avoid gc var hash=top[0]; // mcall hash, reserved on stack to avoid gc
if(hash.type!=vm_hash) if(hash.type!=vm_hash)
vm_error("must call a hash"); vm_error("must call a hash");
nas_hash& ref=hash.hash(); auto& ref=hash.hash();
const string& str=str_table[imm[pc]]; auto& str=cstr[imm[pc]];
memr=ref.get_mem(str); memr=ref.get_mem(str);
if(!memr) // create a new key if(!memr) // create a new key
{ {
@ -1117,4 +1120,3 @@ mcallh: exec_nodie(o_mcallh); // -0
ret: exec_nodie(o_ret ); // -2 ret: exec_nodie(o_ret ); // -2
#endif #endif
} }
#endif

View File

@ -1,7 +1,7 @@
# wave collapse function 2022/4/10 # wave collapse function 2022/4/10
# by ValKmjolnir # by ValKmjolnir
srand(); srand();
var interval=1/60; var interval=1/120;
var table=[ var table=[
# c ,w,a,s,d # c ,w,a,s,d
["═",0,1,0,1], ["═",0,1,0,1],