85 Commits
v8.0 ... v9.0

Author SHA1 Message Date
ValKmjolnir
d567f5abf8 📝 update test/module_test.nas 2022-05-17 21:48:08 +08:00
ValKmjolnir
f8692f1e4e 📝 update test files 2022-05-17 18:22:24 +08:00
ValKmjolnir
712a047a43 🐛 now builtin_md5 uses unsigned char instead of char 2022-05-15 20:35:20 +08:00
ValKmjolnir
396d55a207 fix some warnings 2022-05-09 18:42:40 +08:00
ValKmjolnir
c5171c735a 💬 change code related to macros 'PRTHEX' 2022-05-08 19:43:27 +08:00
ValKmjolnir
07857d980c 📝 update test/utf8chk.nas 2022-05-07 17:18:29 +08:00
ValKmjolnir
51a1279110 add utf-8 identifier check in nasal_lexer & fix printf format at windows platform & add test file utf8chk.nas 2022-05-07 16:50:13 +08:00
ValKmjolnir
de262980cc 🎨 improve rawstr() and builtin_getcwd(..), change format output in nasal_vm::valinfo() 2022-05-07 02:22:49 +08:00
ValKmjolnir
23a5c1b1ad 🐛 bug fix 2022-05-06 20:58:02 +08:00
ValKmjolnir
fd8a148d0c bytecode info print and debugger will show the front 16 characters of strings whose length is greater than 16 2022-05-02 16:56:03 +08:00
ValKmjolnir
9c7f5f1a6e update test file diff.nas& add math.max math.min 2022-05-01 21:10:23 +08:00
ValKmjolnir
f049e1f9fb add test file diff.nas 2022-04-30 20:00:15 +08:00
ValKmjolnir
c4b7712e53 update README.md 2022-04-27 12:49:29 +08:00
ValKmjolnir
7417d5e635 change makefile 2022-04-26 22:53:35 +08:00
ValKmjolnir
785572634b change visual settings in -c/-dbg 2022-04-23 01:51:49 +08:00
ValKmjolnir
2dc8459cbf use effective way to check if file exists 2022-04-21 20:51:47 +08:00
ValKmjolnir
6e035d1951 add lib load code to automatically load lib.nas 2022-04-21 19:45:16 +08:00
ValKmjolnir
4f5fd3de33 op_addeq~op_lnkeq and op_addeqc~op_lnkeqc and op_meq operands now can do pop, this will decrease the frequency of calling op_pop 2022-04-17 17:20:18 +08:00
ValKmjolnir
fc25dd69e1 fix bug in codegen: foreach/forindex(id;vec/hash) may cause segmentation fault because of incorrect generated operand 2022-04-16 19:45:55 +08:00
ValKmjolnir
ca073499ae optimize codes 2022-04-13 19:08:06 +08:00
ValKmjolnir
022460755f optimize codes 2022-04-12 18:26:54 +08:00
ValKmjolnir
b6f174e869 update test/wavecollapse.nas 2022-04-10 16:47:27 +08:00
ValKmjolnir
7b160c4589 add test file wavecollapse.nas 2022-04-10 15:34:20 +08:00
ValKmjolnir
4503239731 change STACK_MAX_DEPTH to nasal_gc::stack_depth 2022-04-09 23:14:28 +08:00
ValKmjolnir
c12e812651 change test/md5compare.nas 2022-04-06 22:56:21 +08:00
ValKmjolnir
87cff700e8 change module/libmd5 to native function builtin_md5() in nasal_builtin.h 2022-04-06 22:30:49 +08:00
ValKmjolnir
bf5737ecfd add native function abort(), assert() 2022-04-06 21:25:20 +08:00
ValKmjolnir
651ae4ef77 add native function isa(object,class) 2022-04-05 22:33:55 +08:00
ValKmjolnir
e846e51175 add native function: srand, values, find. 2022-04-05 22:15:05 +08:00
ValKmjolnir
399b2f0ce9 bug fixed & add systime, finished vecindex 2022-04-04 19:08:48 +08:00
ValKmjolnir
aed5e27409 bug fix & optimize test code & add lib function: subvec, floor, abs, isfunc, isghost, isint, isnum, isscalar, isstr, isvec, vecindex(unfinished) 2022-04-04 18:38:25 +08:00
ValKmjolnir
a2b51fe212 optimize libmd5.nas & test/md5.nas 2022-04-03 18:10:00 +08:00
ValKmjolnir
92b684624d change module/makefile and test/md5compare.nas 2022-04-01 22:52:04 +08:00
ValKmjolnir
83a8632e8e update test/md5compare.nas & optimize test/md5.nas 2022-03-31 19:31:00 +08:00
ValKmjolnir
41b5304712 update test/md5compare.nas
and CAUTION: now the cpp&nas md5 program may not calculate strings including unicode
2022-03-30 21:42:30 +08:00
ValKmjolnir
c5a12ade5c update md5compare.nas 2022-03-29 22:54:17 +08:00
ValKmjolnir
7a939b417d fix bug in test/md5.nas & add test file md5compare.nas 2022-03-29 22:36:28 +08:00
ValKmjolnir
dd7740f1fd update test/md5.nas(still has bug) & add libmd5 in module(written in C++) 2022-03-28 17:14:11 +08:00
ValKmjolnir
617ad03d33 add math.pow 2022-03-27 16:14:55 +08:00
ValKmjolnir
b66ebbef4b fix bytecode output format bug 2022-03-27 13:10:35 +08:00
ValKmjolnir
7f22b25909 update README.md 2022-03-27 01:36:38 +08:00
ValKmjolnir
86f6296268 change opcode print format 2022-03-27 01:20:17 +08:00
ValKmjolnir
cf722fd98c fix bug: windows ps/cmd output unicode in bytecodes abnormally.
so we use the hex format to print them.
2022-03-23 22:54:07 +08:00
ValKmjolnir
1dd3fd445c add test/snake.nas 2022-03-20 22:08:11 +08:00
ValKmjolnir
27e25f84ec update main.cpp and bug fix 2022-03-20 18:28:45 +08:00
ValKmjolnir
e6457651d3 add unix.waitpid 2022-03-16 18:44:38 +08:00
ValKmjolnir
c4d52a88cd update docs & fix bug in nasal_builtin.h 2022-03-16 15:30:34 +08:00
ValKmjolnir
9bcad59e45 change enum obj_type to nasal_obj::obj_type 2022-03-15 22:51:14 +08:00
ValKmjolnir
9a099f66cb update docs 2022-03-14 20:29:49 +08:00
ValKmjolnir
b79d60fab5 add destructors for obj_file, obj_dylib, obj_dir & bug fix 2022-03-13 00:11:50 +08:00
ValKmjolnir
82e9e97a26 add destructor for obj_file & change arguments in test/tetris.nas 2022-03-12 23:37:16 +08:00
ValKmjolnir
6a1338bb23 update test/tetris.nas 2022-03-11 23:42:09 +08:00
ValKmjolnir
3b8a092f36 fix bug in test/json.nas 2022-03-11 15:26:38 +08:00
ValKmjolnir
3d86a32b12 update fully functional test/json.nas 2022-03-11 15:11:24 +08:00
ValKmjolnir
f26719e1d3 visual update 2022-03-10 16:05:49 +08:00
ValKmjolnir
e54ef9620f change nasal_ref value option functions' output types from pointers to references 2022-03-09 22:54:54 +08:00
ValKmjolnir
d8156e839b add unix.fork&unix.pipe(do not work on windows platform) 2022-03-09 19:03:12 +08:00
ValKmjolnir
61666d275d delete lstk&fstk, store local address and function on stack and in vm registers 2022-03-08 17:30:40 +08:00
ValKmjolnir
99f595e16f update num->string algorithm, now the to_string will output strings with no tailing zeros 2022-03-08 13:40:27 +08:00
ValKmjolnir
debe32b187 safer stl/module.nas & add stl/file.nas encapsulated from lib.nas/io 2022-03-06 15:17:39 +08:00
ValKmjolnir
ca9b8581b4 add module.nas to safely use dylib 2022-03-05 21:52:29 +08:00
ValKmjolnir
a0b341deb5 try fix bug 'use of undeclared identifier 'environ'' on MacOS 2022-03-05 19:24:33 +08:00
ValKmjolnir
d3df356299 add unix.environ() & use LPCWSTR in dylib.dlopen on Windows platform 2022-03-05 19:15:52 +08:00
ValKmjolnir
cd808a5e6d update detailed-info 2022-03-03 19:00:23 +08:00
ValKmjolnir
40f61a9dd4 fix bug of upval_state 2022-03-02 19:28:17 +08:00
ValKmjolnir
f312250d27 update 2022-03-01 14:36:05 +08:00
ValKmjolnir
3fac8aa665 fix bug in test/tetris.nas 2022-02-25 23:34:02 +08:00
ValKmjolnir
243aafd417 fix bug of -o not working. 2022-02-23 21:56:45 +08:00
ValKmjolnir
6bc03601d9 update test/tetris.nas 2022-02-23 01:09:31 +08:00
ValKmjolnir
f05acaecc7 fix bug in libkey and test/tetris.nas 2022-02-22 18:01:49 +08:00
ValKmjolnir
9456a903d7 finish tetris.nas 2022-02-21 17:10:13 +08:00
ValKmjolnir
984deed883 finish basic functions of tetris 2022-02-21 00:47:32 +08:00
ValKmjolnir
557cb2ebcf finish map drawing in test/tetris.nas 2022-02-20 17:58:13 +08:00
ValKmjolnir
9c055a9a23 add new third-lib libkey that includes function: kbhit,getch,nonblock 2022-02-19 16:55:54 +08:00
ValKmjolnir
13a09343e6 update README.md 2022-02-18 15:59:27 +08:00
ValKmjolnir
8c67e04cc4 update test file 2022-02-18 15:36:34 +08:00
ValKmjolnir
e77bb73a82 add special character \e. 2022-02-18 01:58:49 +08:00
ValKmjolnir
05fc5db337 change parameter name in native function split. 2022-02-17 23:34:58 +08:00
ValKmjolnir
a4738e8c7d delete operand op_nop 2022-02-16 23:27:22 +08:00
ValKmjolnir
5f6051e333 change tutorial's place in README.md 2022-02-15 23:42:17 +08:00
ValKmjolnir
51afe3dacd fixed bug when -O0 the program crashes with code 01.
add `nasal_err():error(0){}` in `nasal_err.h:47` as the constructor.
2022-02-14 17:40:19 +08:00
ValKmjolnir
0291908675 update README.md 2022-02-14 17:29:26 +08:00
ValKmjolnir
5fba784d05 add new gc type vm_upval 2022-02-13 22:40:54 +08:00
ValKmjolnir
9139e34c0b update README & bug fixed 2022-02-13 16:10:02 +08:00
ValKmjolnir
e7f503fae1 now local values are stored on stack. upvalue is generated when creating a new function in local scope.
may include some bugs inside. but all test files has passed the test so i decide to push it.
2022-02-12 23:12:30 +08:00
65 changed files with 5101 additions and 1852 deletions

1631
README.md

File diff suppressed because it is too large Load Diff

156
lib.nas
View File

@@ -34,11 +34,11 @@ var input=func(){
return __builtin_input();
}
# split a string by delimiter for example:
# split a string by separator for example:
# split("ll","hello world") -> ["he","o world"]
# this function will return a vector.
var split=func(deli,str){
return __builtin_split(deli,str);
var split=func(separator,str){
return __builtin_split(separator,str);
}
# rand has the same function as the rand in C
@@ -60,6 +60,22 @@ var int=func(val){
return __builtin_int(val);
}
# floor will get the integral number of input argument
# which is less than or equal to this argument
var floor=func(val){
return __builtin_floor(val);
}
# abort using std::abort
var abort=func(){
__builtin_abort();
}
# abs gets absolute number.
var abs=func(n){
return n>0?n:-n;
}
# num will change all the other types into number.
# mostly used to change a numerable string.
var num=func(val){
@@ -105,6 +121,9 @@ var keys=func(hash){
var time=func(begin){
return __builtin_time(begin);
}
var systime=func(){
return time(0);
}
# die is a special native function.
# use it at where you want the program to crash immediately.
@@ -112,12 +131,22 @@ var die=func(str){
return __builtin_die(str);
}
# find will give the first position of the needle in haystack
var find=func(needle,haystack){
return __builtin_find(needle,haystack);
}
# typeof is used to get the type of an object.
# this function returns a string.
var typeof=func(object){
return __builtin_type(object);
}
# subvec is used to get part of a vector
var subvec=func(vec,begin,length=nil){
return vec[begin:(length==nil?nil:begin+length-1)];
}
# substr will get the sub-string.
# it gets the string, the begin index and sub-string's length as arguments.
var substr=func(str,begin,len){
@@ -154,6 +183,22 @@ var chr=func(code){
return __builtin_chr(code);
}
# mut is used to change unmutable strings to mutable.
var mut=func(str){
return str~"";
}
# srand wraps up rand, using time(0) as the seed.
var srand=func(){
rand(time(0));
return 0;
}
# values() gets all values in a hash.
var values=func(hash){
return __builtin_values(hash);
}
# println has the same function as print.
# but it will output a '\n' after using print.
var println=func(elems...){
@@ -162,6 +207,71 @@ var println=func(elems...){
return __builtin_print(elems);
}
var isfunc=func(f){
return typeof(f)=="func";
}
var isghost=func(g){
die("this runtime has no ghost object");
return 0;
}
var ishash=func(h){
return typeof(h)=="hash";
}
var isint=func(x){
return x==floor(x);
}
var isnum=func(x){
return typeof(x)=="num" or !math.isnan(num(x));
}
var isscalar=func(s){
var t=typeof(s);
return (t=="num" or t=="str")?1:0;
}
var isstr=func(s){
return typeof(s)=="str";
}
var isvec=func(v){
return typeof(v)=="vec";
}
# get the index of val in the vec
var vecindex=func(vec,val){
forindex(var i;vec)
if(val==vec[i])
return i;
return nil;
}
# check if the object is an instance of the class
var isa=func(object,class){
if(!contains(object,"parents") or typeof(object.parents)!="vec")
return 0;
foreach(var elem;object.parents)
if(elem==class)
return 1;
return 0;
}
# assert aborts when condition is not true
var assert=func(condition,message="assertion failed!"){
if(condition)
return 1;
die(message);
}
# md5
var md5=func(str){
return __builtin_md5(str);
}
var io=
{
SEEK_SET:0,
@@ -176,6 +286,7 @@ var io=
# same as C fclose. close file by FILE*.
close: func(filehandle){return __builtin_close(filehandle);},
# same as C fread. read file by FILE*.
# caution: buf must be a mutable string.use mut("") to get an empty mutable string.
read: func(filehandle,buf,len){return __builtin_read(filehandle,buf,len);},
# same as C fwrite. write file by FILE*.
write: func(filehandle,str){return __builtin_write(filehandle,str);},
@@ -252,6 +363,9 @@ var math=
pi: 3.14159265358979323846264338327950288,
inf: 1/0,
nan: 0/0,
abs: func(x) {return x>0?x:-x; },
floor: func(x) {return __builtin_floor(x); },
pow: func(x,y){return __builtin_pow(x,y); },
sin: func(x) {return __builtin_sin(x); },
cos: func(x) {return __builtin_cos(x); },
tan: func(x) {return __builtin_tan(x); },
@@ -260,16 +374,18 @@ var math=
ln: func(x) {return __builtin_ln(x); },
sqrt: func(x) {return __builtin_sqrt(x); },
atan2: func(x,y){return __builtin_atan2(x,y);},
isnan: func(x) {return __builtin_isnan(x); }
isnan: func(x) {return __builtin_isnan(x); },
max: func(x,y){return x>y?x:y; },
min: func(x,y){return x<y?x:y; }
};
var unix=
{
pipe: func(){die("not supported yet");},
fork: func(){die("not supported yet");},
pipe: func(){return __builtin_pipe;},
fork: func(){return __builtin_fork;},
dup2: func(fd0,fd1){die("not supported yet");},
exec: func(filename,argv,envp){die("not supported yet");},
waitpid: func(pid,nohang=0){die("not supported yet");},
waitpid: func(pid,nohang=0){return __builtin_waitpid;},
isdir: func(path){return bits.bitand(io.stat(path)[2],0x4000);}, # S_IFDIR 0x4000
isfile: func(path){return bits.bitand(io.stat(path)[2],0x8000);}, # S_IFREG 0x8000
opendir: func(path){return __builtin_opendir;},
@@ -278,12 +394,13 @@ var unix=
time: func(){return time(0);},
sleep: func(secs){return __builtin_sleep(secs);},
chdir: func(path){return __builtin_chdir(path);},
environ: func(){die("not supported yet");},
environ: func(){return __builtin_environ();},
getcwd: func(){return __builtin_getcwd();},
getenv: func(envvar){return __builtin_getenv(envvar);}
};
# dylib is the core hashmap for developers to load their own library.
# for safe using dynamic library, you could use 'module' in stl/module.nas
var dylib=
{
# open dynamic lib.
@@ -328,4 +445,25 @@ var M2IN=39.3701;
var M2NM=0.00054;
var MPS2KT=1.9438;
var NM2M=1852;
var R2D=180/math.pi;
var R2D=180/math.pi;
# functions that not supported in this runtime:
var bind=func(function,locals,outer_scope=nil){
die("this runtime does not support bind");
}
var call=func(function,args=nil,_me=nil,locals=nil,error=nil){
die("this runtime does not support call");
}
var caller=func(level=1){
die("this runtime does not support caller");
}
var closure=func(function,level=1){
die("this runtime uses \"vm_upval\" instead of \"vm_hash\" as the closure");
}
var compile=func(code,filename="<compile>"){
die("this runtime uses static code generator");
}

View File

@@ -1,25 +1,25 @@
#include "nasal.h"
const uint32_t VM_LEXINFO =1;
const uint32_t VM_ASTINFO =2;
const uint32_t VM_CODEINFO =4;
const uint32_t VM_EXECTIME =8;
const uint32_t VM_OPCALLNUM=16;
const uint32_t VM_EXEC =32;
const uint32_t VM_DBGINFO =64;
const uint32_t VM_DEBUG =128;
const uint32_t VM_OPTIMIZE =256;
const uint32_t VM_LEXINFO =0x01;
const uint32_t VM_ASTINFO =0x02;
const uint32_t VM_CODEINFO =0x04;
const uint32_t VM_EXECTIME =0x08;
const uint32_t VM_OPCALLNUM=0x10;
const uint32_t VM_EXEC =0x20;
const uint32_t VM_DBGINFO =0x40;
const uint32_t VM_DEBUG =0x80;
const uint32_t VM_OPTIMIZE =0x100;
void help()
{
std::cout
#ifdef _WIN32
<<"use command \'chcp 65001\' if want to use unicode.\n"
<<"use command <chcp 65001> if want to use unicode.\n"
#endif
<<"nasal <option>\n"
<<"option:\n"
<<" -h, --help | get help.\n"
<<" -v, --version | get version of nasal interpreter.\n\n"
<<" -h, --help | get help.\n"
<<" -v, --version | get version of nasal interpreter.\n\n"
<<"nasal <file>\n"
<<"file:\n"
<<" input file name to execute script file.\n\n"
@@ -35,7 +35,7 @@ void help()
<<" | get garbage collector info if didn't crash.\n"
<<" -op, --optimize| use optimizer(beta).\n"
<<" | if want to use -op and run, please use -op -e/-t/-o/-d.\n"
<<" -dbg, --debug | debug mode (this will ignore -t -o -d).\n"
<<" -dbg, --debug | debug mode (this will ignore -t -o -d -e).\n"
<<"file:\n"
<<" input file name to execute script file.\n";
}
@@ -43,12 +43,13 @@ void help()
void logo()
{
std::cout
<<" __ _ \n"
<<" /\\ \\ \\__ _ ___ __ _| | \n"
<<" / \\/ / _` / __|/ _` | | \n"
<<" / /\\ / (_| \\__ \\ (_| | | \n"
<<" __ _\n"
<<" /\\ \\ \\__ _ ___ __ _| |\n"
<<" / \\/ / _` / __|/ _` | |\n"
<<" / /\\ / (_| \\__ \\ (_| | |\n"
<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n"
<<"nasal interpreter ver 8.0\n"
<<"nasal ver : "<<__nasver<<"\n"
<<"c++ std : "<<__cplusplus<<"\n"
<<"thanks to : https://github.com/andyross/nasal\n"
<<"code repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n"
<<"code repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
@@ -84,12 +85,11 @@ void execute(const std::string& file,const uint32_t cmd)
parse.compile(lexer);
// linker gets parser's ast and load import files to this ast
linker.link(parse,file);
if(cmd&VM_ASTINFO)
parse.print();
// optimizer does simple optimization on ast
if(cmd&VM_OPTIMIZE)
optimize(parse.ast());
if(cmd&VM_ASTINFO)
parse.print();
// code generator gets parser's ast and linker's import file list to generate code
gen.compile(parse,linker);
@@ -132,28 +132,22 @@ int main(int argc,const char* argv[])
err();
return 0;
}
std::unordered_map<std::string,uint32_t> cmdlst={
{"--lex",VM_LEXINFO},{"-l",VM_LEXINFO},
{"--ast",VM_ASTINFO},{"-a",VM_ASTINFO},
{"--code",VM_CODEINFO},{"-c",VM_CODEINFO},
{"--exec",VM_EXEC},{"-e",VM_EXEC},
{"--opcnt",VM_OPCALLNUM|VM_EXEC},{"-o",VM_OPCALLNUM|VM_EXEC},
{"--time",VM_EXECTIME|VM_EXEC},{"-t",VM_EXECTIME|VM_EXEC},
{"--detail",VM_DBGINFO|VM_EXEC},{"-d",VM_DBGINFO|VM_EXEC},
{"--optimize",VM_OPTIMIZE},{"-op",VM_OPTIMIZE},
{"--debug",VM_DEBUG},{"-dbg",VM_DEBUG}
};
uint32_t cmd=0;
for(int i=1;i<argc-1;++i)
{
std::string s(argv[i]);
if(s=="--lex" || s=="-l")
cmd|=VM_LEXINFO;
else if(s=="--ast" || s=="-a")
cmd|=VM_ASTINFO;
else if(s=="--code" || s=="-c")
cmd|=VM_CODEINFO;
else if(s=="--exec" || s=="-e")
cmd|=VM_EXEC;
else if(s=="--opcnt" || s=="-o")
cmd|=VM_OPCALLNUM|VM_EXEC;
else if(s=="--time" || s=="-t")
cmd|=VM_EXECTIME;
else if(s=="--detail" || s=="-d")
cmd|=VM_DBGINFO|VM_EXEC;
else if(s=="--optimize" || s=="-op")
cmd|=VM_OPTIMIZE;
else if(s=="--debug" || s=="-dbg")
cmd|=VM_DEBUG;
if(cmdlst.count(argv[i]))
cmd|=cmdlst[argv[i]];
else
err();
}

View File

@@ -1,34 +1,47 @@
.PHONY=test
nasal:main.cpp nasal_ast.h nasal_err.h nasal_builtin.h nasal_opt.h nasal_codegen.h nasal_gc.h nasal_import.h nasal_lexer.h nasal_parse.h nasal_vm.h nasal_dbg.h nasal.h
nasal:main.cpp nasal_ast.h nasal_err.h nasal_builtin.h nasal_opt.h nasal_codegen.h\
nasal_gc.h nasal_import.h nasal_lexer.h nasal_parse.h nasal_vm.h nasal_dbg.h nasal.h
clang++ -std=c++11 -O3 main.cpp -o nasal -fno-exceptions -ldl -Wshadow -Wall
nasal.exe:main.cpp nasal_ast.h nasal_err.h nasal_builtin.h nasal_opt.h nasal_codegen.h\
nasal_gc.h nasal_import.h nasal_lexer.h nasal_parse.h nasal_vm.h nasal_dbg.h nasal.h
g++ -std=c++11 -O3 main.cpp -o nasal.exe -fno-exceptions -Wshadow -Wall -static
test:nasal
./nasal -op -e test/ascii-art.nas
./nasal -op -c test/bf.nas
./nasal -op -c test/bfconvertor.nas
./nasal -op -e -d test/bfs.nas
./nasal -op -t test/bigloop.nas
./nasal -op -e test/bp.nas
./nasal -op -e -d test/calc.nas
./nasal -op -e test/choice.nas
./nasal -op -e test/class.nas
./nasal -op -c test/exception.nas
./nasal -op -t -d test/fib.nas
./nasal -op -e test/filesystem.nas
./nasal -op -e -d test/hexdump.nas
./nasal -op -e test/json.nas
./nasal -op -e test/leetcode1319.nas
./nasal -op -e -d test/lexer.nas
./nasal -op -e -d test/life.nas
./nasal -op -t test/loop.nas
./nasal -op -t -d test/mandel.nas
./nasal -op -t -d test/mandelbrot.nas
./nasal -op -c test/module_test.nas
./nasal -op -e test/nasal_test.nas
./nasal -op -t -d test/pi.nas
./nasal -op -t -d test/prime.nas
./nasal -op -t -d test/quick_sort.nas
./nasal -op -e test/scalar.nas
./nasal -op -e test/trait.nas
./nasal -op -t -d test/turingmachine.nas
./nasal -op -t -d test/ycombinator.nas
@ ./nasal -op -e test/ascii-art.nas
@ ./nasal -op -a -c test/bf.nas
@ ./nasal -op -a -c test/bfcolored.nas
@ ./nasal -op -a -c test/bfconvertor.nas
@ ./nasal -op -e -d test/bfs.nas
@ ./nasal -op -t test/bigloop.nas
@ ./nasal -op -e test/bp.nas
@ ./nasal -op -e -d test/calc.nas
@ ./nasal -op -e test/choice.nas
@ ./nasal -op -e test/class.nas
@ ./nasal -op -e test/diff.nas
-@ ./nasal -op -d test/exception.nas
@ ./nasal -op -t -d test/fib.nas
@ ./nasal -op -e test/filesystem.nas
@ ./nasal -op -e -d test/hexdump.nas
@ ./nasal -op -e test/json.nas
@ ./nasal -op -e test/leetcode1319.nas
@ ./nasal -op -e -d test/lexer.nas
@ ./nasal -op -e -d test/life.nas
@ ./nasal -op -t test/loop.nas
@ ./nasal -op -t -d test/mandel.nas
@ ./nasal -op -t -d test/mandelbrot.nas
@ ./nasal -op -t -d -o test/md5.nas
-@ ./nasal -op -t -d -o test/md5compare.nas
-@ ./nasal -op -d test/module_test.nas
@ ./nasal -op -e test/nasal_test.nas
@ ./nasal -op -t -d test/pi.nas
@ ./nasal -op -t -d test/prime.nas
@ ./nasal -op -t -d test/props_sim.nas
@ ./nasal -op -e test/qrcode.nas
@ ./nasal -op -t -d test/quick_sort.nas
@ ./nasal -op -e test/scalar.nas
-@ ./nasal -op -c -t test/snake.nas
@ ./nasal -op -c -e test/trait.nas
-@ ./nasal -op -c -t test/tetris.nas
@ ./nasal -op -c -t -d test/turingmachine.nas
@ ./nasal -op -c -t -d -o test/ycombinator.nas
@ ./nasal -op -e test/wavecollapse.nas

View File

@@ -8,6 +8,8 @@ double fibonaci(double x){
}
extern "C" nasal_ref fib(std::vector<nasal_ref>& args,nasal_gc& gc){
std::cout<<"[mod] this is the first test module of nasal\n";
if(!args.size())
return builtin_err("fib","lack arguments");
nasal_ref num=args[0];
if(num.type!=vm_num)
return builtin_err("extern_fib","\"num\" must be number");
@@ -15,6 +17,8 @@ extern "C" nasal_ref fib(std::vector<nasal_ref>& args,nasal_gc& gc){
}
extern "C" nasal_ref quick_fib(std::vector<nasal_ref>& args,nasal_gc& gc){
std::cout<<"[mod] this is the first test module of nasal\n";
if(!args.size())
return builtin_err("fib","lack arguments");
nasal_ref num=args[0];
if(num.type!=vm_num)
return builtin_err("extern_quick_fib","\"num\" must be number");

74
module/keyboard.cpp Normal file
View File

@@ -0,0 +1,74 @@
#include "../nasal.h"
#include <iostream>
#ifdef _WIN32
#include <conio.h>
#else
#include <fcntl.h>
#include <termios.h>
#endif
#ifndef _WIN32
static struct termios init_termios;
static struct termios new_termios;
static int peek_char=-1;
int kbhit(){
unsigned char ch=0;
int nread=0;
if(peek_char!=-1)
return 1;
int flag=fcntl(0,F_GETFL);
fcntl(0,F_SETFL,flag|O_NONBLOCK);
nread=read(0,&ch,1);
fcntl(0,F_SETFL,flag);
if(nread==1){
peek_char=ch;
return 1;
}
return 0;
}
int getch(){
int ch=0;
if(peek_char!=-1){
ch=peek_char;
peek_char=-1;
return ch;
}
read(0,&ch,1);
return ch;
}
#endif
extern "C" nasal_ref nas_getch(std::vector<nasal_ref>& args,nasal_gc& gc){
return {vm_num,(double)getch()};
}
extern "C" nasal_ref nas_kbhit(std::vector<nasal_ref>& args,nasal_gc& gc){
return {vm_num,(double)kbhit()};
}
extern "C" nasal_ref nas_noblock(std::vector<nasal_ref>& args,nasal_gc& gc){
if(kbhit())
return {vm_num,(double)getch()};
return nil;
}
extern "C" nasal_ref nas_init(std::vector<nasal_ref>& args,nasal_gc& gc){
#ifndef _WIN32
tcflush(0,TCIOFLUSH);
tcgetattr(0,&init_termios);
new_termios=init_termios;
new_termios.c_lflag&=~(ICANON|ECHO|ECHONL|ECHOE);
// vmin=0 is nonblock input, but in wsl there is a bug that will block input
// so we use fcntl to write the nonblock input
new_termios.c_cc[VMIN]=1;
new_termios.c_cc[VTIME]=0;
tcsetattr(0,TCSANOW,&new_termios);
#endif
return nil;
}
extern "C" nasal_ref nas_close(std::vector<nasal_ref>& args,nasal_gc& gc){
#ifndef _WIN32
tcflush(0,TCIOFLUSH);
tcsetattr(0,TCSANOW,&init_termios);
#endif
return nil;
}

13
module/libfib.nas Normal file
View File

@@ -0,0 +1,13 @@
import("lib.nas");
var libfib=func(){
var dl=dylib.dlopen("./module/libfib."~(os.platform()=="windows"?"dll":"so"));
var fib=dylib.dlsym(dl,"fib");
var qfib=dylib.dlsym(dl,"quick_fib");
var call=dylib.dlcall;
return
{
fib: func(x){return call(fib,x)},
qfib:func(x){return call(qfib,x)}
};
}();

47
module/libkey.nas Normal file
View File

@@ -0,0 +1,47 @@
import("lib.nas");
var libkey=func(){
var lib=dylib.dlopen("./module/libkey"~(os.platform()=="windows"?".dll":".so"));
var kb=dylib.dlsym(lib,"nas_kbhit");
var gt=dylib.dlsym(lib,"nas_getch");
var nb=dylib.dlsym(lib,"nas_noblock");
var init=dylib.dlsym(lib,"nas_init");
var cls=dylib.dlsym(lib,"nas_close");
var call=dylib.dlcall;
var is_init=0;
return {
init:func(){
# change io mode to no echo
call(init);
is_init=1;
},
kbhit:func(){
# check if kerboard is hit
# if keyboard is hit this function will return 1
# until getch() gets all the input characters
# and the input flow becomes empty
if(!is_init)
me.init();
return call(kb);
},
getch:func(){
# get input one character without echo
# block until get one input
if(!is_init)
me.init();
return call(gt);
},
nonblock:func(){
# nonblock input without echo
if(!is_init)
me.init();
return call(nb);
},
close:func(){
# must call this function before exiting the program
# this will change terminal mode to normal io mode
call(cls);
dylib.dlclose(lib);
}
}
}();

View File

@@ -1,9 +1,23 @@
.PHONY=clean
.PHONY=clean all mingw-all
libfib.so: fib.cpp
clang++ -c -O3 fib.cpp -fPIC -o fib.o
clang++ -shared -o libfib.so fib.o
rm fib.o
libfib.dll: fib.cpp
g++ -c -O3 fib.cpp -fPIC -o fib.o
g++ -shared -o libfib.dll fib.o
libkey.so: keyboard.cpp
clang++ -c -O3 keyboard.cpp -fPIC -o keyboard.o
clang++ -shared -o libkey.so keyboard.o
rm keyboard.o
libkey.dll: keyboard.cpp
g++ -c -O3 keyboard.cpp -fPIC -o keyboard.o -static
g++ -shared -o libkey.dll keyboard.o -static
clean:
rm *.o *.so *.dll *.dylib
rm *.o *.so *.dll *.dylib
all: libfib.so libkey.so
@ echo "build done"
mingw-all: libfib.dll libkey.dll
@ echo "build done"

77
nasal.h
View File

@@ -1,10 +1,14 @@
#ifndef __NASAL_H__
#define __NASAL_H__
#include <stdint.h>
#define __nasver "9.0"
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <cstdint>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <fstream>
#include <sstream>
@@ -27,6 +31,17 @@
#include <windows.h>
#else
#include <dlfcn.h>
#include <sys/wait.h>
#endif
#ifdef __linux__
#define PRTHEX64 "%lx"
#define PRTHEX64_8 "%.8lx"
#define PRTINT64 "%ld"
#else
#define PRTHEX64 "%llx"
#define PRTHEX64_8 "%.8llx"
#define PRTINT64 "%lld"
#endif
inline double hex_to_double(const char* str)
@@ -109,22 +124,60 @@ double str2num(const char* str)
return is_negative?-ret_num:ret_num;
}
int utf8_hdchk(char head)
{
// RFC-2279 but in fact now we use RFC-3629 so nbytes is less than 4
uint8_t c=(uint8_t)head;
uint32_t nbytes=0;
if((c>>5)==0x06) // 110x xxxx (10xx xxxx)^1
nbytes=1;
if((c>>4)==0x0e) // 1110 xxxx (10xx xxxx)^2
nbytes=2;
if((c>>3)==0x1e) // 1111 0xxx (10xx xxxx)^3
nbytes=3;
// these should not be true
if((c>>2)==0x3e) // 1111 10xx (10xx xxxx)^4
nbytes=4;
if((c>>1)==0x7e) // 1111 110x (10xx xxxx)^5
nbytes=5;
if(c==0xfe) // 1111 1110 (10xx xxxx)^6
nbytes=6;
return nbytes;
}
std::string rawstr(const std::string& str)
{
std::string ret("");
for(auto i:str)
{
#ifdef _WIN32
// windows ps or cmd doesn't output unicode normally
// if 'chcp65001' is not enabled, so we output the hex
if(i<=0)
{
ret+="\\x";
ret+="0123456789abcdef"[(i>>4)&15];
ret+="0123456789abcdef"[i&15];
continue;
}
#endif
switch(i)
{
case '\a': ret+="\\a";break;
case '\b': ret+="\\b";break;
case '\f': ret+="\\f";break;
case '\n': ret+="\\n";break;
case '\r': ret+="\\r";break;
case '\t': ret+="\\t";break;
case '\v': ret+="\\v";break;
case '\0': ret+="\\0";break;
default: ret+=i; break;
case '\0': ret+="\\0"; break;
case '\a': ret+="\\a"; break;
case '\b': ret+="\\b"; break;
case '\e': ret+="\\e"; break;
case '\t': ret+="\\t"; break;
case '\n': ret+="\\n"; break;
case '\v': ret+="\\v"; break;
case '\f': ret+="\\f"; break;
case '\r': ret+="\\r"; break;
case '\\': ret+="\\\\";break;
case '\'': ret+="\\\'";break;
case '\"': ret+="\\\"";break;
default: ret+=i; break;
}
}
return ret;
}
#include "nasal_err.h"

View File

@@ -116,10 +116,10 @@ const char* ast_name[]=
"if",
"elsif",
"else",
"multi_id",
"multi_scalar",
"multi-id",
"multi-scalar",
"def",
"multi_assign",
"multi-assign",
"continue",
"break",
"return",
@@ -135,7 +135,7 @@ private:
std::string _str;
std::vector<nasal_ast> _child;
public:
nasal_ast(const uint32_t l=0,const uint32_t t=ast_null):_line(l),_type(t){}
nasal_ast(const uint32_t l=0,const uint32_t t=ast_null):_line(l),_type(t),_num(0){}
nasal_ast(const nasal_ast&);
nasal_ast(nasal_ast&&);
void print(int,bool);
@@ -162,13 +162,12 @@ public:
inline std::vector<nasal_ast>& child(){return _child;}
};
nasal_ast::nasal_ast(const nasal_ast& tmp)
nasal_ast::nasal_ast(const nasal_ast& tmp):
_str(tmp._str),_child(tmp._child)
{
_line=tmp._line;
_type=tmp._type;
_num =tmp._num;
_str =tmp._str;
_child=tmp._child;
}
nasal_ast::nasal_ast(nasal_ast&& tmp)

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
enum op_code
{
op_nop, // do nothing
op_exit, // stop the virtual machine
op_intg, // global scope size
op_intl, // local scope size
op_loadg, // load global value
@@ -77,8 +77,7 @@ enum op_code
op_mupval, // get memory space of value in closure
op_mcallv, // get memory space of vec[index]
op_mcallh, // get memory space of hash.label
op_ret, // return
op_exit // stop the virtual machine
op_ret // return
};
struct
@@ -87,7 +86,7 @@ struct
const char* name;
}code_table[]=
{
{op_nop, "nop "},
{op_exit, "exit "},
{op_intg, "intg "},
{op_intl, "intl "},
{op_loadg, "loadg "},
@@ -162,17 +161,16 @@ struct
{op_mcallv, "mcallv"},
{op_mcallh, "mcallh"},
{op_ret, "ret "},
{op_exit, "exit "},
{-1, nullptr },
};
struct opcode
{
uint16_t op; // opcode
uint8_t op; // opcode
uint16_t fidx;// source code file index
uint32_t num; // imm num
uint32_t line;// line of source code
opcode(uint8_t o=op_nop,uint16_t f=0,uint32_t n=0,uint32_t l=0):
opcode(uint8_t o=op_exit,uint16_t f=0,uint32_t n=0,uint32_t l=0):
op(o),fidx(f),num(n),line(l){}
opcode& operator=(const opcode& tmp)
{
@@ -202,6 +200,10 @@ private:
std::unordered_map<std::string,int> global;
// local : max 32768 upvalues 65536 values
std::list<std::unordered_map<std::string,int>> local;
// func end stack, reserved for code print
std::stack<uint32_t> fbstk;
std::stack<uint32_t> festk;
void die(std::string,const uint32_t);
void regist_number(const double);
@@ -244,7 +246,7 @@ private:
void block_gen(const nasal_ast&);
void ret_gen(const nasal_ast&);
public:
nasal_codegen(nasal_err& e):nerr(e){}
nasal_codegen(nasal_err& e):fileindex(0),nerr(e),file(nullptr){}
void compile(const nasal_parse&,const nasal_import&);
void print_op(uint32_t);
void print();
@@ -428,7 +430,7 @@ void nasal_codegen::func_gen(const nasal_ast& ast)
block_gen(block);
in_iterloop.pop();
code[local_label].num=local.back().size();
if(local.back().size()>65536)
if(local.back().size()>=nasal_gc::stack_depth)
die("too many local variants: "+std::to_string(local.back().size())+".",block.line());
local.pop_back();
@@ -545,8 +547,13 @@ void nasal_codegen::mcall(const nasal_ast& ast)
mcall_id(ast);
return;
}
if(ast.size()==1) // foreach and forindex use call-id ast to get mcall
{
mcall_id(ast[0]);
return;
}
calc_gen(ast[0]);
for(int i=1;i<ast.size()-1;++i)
for(size_t i=1;i<ast.size()-1;++i)
{
const nasal_ast& tmp=ast[i];
switch(tmp.type())
@@ -615,7 +622,7 @@ void nasal_codegen::multi_def(const nasal_ast& ast)
{
auto& ids=ast[0].child();
int size=ids.size();
if(ast[1].type()==ast_multi_scalar)
if(ast[1].type()==ast_multi_scalar) // (var a,b,c)=(c,b,a);
{
auto& vals=ast[1].child();
for(int i=0;i<size;++i)
@@ -627,7 +634,7 @@ void nasal_codegen::multi_def(const nasal_ast& ast)
gen(op_loadl,local_find(str),ids[i].line());
}
}
else
else // (var a,b,c)=[0,1,2];
{
calc_gen(ast[1]);
for(int i=0;i<size;++i)
@@ -668,10 +675,7 @@ void nasal_codegen::multi_assign_gen(const nasal_ast& ast)
else if(code.back().op==op_mcallg)
code.back().op=op_loadg;
else
{
gen(op_meq,0,ast[0][i].line());
gen(op_pop,0,ast[0][i].line());
}
gen(op_meq,1,ast[0][i].line());
}
}
else
@@ -690,10 +694,7 @@ void nasal_codegen::multi_assign_gen(const nasal_ast& ast)
else if(code.back().op==op_mcallg)
code.back().op=op_loadg;
else
{
gen(op_meq,0,ast[0][i].line());
gen(op_pop,0,ast[0][i].line());
}
gen(op_meq,1,ast[0][i].line());
}
gen(op_pop,0,ast.line());
}
@@ -771,35 +772,54 @@ void nasal_codegen::for_gen(const nasal_ast& ast)
case ast_null:break;
case ast_def:def_gen(ast[0]);break;
case ast_multi_assign:multi_assign_gen(ast[0]);break;
case ast_nil:
case ast_num:
case ast_str:
case ast_func:break;
case ast_vec:
case ast_hash:
case ast_addeq:case ast_subeq:
case ast_multeq:case ast_diveq:case ast_lnkeq:
calc_gen(ast[0]);
if(op_addeq<=code.back().op && code.back().op<=op_lnkeq)
code.back().num=1;
else if(op_addeqc<=code.back().op && code.back().op<=op_lnkeqc)
code.back().num|=0x80000000;
else
gen(op_pop,0,ast[0].line());
break;
case ast_nil:case ast_num:case ast_str:break;
case ast_vec:case ast_hash:case ast_func:
case ast_call:
case ast_equal:
case ast_addeq:
case ast_subeq:
case ast_multeq:
case ast_diveq:
case ast_lnkeq:
case ast_neg:
case ast_not:
case ast_add:
case ast_sub:
case ast_mult:
case ast_div:
case ast_neg:case ast_not:
case ast_add:case ast_sub:
case ast_mult:case ast_div:
case ast_link:
case ast_cmpeq:
case ast_neq:
case ast_leq:
case ast_less:
case ast_geq:
case ast_grt:
case ast_cmpeq:case ast_neq:
case ast_leq:case ast_less:
case ast_geq:case ast_grt:
case ast_trino:
calc_gen(ast[0]);
gen(op_pop,0,ast[0].line());
if(code.back().op==op_meq)
code.back().num=1;
else
gen(op_pop,0,ast[0].line());
break;
case ast_equal:
if(ast[0][0].type()==ast_id)
{
calc_gen(ast[0][1]);
mcall_id(ast[0][0]);
// only the first mcall_id can use load
if(code.back().op==op_mcalll)
code.back().op=op_loadl;
else if(code.back().op==op_mupval)
code.back().op=op_loadu;
else
code.back().op=op_loadg;
}
else
{
calc_gen(ast[0]);
if(code.back().op==op_meq)
code.back().num=1;
else
gen(op_pop,0,ast[0].line());
}
break;
}
int jmp_place=code.size();
@@ -817,12 +837,19 @@ void nasal_codegen::for_gen(const nasal_ast& ast)
case ast_null:break;
case ast_def:def_gen(ast[2]);break;
case ast_multi_assign:multi_assign_gen(ast[2]);break;
case ast_nil:case ast_num:case ast_str:case ast_func:break;
case ast_vec:case ast_hash:
case ast_addeq:case ast_subeq:
case ast_multeq:case ast_diveq:case ast_lnkeq:
calc_gen(ast[2]);
if(op_addeq<=code.back().op && code.back().op<=op_lnkeq)
code.back().num=1;
else if(op_addeqc<=code.back().op && code.back().op<=op_lnkeqc)
code.back().num|=0x80000000;
else
gen(op_pop,0,ast[2].line());
break;
case ast_nil:case ast_num:case ast_str:break;
case ast_vec:case ast_hash:case ast_func:
case ast_call:
case ast_equal:case ast_addeq:
case ast_subeq:case ast_multeq:
case ast_diveq:case ast_lnkeq:
case ast_neg:case ast_not:
case ast_add:case ast_sub:case ast_mult:
case ast_div:case ast_link:
@@ -830,7 +857,32 @@ void nasal_codegen::for_gen(const nasal_ast& ast)
case ast_less:case ast_geq:case ast_grt:
case ast_trino:
calc_gen(ast[2]);
gen(op_pop,0,ast[2].line());
if(code.back().op==op_meq)
code.back().num=1;
else
gen(op_pop,0,ast[2].line());
break;
case ast_equal:
if(ast[2][0].type()==ast_id)
{
calc_gen(ast[2][1]);
mcall_id(ast[2][0]);
// only the first mcall_id can use load
if(code.back().op==op_mcalll)
code.back().op=op_loadl;
else if(code.back().op==op_mupval)
code.back().op=op_loadu;
else
code.back().op=op_loadg;
}
else
{
calc_gen(ast[2]);
if(code.back().op==op_meq)
code.back().num=1;
else
gen(op_pop,0,ast[2].line());
}
break;
}
gen(op_jmp,jmp_place,ast[2].line());
@@ -844,18 +896,24 @@ void nasal_codegen::forindex_gen(const nasal_ast& ast)
gen(op_cnt,0,ast[1].line());
int ptr=code.size();
gen(op_findex,0,ast.line());
if(ast[0].type()==ast_iter)
if(ast[0].type()==ast_iter) // define a new iterator
{
const std::string& str=ast[0][0].str();
local.empty()?
gen(op_loadg,global_find(str),ast[0][0].line()):
gen(op_loadl,local_find(str),ast[0][0].line());
}
else
else // use exist variable as the iterator
{
mcall(ast[0]);
gen(op_meq,0,ast[0].line());
gen(op_pop,0,ast[0].line());
if(code.back().op==op_mcallg)
code.back().op=op_loadg;
else if(code.back().op==op_mcalll)
code.back().op=op_loadl;
else if(code.back().op==op_mupval)
code.back().op=op_loadu;
else
gen(op_meq,1,ast[0].line());
}
++in_iterloop.top();
block_gen(ast[2]);
@@ -872,18 +930,24 @@ void nasal_codegen::foreach_gen(const nasal_ast& ast)
gen(op_cnt,0,ast.line());
int ptr=code.size();
gen(op_feach,0,ast.line());
if(ast[0].type()==ast_iter)
if(ast[0].type()==ast_iter) // define a new iterator
{
const std::string& str=ast[0][0].str();
local.empty()?
gen(op_loadg,global_find(str),ast[0][0].line()):
gen(op_loadl,local_find(str),ast[0][0].line());
}
else
else // use exist variable as the iterator
{
mcall(ast[0]);
gen(op_meq,0,ast[0].line());
gen(op_pop,0,ast[0].line());
if(code.back().op==op_mcallg)
code.back().op=op_loadg;
else if(code.back().op==op_mcalll)
code.back().op=op_loadl;
else if(code.back().op==op_mupval)
code.back().op=op_loadu;
else
gen(op_meq,1,ast[0].line());
}
++in_iterloop.top();
block_gen(ast[2]);
@@ -1053,7 +1117,7 @@ void nasal_codegen::block_gen(const nasal_ast& ast)
for(auto& tmp:ast.child())
switch(tmp.type())
{
case ast_null:case ast_nil:case ast_num:case ast_str:case ast_func:break;
case ast_null:case ast_nil:case ast_num:case ast_str:break;
case ast_file:fileindex=tmp.num();break; // special node type in main block
case ast_def:def_gen(tmp);break;
case ast_multi_assign:multi_assign_gen(tmp);break;
@@ -1086,18 +1150,27 @@ void nasal_codegen::block_gen(const nasal_ast& ast)
else
{
calc_gen(tmp);
gen(op_pop,0,tmp.line());
if(code.back().op==op_meq)
code.back().num=1;
else
gen(op_pop,0,tmp.line());
}
break;
case ast_addeq:case ast_subeq:
case ast_multeq:case ast_diveq:case ast_lnkeq:
calc_gen(tmp);
if(op_addeq<=code.back().op && code.back().op<=op_lnkeq)
code.back().num=1;
else if(op_addeqc<=code.back().op && code.back().op<=op_lnkeqc)
code.back().num|=0x80000000;
else
gen(op_pop,0,tmp.line());
break;
case ast_id:
case ast_vec:
case ast_hash:
case ast_func:
case ast_call:
case ast_addeq:
case ast_subeq:
case ast_multeq:
case ast_diveq:
case ast_lnkeq:
case ast_neg:
case ast_not:
case ast_add:
@@ -1113,7 +1186,13 @@ void nasal_codegen::block_gen(const nasal_ast& ast)
case ast_grt:
case ast_or:
case ast_and:
case ast_trino:calc_gen(tmp);gen(op_pop,0,tmp.line());break;
case ast_trino:
calc_gen(tmp);
if(code.back().op==op_meq)
code.back().num=1;
else
gen(op_pop,0,tmp.line());
break;
case ast_ret:ret_gen(tmp);break;
}
}
@@ -1145,7 +1224,7 @@ void nasal_codegen::compile(const nasal_parse& parse,const nasal_import& import)
gen(op_intg,global.size(),0);
block_gen(parse.ast()); // generate main block
gen(op_exit,0,0);
if(global.size()>=STACK_MAX_DEPTH)
if(global.size()>=nasal_gc::stack_depth)
die("too many global variants: "+std::to_string(global.size())+".",0);
nerr.chkerr();
}
@@ -1154,31 +1233,71 @@ void nasal_codegen::print_op(uint32_t index)
{
// print opcode index,opcode name,opcode immediate number
const opcode& c=code[index];
printf("0x%.8x: %s ",index,code_table[c.op].name);
if(!festk.empty() && index==festk.top())
{
printf("<0x%x>;\n",fbstk.top());
if(code[index].op!=op_newf) // avoid two empty lines
printf("\n");
fbstk.pop();
festk.pop();
}
if(c.op==op_newf)
{
printf("\nfunc <0x%x>:\n",index);
for(uint32_t i=index;i<code.size();++i)
if(code[i].op==op_jmp)
{
fbstk.push(index);
festk.push(code[i].num);
break;
}
}
printf(" 0x%.8x: %.2x %.2x %.2x %.2x %.2x %s ",
index,
c.op,
uint8_t((c.num>>24)&0xff),
uint8_t((c.num>>16)&0xff),
uint8_t((c.num>>8)&0xff),
uint8_t(c.num&0xff),
code_table[c.op].name
);
// print detail info
switch(c.op)
{
case op_addc: case op_subc: case op_mulc: case op_divc:
case op_addeq: case op_subeq: case op_muleq: case op_diveq:
case op_lnkeq: case op_meq:
printf("0x%x sp-%u\n",c.num,c.num);break;
case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc:
printf("0x%x (",c.num&0x7fffffff);
std::cout<<num_res[c.num&0x7fffffff]<<") sp-"<<(c.num>>31)<<"\n";
break;
case op_lnkeqc:
{
std::string tmp=rawstr(str_res[c.num&0x7fffffff]);
printf("0x%x (\"%.16s%s\") sp-%u\n",c.num&0x7fffffff,tmp.c_str(),tmp.length()>16?"...":"",c.num>>31);
}break;
case op_addc: case op_subc: case op_mulc: case op_divc:
case op_lessc: case op_leqc: case op_grtc: case op_geqc:
case op_pnum:
printf("0x%x (",c.num);std::cout<<num_res[c.num]<<")\n";break;
case op_callvi:case op_newv: case op_callfv:
case op_intg: case op_intl:
case op_newf: case op_jmp: case op_jt: case op_jf:
printf("0x%x\n",c.num);break;
case op_callb:
printf("0x%x <%s@0x%lx>\n",c.num,builtin[c.num].name,(uint64_t)builtin[c.num].func);break;
case op_callg: case op_mcallg: case op_loadg:
case op_calll: case op_mcalll: case op_loadl:
printf("0x%x\n",c.num);break;
case op_callb:
printf("0x%x <%s@0x" PRTHEX64 ">\n",c.num,builtin[c.num].name,(uint64_t)builtin[c.num].func);break;
case op_upval:case op_mupval: case op_loadu:
printf("0x%x[0x%x]\n",(c.num>>16)&0xffff,c.num&0xffff);break;
case op_happ: case op_pstr:
case op_lnkc: case op_lnkeqc:
case op_lnkc:
case op_callh: case op_mcallh:
case op_para: case op_defpara:case op_dynpara:
printf("0x%x (\"%s\")\n",c.num,rawstr(str_res[c.num]).c_str());break;
{
std::string tmp=rawstr(str_res[c.num]);
printf("0x%x (\"%.16s%s\")\n",c.num,tmp.c_str(),tmp.length()>16?"...":"");
}break;
default:printf("\n");break;
}
}
@@ -1186,9 +1305,10 @@ void nasal_codegen::print_op(uint32_t index)
void nasal_codegen::print()
{
for(auto& num:num_res)
std::cout<<".number "<<num<<'\n';
std::cout<<" .number "<<num<<'\n';
for(auto& str:str_res)
std::cout<<".symbol \""<<rawstr(str)<<"\"\n";
std::cout<<" .symbol \""<<rawstr(str)<<"\"\n";
std::cout<<"\n";
for(uint32_t i=0;i<code.size();++i)
print_op(i);
}

View File

@@ -68,6 +68,7 @@ void nasal_dbg::help()
<<"\th, help | get help\n"
<<"\tbt, backtrace | get function call trace\n"
<<"\tc, continue | run program until break point or exit\n"
<<"\tf, file | see all the compiled files\n"
<<"\tg, global | see global values\n"
<<"\tl, local | see local values\n"
<<"\tu, upval | see upvalue\n"
@@ -105,7 +106,7 @@ void nasal_dbg::interact()
<<"[debug] nasal debug mode\n"
<<"input \'h\' to get help\n";
}
else if(bytecode[pc].op==op_nop || bytecode[pc].op==op_exit)
else if(bytecode[pc].op==op_exit)
return;
if(
@@ -129,6 +130,9 @@ void nasal_dbg::interact()
traceback();
else if(res[0]=="c" || res[0]=="continue")
return;
else if(res[0]=="f" || res[0]=="file")
for(size_t i=0;i<files_size;++i)
printf("[%zu] %s\n",i,files[i].c_str());
else if(res[0]=="g" || res[0]=="global")
global_state();
else if(res[0]=="l" || res[0]=="local")
@@ -136,11 +140,7 @@ void nasal_dbg::interact()
else if(res[0]=="u" || res[0]=="upval")
upval_state();
else if(res[0]=="a" || res[0]=="all")
{
global_state();
local_state();
upval_state();
}
detail();
else if(res[0]=="n" || res[0]=="next")
{
next_step=true;
@@ -151,24 +151,19 @@ void nasal_dbg::interact()
else
err();
}
else if(res.size()==3)
else if(res.size()==3 && (res[0]=="bk" || res[0]=="break"))
{
if(res[0]=="bk" || res[0]=="break")
bk_fidx=get_fileindex(res[1]);
if(bk_fidx==65535)
{
bk_fidx=get_fileindex(res[1]);
if(bk_fidx==65535)
{
printf("cannot find file named \"%s\"\n",res[1].c_str());
bk_fidx=0;
}
int tmp=atoi(res[2].c_str());
if(tmp<=0)
printf("incorrect line number \"%s\"\n",res[2].c_str());
else
bk_line=tmp;
printf("cannot find file named \"%s\"\n",res[1].c_str());
bk_fidx=0;
}
int tmp=atoi(res[2].c_str());
if(tmp<=0)
printf("incorrect line number \"%s\"\n",res[2].c_str());
else
err();
bk_line=tmp;
}
else
err();
@@ -180,10 +175,10 @@ void nasal_dbg::run(
const nasal_import& linker)
{
detail_info=true;
init(gen.get_strs(),gen.get_nums(),linker.get_file());
init(gen.get_strs(),gen.get_nums(),gen.get_code(),linker.get_file());
const void* opr_table[]=
{
&&nop, &&intg, &&intl, &&loadg,
&&vmexit, &&intg, &&intl, &&loadg,
&&loadl, &&loadu, &&pnum, &&pnil,
&&pstr, &&newv, &&newh, &&newf,
&&happ, &&para, &&defpara,&&dynpara,
@@ -201,19 +196,14 @@ void nasal_dbg::run(
&&callvi, &&callh, &&callfv, &&callfh,
&&callb, &&slcbegin, &&slcend, &&slc,
&&slc2, &&mcallg, &&mcalll, &&mupval,
&&mcallv, &&mcallh, &&ret, &&vmexit
&&mcallv, &&mcallh, &&ret
};
bytecode=gen.get_code().data();
std::vector<const void*> code;
for(auto& i:gen.get_code())
{
code.push_back(opr_table[i.op]);
imm.push_back(i.num);
}
// set canary and program counter
auto canary=gc.stack+STACK_MAX_DEPTH-1;
pc=0;
// goto the first operand
goto *code[pc];
@@ -226,7 +216,6 @@ vmexit:
return;
#define dbg(op) {interact();op();if(gc.top<canary)goto *code[++pc];goto vmexit;}
nop: dbg(opr_nop );
intg: dbg(opr_intg );
intl: dbg(opr_intl );
loadg: dbg(opr_loadg );

View File

@@ -45,10 +45,11 @@ class nasal_err:public file_line
private:
uint32_t error;
public:
void err(const char* stage,const std::string& info)
nasal_err():error(0){}
void err(const char* stage,const std::string& info,const char end='\n')
{
++error;
std::cerr<<"["<<stage<<"] "<<info<<'\n';
std::cerr<<"["<<stage<<"] "<<info<<end;
}
void err(const char* stage,uint32_t line,uint32_t column,const std::string& info)
{

View File

@@ -6,6 +6,7 @@ enum nasal_type
/* none-gc object */
vm_none=0,
vm_cnt,
vm_addr,
vm_ret,
vm_nil,
vm_num,
@@ -14,33 +15,54 @@ enum nasal_type
vm_func,
vm_vec,
vm_hash,
vm_upval,
vm_obj,
vm_type_size
};
// change parameters here to make your own efficient gc
// better set bigger number on vm_vec
const uint32_t initialize[vm_type_size]=
{
/* none-gc object */
0, // vm_none, error type
0, // vm_count, used in foreach/forindex
0, // vm_addr, used to store local address pointers
0, // vm_ret, used to store call-return address
0, // vm_nil
0, // vm_num
/* gc object */
128, // vm_str
512, // vm_func
128, // vm_vec
64, // vm_hash
512, // vm_upval
16 // vm_obj
};
const uint32_t increment[vm_type_size]=
{
/* none-gc object */
0, // vm_none, error type
0, // vm_count, used in foreach/forindex
0, // vm_addr, used to store local address pointers
0, // vm_ret, used to store call-return address
0, // vm_nil
0, // vm_num
/* gc object */
256, // vm_str
1024,// vm_str
512, // vm_func
512, // vm_vec
128, // vm_hash
16 // vm_obj
8192,// vm_vec
1024,// vm_hash
128, // vm_upval
256 // vm_obj
};
struct nasal_vec; // vector
struct nasal_hash;// hashmap(dict)
struct nasal_func;// function(lambda)
struct nasal_obj; // special objects
struct nasal_val; // nasal_val includes gc-managed types
struct nasal_vec; // vector
struct nasal_hash; // hashmap(dict)
struct nasal_func; // function(lambda)
struct nasal_upval;// upvalue
struct nasal_obj; // special objects
struct nasal_val; // nasal_val includes gc-managed types
struct nasal_ref
{
@@ -50,14 +72,22 @@ struct nasal_ref
uint32_t ret;
int64_t cnt;
double num;
nasal_ref* addr;
nasal_val* gcobj;
}value;
} value;
// vm_none/vm_nil
nasal_ref(const uint8_t t=vm_none):type(t){}
// vm_ret
nasal_ref(const uint8_t t,const uint32_t n):type(t){value.ret=n;}
// vm_cnt
nasal_ref(const uint8_t t,const int64_t n):type(t){value.cnt=n;}
// vm_num
nasal_ref(const uint8_t t,const double n):type(t){value.num=n;}
// vm_str/vm_func/vm_vec/vm_hash/vm_upval/vm_obj
nasal_ref(const uint8_t t,nasal_val* n):type(t){value.gcobj=n;}
// vm_addr
nasal_ref(const uint8_t t,nasal_ref* n):type(t){value.addr=n;}
nasal_ref(const nasal_ref& nr):type(nr.type),value(nr.value){}
nasal_ref& operator=(const nasal_ref& nr)
{
@@ -71,30 +101,39 @@ struct nasal_ref
double to_number();
std::string to_string();
void print();
bool objchk(uint32_t);
inline nasal_ref* addr();
inline uint32_t ret ();
inline int64_t& cnt ();
inline double& num ();
inline std::string* str ();
inline nasal_vec* vec ();
inline nasal_hash* hash();
inline nasal_func* func();
inline nasal_obj* obj ();
inline double num ();
inline std::string& str ();
inline nasal_vec& vec ();
inline nasal_hash& hash();
inline nasal_func& func();
inline nasal_upval& upval();
inline nasal_obj& obj ();
};
struct nasal_vec
{
bool printed;
std::vector<nasal_ref> elems;
nasal_vec():printed(false){}
void print();
size_t size(){return elems.size();}
nasal_ref get_val(const int);
nasal_ref* get_mem(const int);
};
struct nasal_hash
{
bool printed;
std::unordered_map<std::string,nasal_ref> elems;
nasal_hash():printed(false){}
void print();
size_t size(){return elems.size();}
nasal_ref get_val(const std::string&);
nasal_ref* get_mem(const std::string&);
};
@@ -109,16 +148,51 @@ struct nasal_func
std::vector<nasal_ref> upvalue; // closure
std::unordered_map<std::string,size_t> keys; // parameter name table, size_t begins from 1
nasal_func():dynpara(-1){}
nasal_func():dynpara(-1),entry(0),psize(0),lsize(0){}
void clear();
};
struct nasal_upval
{
bool onstk;
uint32_t size;
nasal_ref* stk;
std::vector<nasal_ref> elems;
nasal_upval(){onstk=true;stk=nullptr;size=0;}
nasal_ref& operator[](const int i){return onstk?stk[i]:elems[i];}
void clear(){onstk=true;elems.clear();size=0;}
};
struct nasal_obj
{
enum obj_type
{
null,
file=1,
dir,
dylib,
externfunc
};
/* RAII constructor */
/* new object is initialized when creating */
uint32_t type;
void* ptr;
nasal_obj():ptr(nullptr){}
void clear(){ptr=nullptr;}
/* RAII destroyer */
/* default destroyer does nothing */
typedef void (*dest)(void*);
dest destructor;
nasal_obj():type(obj_type::null),ptr(nullptr),destructor(nullptr){}
~nasal_obj(){clear();}
void clear()
{
if(destructor && ptr)
destructor(ptr);
ptr=nullptr;
destructor=nullptr;
}
};
const uint8_t GC_UNCOLLECTED=0;
@@ -135,6 +209,7 @@ struct nasal_val
nasal_vec* vec;
nasal_hash* hash;
nasal_func* func;
nasal_upval* upval;
nasal_obj* obj;
}ptr;
@@ -158,13 +233,12 @@ nasal_ref* nasal_vec::get_mem(const int index)
}
void nasal_vec::print()
{
static int depth=0;
if(!elems.size() || depth>8)
if(!elems.size() || printed)
{
std::cout<<(elems.size()?"[..]":"[]");
return;
}
++depth;
printed=true;
size_t iter=0;
std::cout<<'[';
for(auto& i:elems)
@@ -172,7 +246,7 @@ void nasal_vec::print()
i.print();
std::cout<<",]"[(++iter)==elems.size()];
}
--depth;
printed=false;
}
nasal_ref nasal_hash::get_val(const std::string& key)
@@ -184,10 +258,10 @@ nasal_ref nasal_hash::get_val(const std::string& key)
nasal_ref ret(vm_none);
nasal_ref val=elems["parents"];
if(val.type==vm_vec)
for(auto& i:val.vec()->elems)
for(auto& i:val.vec().elems)
{
if(i.type==vm_hash)
ret=i.hash()->get_val(key);
ret=i.hash().get_val(key);
if(ret.type!=vm_none)
return ret;
}
@@ -203,10 +277,10 @@ nasal_ref* nasal_hash::get_mem(const std::string& key)
nasal_ref* addr=nullptr;
nasal_ref val=elems["parents"];
if(val.type==vm_vec)
for(auto& i:val.vec()->elems)
for(auto& i:val.vec().elems)
{
if(i.type==vm_hash)
addr=i.hash()->get_mem(key);
addr=i.hash().get_mem(key);
if(addr)
return addr;
}
@@ -215,13 +289,12 @@ nasal_ref* nasal_hash::get_mem(const std::string& key)
}
void nasal_hash::print()
{
static int depth=0;
if(!elems.size() || depth>8)
if(!elems.size() || printed)
{
std::cout<<(elems.size()?"{..}":"{}");
return;
}
++depth;
printed=true;
size_t iter=0;
std::cout<<'{';
for(auto& i:elems)
@@ -230,7 +303,7 @@ void nasal_hash::print()
i.second.print();
std::cout<<",}"[(++iter)==elems.size()];
}
--depth;
printed=false;
}
void nasal_func::clear()
@@ -248,11 +321,12 @@ nasal_val::nasal_val(uint8_t val_type)
unmut=0;
switch(val_type)
{
case vm_str: ptr.str=new std::string; break;
case vm_vec: ptr.vec=new nasal_vec; break;
case vm_hash: ptr.hash=new nasal_hash; break;
case vm_func: ptr.func=new nasal_func; break;
case vm_obj: ptr.obj=new nasal_obj; break;
case vm_str: ptr.str=new std::string; break;
case vm_vec: ptr.vec=new nasal_vec; break;
case vm_hash: ptr.hash=new nasal_hash; break;
case vm_func: ptr.func=new nasal_func; break;
case vm_upval:ptr.upval=new nasal_upval;break;
case vm_obj: ptr.obj=new nasal_obj; break;
}
}
nasal_val::~nasal_val()
@@ -263,20 +337,26 @@ nasal_val::~nasal_val()
case vm_vec: delete ptr.vec; break;
case vm_hash: delete ptr.hash; break;
case vm_func: delete ptr.func; break;
case vm_upval:delete ptr.upval;break;
case vm_obj: delete ptr.obj; break;
}
type=vm_nil;
}
double nasal_ref::to_number()
{
return type!=vm_str?value.num:str2num(str()->c_str());
return type!=vm_str?value.num:str2num(str().c_str());
}
std::string nasal_ref::to_string()
{
if(type==vm_str)
return *str();
return str();
else if(type==vm_num)
return std::to_string(num());
{
std::string tmp=std::to_string(num());
tmp.erase(tmp.find_last_not_of('0')+1,std::string::npos);
tmp.erase(tmp.find_last_not_of('.')+1,std::string::npos);
return tmp;
}
return "";
}
void nasal_ref::print()
@@ -286,34 +366,47 @@ void nasal_ref::print()
case vm_none: std::cout<<"undefined"; break;
case vm_nil: std::cout<<"nil"; break;
case vm_num: std::cout<<value.num; break;
case vm_str: std::cout<<*(this->str());break;
case vm_vec: this->vec()->print(); break;
case vm_hash: this->hash()->print(); break;
case vm_str: std::cout<<str(); break;
case vm_vec: vec().print(); break;
case vm_hash: hash().print(); break;
case vm_func: std::cout<<"func(..){..}";break;
case vm_obj: std::cout<<"<object>"; break;
}
}
inline uint32_t nasal_ref::ret (){return value.ret; }
inline int64_t& nasal_ref::cnt (){return value.cnt; }
inline double& nasal_ref::num (){return value.num; }
inline std::string* nasal_ref::str (){return value.gcobj->ptr.str; }
inline nasal_vec* nasal_ref::vec (){return value.gcobj->ptr.vec; }
inline nasal_hash* nasal_ref::hash(){return value.gcobj->ptr.hash;}
inline nasal_func* nasal_ref::func(){return value.gcobj->ptr.func;}
inline nasal_obj* nasal_ref::obj (){return value.gcobj->ptr.obj; }
bool nasal_ref::objchk(uint32_t objtype)
{
return type==vm_obj && obj().type==objtype && obj().ptr;
}
inline nasal_ref* nasal_ref::addr (){return value.addr; }
inline uint32_t nasal_ref::ret (){return value.ret; }
inline int64_t& nasal_ref::cnt (){return value.cnt; }
inline double nasal_ref::num (){return value.num; }
inline std::string& nasal_ref::str (){return *value.gcobj->ptr.str; }
inline nasal_vec& nasal_ref::vec (){return *value.gcobj->ptr.vec; }
inline nasal_hash& nasal_ref::hash (){return *value.gcobj->ptr.hash; }
inline nasal_func& nasal_ref::func (){return *value.gcobj->ptr.func; }
inline nasal_upval& nasal_ref::upval(){return *value.gcobj->ptr.upval;}
inline nasal_obj& nasal_ref::obj (){return *value.gcobj->ptr.obj; }
const uint32_t STACK_MAX_DEPTH=4095;
const nasal_ref zero={vm_num,(double)0};
const nasal_ref one ={vm_num,(double)1};
const nasal_ref nil ={vm_nil,nullptr};
const nasal_ref nil ={vm_nil,(double)0};
struct nasal_gc
{
nasal_ref stack[STACK_MAX_DEPTH+1];// 1 reserved to avoid stack overflow
static const uint32_t stack_depth=8192; // depth of value stack
nasal_ref funcr; // function register
nasal_ref stack[stack_depth]; // the last one is reserved to avoid stack overflow
nasal_ref* top; // stack top
std::vector<nasal_ref> strs; // reserved address for const vm_str
std::vector<nasal_val*> memory; // gc memory
std::queue<nasal_val*> free_list[vm_type_size]; // gc free list
std::vector<nasal_ref> local;
/* upvalue is a temporary space to store upvalues */
/* if no new functions generated in local scope */
/* upvalue will pushback(nil) */
/* if new functions generated in local scope */
/* they will share the same upvalue stored here */
std::vector<nasal_ref> upvalue;
uint64_t size[vm_type_size];
uint64_t count[vm_type_size];
void mark();
@@ -329,7 +422,8 @@ struct nasal_gc
void nasal_gc::mark()
{
std::queue<nasal_ref> bfs;
for(auto& i:local)
bfs.push(funcr);
for(auto& i:upvalue)
bfs.push(i);
for(nasal_ref* i=stack;i<=top;++i)
bfs.push(*i);
@@ -342,19 +436,22 @@ void nasal_gc::mark()
switch(tmp.type)
{
case vm_vec:
for(auto& i:tmp.vec()->elems)
for(auto& i:tmp.vec().elems)
bfs.push(i);
break;
case vm_hash:
for(auto& i:tmp.hash()->elems)
for(auto& i:tmp.hash().elems)
bfs.push(i.second);
break;
case vm_func:
for(auto& i:tmp.func()->local)
for(auto& i:tmp.func().local)
bfs.push(i);
for(auto& i:tmp.func()->upvalue)
for(auto& i:tmp.func().upvalue)
bfs.push(i);
break;
case vm_upval:
for(auto& i:tmp.upval().elems)
bfs.push(i);
}
}
}
@@ -366,11 +463,12 @@ void nasal_gc::sweep()
{
switch(i->type)
{
case vm_str: i->ptr.str->clear(); break;
case vm_vec: i->ptr.vec->elems.clear(); break;
case vm_hash:i->ptr.hash->elems.clear();break;
case vm_func:i->ptr.func->clear(); break;
case vm_obj: i->ptr.obj->clear(); break;
case vm_str: i->ptr.str->clear(); break;
case vm_vec: i->ptr.vec->elems.clear(); break;
case vm_hash: i->ptr.hash->elems.clear();break;
case vm_func: i->ptr.func->clear(); break;
case vm_upval:i->ptr.upval->clear(); break;
case vm_obj: i->ptr.obj->clear(); break;
}
free_list[i->type].push(i);
i->mark=GC_COLLECTED;
@@ -381,10 +479,13 @@ void nasal_gc::sweep()
}
void nasal_gc::init(const std::vector<std::string>& s)
{
// initiaize function register
funcr=nil;
for(uint8_t i=0;i<vm_type_size;++i)
size[i]=count[i]=0;
for(uint8_t i=vm_str;i<vm_type_size;++i)
for(uint32_t j=0;j<increment[i];++j)
for(uint32_t j=0;j<initialize[i];++j)
{
nasal_val* tmp=new nasal_val(i);
memory.push_back(tmp);
@@ -397,7 +498,7 @@ void nasal_gc::init(const std::vector<std::string>& s)
{
strs[i]={vm_str,new nasal_val(vm_str)};
strs[i].value.gcobj->unmut=1;
*strs[i].str()=s[i];
strs[i].str()=s[i];
}
}
void nasal_gc::clear()
@@ -405,10 +506,10 @@ void nasal_gc::clear()
for(auto i:memory)
delete i;
memory.clear();
upvalue.clear();
for(uint8_t i=0;i<vm_type_size;++i)
while(!free_list[i].empty())
free_list[i].pop();
local.clear();
for(auto& i:strs)
delete i.value.gcobj;
strs.clear();
@@ -416,16 +517,17 @@ void nasal_gc::clear()
void nasal_gc::info()
{
const char* name[]={
"null","cnt ","ret ",
"nil ","num ","str ",
"func","vec ","hash","obj "
"null ","cnt ","addr ",
"ret ","nil ","num ",
"str ","func ","vec ",
"hash ","upval","obj "
};
std::cout<<"\ngarbage collector info:\n";
for(uint8_t i=vm_str;i<vm_type_size;++i)
std::cout<<name[i]<<" | "<<count[i]<<"\n";
std::cout<<" "<<name[i]<<" | "<<count[i]<<"\n";
std::cout<<"\nmemory allocator info(max size):\n";
for(uint8_t i=vm_str;i<vm_type_size;++i)
std::cout<<name[i]<<" | "<<(size[i]+1)*increment[i]<<"(+"<<size[i]<<")\n";
std::cout<<" "<<name[i]<<" | "<<initialize[i]+size[i]*increment[i]<<"(+"<<size[i]<<")\n";
}
nasal_ref nasal_gc::alloc(uint8_t type)
{

View File

@@ -4,15 +4,17 @@
class nasal_import
{
private:
bool lib_loaded;
nasal_err& nerr;
std::vector<std::string> files;
bool check_import(const nasal_ast&);
bool check_exist(const std::string&);
void linker(nasal_ast&,nasal_ast&&);
nasal_ast file_import(nasal_ast&);
nasal_ast lib_import();
nasal_ast load(nasal_ast&,uint16_t);
public:
nasal_import(nasal_err& e):nerr(e){}
nasal_import(nasal_err& e):lib_loaded(false),nerr(e){}
void link(nasal_parse&,const std::string&);
const std::vector<std::string>& get_file() const {return files;}
};
@@ -61,6 +63,51 @@ nasal_ast nasal_import::file_import(nasal_ast& node)
std::string filename=node[1][0].str();
node.clear();
// avoid infinite loading loop
if(check_exist(filename))
return {0,ast_root};
if(access(filename.c_str(),F_OK)==-1)
{
nerr.err("link","cannot open file <"+filename+">");
return {0,ast_root};
}
// start importing...
lex.scan(filename);
par.compile(lex);
nasal_ast tmp=std::move(par.ast());
// check if tmp has 'import'
return load(tmp,files.size()-1);
}
nasal_ast nasal_import::lib_import()
{
nasal_lexer lex(nerr);
nasal_parse par(nerr);
const std::vector<std::string> libpath=
{
"lib.nas",
"stl/lib.nas"
};
std::string filename="";
for(auto& i:libpath)
if(access(i.c_str(),F_OK)!=-1)
{
filename=i;
break;
}
if(!filename.length())
{
std::string paths="";
for(auto& i:libpath)
paths+=" "+i+"\n";
nerr.err("link","cannot find lib file in these paths:\n"+paths,' ');
nerr.chkerr();
return {0,ast_root};
}
// avoid infinite loading loop
if(check_exist(filename))
return {0,ast_root};
@@ -76,6 +123,11 @@ nasal_ast nasal_import::file_import(nasal_ast& node)
nasal_ast nasal_import::load(nasal_ast& root,uint16_t fileindex)
{
nasal_ast new_root(0,ast_root);
if(!lib_loaded)
{
linker(new_root,lib_import());
lib_loaded=true;
}
for(auto& i:root.child())
if(check_import(i))
linker(new_root,file_import(i));

View File

@@ -1,7 +1,7 @@
#ifndef __NASAL_LEXER_H__
#define __NASAL_LEXER_H__
#define ID(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z'))
#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')
@@ -93,12 +93,11 @@ struct token
uint32_t column;
uint32_t type;
std::string str;
token(uint32_t l=0,uint32_t c=0,uint32_t t=tok_null,std::string s="")
token(uint32_t l=0,uint32_t c=0,uint32_t t=tok_null,const std::string& s=""):str(s)
{
line=l;
column=c;
type=t;
str=s;
}
};
@@ -115,11 +114,12 @@ private:
uint32_t get_type(const std::string&);
void die(std::string info){nerr.err("lexer",line,column,info);};
void open(const std::string&);
std::string utf8_gen();
std::string id_gen();
std::string num_gen();
std::string str_gen();
public:
nasal_lexer(nasal_err& e):nerr(e){}
nasal_lexer(nasal_err& e):line(0),column(0),ptr(0),nerr(e){}
void scan(const std::string&);
void print();
const std::vector<token>& get_tokens() const {return tokens;}
@@ -127,9 +127,16 @@ public:
void nasal_lexer::open(const std::string& file)
{
struct stat buffer;
if(stat(file.c_str(),&buffer)==0 && !S_ISREG(buffer.st_mode))
{
nerr.err("lexer","<"+file+"> is not a regular file.");
res="";
return;
}
std::ifstream fin(file,std::ios::binary);
if(fin.fail())
nerr.err("lexer","cannot open file <"+file+">.");
nerr.err("lexer","failed to open <"+file+">.");
else
nerr.load(file);
std::stringstream ss;
@@ -145,12 +152,43 @@ uint32_t nasal_lexer::get_type(const std::string& tk_str)
return tok_null;
}
std::string nasal_lexer::utf8_gen()
{
std::string str="";
while(ptr<res.size() && res[ptr]<0)
{
std::string tmp="";
uint32_t nbytes=utf8_hdchk(res[ptr]);
if(nbytes)
{
tmp+=res[ptr++];
for(uint32_t i=0;i<nbytes;++i,++ptr)
if(ptr<res.size() && (res[ptr]&0xc0)==0x80)
tmp+=res[ptr];
if(tmp.length()!=1+nbytes)
die("invalid utf-8 character here");
str+=tmp;
++column;
}
else
++ptr;
}
return str;
}
std::string nasal_lexer::id_gen()
{
std::string str="";
while(ptr<res.size() && (ID(res[ptr])||DIGIT(res[ptr])))
str+=res[ptr++];
column+=str.length();
{
if(res[ptr]<0) // utf-8
str+=utf8_gen();
else // ascii
{
str+=res[ptr++];
++column;
}
}
return str;
}
@@ -239,6 +277,7 @@ std::string nasal_lexer::str_gen()
case '0': str+='\0'; break;
case 'a': str+='\a'; break;
case 'b': str+='\b'; break;
case 'e': str+='\e'; break;
case 't': str+='\t'; break;
case 'n': str+='\n'; break;
case 'v': str+='\v'; break;
@@ -276,7 +315,7 @@ void nasal_lexer::scan(const std::string& file)
std::string str;
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() && (res[ptr]==' ' || res[ptr]=='\n' || res[ptr]=='\t' || res[ptr]=='\r'))// || res[ptr]<0))
{
// these characters will be ignored, and '\n' will cause ++line
++column;

View File

@@ -37,6 +37,14 @@ void calc_const(nasal_ast& root)
auto& vec=root.child();
for(auto& i:vec)
calc_const(i);
if(vec.size()==1 && root.type()==ast_neg && vec[0].type()==ast_num)
{
double res=-vec[0].num();
root.set_num(res);
root.child().clear();
root.set_type(ast_num);
return;
}
if(vec.size()!=2)
return;
if(root.type()!=ast_add &&

View File

@@ -98,7 +98,7 @@ private:
nasal_ast break_expr();
nasal_ast ret_expr();
public:
nasal_parse(nasal_err& e):nerr(e){}
nasal_parse(nasal_err& e):ptr(0),in_func(0),in_loop(0),tokens(nullptr),nerr(e){}
void print(){root.print(0);}
void compile(const nasal_lexer&);
nasal_ast& ast(){return root;}

View File

@@ -6,10 +6,9 @@ class nasal_vm
protected:
/* values of nasal_vm */
uint32_t pc; // program counter
nasal_ref* localr; // local scope register
const double* num_table;// const numbers, ref from nasal_codegen
const std::string* str_table;// const symbols, ref from nasal_codegen
std::stack<nasal_func*> fstk; // stack to store function, used to get upvalues
std::stack<uint32_t> local_stk;
std::vector<uint32_t> imm; // immediate number
nasal_ref* mem_addr; // used for mem_call
/* garbage collector */
@@ -24,6 +23,7 @@ protected:
void init(
const std::vector<std::string>&,
const std::vector<double>&,
const std::vector<opcode>&,
const std::vector<std::string>&);
/* debug functions */
bool detail_info;
@@ -39,7 +39,7 @@ protected:
void die(std::string);
/* vm calculation functions*/
bool condition(nasal_ref);
void opr_nop();
/* vm operands */
void opr_intg();
void opr_intl();
void opr_loadg();
@@ -125,13 +125,20 @@ public:
void nasal_vm::init(
const std::vector<std::string>& strs,
const std::vector<double>& nums,
const std::vector<opcode>& code,
const std::vector<std::string>& filenames)
{
gc.init(strs);
num_table=nums.data();
str_table=strs.data();
bytecode=code.data();
files=filenames.data();
files_size=filenames.size();
/* set canary and program counter */
canary=gc.stack+nasal_gc::stack_depth-1; // gc.stack[nasal_gc::stack_depth-1]
mem_addr=nullptr;
pc=0;
localr=nullptr;
}
void nasal_vm::valinfo(nasal_ref& val)
{
@@ -140,41 +147,75 @@ void nasal_vm::valinfo(nasal_ref& val)
switch(val.type)
{
case vm_none: printf("| null |\n");break;
case vm_ret: printf("| addr | pc:0x%x\n",val.ret());break;
case vm_cnt: printf("| cnt | %ld\n",val.cnt());break;
case vm_ret: printf("| pc | 0x%x\n",val.ret());break;
case vm_addr: printf("| addr | 0x" PRTHEX64 "\n",(uint64_t)val.addr());break;
case vm_cnt: printf("| cnt | " PRTINT64 "\n",val.cnt());break;
case vm_nil: printf("| nil |\n");break;
case vm_num: printf("| num | ");std::cout<<val.num()<<'\n';break;
case vm_str: printf("| str | <0x%lx> %s\n",(uint64_t)p,rawstr(*val.str()).c_str());break;
case vm_func: printf("| func | <0x%lx> entry:0x%x\n",(uint64_t)p,val.func()->entry);break;
case vm_vec: printf("| vec | <0x%lx> [%lu val]\n",(uint64_t)p,val.vec()->elems.size());break;
case vm_hash: printf("| hash | <0x%lx> {%lu val}\n",(uint64_t)p,val.hash()->elems.size());break;
case vm_obj: printf("| obj | <0x%lx> obj:0x%lx\n",(uint64_t)p,(uint64_t)val.obj()->ptr);break;
default: printf("| err | <0x%lx> unknown object\n",(uint64_t)p);break;
case vm_str:
{
std::string tmp=rawstr(val.str());
printf("| str | <0x" PRTHEX64 "> %.16s%s\n",(uint64_t)p,tmp.c_str(),tmp.length()>16?"...":"");
}break;
case vm_func: printf("| func | <0x" PRTHEX64 "> entry:0x%x\n",(uint64_t)p,val.func().entry);break;
case vm_vec: printf("| vec | <0x" PRTHEX64 "> [%zu val]\n",(uint64_t)p,val.vec().size());break;
case vm_hash: printf("| hash | <0x" PRTHEX64 "> {%zu val}\n",(uint64_t)p,val.hash().size());break;
case vm_obj: printf("| obj | <0x" PRTHEX64 "> obj:0x" PRTHEX64 "\n",(uint64_t)p,(uint64_t)val.obj().ptr);break;
default: printf("| err | <0x" PRTHEX64 "> unknown object\n",(uint64_t)p);break;
}
}
void nasal_vm::bytecodeinfo(const char* header,const uint32_t p)
{
const opcode& c=bytecode[p];
printf("%s0x%.8x: %s 0x%x",header,p,code_table[c.op].name,c.num);
printf("%s0x%.8x: %.2x %.2x %.2x %.2x %.2x %s ",
header,
p,
c.op,
uint8_t((c.num>>24)&0xff),
uint8_t((c.num>>16)&0xff),
uint8_t((c.num>>8)&0xff),
uint8_t(c.num&0xff),
code_table[c.op].name
);
switch(c.op)
{
case op_addc: case op_subc: case op_mulc: case op_divc:
case op_addeq: case op_subeq: case op_muleq: case op_diveq:
case op_lnkeq: case op_meq:
printf("0x%x sp-%u",c.num,c.num);break;
case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc:
printf("0x%x (",c.num&0x7fffffff);
std::cout<<num_table[c.num&0x7fffffff]<<") sp-"<<(c.num>>31);
break;
case op_lnkeqc:
{
std::string tmp=rawstr(str_table[c.num&0x7fffffff]);
printf("0x%x (\"%.16s%s\") sp-%u",c.num&0x7fffffff,tmp.c_str(),tmp.length()>16?"...":"",c.num>>31);
}break;
case op_addc: case op_subc: case op_mulc: case op_divc:
case op_lessc: case op_leqc: case op_grtc: case op_geqc:
case op_pnum:
std::cout<<" ("<<num_table[c.num]<<")";break;
printf("0x%x (",c.num);std::cout<<num_table[c.num]<<")";break;
case op_callvi:case op_newv: case op_callfv:
case op_intg: case op_intl:
case op_newf: case op_jmp: case op_jt: case op_jf:
case op_callg: case op_mcallg: case op_loadg:
case op_calll: case op_mcalll: case op_loadl:
printf("0x%x",c.num);break;
case op_callb:
printf(" <%s@0x%lx>",builtin[c.num].name,(uint64_t)builtin[c.num].func);break;
printf("0x%x <%s@0x" PRTHEX64 ">",c.num,builtin[c.num].name,(uint64_t)builtin[c.num].func);break;
case op_upval: case op_mupval: case op_loadu:
printf(" (0x%x[0x%x])",(c.num>>16)&0xffff,c.num&0xffff);break;
case op_happ: case op_pstr:
case op_lnkc: case op_lnkeqc:
case op_lnkc:
case op_callh: case op_mcallh:
case op_para: case op_defpara:case op_dynpara:
printf(" (\"%s\")",rawstr(str_table[c.num]).c_str());break;
case op_upval:case op_mupval: case op_loadu:
printf(" (0x%x[0x%x])",(c.num>>16)&0xffff,c.num&0xffff);break;
default:break;
{
std::string tmp=rawstr(str_table[c.num]);
printf("0x%x (\"%.16s%s\")",c.num,tmp.c_str(),tmp.length()>16?"...":"");
}break;
default:printf("0x%x",c.num);break;
}
printf(" (%s:%d)\n",files[c.fidx].c_str(),c.line);
printf(" (%s:%u)\n",files[c.fidx].c_str(),c.line);
}
void nasal_vm::traceback()
{
@@ -197,78 +238,82 @@ void nasal_vm::traceback()
continue;
}
if(same)
printf("\t0x%.8x: %d same call(s)\n",last,same);
printf("\t0x%.8x: %u same call(s)\n",last,same);
same=0;
bytecodeinfo("\t",point);
}
if(same)
printf("\t0x%.8x: %d same call(s)\n",last,same);
printf("\t0x%.8x: %u same call(s)\n",last,same);
}
void nasal_vm::stackinfo(const uint32_t limit=10)
{
uint32_t global_size=bytecode[0].num; // bytecode[0] is op_intg
/* bytecode[0] is op_intg, the .num is the global size */
uint32_t gsize=bytecode[0].num;
nasal_ref* top=gc.top;
nasal_ref* bottom=gc.stack+global_size;
nasal_ref* bottom=gc.stack+gsize;
printf("vm stack(0x" PRTHEX64 "<sp+%u>, limit %u, total ",(uint64_t)bottom,gsize,limit);
if(top<bottom)
{
printf("vm stack(limit %d, total 0)\n",limit);
printf("0)\n");
return;
}
printf("vm stack(limit %d, total %ld):\n",limit,top-bottom+1);
printf("" PRTINT64 "):\n",(int64_t)(top-bottom+1));
for(uint32_t i=0;i<limit && top>=bottom;++i,--top)
{
printf(" 0x" PRTHEX64_8 "",(uint64_t)(top-gc.stack));
valinfo(top[0]);
}
}
void nasal_vm::global_state()
{
if(!bytecode[0].num || gc.stack[0].type==vm_none) // bytecode[0].op is op_intg
{
printf("no global value exists\n");
return;
}
printf("global:\n");
printf("global(0x" PRTHEX64 "<sp+0>):\n",(uint64_t)gc.stack);
for(uint32_t i=0;i<bytecode[0].num;++i)
{
printf("[0x%.8x]",i);
printf(" 0x%.8x",i);
valinfo(gc.stack[i]);
}
}
void nasal_vm::local_state()
{
if(gc.local.empty() || !gc.local.back().vec()->elems.size())
{
printf("no local value exists\n");
if(!localr || !gc.funcr.func().lsize)
return;
}
printf("local:\n");
auto& vec=gc.local.back().vec()->elems;
for(uint32_t i=0;i<vec.size();++i)
uint32_t lsize=gc.funcr.func().lsize;
printf("local(0x" PRTHEX64 "<sp+" PRTINT64 ">):\n",(uint64_t)localr,(int64_t)(localr-gc.stack));
for(uint32_t i=0;i<lsize;++i)
{
printf("[0x%.8x]",i);
valinfo(vec[i]);
printf(" 0x%.8x",i);
valinfo(localr[i]);
}
}
void nasal_vm::upval_state()
{
if(fstk.empty() || fstk.top()->upvalue.empty())
{
printf("no upvalue exists\n");
if(gc.funcr.type==vm_nil || gc.funcr.func().upvalue.empty())
return;
}
printf("upvalue:\n");
auto& upval=fstk.top()->upvalue;
auto& upval=gc.funcr.func().upvalue;
for(uint32_t i=0;i<upval.size();++i)
{
auto& vec=upval[i].vec()->elems;
for(uint32_t j=0;j<vec.size();++j)
printf(" -> upval[%u]:\n",i);
auto& uv=upval[i].upval();
for(uint32_t j=0;j<uv.size;++j)
{
printf("[%.4x][%.4x]",i,j);
valinfo(vec[j]);
printf(" 0x%.8x",j);
valinfo(uv[j]);
}
}
}
void nasal_vm::detail()
{
printf("mcall address: 0x%lx\n",(uint64_t)mem_addr);
printf("maddr:\n (0x" PRTHEX64 ")\n",(uint64_t)mem_addr);
printf("localr:\n (0x" PRTHEX64 ")\n",(uint64_t)localr);
if(gc.funcr.type==vm_nil)
printf("funcr:\n (nil)\n");
else
printf("funcr:\n (<0x" PRTHEX64 "> entry:0x%x)\n",
(uint64_t)gc.funcr.value.gcobj,
gc.funcr.func().entry);
global_state();
local_state();
upval_state();
@@ -277,22 +322,23 @@ void nasal_vm::opcallsort(const uint64_t* arr)
{
typedef std::pair<uint32_t,uint64_t> op;
std::vector<op> opcall;
for(uint32_t i=0;i<=op_exit;++i)
for(uint32_t i=0;i<=op_ret;++i)
opcall.push_back({i,arr[i]});
std::sort(
opcall.begin(),
opcall.end(),
[](op& a,op& b){return a.second>b.second;}
);
std::cout<<"\noperands call info:";
uint64_t total=0;
for(auto& i:opcall)
{
if(!i.second)
break;
total+=i.second;
std::cout<<'\n'<<code_table[i.first].name<<": "<<i.second;
std::cout<<"\n "<<code_table[i.first].name<<" : "<<i.second;
}
std::cout<<"\ntotal : "<<total<<'\n';
std::cout<<"\n total : "<<total<<'\n';
}
void nasal_vm::die(std::string str)
{
@@ -309,14 +355,13 @@ inline bool nasal_vm::condition(nasal_ref val)
return val.value.num;
else if(val.type==vm_str)
{
double num=str2num(val.str()->c_str());
double num=str2num(val.str().c_str());
if(std::isnan(num))
return !val.str()->empty();
return !val.str().empty();
return num;
}
return false;
}
inline void nasal_vm::opr_nop(){}
inline void nasal_vm::opr_intg()
{
// global values store on stack
@@ -326,8 +371,8 @@ inline void nasal_vm::opr_intg()
}
inline void nasal_vm::opr_intl()
{
gc.top[0].func()->local.resize(imm[pc],nil);
gc.top[0].func()->lsize=imm[pc];
gc.top[0].func().local.resize(imm[pc],nil);
gc.top[0].func().lsize=imm[pc];
}
inline void nasal_vm::opr_loadg()
{
@@ -335,11 +380,11 @@ inline void nasal_vm::opr_loadg()
}
inline void nasal_vm::opr_loadl()
{
gc.local.back().vec()->elems[imm[pc]]=(gc.top--)[0];
localr[imm[pc]]=(gc.top--)[0];
}
inline void nasal_vm::opr_loadu()
{
fstk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]=(gc.top--)[0];
gc.funcr.func().upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]=(gc.top--)[0];
}
inline void nasal_vm::opr_pnum()
{
@@ -347,7 +392,7 @@ inline void nasal_vm::opr_pnum()
}
inline void nasal_vm::opr_pnil()
{
(++gc.top)[0]={vm_nil,(double)0};
(++gc.top)[0]=nil;
}
inline void nasal_vm::opr_pstr()
{
@@ -356,7 +401,7 @@ inline void nasal_vm::opr_pstr()
inline void nasal_vm::opr_newv()
{
nasal_ref newv=gc.alloc(vm_vec);
auto& vec=newv.vec()->elems;
auto& vec=newv.vec().elems;
vec.resize(imm[pc]);
// use top-=imm[pc]-1 here will cause error if imm[pc] is 0
gc.top=gc.top-imm[pc]+1;
@@ -371,36 +416,42 @@ inline void nasal_vm::opr_newh()
inline void nasal_vm::opr_newf()
{
(++gc.top)[0]=gc.alloc(vm_func);
nasal_func* func=gc.top[0].func();
func->entry=imm[pc];
func->psize=1;
if(!gc.local.empty())
nasal_func& func=gc.top[0].func();
func.entry=imm[pc];
func.psize=1;
/* this means you create a new function in local scope */
if(localr)
{
func->upvalue=fstk.top()->upvalue;
func->upvalue.push_back(gc.local.back());
func.upvalue=gc.funcr.func().upvalue;
nasal_ref upval=(gc.upvalue.back().type==vm_nil)?gc.alloc(vm_upval):gc.upvalue.back();
upval.upval().size=gc.funcr.func().lsize;
upval.upval().stk=localr;
func.upvalue.push_back(upval);
gc.upvalue.back()=upval;
}
}
inline void nasal_vm::opr_happ()
{
gc.top[-1].hash()->elems[str_table[imm[pc]]]=gc.top[0];
gc.top[-1].hash().elems[str_table[imm[pc]]]=gc.top[0];
--gc.top;
}
inline void nasal_vm::opr_para()
{
nasal_func* func=gc.top[0].func();
func->keys[str_table[imm[pc]]]=func->psize;// func->size has 1 place reserved for "me"
func->local[func->psize++]={vm_none};
nasal_func& func=gc.top[0].func();
func.keys[str_table[imm[pc]]]=func.psize;// func->size has 1 place reserved for "me"
func.local[func.psize++]={vm_none};
}
inline void nasal_vm::opr_defpara()
{
nasal_ref val=gc.top[0];
nasal_func* func=(--gc.top)[0].func();
func->keys[str_table[imm[pc]]]=func->psize;// func->size has 1 place reserved for "me"
func->local[func->psize++]=val;
nasal_func& func=(--gc.top)[0].func();
func.keys[str_table[imm[pc]]]=func.psize;// func->size has 1 place reserved for "me"
func.local[func.psize++]=val;
}
inline void nasal_vm::opr_dynpara()
{
gc.top[0].func()->dynpara=imm[pc];
gc.top[0].func().dynpara=imm[pc];
}
inline void nasal_vm::opr_unot()
{
@@ -411,9 +462,9 @@ inline void nasal_vm::opr_unot()
case vm_num:gc.top[0]=val.num()?zero:one;break;
case vm_str:
{
double num=str2num(val.str()->c_str());
double num=str2num(val.str().c_str());
if(std::isnan(num))
gc.top[0]={vm_num,(double)val.str()->empty()};
gc.top[0]={vm_num,(double)val.str().empty()};
else
gc.top[0]=num?zero:one;
}
@@ -437,7 +488,7 @@ inline void nasal_vm::opr_div(){op_calc(/);}
inline void nasal_vm::opr_lnk()
{
nasal_ref val=gc.alloc(vm_str);
*val.str()=gc.top[-1].to_string()+gc.top[0].to_string();
val.str()=gc.top[-1].to_string()+gc.top[0].to_string();
(--gc.top)[0]=val;
}
@@ -452,13 +503,15 @@ inline void nasal_vm::opr_divc(){op_calc_const(/);}
inline void nasal_vm::opr_lnkc()
{
nasal_ref val=gc.alloc(vm_str);
*val.str()=gc.top[0].to_string()+str_table[imm[pc]];
val.str()=gc.top[0].to_string()+str_table[imm[pc]];
gc.top[0]=val;
}
#define op_calc_eq(type)\
nasal_ref val(vm_num,mem_addr[0].to_number() type gc.top[-1].to_number());\
(--gc.top)[0]=mem_addr[0]=val;
(--gc.top)[0]=mem_addr[0]=val;\
mem_addr=nullptr;\
gc.top-=imm[pc];
inline void nasal_vm::opr_addeq(){op_calc_eq(+);}
inline void nasal_vm::opr_subeq(){op_calc_eq(-);}
@@ -467,13 +520,17 @@ inline void nasal_vm::opr_diveq(){op_calc_eq(/);}
inline void nasal_vm::opr_lnkeq()
{
nasal_ref val=gc.alloc(vm_str);
*val.str()=mem_addr[0].to_string()+gc.top[-1].to_string();
val.str()=mem_addr[0].to_string()+gc.top[-1].to_string();
(--gc.top)[0]=mem_addr[0]=val;
mem_addr=nullptr;
gc.top-=imm[pc];
}
#define op_calc_eq_const(type)\
nasal_ref val(vm_num,mem_addr[0].to_number() type num_table[imm[pc]]);\
gc.top[0]=mem_addr[0]=val;
nasal_ref val(vm_num,mem_addr[0].to_number() type num_table[imm[pc]&0x7fffffff]);\
gc.top[0]=mem_addr[0]=val;\
mem_addr=nullptr;\
gc.top-=(imm[pc]>>31);
inline void nasal_vm::opr_addeqc(){op_calc_eq_const(+);}
inline void nasal_vm::opr_subeqc(){op_calc_eq_const(-);}
@@ -482,13 +539,22 @@ inline void nasal_vm::opr_diveqc(){op_calc_eq_const(/);}
inline void nasal_vm::opr_lnkeqc()
{
nasal_ref val=gc.alloc(vm_str);
*val.str()=mem_addr[0].to_string()+str_table[imm[pc]];
val.str()=mem_addr[0].to_string()+str_table[imm[pc]&0x7fffffff];
gc.top[0]=mem_addr[0]=val;
mem_addr=nullptr;
gc.top-=(imm[pc]>>31);
}
inline void nasal_vm::opr_meq()
{
// pop old mem_addr[0] and replace it
// the reason why we should get mem_addr and push the old value on stack
// is that when lnkeq/lnkeqc is called, there will be
// a new gc object vm_str which is returned by gc::alloc
// this may cause gc, so we should temporarily put it on stack
mem_addr[0]=(--gc.top)[0];
mem_addr=nullptr;
gc.top-=imm[pc];
}
inline void nasal_vm::opr_eq()
{
@@ -497,8 +563,9 @@ inline void nasal_vm::opr_eq()
if(val1.type==vm_nil && val2.type==vm_nil)
gc.top[0]=one;
else if(val1.type==vm_str && val2.type==vm_str)
gc.top[0]=(*val1.str()==*val2.str())?one:zero;
else if(val1.type==vm_num || val2.type==vm_num)
gc.top[0]=(val1.str()==val2.str())?one:zero;
else if((val1.type==vm_num || val2.type==vm_num)
&& val1.type!=vm_nil && val2.type!=vm_nil)
gc.top[0]=(val1.to_number()==val2.to_number())?one:zero;
else
gc.top[0]=(val1==val2)?one:zero;
@@ -510,8 +577,9 @@ inline void nasal_vm::opr_neq()
if(val1.type==vm_nil && val2.type==vm_nil)
gc.top[0]=zero;
else if(val1.type==vm_str && val2.type==vm_str)
gc.top[0]=(*val1.str()!=*val2.str())?one:zero;
else if(val1.type==vm_num || val2.type==vm_num)
gc.top[0]=(val1.str()!=val2.str())?one:zero;
else if((val1.type==vm_num || val2.type==vm_num)
&& val1.type!=vm_nil && val2.type!=vm_nil)
gc.top[0]=(val1.to_number()!=val2.to_number())?one:zero;
else
gc.top[0]=(val1!=val2)?one:zero;
@@ -561,7 +629,7 @@ inline void nasal_vm::opr_counter()
}
inline void nasal_vm::opr_findex()
{
if(++gc.top[0].cnt()>=gc.top[-1].vec()->elems.size())
if((size_t)(++gc.top[0].cnt())>=gc.top[-1].vec().size())
{
pc=imm[pc]-1;
return;
@@ -571,8 +639,8 @@ inline void nasal_vm::opr_findex()
}
inline void nasal_vm::opr_feach()
{
std::vector<nasal_ref>& ref=gc.top[-1].vec()->elems;
if(++gc.top[0].cnt()>=ref.size())
std::vector<nasal_ref>& ref=gc.top[-1].vec().elems;
if((size_t)(++gc.top[0].cnt())>=ref.size())
{
pc=imm[pc]-1;
return;
@@ -586,11 +654,11 @@ inline void nasal_vm::opr_callg()
}
inline void nasal_vm::opr_calll()
{
(++gc.top)[0]=gc.local.back().vec()->elems[imm[pc]];
(++gc.top)[0]=localr[imm[pc]];
}
inline void nasal_vm::opr_upval()
{
(++gc.top)[0]=fstk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff];
(++gc.top)[0]=gc.funcr.func().upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff];
}
inline void nasal_vm::opr_callv()
{
@@ -598,7 +666,7 @@ inline void nasal_vm::opr_callv()
nasal_ref vec=(--gc.top)[0];
if(vec.type==vm_vec)
{
gc.top[0]=vec.vec()->get_val(val.to_number());
gc.top[0]=vec.vec().get_val(val.to_number());
if(gc.top[0].type==vm_none)
die("callv: index out of range:"+std::to_string(val.to_number()));
}
@@ -606,15 +674,15 @@ inline void nasal_vm::opr_callv()
{
if(val.type!=vm_str)
die("callv: must use string as the key");
gc.top[0]=vec.hash()->get_val(*val.str());
gc.top[0]=vec.hash().get_val(val.str());
if(gc.top[0].type==vm_none)
die("callv: cannot find member \""+*val.str()+"\" of this hash");
die("callv: cannot find member \""+val.str()+"\" of this hash");
if(gc.top[0].type==vm_func)
gc.top[0].func()->local[0]=val;// 'me'
gc.top[0].func().local[0]=val;// 'me'
}
else if(vec.type==vm_str)
{
std::string& str=*vec.str();
std::string& str=vec.str();
int num=val.to_number();
int str_size=str.length();
if(num<-str_size || num>=str_size)
@@ -631,7 +699,7 @@ inline void nasal_vm::opr_callvi()
die("callvi: must use a vector");
// cannot use operator[],because this may cause overflow
(++gc.top)[0]=val.vec()->get_val(imm[pc]);
(++gc.top)[0]=val.vec().get_val(imm[pc]);
if(gc.top[0].type==vm_none)
die("callvi: index out of range:"+std::to_string(imm[pc]));
}
@@ -641,70 +709,75 @@ inline void nasal_vm::opr_callh()
if(val.type!=vm_hash)
die("callh: must call a hash");
gc.top[0]=val.hash()->get_val(str_table[imm[pc]]);
gc.top[0]=val.hash().get_val(str_table[imm[pc]]);
if(gc.top[0].type==vm_none)
die("callh: member \""+str_table[imm[pc]]+"\" does not exist");
if(gc.top[0].type==vm_func)
gc.top[0].func()->local[0]=val;// 'me'
gc.top[0].func().local[0]=val;// 'me'
}
inline void nasal_vm::opr_callfv()
{
uint32_t argc=imm[pc]; // arguments counter
nasal_ref* args=gc.top-argc+1;// arguments begin place
if(args[-1].type!=vm_func)
uint32_t argc=imm[pc]; // arguments counter
nasal_ref* local=gc.top-argc+1;// arguments begin address
if(local[-1].type!=vm_func)
die("callfv: must call a function");
nasal_func* func=args[-1].func();
if(gc.top+func->lsize>=canary)
die("stackoverflow");
fstk.push(func);// push called function into stack to provide upvalue
gc.local.push_back(gc.alloc(vm_vec)); // get new vector as local scope
gc.local.back().vec()->elems=func->local;// copy data from func.local to local scope
auto& local=gc.local.back().vec()->elems;
auto& func=local[-1].func();
nasal_ref tmp=local[-1];
local[-1]=gc.funcr;
gc.funcr=tmp;
if(gc.top-argc+func.lsize+2>=canary) // gc.top-argc+lsize(local) +1(old pc) +1(old localr)
die("stack overflow");
uint32_t psize=func->psize-1;// parameter size is func->psize-1, 1 is reserved for "me"
// load arguments
// if the first default value is not vm_none,then values after it are not nullptr
// args_size+1 is because the first space is reserved for 'me'
if(argc<psize && func->local[argc+1].type==vm_none)
uint32_t psize=func.psize-1; // parameter size is func->psize-1, 1 is reserved for "me"
if(argc<psize && func.local[argc+1].type==vm_none)
die("callfv: lack argument(s)");
// if args_size>para_size,for 0 to args_size will cause corruption
uint32_t min_size=std::min(psize,argc);
for(uint32_t i=0;i<min_size;++i)
local[i+1]=args[i];
// load dynamic argument if args_size>=para_size
if(func->dynpara>=0)
nasal_ref dynamic=nil;
gc.top=local+func.lsize;
if(func.dynpara>=0)// load dynamic arguments
{
nasal_ref vec=gc.alloc(vm_vec);
dynamic=gc.alloc(vm_vec);
for(uint32_t i=psize;i<argc;++i)
vec.vec()->elems.push_back(args[i]);
local[min_size+1]=vec;
dynamic.vec().elems.push_back(local[i]);
}
gc.top-=argc; // pop arguments
uint32_t min_size=std::min(psize,argc);
for(uint32_t i=min_size;i>=1;--i)// load arguments
local[i]=local[i-1];
local[0]=func.local[0];// load "me"
for(uint32_t i=min_size+1;i<func.lsize;++i)// load local scope & default arguments
local[i]=func.local[i];
if(func.dynpara>=0)
local[psize+1]=dynamic;
gc.top[0]={vm_addr,localr};
(++gc.top)[0]={vm_ret,pc};
pc=func->entry-1;
pc=func.entry-1;
localr=local;
gc.upvalue.push_back(nil);
}
inline void nasal_vm::opr_callfh()
{
auto& hash=gc.top[0].hash()->elems;
auto& hash=gc.top[0].hash().elems;
if(gc.top[-1].type!=vm_func)
die("callfh: must call a function");
// push function and new local scope
nasal_func* func=gc.top[-1].func();
if(gc.top+func->lsize>=canary)
die("stackoverflow");
if(func->dynpara>=0)
die("callfh: special call cannot use dynamic argument");
fstk.push(func);
gc.local.push_back(gc.alloc(vm_vec));
gc.local.back().vec()->elems=func->local;
auto& local=gc.local.back().vec()->elems;
auto& func=gc.top[-1].func();
nasal_ref tmp=gc.top[-1];
gc.top[-1]=gc.funcr;
gc.funcr=tmp;
if(gc.top+func.lsize+1>=canary) // gc.top -1(hash) +lsize(local) +1(old pc) +1(old localr)
die("stack overflow");
if(func.dynpara>=0)
die("callfh: special call cannot use dynamic argument");
nasal_ref* local=gc.top;
gc.top+=func.lsize;
for(uint32_t i=0;i<func.lsize;++i)
local[i]=func.local[i];
for(auto& i:func->keys)
for(auto& i:func.keys)
{
if(hash.count(i.first))
local[i.second]=hash[i.first];
@@ -712,17 +785,21 @@ inline void nasal_vm::opr_callfh()
die("callfh: lack argument(s): \""+i.first+"\"");
}
gc.top[0]={vm_ret,(uint32_t)pc}; // rewrite top with vm_ret
pc=func->entry-1;
gc.top[0]={vm_addr,localr};
(++gc.top)[0]={vm_ret,pc}; // rewrite top with vm_ret
pc=func.entry-1;
localr=local;
gc.upvalue.push_back(nil);
}
inline void nasal_vm::opr_callb()
{
(++gc.top)[0]=(*builtin[imm[pc]].func)(gc.local.back().vec()->elems,gc);
(++gc.top)[0]=(*builtin[imm[pc]].func)(localr,gc);
if(gc.top[0].type==vm_none)
die("native function error.");
}
inline void nasal_vm::opr_slcbegin()
{
// +--------------+
// | slice_vector | <-- gc.top[0]
// +--------------+
// | resource_vec | <-- gc.top[-1]
@@ -739,17 +816,17 @@ inline void nasal_vm::opr_slcend()
inline void nasal_vm::opr_slc()
{
nasal_ref val=(gc.top--)[0];
nasal_ref res=gc.top[-1].vec()->get_val(val.to_number());
nasal_ref res=gc.top[-1].vec().get_val(val.to_number());
if(res.type==vm_none)
die("slc: index out of range:"+std::to_string(val.to_number()));
gc.top[0].vec()->elems.push_back(res);
gc.top[0].vec().elems.push_back(res);
}
inline void nasal_vm::opr_slc2()
{
nasal_ref val2=(gc.top--)[0];
nasal_ref val1=(gc.top--)[0];
std::vector<nasal_ref>& ref=gc.top[-1].vec()->elems;
std::vector<nasal_ref>& aim=gc.top[0].vec()->elems;
std::vector<nasal_ref>& ref=gc.top[-1].vec().elems;
std::vector<nasal_ref>& aim=gc.top[0].vec().elems;
uint8_t type1=val1.type,type2=val2.type;
int num1=val1.to_number();
@@ -765,8 +842,8 @@ inline void nasal_vm::opr_slc2()
else if(type1!=vm_nil && type2==vm_nil)
num2=num1<0? -1:size-1;
if(num1>=num2)
die("slc2: begin index must be less than end index");
if(num1>num2)
die("slc2: begin index must be less than or equal to end index");
else if(num1<-size || num1>=size)
die("slc2: begin index out of range: "+std::to_string(num1));
else if(num2<-size || num2>=size)
@@ -779,16 +856,22 @@ inline void nasal_vm::opr_mcallg()
{
mem_addr=gc.stack+imm[pc];
(++gc.top)[0]=mem_addr[0];
// push value in this memory space on stack
// to avoid being garbage collected
}
inline void nasal_vm::opr_mcalll()
{
mem_addr=&(gc.local.back().vec()->elems[imm[pc]]);
mem_addr=localr+imm[pc];
(++gc.top)[0]=mem_addr[0];
// push value in this memory space on stack
// to avoid being garbage collected
}
inline void nasal_vm::opr_mupval()
{
mem_addr=&fstk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff];
mem_addr=&(gc.funcr.func().upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]);
(++gc.top)[0]=mem_addr[0];
// push value in this memory space on stack
// to avoid being garbage collected
}
inline void nasal_vm::opr_mcallv()
{
@@ -796,7 +879,7 @@ inline void nasal_vm::opr_mcallv()
nasal_ref vec=(--gc.top)[0];
if(vec.type==vm_vec)
{
mem_addr=vec.vec()->get_mem(val.to_number());
mem_addr=vec.vec().get_mem(val.to_number());
if(!mem_addr)
die("mcallv: index out of range:"+std::to_string(val.to_number()));
}
@@ -804,12 +887,12 @@ inline void nasal_vm::opr_mcallv()
{
if(val.type!=vm_str)
die("mcallv: must use string as the key");
nasal_hash& ref=*vec.hash();
std::string& str=*val.str();
nasal_hash& ref=vec.hash();
std::string& str=val.str();
mem_addr=ref.get_mem(str);
if(!mem_addr)
{
ref.elems[str]={vm_nil};
ref.elems[str]=nil;
mem_addr=ref.get_mem(str);
}
}
@@ -821,30 +904,51 @@ inline void nasal_vm::opr_mcallh()
nasal_ref hash=gc.top[0];
if(hash.type!=vm_hash)
die("mcallh: must call a hash");
nasal_hash& ref=*hash.hash();
nasal_hash& ref=hash.hash();
const std::string& str=str_table[imm[pc]];
mem_addr=ref.get_mem(str);
if(!mem_addr) // create a new key
{
ref.elems[str]={vm_nil};
ref.elems[str]=nil;
mem_addr=ref.get_mem(str);
}
}
inline void nasal_vm::opr_ret()
{
// +-----------------+
// | return value | <- gc.top[0]
// +-----------------+
// | return address | <- gc.top[-1]
// | old pc | <- gc.top[-1]
// +-----------------+
// | called function | <- gc.top[-2] funct is set on stack because gc may mark it
// | old localr | <- gc.top[-2]
// +-----------------+
pc=gc.top[-1].ret();
gc.top[-2].func()->local[0]={vm_nil,nullptr}; // get func and set 'me' to nil
gc.top[-2]=gc.top[0]; // rewrite func with returned value
gc.top-=2;
// | local scope |
// | ... |
// +-----------------+ <- local pointer stored in localr
// | old funcr | <- old function stored in gc.funcr
// +-----------------+
nasal_ref ret=gc.top[0];
nasal_ref* local=localr;
nasal_ref func=gc.funcr;
fstk.pop();
gc.local.pop_back();
pc=gc.top[-1].ret();
localr=gc.top[-2].addr();
gc.top=local-1;
func.func().local[0]=nil;// get func and set 'me' to nil
gc.funcr=gc.top[0];
gc.top[0]=ret; // rewrite func with returned value
if(gc.upvalue.back().type==vm_upval) // synchronize upvalue
{
auto& upval=gc.upvalue.back().upval();
auto size=func.func().lsize;
upval.onstk=false;
for(uint32_t i=0;i<size;++i)
upval.elems.push_back(local[i]);
}
gc.upvalue.pop_back();
}
void nasal_vm::run(
const nasal_codegen& gen,
@@ -853,11 +957,11 @@ void nasal_vm::run(
const bool detail)
{
detail_info=detail;
init(gen.get_strs(),gen.get_nums(),linker.get_file());
uint64_t count[op_exit+1]={0};
init(gen.get_strs(),gen.get_nums(),gen.get_code(),linker.get_file());
uint64_t count[op_ret+1]={0};
const void* opr_table[]=
{
&&nop, &&intg, &&intl, &&loadg,
&&vmexit, &&intg, &&intl, &&loadg,
&&loadl, &&loadu, &&pnum, &&pnil,
&&pstr, &&newv, &&newh, &&newf,
&&happ, &&para, &&defpara,&&dynpara,
@@ -875,19 +979,14 @@ void nasal_vm::run(
&&callvi, &&callh, &&callfv, &&callfh,
&&callb, &&slcbegin, &&slcend, &&slc,
&&slc2, &&mcallg, &&mcalll, &&mupval,
&&mcallv, &&mcallh, &&ret, &&vmexit
&&mcallv, &&mcallh, &&ret
};
bytecode=gen.get_code().data();
std::vector<const void*> code;
for(auto& i:gen.get_code())
{
code.push_back(opr_table[i.op]);
imm.push_back(i.num);
}
// set canary and program counter
canary=gc.stack+STACK_MAX_DEPTH-1;
pc=0;
// goto the first operand
goto *code[pc];
@@ -906,7 +1005,6 @@ vmexit:
// do not cause stackoverflow
#define exec_opnodie(op,num) {op();++count[num];goto *code[++pc];}
nop: exec_opnodie(opr_nop ,op_nop ); // 0
intg: exec_opnodie(opr_intg ,op_intg ); // +imm[pc] (detected at codegen)
intl: exec_opnodie(opr_intl ,op_intl ); // -0
loadg: exec_opnodie(opr_loadg ,op_loadg ); // -1
@@ -968,8 +1066,8 @@ upval: exec_operand(opr_upval ,op_upval ); // +1
callv: exec_opnodie(opr_callv ,op_callv ); // -0
callvi: exec_opnodie(opr_callvi ,op_callvi ); // -0
callh: exec_opnodie(opr_callh ,op_callh ); // -0
callfv: exec_operand(opr_callfv ,op_callfv ); // +1-imm[pc] call this will push >=0 arguments
callfh: exec_opnodie(opr_callfh ,op_callfh ); // -0 call this will push one hash
callfv: exec_opnodie(opr_callfv ,op_callfv ); // check in the function
callfh: exec_opnodie(opr_callfh ,op_callfh ); // check in the function
callb: exec_opnodie(opr_callb ,op_callb ); // -0
slcbegin:exec_operand(opr_slcbegin,op_slcbegin); // +1
slcend: exec_opnodie(opr_slcend ,op_slcend ); // -1

BIN
pic/mandelbrot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

26
stl/file.nas Normal file
View File

@@ -0,0 +1,26 @@
# lib file.nas
# ValKmjolnir 2022/3/6
import("lib.nas");
var file={
SEEK_SET:io.SEEK_SET,
SEEK_CUR:io.SEEK_CUR,
SEEK_END:io.SEEK_END,
new: func(filename,mode="r"){
var fd=io.open(filename,mode);
return {
close: func(){io.close(fd);},
read: func(len){
var buf=mut("");
io.read(fd,buf,len);
return buf;
},
write: func(str){return io.write(fd,str);},
seek: func(pos,whence){return io.seek(fd,pos,whence);},
tell: func(){return io.tell(fd);},
readln: func(){return io.readln(fd);},
stat: func(){return io.stat(filename);},
eof: func(){return io.eof(fd);}
};
}
};

View File

@@ -34,11 +34,11 @@ var input=func(){
return __builtin_input();
}
# split a string by delimiter for example:
# split a string by separator for example:
# split("ll","hello world") -> ["he","o world"]
# this function will return a vector.
var split=func(deli,str){
return __builtin_split(deli,str);
var split=func(separator,str){
return __builtin_split(separator,str);
}
# rand has the same function as the rand in C
@@ -60,6 +60,22 @@ var int=func(val){
return __builtin_int(val);
}
# floor will get the integral number of input argument
# which is less than or equal to this argument
var floor=func(val){
return __builtin_floor(val);
}
# abort using std::abort
var abort=func(){
__builtin_abort();
}
# abs gets absolute number.
var abs=func(n){
return n>0?n:-n;
}
# num will change all the other types into number.
# mostly used to change a numerable string.
var num=func(val){
@@ -105,6 +121,9 @@ var keys=func(hash){
var time=func(begin){
return __builtin_time(begin);
}
var systime=func(){
return time(0);
}
# die is a special native function.
# use it at where you want the program to crash immediately.
@@ -112,12 +131,22 @@ var die=func(str){
return __builtin_die(str);
}
# find will give the first position of the needle in haystack
var find=func(needle,haystack){
return __builtin_find(needle,haystack);
}
# typeof is used to get the type of an object.
# this function returns a string.
var typeof=func(object){
return __builtin_type(object);
}
# subvec is used to get part of a vector
var subvec=func(vec,begin,length=nil){
return vec[begin:(length==nil?nil:begin+length-1)];
}
# substr will get the sub-string.
# it gets the string, the begin index and sub-string's length as arguments.
var substr=func(str,begin,len){
@@ -154,6 +183,22 @@ var chr=func(code){
return __builtin_chr(code);
}
# mut is used to change unmutable strings to mutable.
var mut=func(str){
return str~"";
}
# srand wraps up rand, using time(0) as the seed.
var srand=func(){
rand(time(0));
return 0;
}
# values() gets all values in a hash.
var values=func(hash){
return __builtin_values(hash);
}
# println has the same function as print.
# but it will output a '\n' after using print.
var println=func(elems...){
@@ -162,6 +207,71 @@ var println=func(elems...){
return __builtin_print(elems);
}
var isfunc=func(f){
return typeof(f)=="func";
}
var isghost=func(g){
die("this runtime has no ghost object");
return 0;
}
var ishash=func(h){
return typeof(h)=="hash";
}
var isint=func(x){
return x==floor(x);
}
var isnum=func(x){
return typeof(x)=="num" or !math.isnan(num(x));
}
var isscalar=func(s){
var t=typeof(s);
return (t=="num" or t=="str")?1:0;
}
var isstr=func(s){
return typeof(s)=="str";
}
var isvec=func(v){
return typeof(v)=="vec";
}
# get the index of val in the vec
var vecindex=func(vec,val){
forindex(var i;vec)
if(val==vec[i])
return i;
return nil;
}
# check if the object is an instance of the class
var isa=func(object,class){
if(!contains(object,"parents") or typeof(object.parents)!="vec")
return 0;
foreach(var elem;object.parents)
if(elem==class)
return 1;
return 0;
}
# assert aborts when condition is not true
var assert=func(condition,message="assertion failed!"){
if(condition)
return 1;
die(message);
}
# md5
var md5=func(str){
return __builtin_md5(str);
}
var io=
{
SEEK_SET:0,
@@ -176,6 +286,7 @@ var io=
# same as C fclose. close file by FILE*.
close: func(filehandle){return __builtin_close(filehandle);},
# same as C fread. read file by FILE*.
# caution: buf must be a mutable string.use mut("") to get an empty mutable string.
read: func(filehandle,buf,len){return __builtin_read(filehandle,buf,len);},
# same as C fwrite. write file by FILE*.
write: func(filehandle,str){return __builtin_write(filehandle,str);},
@@ -252,6 +363,9 @@ var math=
pi: 3.14159265358979323846264338327950288,
inf: 1/0,
nan: 0/0,
abs: func(x) {return x>0?x:-x; },
floor: func(x) {return __builtin_floor(x); },
pow: func(x,y){return __builtin_pow(x,y); },
sin: func(x) {return __builtin_sin(x); },
cos: func(x) {return __builtin_cos(x); },
tan: func(x) {return __builtin_tan(x); },
@@ -260,16 +374,18 @@ var math=
ln: func(x) {return __builtin_ln(x); },
sqrt: func(x) {return __builtin_sqrt(x); },
atan2: func(x,y){return __builtin_atan2(x,y);},
isnan: func(x) {return __builtin_isnan(x); }
isnan: func(x) {return __builtin_isnan(x); },
max: func(x,y){return x>y?x:y; },
min: func(x,y){return x<y?x:y; }
};
var unix=
{
pipe: func(){die("not supported yet");},
fork: func(){die("not supported yet");},
pipe: func(){return __builtin_pipe;},
fork: func(){return __builtin_fork;},
dup2: func(fd0,fd1){die("not supported yet");},
exec: func(filename,argv,envp){die("not supported yet");},
waitpid: func(pid,nohang=0){die("not supported yet");},
waitpid: func(pid,nohang=0){return __builtin_waitpid;},
isdir: func(path){return bits.bitand(io.stat(path)[2],0x4000);}, # S_IFDIR 0x4000
isfile: func(path){return bits.bitand(io.stat(path)[2],0x8000);}, # S_IFREG 0x8000
opendir: func(path){return __builtin_opendir;},
@@ -278,12 +394,13 @@ var unix=
time: func(){return time(0);},
sleep: func(secs){return __builtin_sleep(secs);},
chdir: func(path){return __builtin_chdir(path);},
environ: func(){die("not supported yet");},
environ: func(){return __builtin_environ();},
getcwd: func(){return __builtin_getcwd();},
getenv: func(envvar){return __builtin_getenv(envvar);}
};
# dylib is the core hashmap for developers to load their own library.
# for safe using dynamic library, you could use 'module' in stl/module.nas
var dylib=
{
# open dynamic lib.
@@ -328,4 +445,25 @@ var M2IN=39.3701;
var M2NM=0.00054;
var MPS2KT=1.9438;
var NM2M=1852;
var R2D=180/math.pi;
var R2D=180/math.pi;
# functions that not supported in this runtime:
var bind=func(function,locals,outer_scope=nil){
die("this runtime does not support bind");
}
var call=func(function,args=nil,_me=nil,locals=nil,error=nil){
die("this runtime does not support call");
}
var caller=func(level=1){
die("this runtime does not support caller");
}
var closure=func(function,level=1){
die("this runtime uses \"vm_upval\" instead of \"vm_hash\" as the closure");
}
var compile=func(code,filename="<compile>"){
die("this runtime uses static code generator");
}

43
stl/module.nas Normal file
View File

@@ -0,0 +1,43 @@
# lib module.nas
# ValKmjolnir 2022/3/5
# this provides safe usage of dylib
# when dylib is closed,
# all the invalid functions cannot be called
var module_call_func=func(fptr,args){
return __builtin_dlcall;
}
var extern={
new: func(fptr){
var isopen=1;
return {
close:func(){isopen=0;},
call:func(args...){
return (!isopen)?
nil:
module_call_func(fptr,args);
}
};
}
};
var module={
new: func(name){
var lib=dylib.dlopen(name);
var f={};
return {
get:func(symbol){
if(contains(f,symbol))
return f[symbol];
var fp=extern.new(dylib.dlsym(lib,symbol));
f[symbol]=fp;
return fp;
},
close: func(){
foreach(var i;keys(f))
f[i].close();
dylib.dlclose(lib);
}
};
}
};

View File

@@ -1,4 +1,3 @@
import("lib.nas");
var char_ttf=[
[" "," "," "," "," "," "],
[" ████╗"," ██╔██║"," ██╔╝██║"," ███████║","██╔═══██║","╚═╝ ╚═╝"],
@@ -114,9 +113,43 @@ var curve4=func()
}
return;
}
var curve5=func(){
for(var i=0;i<=9;i+=1)
println(i,"\e["~i~"mh \e[0m");
for(var i=30;i<=37;i+=1)
println(i,"\e["~i~"mh \e[0m");
for(var i=40;i<=47;i+=1)
println(i,"\e["~i~"mh \e[0m");
for(var i=90;i<=97;i+=1)
println(i,"\e["~i~"mh \e[0m");
for(var i=100;i<=107;i+=1)
println(i,"\e["~i~"mh \e[0m");
}
var curve6=func(){
var shadow=["m░\e[0m","m▒\e[0m","m▓\e[0m","m█\e[0m","m▀\e[0m","m▄\e[0m","m▐\e[0m","m▌\e[0m"];
var front=[
"30","31","32","33","34","35","36","37",
"90","91","92","93","94","95","96","97"
];
var back=[
"40","41","42","43","44","45","46","47",
"100","101","102","103","104","105","106","107"
];
rand(time(0));
for(var i=0;i<15;i+=1){
for(var j=0;j<45;j+=1)
print("\e["~front[16*rand()]~";"~back[16*rand()]~shadow[8*rand()]);
print('\n');
}
}
if(os.platform()=="windows")
system("chcp 65001");
trans_ttf("just for test");
trans_ttf(" ValKmjolnir ");
trans_ttf("just for fun");
curve1();
curve2();
curve3();
curve4();
curve4();
curve5();
curve6();

View File

@@ -1,6 +1,5 @@
# Road check and auto pilot by ValKmjolnir
import("lib.nas");
import("props.nas");
import("test/props_sim.nas");
var dt=0.01;
var intergral=0;
var derivative=0;

View File

@@ -1,5 +1,3 @@
import("lib.nas");
var mandelbrot=
"[A mandelbrot set fractal viewer in brainf*** written by Erik Bosman]
+++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++++++++[[
@@ -152,6 +150,15 @@ var (ptr,pc)=(0,0);
var (code,inum,stack)=([],[],[]);
var (add,mov,jt,jf,in,out)=(0,1,2,3,4,5);
var funcs=[
func{paper[ptr]+=inum[pc];},
func{ptr+=inum[pc];},
func{if(paper[ptr])pc=inum[pc];},
func{if(!paper[ptr])pc=inum[pc];},
func{paper[ptr]=input()[0];},
func{print(chr(paper[ptr]));}
];
var bf=func(program){
setsize(paper,131072);
var len=size(program);
@@ -212,15 +219,8 @@ var bf=func(program){
return;
}
len=size(code);
for(pc=0;pc<len;pc+=1){
var c=code[pc];
if(c==add) paper[ptr]+=inum[pc];
elsif(c==mov)ptr+=inum[pc];
elsif(c==jt){if(paper[ptr])pc=inum[pc];}
elsif(c==jf){if(!paper[ptr])pc=inum[pc];}
elsif(c==in) paper[ptr]=input()[0];
else print(chr(paper[ptr]));
}
for(pc=0;pc<len;pc+=1)
funcs[code[pc]]();
return;
}

242
test/bfcolored.nas Normal file
View File

@@ -0,0 +1,242 @@
var mandelbrot=
"[A mandelbrot set fractal viewer in brainf*** written by Erik Bosman]
+++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++++++++[[
>>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-]>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+
<<<<<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>>>>>
>+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+[>>>>>>[>>>>>>>[-]>>]<<<<<<<<<[<<<<<<<<<]>>
>>>>>[-]+<<<<<<++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<+++++++[-[->>>
>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[[-]>>>>>>[>>>>>
>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>
[>>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<
<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>+++++++++++++++[[
>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[
>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[
-<<+>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<
<<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<
[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>
>>>>[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+
<<<<<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>
>>>>>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<
+>>>>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<
<]<+<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>
>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<
<<<]>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<
<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->
>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<
<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++++++++++++++++
+++++++>>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>[<<<<<<<+<[-<+>>>>+<<[-]]>[-<<[->+>>>-
<<<<]>>>]>>>>>>>>>>>>>[>>[-]>[-]>[-]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>>>>>>[>>>>>
[-<<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>[-<<<<<<<<
<+>>>>>>>>>]>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>>]+>[-
]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>>>>>>>]<<<
<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+>>]<
<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[->>>>
>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-]<->>>
[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-<
<<<<+>>>>>]<<<<<[->>>>>+<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+>>>>>>>>
]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+
>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>
[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-
]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>>
[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++
+++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-<<<<<<<+
>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[
-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>>]>[-<<<<<<[->>>>>+<++<<<<]>>>>>[-<
<<<<+>>>>>]<->+>]<[->+<]<<<<<[->>>>>+<<<<<]>>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<<
[->>>>->>>>>[>>[-<<->>]+<<[->>->[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]
+>>>>>>[>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<<<<<<<<<<[<<<<<
<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<
[<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<
<<<+<[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<
<<<<<+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<
<<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+<]>>>>>>>>]<<<
<<<<<+<[>[->>>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>[->>>>+<<<<]>]<[->>>>-<<<<<<<
<<<<<<<+>>>>>>>>>>]<]>>[->>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>>+<<<<
]<<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>>>>>>>>>]<<<<<<<<<
[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<<<<<<
+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<<<<<<
<<<<<]]>[-]>>[-]>[-]>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<
<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[
[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+
[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>
[-<<+>>]<<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<
<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[
>[-]<->>>[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[
>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>
>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>[-]>>>>+++++++++++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<
<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<
<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-
<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>
>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>>>
[-<<<->>>]<<<[->>>+<<<]>>>>>>>>]<<<<<<<<+<[>[->+>[-<-<<<<<<<<<<+>>>>>>>>>>>>[-<<
+>>]<]>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<<<]>>[-<+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<]>
[-<<+>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>
>>>>>>]<<<<<<<<+<[>[->+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>[-<+>]>]<[-<-<<<<<<<<<<+>>>>
>>>>>>>]<<]>>>[-<<+>[-<-<<<<<<<<<<+>>>>>>>>>>>]>]<[-<+>]<<<<<<<<<<<<]>>>>>+<<<<<
]>>>>>>>>>[>>>[-]>[-]>[-]>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>>>[-<<<<<
<+>>>>>>]<<<<<<[->>>>>>+<<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>
>]>>[-<<<<<<<[->>>>>+<++<<<<]>>>>>[-<<<<<+>>>>>]<->+>>]<<[->>+<<]<<<<<[->>>>>+<<
<<<]+>>>>[-<<<<->>>>]+<<<<[->>>>->>>>>[>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<
<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>[-<<->>]+<<[->>->[-<<<+>>>]<
<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<
<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+
<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>[->>>+<<<]>]<[->>>-
<<<<<<<<<<<<<+>>>>>>>>>>]<]>>[->>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>+<<<
]<<<<<<<<<<<]>>>>>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]]>>>>[-<<<<+>
>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<<[->>>-
<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[
->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>>
>>]<<<<[->>>>+>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>[>>>>>>
>>>]<<<<<<<<<[>[->>>>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<
<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<
<<<<]]>>>>>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>[-<<<<+
>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<+>>>>>
]<<<<<[->>>>>+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>
>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>
>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[-<<+
>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>
[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-
]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>>
[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<
<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>
>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<+>>>
>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+
<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>
>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<<<<]
>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<
]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->>>+<
<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>
>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>->>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>]<<+>>>>[-<<<<
->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[-<<<<<<<.>>>>>>>]<<<[-]>[-]>[-]>[-]>[-]>[-]>>>[
>[-]>[-]>[-]>[-]>[-]>[-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]>>>>]<<<<<<<<<
[<<<<<<<<<]>+++++++++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+>>>>>>>>>+<<<<<<<<
<<<<<<[<<<<<<<<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+[-]>>[>>>>>>>>>]<<<<<
<<<<[>>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<[<<<<<<<<<]>>>>>>>[-]+>>>]<<<<
<<<<<<]]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+>>[>+>>>>[-<<<<->>>>]<<<<[->>>
>+<<<<]>>>>>>>>]<<+<<<<<<<[>>>>>[->>+<<]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<
<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<<<<<[->>>>>>+<<<<<<]<
+<<<<<<<<<]>>>>>>>-<<<<[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>->>[>>
>>>[->>+<<]>>>>]<<<<<<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<
<<<<[->>>>>>+<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+<<<
<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>->>[-<<<<<<<+>>>>>>>]<<<<
<<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>[-<
<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<<
<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<
<<[<<<<<<<<<]>>>>[-]<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>-<<<<<[<<<<<<<
<<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++[-[->>>>>>>>
>+<<<<<<<<<]>>>>>>>>>]>>>>>+>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<<
<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+[-]>[>>>>>>>>>]<<<<<<<<<[>>>>>>>>[-<<<<<<<+>>>>>>
>]<<<<<<<[->>>>>>>+<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+>>]<<<<<<<<<<]]>>>>>>>>[-<<<<<
<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+>[>+>>>>>[-<<<<<->>>>>]<<<<<[->>>>>+<<<<<]>>>>>>
>>]<+<<<<<<<<[>>>>>>[->>+<<]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<-
>>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<]<+<<<<<<
<<<]>>>>>>>>-<<<<<[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>->[>>>
>>>[->>+<<]>>>]<<<<<<<<<[>[-]<->>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<
<<<<<[->>>>>>>+<<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<->>>>>>]+<
<<<<<[->>>>>>->>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<
<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>
-<<[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>
>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<++++
+[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>->>>>>>>>>>>>>>>>>>>>>>>>>>>-<<<<<<[<<<<
<<<<<]]>>>]";
var paper=[];
var (ptr,pc)=(0,0);
var (code,inum,stack)=([],[],[]);
var (add,mov,jt,jf,in,out)=(0,1,2,3,4,5);
var color=[
"\e[31m","\e[32m","\e[33m","\e[34m","\e[35m","\e[36m",
"\e[90m","\e[91m","\e[92m","\e[93m","\e[94m","\e[95m","\e[96m"
];
var table=[];
func(){
var cnt=0;
for(var i=0;i<256;i+=1){
append(table,color[cnt]~chr(i)~"\e[0m");
cnt+=1;
if(cnt>12)
cnt=0;
}
}();
var funcs=[
func{paper[ptr]+=inum[pc];},
func{ptr+=inum[pc];},
func{if(paper[ptr])pc=inum[pc];},
func{if(!paper[ptr])pc=inum[pc];},
func{paper[ptr]=input()[0];},
func{print(table[paper[ptr]]);}
];
var bf=func(program){
setsize(paper,131072);
var len=size(program);
for(var i=0;i<len;i+=1){
var c=chr(program[i]);
if(c=='+' or c=='-'){
append(code,add);
append(inum,0);
for(;i<len;i+=1){
if(chr(program[i])=='+')
inum[-1]+=1;
elsif(chr(program[i])=='-')
inum[-1]-=1;
elsif(chr(program[i])!='\n'){
i-=1;
break;
}
}
}
elsif(c=='<' or c=='>'){
append(code,mov);
append(inum,0);
for(;i<len;i+=1){
if(chr(program[i])=='>')
inum[-1]+=1;
elsif(chr(program[i])=='<')
inum[-1]-=1;
elsif(chr(program[i])!='\n'){
i-=1;
break;
}
}
}
elsif(c==','){
append(code,in);
append(inum,0);
}
elsif(c=='.'){
append(code,out);
append(inum,0);
}
elsif(c=='['){
append(code,jf);
append(inum,0);
append(stack,size(code)-1);
}
elsif(c==']'){
if(!size(stack))
die("lack [");
var label=pop(stack);
append(code,jt);
append(inum,label-1);
inum[label]=size(code)-2;
}
}
if(size(stack)){
die("lack ]");
return;
}
len=size(code);
for(pc=0;pc<len;pc+=1)
funcs[code[pc]]();
return;
}
bf(mandelbrot);

View File

@@ -151,7 +151,7 @@ var bf=func(program)
{
var stack=[];
var len=size(program);
var f="import('lib.nas');\nvar ptr=0;\nvar paper=[];\nsetsize(paper,131072);\n";
var f="#automatically generated by bfconvertor.nas\nimport('lib.nas');\nvar ptr=0;\nvar paper=[];\nsetsize(paper,131072);\n";
for(var i=0;i<len;i+=1)
{
var c=chr(program[i]);

View File

@@ -1,8 +1,6 @@
import("stl/lib.nas");
import("stl/queue.nas");
rand(time(0));
var pixel=[' ','#','.','*'];
var map=[];
for(var i=0;i<10;i+=1)
@@ -14,11 +12,7 @@ for(var i=0;i<10;i+=1)
var prt=func()
{
if(os.platform()=="windows")
system("cls");
else
system("clear");
var s="+--------------------+\n";
var s="\e[0;0H+--------------------+\n";
for(var i=0;i<10;i+=1)
{
s~="|";
@@ -28,6 +22,7 @@ var prt=func()
}
s~='+--------------------+\n';
print(s);
unix.sleep(1/144);
}
var bfs=func(begin,end)
@@ -49,6 +44,7 @@ var bfs=func(begin,end)
{
map[x][y]=3;
prt();
print("reached.\n");
return;
}
if(0<=x and x<10 and 0<=y and y<20 and map[x][y]==0)
@@ -63,4 +59,7 @@ var bfs=func(begin,end)
return;
}
if(os.platform()=="windows")
system("chcp 65001");
print("\ec");
bfs([0,0],[9,19]);

View File

@@ -1 +1 @@
for(var i=0;i<4e6;i+=1);
for(var i=0;i<4e6;i+=1);

View File

@@ -1,5 +1,3 @@
import("lib.nas");
rand(time(0));
var new_neuron=func()

View File

@@ -1,4 +1,3 @@
import("lib.nas");
var source=[
"main.cpp ",
"nasal_err.h ",
@@ -16,8 +15,10 @@ var source=[
];
var lib=[
"stl/file.nas ",
"stl/lib.nas ",
"stl/list.nas ",
"stl/module.nas ",
"stl/queue.nas ",
"stl/result.nas ",
"stl/sort.nas ",
@@ -28,6 +29,7 @@ var testfile=[
"test/ascii-art.nas ",
"test/auto_crash.nas ",
"test/bf.nas ",
"test/bfcolored.nas ",
"test/bfconvertor.nas ",
"test/bfs.nas ",
"test/bigloop.nas ",
@@ -35,6 +37,7 @@ var testfile=[
"test/calc.nas ",
"test/choice.nas ",
"test/class.nas ",
"test/diff.nas ",
"test/exception.nas ",
"test/fib.nas ",
"test/filesystem.nas ",
@@ -46,20 +49,31 @@ var testfile=[
"test/loop.nas ",
"test/mandel.nas ",
"test/mandelbrot.nas ",
"test/md5.nas ",
"test/md5compare.nas ",
"test/module_test.nas ",
"test/nasal_test.nas ",
"test/pi.nas ",
"test/prime.nas ",
"test/props_sim.nas ",
"test/props.nas ",
"test/qrcode.nas ",
"test/quick_sort.nas ",
"test/scalar.nas ",
"test/snake.nas ",
"test/tetris.nas ",
"test/trait.nas ",
"test/turingmachine.nas",
"test/utf8chk.nas ",
"test/wavecollapse.nas ",
"test/ycombinator.nas "
];
var module=[
"module/fib.cpp "
"module/fib.cpp ",
"module/keyboard.cpp ",
"module/libfib.nas ",
"module/libkey.nas "
];
var getname=func(s){
@@ -87,7 +101,7 @@ var calc=func(codetype,files){
semi+=semi_cnt;
}
println('total: | ',line,' \tline | ',semi,' \tsemi');
println('bytes: | ',bytes,'\tbytes| ',int(bytes/1024),' \tkb');
println(' | ',bytes,'\tbytes| ',int(bytes/1024),' \tkb');
}
calc("source code:",source);

View File

@@ -1,4 +1,3 @@
import("lib.nas");
var condition_true=1;
var condition_false=0;
if(condition_true)

View File

@@ -1,5 +1,3 @@
import("lib.nas");
var student=func(n,a){
return {
print_info:func println(n,' ',a),

129
test/diff.nas Normal file
View File

@@ -0,0 +1,129 @@
var myers=func(src,dst,show_table=0){
(src,dst)=(split("\n",src),split("\n",dst));
append(src,"");
append(dst,"");
var (src_len,dst_len)=(size(src),size(dst));
var mat=[];
setsize(mat,dst_len*src_len);
forindex(var i;mat){
mat[i]=0;
}
var visited=[];
setsize(visited,dst_len*src_len);
forindex(var i;visited){
visited[i]=0;
}
forindex(var y;dst)
forindex(var x;src)
mat[y*src_len+x]=(src[x]==dst[y]);
if(show_table){
var curve=[
["+---",
"| "],
[
"+---",
"| \\ "]
];
var s="";
forindex(var y;dst){
forindex(var t;curve[0]){
forindex(var x;src){
s~=curve[mat[y*src_len+x]][t];
}
s~=["+","|"][t]~"\n";
}
}
forindex(var i;src)
s~="+---";
print(s~"+\n");
}
var total=[];
var path=[];
var vec=[[0,0,-1]];
visited[0]=1;
while(size(vec)){
append(total,vec);
var tmp=[];
forindex(var i;vec){
var elem=vec[i];
var (x,y)=(elem[1],elem[0]);
# find solution
if(x==src_len-1 and y==dst_len-1){
append(path,vec[i]);
for(var (prev,iter)=(elem[2],size(total)-1);iter>0;iter-=1){
var t=total[iter-1][prev];
append(path,t);
prev=t[2];
}
if(show_table){
for(var t=size(path)-1;t>=0;t-=1)
print("("~path[t][1]~","~path[t][0]~")",t==0?"":"->");
println();
}
# reverse path
for(var t=0;t<size(path)/2;t+=1)
(path[t],path[-1-t])=(path[-1-t],path[t]);
# print diff
for(var t=1;t<size(path);t+=1){
var (prev_x,prev_y)=(path[t-1][1],path[t-1][0]);
var (x,y)=(path[t][1],path[t][0]);
var (sub_x,sub_y)=(x-prev_x,y-prev_y);
if(sub_x==1 and sub_y==1){
if(show_table)
println(" ",src[prev_x]);
}elsif(sub_x==1 and sub_y==0){
println("\e[31m - ",src[prev_x],"\e[0m");
}elsif(sub_x==0 and sub_y==1){
println("\e[32m + ",dst[prev_y],"\e[0m");
}
}
return;
}
# do bfs
if(mat[y*src_len+x]==1){
if(x+1<src_len and y+1<dst_len and visited[(y+1)*src_len+x+1]==0){
append(tmp,[y+1,x+1,i]);
visited[(y+1)*src_len+x+1]=1;
}
}
else{
if(x+1<src_len and visited[y*src_len+x+1]==0){
append(tmp,[y,x+1,i]);
visited[y*src_len+x+1]=1;
}
if(y+1<dst_len and visited[(y+1)*src_len+x]==0){
append(tmp,[y+1,x,i]);
visited[(y+1)*src_len+x]=1;
}
}
}
vec=tmp;
}
}
func(diff){
diff(
"var a=0;\nvar b=1;\nprint(\"hello \",a);\nvar c=2;\nc=[];\nvar d=3;\nvar l=list();\nvar q=queue();\n",
"var a=0;\nvar b=1;\nb=[];\nprintln(\"hello \",a);\nvar c=2;\nvar d=3;\nprintln(\"hello world!\");\nvar l=list();\nvar q=queue();\n",
1
);
print("\n");
diff(
"A\nB\nC\nA\nB\nB\nA\n",
"C\nB\nA\nB\nA\nC\n",
1
);
print("\n");
diff(
io.fin("test/bf.nas"),
io.fin("test/bfcolored.nas")
);
}(myers);

View File

@@ -1,5 +1,3 @@
import("lib.nas");
var ResultTrait={
Ok:func(val){
me.ok=val;

View File

@@ -1,4 +1,3 @@
import("lib.nas");
var fib=func(x)
{
if(x<2) return x;

View File

@@ -1,5 +1,3 @@
import("lib.nas");
var fd=io.open("test/filesystem.nas");
while((var line=io.readln(fd))!=nil)
println(line);

View File

@@ -1,8 +1,6 @@
# hexdump.nas by ValKmjolnir
# 2021/8/13
import("lib.nas");
# init
var hex_num=[
'0','1','2','3',

View File

@@ -1,196 +1,322 @@
#lib json.nas
import("lib.nas");
var json={
text:'',
line:1,
size:0,
ptr:0,
get:nil,
check:nil,
next:nil,
match:nil,
hash_gen:nil,
vec_gen:nil,
member:nil,
parse:nil,
token:{content:'',type:''},
content:[],
};
var JSON=func(){
json.get=func(filename)
{
me.line=1;
me.ptr=0;
me.content=[];
me.token={content:'',type:''};
me.text=io.fin(filename);
if(!size(me.text))
die("cannot open "~filename);
me.text=split('',me.text);
me.size=size(me.text);
return;
}
var (
j_eof,
j_lbrace,
j_rbrace,
j_lbracket,
j_rbracket,
j_comma,
j_colon,
j_str,
j_num,
j_id
)=(
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
);
var j_content=[
"eof",
"`{`",
"`}`",
"`[`",
"`]`",
"`,`",
"`:`",
"string",
"number",
"identifier"
];
json.check=func(ptr)
{
var str=me.text[ptr];
return (str=='{' or str=='}' or str=='[' or str==']' or str==',' or str==':' or str=='\"' or ('0'<=str and str<='9'));
}
json.next=func()
{
while(me.ptr<me.size and !json.check(me.ptr))
{
if(me.text[me.ptr]=='\n')
me.line+=1;
me.ptr+=1;
var text='';
var line=1;
var text_size=0;
var ptr=0;
var token={content:'',type:''};
var content={};
var init=func(){
line=1;
text_size=0;
ptr=0;
content={};
token={content:'',type:''};
text='';
}
if(me.ptr>=me.size)
var isnum=func(c){
return '0'<=c and c<='9';
}
var isid=func(c){
var tmp=c[0];
return ('a'[0]<=tmp and tmp<='z'[0]) or
('A'[0]<=tmp and tmp<='Z'[0]) or
c=='_';
}
var check=func()
{
me.token.content="";
me.token.type="eof";
var c=text[ptr];
return (
c=='{' or c=='}' or
c=='[' or c==']' or
c==',' or c==':' or
c=='\"' or c=='\'' or
isnum(c) or isid(c)
);
}
var get=func(str)
{
init();
if(!size(str))
die("empty string");
text=split('',str);
text_size=size(text);
return;
}
if(me.text[me.ptr]=='{')
var next=func()
{
me.token.content='{';
me.token.type="left brace";
}
elsif(me.text[me.ptr]=='}')
{
me.token.content='}';
me.token.type="right brace";
}
elsif(me.text[me.ptr]=='[')
{
me.token.content='[';
me.token.type="left bracket";
}
elsif(me.text[me.ptr]==']')
{
me.token.content=']';
me.token.type="right bracket";
}
elsif(me.text[me.ptr]==',')
{
me.token.content=',';
me.token.type="comma";
}
elsif(me.text[me.ptr]==':')
{
me.token.content=':';
me.token.type="colon";
}
elsif(me.text[me.ptr]=='\"')
{
var s="";
me.ptr+=1;
while(me.ptr<me.size and me.text[me.ptr]!='\"')
while(ptr<text_size and !check())
{
s~=me.text[me.ptr];
me.ptr+=1;
if(text[ptr]=='\n')
line+=1;
ptr+=1;
}
me.token.content=s;
me.token.type="string";
}
elsif('0'<=me.text[me.ptr] and me.text[me.ptr]<='9')
{
var s=me.text[me.ptr];
me.ptr+=1;
while(me.ptr<me.size and (('0'<=me.text[me.ptr] and me.text[me.ptr]<='9') or me.text[me.ptr]=='.'))
if(ptr>=text_size)
{
s~=me.text[me.ptr];
me.ptr+=1;
token.content="eof";
token.type=j_eof;
return;
}
me.ptr-=1;
me.token.content=num(s);
me.token.type="number";
}
me.ptr+=1;
return;
}
json.match=func(type)
{
if(me.token.type!=type)
print("line ",me.line,": expect ",type," but get ",me.token.content,".");
me.next();
return;
}
json.hash_gen=func()
{
var hash={};
me.match("left brace");
me.member(hash);
while(me.token.type=="comma")
{
me.match("comma");
me.member(hash);
}
me.match("right brace");
return hash;
}
json.vec_gen=func()
{
var vec=[];
me.match("left bracket");
if(me.token.type=="left brace")
append(vec,me.hash_gen());
elsif(me.token.type=="left bracket")
append(vec,me.vec_gen());
elsif(me.token.type=="string" or me.token.type=="number")
{
append(vec,me.token.content);
me.next();
}
while(me.token.type=="comma")
{
me.match("comma");
if(me.token.type=="left brace")
append(vec,me.hash_gen());
elsif(me.token.type=="left bracket")
append(vec,me.vec_gen());
elsif(me.token.type=="string" or me.token.type=="number")
var c=text[ptr];
if(c=='{')
{
append(vec,me.token.content);
me.next();
token.content='{';
token.type=j_lbrace;
}
elsif(c=='}')
{
token.content='}';
token.type=j_rbrace;
}
elsif(c=='[')
{
token.content='[';
token.type=j_lbracket;
}
elsif(c==']')
{
token.content=']';
token.type=j_rbracket;
}
elsif(c==',')
{
token.content=',';
token.type=j_comma;
}
elsif(c==':')
{
token.content=':';
token.type=j_colon;
}
elsif(c=='\"' or c=='\'')
{
var strbegin=c;
var s="";
ptr+=1;
while(ptr<text_size and text[ptr]!=strbegin)
{
s~=text[ptr];
ptr+=1;
}
token.content=s;
token.type=j_str;
}
elsif(isnum(c))
{
var s=c;
ptr+=1;
while(ptr<text_size and ((isnum(text[ptr]) or text[ptr]=='.')))
{
s~=text[ptr];
ptr+=1;
}
ptr-=1;
token.content=num(s);
token.type=j_num;
}
elsif(isid(c))
{
var s=c;
ptr+=1;
while(ptr<text_size and (isid(text[ptr]) or isnum(text[ptr])))
{
s~=text[ptr];
ptr+=1;
}
ptr-=1;
token.content=s;
token.type=j_id;
}
ptr+=1;
return;
}
me.match("right bracket");
return vec;
}
json.member=func(hash)
{
var name=me.token.content;
me.match("string");
me.match("colon");
if(me.token.type=="left brace")
hash[name]=me.hash_gen();
elsif(me.token.type=="left bracket")
hash[name]=me.vec_gen();
elsif(me.token.type=="string" or me.token.type=="number")
var match=func(type)
{
hash[name]=me.token.content;
me.next();
if(token.type!=type)
print("line ",line,": expect ",j_content[type]," but get `",token.content,"`.\n");
next();
return;
}
return;
}
json.parse=func()
{
me.content={};
me.next();
me.match("left brace");
me.member(me.content);
while(me.token.type=="comma")
var hash_gen=func()
{
me.match("comma");
me.member(me.content);
var hash={};
match(j_lbrace);
member(hash);
while(token.type==j_comma)
{
match(j_comma);
member(hash);
}
match(j_rbrace);
return hash;
}
me.match("right brace");
return;
}
var vec_gen=func()
{
var vec=[];
match(j_lbracket);
if(token.type==j_lbrace)
append(vec,hash_gen());
elsif(token.type==j_lbracket)
append(vec,vec_gen());
elsif(token.type==j_str or token.type==j_num)
{
append(vec,token.content);
next();
}
while(token.type==j_comma)
{
match(j_comma);
if(token.type==j_lbrace)
append(vec,me.hash_gen());
elsif(token.type==j_lbracket)
append(vec,vec_gen());
elsif(token.type==j_str or token.type==j_num)
{
append(vec,token.content);
next();
}
}
match(j_rbracket);
return vec;
}
var member=func(hash)
{
var name=token.content;
if(token.type==j_str)
match(j_str);
else
match(j_id);
match(j_colon);
if(token.type==j_lbrace)
hash[name]=hash_gen();
elsif(token.type==j_lbracket)
hash[name]=vec_gen();
elsif(token.type==j_str or token.type==j_num)
{
hash[name]=token.content;
next();
}
return;
}
return {
parse:func(str)
{
if(typeof(str)!="str")
die("JSON.parse: must use string");
get(str);
next();
match(j_lbrace);
member(content);
while(token.type==j_comma)
{
match(j_comma);
member(content);
}
match(j_rbrace);
var res=content;
init();
return res;
},
stringify:func(hash){
if(typeof(hash)!="hash")
die("JSON.stringify: must use hashmap");
var s="";
var gen=func(elem){
var t=typeof(elem);
if(t=="num")
s~=elem;
elsif(t=="str")
s~='"'~elem~'"';
elsif(t=="vec")
vgen(elem);
elsif(t=="hash")
hgen(elem);
else
s~='"undefined"';
}
var vgen=func(v){
s~="[";
var vsize=size(v);
for(var i=0;i<vsize;i+=1){
gen(v[i]);
if(i!=vsize-1)
s~=",";
}
s~="]";
}
var hgen=func(h){
s~="{";
var k=keys(h);
var vsize=size(k);
for(var i=0;i<vsize;i+=1){
s~=k[i]~":";
gen(h[k[i]]);
if(i!=vsize-1)
s~=",";
}
s~="}";
}
hgen(hash);
return s;
}
};
}();
var ss=JSON.stringify({
vec:[0,1,2],
hash:{
m1:0,
m2:"str",
m3:[114514],
m4:{year:1919,month:8,date:10}
},
function:func(){}
});
println(ss);
println(JSON.parse(ss));

View File

@@ -1,4 +1,3 @@
import("lib.nas");
# union set
var n=4;
var input=[[0,1],[0,2],[1,2]];

View File

@@ -1,16 +1,24 @@
import("lib.nas");
var lexer=func(file)
{
var (ptr,token)=(0,[]);
var s=io.fin(file);
var len=size(s);
var line=0;
var gen=func(tok)
{
append(token,{
line:line,
token:tok
});
}
return
{
jmp_note:func()
{
while(ptr<len and chr(s[ptr])!='\n')
while(ptr<len and s[ptr]!='\n'[0])
ptr+=1;
if(ptr<len and s[ptr]=='\n'[0])
line+=1;
ptr+=1;
},
id_gen:func()
@@ -28,7 +36,7 @@ var lexer=func(file)
break;
ptr+=1;
}
append(token,tmp);
gen(tmp);
},
str_gen:func()
{
@@ -43,6 +51,7 @@ var lexer=func(file)
var c=chr(s[ptr]);
if (c=='a' ) str~='\a';
elsif(c=='b' ) str~='\b';
elsif(c=='e' ) str~='\e';
elsif(c=='f' ) str~='\f';
elsif(c=='n' ) str~='\n';
elsif(c=='r' ) str~='\r';
@@ -56,13 +65,17 @@ var lexer=func(file)
else str~=c;
}
else
{
if(s[ptr]=='\n'[0])
line+=1;
str~=chr(s[ptr]);
}
ptr+=1;
}
if(ptr>=len)
print("read eof when generating string.\n");
ptr+=1;
append(token,str);
gen(str);
},
num_gen:func()
{
@@ -78,7 +91,7 @@ var lexer=func(file)
number~=chr(s[ptr]);
ptr+=1;
}
append(token,num(number));
gen(num(number));
return;
}
elsif(ptr<len and chr(s[ptr])=='o')
@@ -89,7 +102,7 @@ var lexer=func(file)
number~=chr(s[ptr]);
ptr+=1;
}
append(token,num(number));
gen(num(number));
return;
}
while(ptr<len and ('0'[0]<=s[ptr] and s[ptr]<='9'[0]))
@@ -125,7 +138,7 @@ var lexer=func(file)
var last_c=chr(number[-1]);
if(last_c=='.' or last_c=='e' or last_c=='E' or last_c=='-' or last_c=='+')
println("error number: ",number);
append(token,num(number));
gen(num(number));
},
opr_gen:func()
{
@@ -139,35 +152,41 @@ var lexer=func(file)
tmp~=chr(s[ptr]);
ptr+=1;
}
append(token,tmp);
gen(tmp);
return;
}
elsif(c=='.')
{
if(ptr+2<len and chr(s[ptr+1])=='.' and chr(s[ptr+2])=='.')
{
append(token,"...");
gen("...");
ptr+=3;
}
else
{
append(token,".");
gen(".");
ptr+=1;
}
return;
}
elsif(c!=' ' and c!='\t' and c!='\n' and c!='\r' and s[ptr]>0)
append(token,c);
gen(c);
ptr+=1;
return;
},
compile:func()
{
line=1;
while(ptr<len)
{
var c=s[ptr];
if(c=='#'[0])
me.jmp_note();
elsif(c=='\n'[0])
{
line+=1;
ptr+=1;
}
elsif('a'[0]<=c and c<='z'[0]
or 'A'[0]<=c and c<='Z'[0]
or c=='_'[0])
@@ -188,5 +207,4 @@ var lexer=func(file)
var lex=lexer("test/props.nas");
lex.compile();
foreach(var tok;lex.get_token())
print(tok,' ');
print('\n');
print('(',tok.line,' | ',tok.token,')\n');

View File

@@ -1,5 +1,3 @@
import("lib.nas");
var map=nil;
var check=func(x,y)
@@ -23,22 +21,22 @@ var new_map=func()
var prt=func()
{
var s='';
var s='\e[0;0H';
foreach(var line;map)
{
foreach(var elem;line)
s~=elem~' ';
s~='\n';
}
if(os.platform()=="windows")
system("cls");
else
system("clear");
print(s);
unix.sleep(1/144);
}
func()
{
if(os.platform()=="windows")
system("chcp 65001");
print("\ec");
rand(time(0));
map=new_map();
forindex(var i;map)

View File

@@ -1,4 +1,3 @@
import("lib.nas");
for(;;)break;
for(;;)
{

View File

@@ -1,4 +1,4 @@
import('lib.nas');
#automatically generated by bfconvertor.nas
var ptr=0;
var paper=[];
setsize(paper,131072);
@@ -76,8 +76,7 @@ while(paper[ptr])
}
ptr+=7.000000;
paper[ptr]+=1.000000;
ptr+=26.000000;
ptr+=1.000000;
ptr+=27.000000;
paper[ptr]+=1.000000;
ptr-=17.000000;
while(paper[ptr])
@@ -107,8 +106,7 @@ while(paper[ptr])
{
ptr-=9.000000;
}
ptr+=2.000000;
ptr+=5.000000;
ptr+=7.000000;
while(paper[ptr])
{
paper[ptr]-=1.000000;
@@ -138,8 +136,7 @@ while(paper[ptr])
while(paper[ptr])
{
paper[ptr]-=1.000000;
ptr+=3.000000;
ptr+=6.000000;
ptr+=9.000000;
paper[ptr]+=1.000000;
ptr-=9.000000;
}
@@ -162,8 +159,7 @@ while(paper[ptr])
ptr+=6.000000;
while(paper[ptr])
{
ptr+=5.000000;
ptr+=2.000000;
ptr+=7.000000;
while(paper[ptr])
{
paper[ptr]-=1.000000;
@@ -218,8 +214,7 @@ while(paper[ptr])
ptr-=9.000000;
while(paper[ptr])
{
ptr-=7.000000;
ptr-=2.000000;
ptr-=9.000000;
}
ptr+=7.000000;
while(paper[ptr])
@@ -368,8 +363,7 @@ while(paper[ptr])
{
ptr+=9.000000;
}
ptr-=7.000000;
ptr-=2.000000;
ptr-=9.000000;
while(paper[ptr])
{
ptr+=1.000000;
@@ -443,8 +437,7 @@ while(paper[ptr])
paper[ptr]+=1.000000;
ptr-=9.000000;
}
ptr+=5.000000;
ptr+=4.000000;
ptr+=9.000000;
while(paper[ptr])
{
ptr+=1.000000;
@@ -509,8 +502,7 @@ while(paper[ptr])
ptr+=9.000000;
while(paper[ptr])
{
ptr+=2.000000;
ptr+=7.000000;
ptr+=9.000000;
}
ptr-=9.000000;
while(paper[ptr])
@@ -580,8 +572,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr+=3.000000;
paper[ptr]+=1.000000;
ptr-=2.000000;
ptr-=1.000000;
ptr-=3.000000;
}
ptr-=1.000000;
paper[ptr]+=1.000000;
@@ -596,8 +587,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr-=36.000000;
paper[ptr]+=1.000000;
ptr+=13.000000;
ptr+=23.000000;
ptr+=36.000000;
}
ptr+=5.000000;
}
@@ -612,8 +602,7 @@ while(paper[ptr])
{
while(paper[ptr])
{
ptr+=4.000000;
ptr+=5.000000;
ptr+=9.000000;
}
ptr-=9.000000;
paper[ptr]-=1.000000;
@@ -631,8 +620,7 @@ while(paper[ptr])
ptr-=3.000000;
while(paper[ptr])
{
ptr-=6.000000;
ptr-=3.000000;
ptr-=9.000000;
}
ptr+=9.000000;
while(paper[ptr])
@@ -669,8 +657,7 @@ while(paper[ptr])
ptr-=13.000000;
while(paper[ptr])
{
ptr-=5.000000;
ptr-=4.000000;
ptr-=9.000000;
}
ptr+=4.000000;
while(paper[ptr])
@@ -716,8 +703,7 @@ while(paper[ptr])
while(paper[ptr])
{
paper[ptr]-=1.000000;
ptr+=1.000000;
ptr+=2.000000;
ptr+=3.000000;
paper[ptr]+=1.000000;
ptr-=12.000000;
while(paper[ptr])
@@ -754,8 +740,7 @@ while(paper[ptr])
{
ptr+=9.000000;
}
ptr-=6.000000;
ptr-=2.000000;
ptr-=8.000000;
}
ptr+=8.000000;
}
@@ -775,8 +760,7 @@ while(paper[ptr])
ptr-=4.000000;
}
ptr+=9.000000;
paper[ptr]+=19.000000;
paper[ptr]+=7.000000;
paper[ptr]+=26.000000;
ptr+=2.000000;
while(paper[ptr])
{
@@ -898,8 +882,7 @@ while(paper[ptr])
while(paper[ptr])
{
paper[ptr]-=1.000000;
ptr-=8.000000;
ptr-=1.000000;
ptr-=9.000000;
paper[ptr]+=1.000000;
ptr+=9.000000;
}
@@ -979,8 +962,7 @@ while(paper[ptr])
paper[ptr]+=1.000000;
ptr+=8.000000;
}
ptr-=3.000000;
ptr-=6.000000;
ptr-=9.000000;
while(paper[ptr])
{
ptr-=9.000000;
@@ -1016,8 +998,7 @@ while(paper[ptr])
paper[ptr]+=1.000000;
ptr+=2.000000;
}
ptr-=1.000000;
ptr-=1.000000;
ptr-=2.000000;
while(paper[ptr])
{
paper[ptr]-=1.000000;
@@ -1048,8 +1029,7 @@ while(paper[ptr])
while(paper[ptr])
{
paper[ptr]-=1.000000;
ptr+=4.000000;
ptr+=5.000000;
ptr+=9.000000;
paper[ptr]+=1.000000;
ptr-=9.000000;
}
@@ -1123,8 +1103,7 @@ while(paper[ptr])
while(paper[ptr])
{
paper[ptr]-=1.000000;
ptr-=1.000000;
ptr-=4.000000;
ptr-=5.000000;
paper[ptr]+=1.000000;
ptr+=5.000000;
}
@@ -1313,8 +1292,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr-=36.000000;
paper[ptr]+=1.000000;
ptr+=1.000000;
ptr+=35.000000;
ptr+=36.000000;
}
ptr+=6.000000;
}
@@ -1324,8 +1302,7 @@ while(paper[ptr])
ptr-=9.000000;
}
ptr+=9.000000;
paper[ptr]+=8.000000;
paper[ptr]+=7.000000;
paper[ptr]+=15.000000;
while(paper[ptr])
{
while(paper[ptr])
@@ -1415,8 +1392,7 @@ while(paper[ptr])
while(paper[ptr])
{
paper[ptr]-=1.000000;
ptr-=1.000000;
ptr-=4.000000;
ptr-=5.000000;
paper[ptr]+=1.000000;
ptr+=5.000000;
}
@@ -1550,8 +1526,7 @@ while(paper[ptr])
ptr-=11.000000;
while(paper[ptr])
{
ptr-=5.000000;
ptr-=4.000000;
ptr-=9.000000;
}
ptr+=4.000000;
while(paper[ptr])
@@ -1629,8 +1604,7 @@ while(paper[ptr])
}
ptr+=8.000000;
}
ptr-=5.000000;
ptr-=3.000000;
ptr-=8.000000;
paper[ptr]+=1.000000;
ptr-=1.000000;
while(paper[ptr])
@@ -1665,8 +1639,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr+=3.000000;
paper[ptr]-=1.000000;
ptr-=9.000000;
ptr-=5.000000;
ptr-=14.000000;
paper[ptr]+=1.000000;
ptr+=11.000000;
}
@@ -1698,8 +1671,7 @@ while(paper[ptr])
paper[ptr]+=1.000000;
ptr-=3.000000;
}
ptr-=2.000000;
ptr-=10.000000;
ptr-=12.000000;
}
ptr+=4.000000;
while(paper[ptr])
@@ -1745,8 +1717,7 @@ while(paper[ptr])
}
ptr+=8.000000;
}
ptr-=3.000000;
ptr-=5.000000;
ptr-=8.000000;
paper[ptr]+=1.000000;
ptr-=1.000000;
while(paper[ptr])
@@ -1781,8 +1752,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr+=4.000000;
paper[ptr]-=1.000000;
ptr-=7.000000;
ptr-=7.000000;
ptr-=14.000000;
paper[ptr]+=1.000000;
ptr+=10.000000;
}
@@ -1905,8 +1875,7 @@ while(paper[ptr])
paper[ptr]+=1.000000;
ptr-=3.000000;
}
ptr-=7.000000;
ptr-=5.000000;
ptr-=12.000000;
}
}
ptr+=1.000000;
@@ -1951,8 +1920,7 @@ while(paper[ptr])
while(paper[ptr])
{
paper[ptr]-=1.000000;
ptr-=1.000000;
ptr-=3.000000;
ptr-=4.000000;
paper[ptr]+=1.000000;
ptr+=4.000000;
}
@@ -2102,8 +2070,7 @@ while(paper[ptr])
{
ptr+=9.000000;
}
ptr-=8.000000;
ptr-=1.000000;
ptr-=9.000000;
while(paper[ptr])
{
ptr+=1.000000;
@@ -2188,8 +2155,7 @@ while(paper[ptr])
paper[ptr]+=1.000000;
ptr+=36.000000;
}
ptr+=1.000000;
ptr+=5.000000;
ptr+=6.000000;
}
ptr-=9.000000;
while(paper[ptr])
@@ -2211,8 +2177,7 @@ while(paper[ptr])
}
ptr-=9.000000;
paper[ptr]-=1.000000;
ptr-=5.000000;
ptr-=4.000000;
ptr-=9.000000;
while(paper[ptr])
{
ptr-=9.000000;
@@ -2252,8 +2217,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr+=4.000000;
paper[ptr]+=1.000000;
ptr-=5.000000;
ptr-=8.000000;
ptr-=13.000000;
while(paper[ptr])
{
ptr-=9.000000;
@@ -2337,8 +2301,7 @@ while(paper[ptr])
ptr-=1.000000;
while(paper[ptr])
{
ptr+=2.000000;
ptr+=7.000000;
ptr+=9.000000;
}
ptr-=8.000000;
}
@@ -2491,8 +2454,7 @@ while(paper[ptr])
paper[ptr]+=1.000000;
ptr-=2.000000;
}
ptr+=2.000000;
ptr+=6.000000;
ptr+=8.000000;
}
ptr-=8.000000;
paper[ptr]+=1.000000;
@@ -2531,8 +2493,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr-=10.000000;
paper[ptr]+=1.000000;
ptr+=4.000000;
ptr+=7.000000;
ptr+=11.000000;
}
ptr-=2.000000;
}
@@ -2610,8 +2571,7 @@ while(paper[ptr])
while(paper[ptr])
{
paper[ptr]-=1.000000;
ptr-=5.000000;
ptr-=1.000000;
ptr-=6.000000;
paper[ptr]+=1.000000;
ptr+=6.000000;
}
@@ -2642,8 +2602,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr-=4.000000;
paper[ptr]+=1.000000;
ptr+=4.000000;
ptr+=1.000000;
ptr+=5.000000;
}
ptr+=2.000000;
while(paper[ptr])
@@ -2687,8 +2646,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr+=5.000000;
paper[ptr]+=1.000000;
ptr-=2.000000;
ptr-=3.000000;
ptr-=5.000000;
}
paper[ptr]+=1.000000;
ptr+=4.000000;
@@ -2738,8 +2696,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr+=2.000000;
paper[ptr]+=1.000000;
ptr-=2.000000;
ptr-=9.000000;
ptr-=11.000000;
while(paper[ptr])
{
ptr-=9.000000;
@@ -2784,8 +2741,7 @@ while(paper[ptr])
paper[ptr]+=1.000000;
ptr+=3.000000;
}
ptr-=1.000000;
ptr-=2.000000;
ptr-=3.000000;
while(paper[ptr])
{
paper[ptr]-=1.000000;
@@ -2826,8 +2782,7 @@ while(paper[ptr])
{
ptr+=9.000000;
}
ptr-=1.000000;
ptr-=7.000000;
ptr-=8.000000;
}
ptr+=8.000000;
}
@@ -2972,8 +2927,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr-=4.000000;
paper[ptr]+=1.000000;
ptr+=1.000000;
ptr+=3.000000;
ptr+=4.000000;
}
ptr-=4.000000;
while(paper[ptr])
@@ -3087,8 +3041,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr-=4.000000;
paper[ptr]+=1.000000;
ptr+=2.000000;
ptr+=2.000000;
ptr+=4.000000;
}
ptr-=4.000000;
while(paper[ptr])
@@ -3122,8 +3075,7 @@ while(paper[ptr])
ptr+=9.000000;
while(paper[ptr])
{
ptr+=6.000000;
ptr+=3.000000;
ptr+=9.000000;
}
ptr-=9.000000;
while(paper[ptr])
@@ -3158,8 +3110,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr+=2.000000;
paper[ptr]-=1.000000;
ptr-=8.000000;
ptr-=5.000000;
ptr-=13.000000;
paper[ptr]+=1.000000;
ptr+=11.000000;
}
@@ -3191,8 +3142,7 @@ while(paper[ptr])
paper[ptr]+=1.000000;
ptr-=2.000000;
}
ptr-=8.000000;
ptr-=4.000000;
ptr-=12.000000;
}
}
ptr+=9.000000;
@@ -3287,8 +3237,7 @@ while(paper[ptr])
{
while(paper[ptr])
{
ptr+=4.000000;
ptr+=5.000000;
ptr+=9.000000;
}
paper[ptr]+=1.000000;
ptr+=1.000000;
@@ -3349,8 +3298,7 @@ while(paper[ptr])
{
ptr+=1.000000;
paper[ptr]+=1.000000;
ptr+=2.000000;
ptr+=6.000000;
ptr+=8.000000;
}
ptr-=9.000000;
while(paper[ptr])
@@ -3517,8 +3465,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr+=5.000000;
paper[ptr]+=1.000000;
ptr-=4.000000;
ptr-=2.000000;
ptr-=6.000000;
while(paper[ptr])
{
paper[ptr]-=1.000000;
@@ -3552,8 +3499,7 @@ while(paper[ptr])
ptr+=9.000000;
while(paper[ptr])
{
ptr+=6.000000;
ptr+=3.000000;
ptr+=9.000000;
}
ptr-=9.000000;
while(paper[ptr])
@@ -3578,8 +3524,7 @@ while(paper[ptr])
}
ptr-=2.000000;
paper[ptr]+=1.000000;
ptr+=3.000000;
ptr+=5.000000;
ptr+=8.000000;
}
ptr-=9.000000;
while(paper[ptr])
@@ -3639,8 +3584,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr-=36.000000;
paper[ptr]+=1.000000;
ptr+=17.000000;
ptr+=19.000000;
ptr+=36.000000;
}
ptr+=5.000000;
}
@@ -3655,8 +3599,7 @@ while(paper[ptr])
{
while(paper[ptr])
{
ptr+=8.000000;
ptr+=1.000000;
ptr+=9.000000;
}
ptr-=9.000000;
paper[ptr]-=1.000000;
@@ -3759,8 +3702,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr+=3.000000;
paper[ptr]+=1.000000;
ptr-=1.000000;
ptr-=11.000000;
ptr-=12.000000;
while(paper[ptr])
{
ptr-=9.000000;
@@ -3797,8 +3739,7 @@ while(paper[ptr])
}
ptr-=8.000000;
}
ptr+=1.000000;
ptr+=7.000000;
ptr+=8.000000;
}
ptr-=9.000000;
while(paper[ptr])
@@ -3962,8 +3903,7 @@ while(paper[ptr])
paper[ptr]+=1.000000;
ptr+=9.000000;
paper[ptr]+=1.000000;
ptr-=8.000000;
ptr-=6.000000;
ptr-=14.000000;
while(paper[ptr])
{
ptr-=9.000000;
@@ -3991,8 +3931,7 @@ while(paper[ptr])
{
ptr+=9.000000;
}
ptr-=5.000000;
ptr-=4.000000;
ptr-=9.000000;
while(paper[ptr])
{
ptr+=7.000000;
@@ -4022,8 +3961,7 @@ while(paper[ptr])
paper[ptr]+=1.000000;
ptr+=3.000000;
}
ptr-=4.000000;
ptr-=6.000000;
ptr-=10.000000;
}
}
ptr+=7.000000;
@@ -4057,8 +3995,7 @@ while(paper[ptr])
while(paper[ptr])
{
paper[ptr]-=1.000000;
ptr+=3.000000;
ptr+=1.000000;
ptr+=4.000000;
paper[ptr]+=1.000000;
ptr-=4.000000;
}
@@ -4084,8 +4021,7 @@ while(paper[ptr])
{
ptr+=9.000000;
}
ptr-=5.000000;
ptr-=4.000000;
ptr-=9.000000;
while(paper[ptr])
{
ptr+=1.000000;
@@ -4163,8 +4099,7 @@ while(paper[ptr])
ptr+=2.000000;
while(paper[ptr])
{
ptr+=2.000000;
ptr+=3.000000;
ptr+=5.000000;
while(paper[ptr])
{
paper[ptr]-=1.000000;
@@ -4211,8 +4146,7 @@ while(paper[ptr])
}
ptr+=7.000000;
}
ptr-=2.000000;
ptr-=4.000000;
ptr-=6.000000;
while(paper[ptr])
{
paper[ptr]-=1.000000;
@@ -4240,8 +4174,7 @@ while(paper[ptr])
}
ptr+=4.000000;
paper[ptr]+=1.000000;
ptr-=3.000000;
ptr-=2.000000;
ptr-=5.000000;
while(paper[ptr])
{
ptr-=9.000000;
@@ -4272,8 +4205,7 @@ while(paper[ptr])
paper[ptr]+=1.000000;
ptr+=7.000000;
}
ptr-=4.000000;
ptr-=3.000000;
ptr-=7.000000;
while(paper[ptr])
{
paper[ptr]-=1.000000;
@@ -4305,8 +4237,7 @@ while(paper[ptr])
while(paper[ptr])
{
paper[ptr]-=1.000000;
ptr-=1.000000;
ptr-=6.000000;
ptr-=7.000000;
paper[ptr]-=1.000000;
ptr+=7.000000;
}
@@ -4334,8 +4265,7 @@ while(paper[ptr])
ptr-=14.000000;
while(paper[ptr])
{
ptr-=3.000000;
ptr-=6.000000;
ptr-=9.000000;
}
ptr+=3.000000;
while(paper[ptr])
@@ -4371,8 +4301,7 @@ while(paper[ptr])
}
ptr+=8.000000;
}
ptr-=7.000000;
ptr-=2.000000;
ptr-=9.000000;
while(paper[ptr])
{
ptr-=9.000000;
@@ -4401,8 +4330,7 @@ while(paper[ptr])
ptr-=5.000000;
while(paper[ptr])
{
ptr-=7.000000;
ptr-=2.000000;
ptr-=9.000000;
}
}
ptr+=3.000000;
@@ -4432,8 +4360,7 @@ while(paper[ptr])
while(paper[ptr])
{
paper[ptr]-=1.000000;
ptr+=8.000000;
ptr+=1.000000;
ptr+=9.000000;
paper[ptr]+=1.000000;
ptr-=9.000000;
}
@@ -4452,8 +4379,7 @@ while(paper[ptr])
while(paper[ptr])
{
paper[ptr]-=1.000000;
ptr-=6.000000;
ptr-=2.000000;
ptr-=8.000000;
paper[ptr]+=1.000000;
ptr+=8.000000;
}
@@ -4481,8 +4407,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
ptr-=7.000000;
paper[ptr]+=1.000000;
ptr+=6.000000;
ptr+=1.000000;
ptr+=7.000000;
}
ptr-=7.000000;
while(paper[ptr])
@@ -4510,8 +4435,7 @@ while(paper[ptr])
while(paper[ptr])
{
paper[ptr]-=1.000000;
ptr-=5.000000;
ptr-=3.000000;
ptr-=8.000000;
paper[ptr]+=1.000000;
ptr+=8.000000;
}
@@ -4542,8 +4466,7 @@ while(paper[ptr])
paper[ptr]+=1.000000;
ptr-=5.000000;
}
ptr+=6.000000;
ptr+=2.000000;
ptr+=8.000000;
}
ptr-=1.000000;
paper[ptr]+=1.000000;
@@ -4612,8 +4535,7 @@ while(paper[ptr])
}
ptr-=1.000000;
paper[ptr]+=1.000000;
ptr-=6.000000;
ptr-=3.000000;
ptr-=9.000000;
}
ptr+=8.000000;
paper[ptr]-=1.000000;
@@ -4644,8 +4566,7 @@ while(paper[ptr])
ptr+=1.000000;
while(paper[ptr])
{
ptr+=3.000000;
ptr+=3.000000;
ptr+=6.000000;
while(paper[ptr])
{
paper[ptr]-=1.000000;
@@ -4692,8 +4613,7 @@ while(paper[ptr])
}
ptr+=8.000000;
}
ptr-=2.000000;
ptr-=5.000000;
ptr-=7.000000;
while(paper[ptr])
{
paper[ptr]-=1.000000;
@@ -4740,8 +4660,7 @@ while(paper[ptr])
ptr+=6.000000;
}
paper[ptr]+=1.000000;
ptr-=1.000000;
ptr-=5.000000;
ptr-=6.000000;
while(paper[ptr])
{
paper[ptr]-=1.000000;
@@ -4764,8 +4683,7 @@ while(paper[ptr])
ptr-=17.000000;
while(paper[ptr])
{
ptr-=7.000000;
ptr-=2.000000;
ptr-=9.000000;
}
ptr+=4.000000;
while(paper[ptr])
@@ -4827,8 +4745,7 @@ while(paper[ptr])
ptr+=6.000000;
while(paper[ptr])
{
ptr+=6.000000;
ptr+=3.000000;
ptr+=9.000000;
}
ptr+=1.000000;
while(paper[ptr])
@@ -4864,8 +4781,7 @@ while(paper[ptr])
paper[ptr]-=1.000000;
}
ptr-=3.000000;
paper[ptr]+=4.000000;
paper[ptr]+=1.000000;
paper[ptr]+=5.000000;
while(paper[ptr])
{
paper[ptr]-=1.000000;
@@ -4885,8 +4801,7 @@ while(paper[ptr])
ptr-=6.000000;
while(paper[ptr])
{
ptr-=4.000000;
ptr-=5.000000;
ptr-=9.000000;
}
}
ptr+=3.000000;

View File

@@ -1,4 +1,3 @@
import("lib.nas");
var (yMin,yMax,xMin,xMax,line)=(-0.2,0.2,-1.5,-1.0,"");
var (yDel,xDel)=(yMax-yMin,xMax-xMin);
for(var yPixel=0;yPixel<24;yPixel+=1)

247
test/md5.nas Normal file
View File

@@ -0,0 +1,247 @@
var check=func(x){
if(x<0x100000000)
return x;
return x-floor(x/0x100000000)*0x100000000;
}
var u32_bits_and=func(x,y){
(x,y)=(check(x),check(y));
var (res,op)=(0,1);
for(var i=0;i<32;i+=1){
var (tmpx,tmpy)=(x-floor(x/2)*2,y-floor(y/2)*2);
res+=op*(tmpx==1 and tmpy==1);
(x,y)=(floor(x/2),floor(y/2));
op*=2;
}
return res;
}
var u32_bits_or=func(x,y){
(x,y)=(check(x),check(y));
var (res,op)=(0,1);
for(var i=0;i<32;i+=1){
var (tmpx,tmpy)=(x-floor(x/2)*2,y-floor(y/2)*2);
res+=op*(tmpx==1 or tmpy==1);
(x,y)=(floor(x/2),floor(y/2));
op*=2;
}
return res;
}
var u32_bits_xor=func(x,y){
(x,y)=(check(x),check(y));
var (res,op)=(0,1);
for(var i=0;i<32;i+=1){
var (tmpx,tmpy)=(x-floor(x/2)*2,y-floor(y/2)*2);
res+=op*(tmpx!=tmpy);
(x,y)=(floor(x/2),floor(y/2));
op*=2;
}
return res;
}
var u32_bits_not=func(x){
x=check(x);
var (res,op)=(0,1);
for(var i=0;i<32;i+=1){
res+=op*((x-floor(x/2)*2)==1?0:1);
x=floor(x/2);
op*=2;
}
return res;
}
var hex32str=func(){
var ch=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"];
var tbl=[];
setsize(tbl,256);
for(var i=0;i<16;i+=1){
for(var j=0;j<16;j+=1)
tbl[i*16+j]=ch[i]~ch[j];
}
return func(num){
var res="";
for(var i=0;i<4;i+=1){
res~=tbl[u32_bits_and(num,0xff)];
num=floor(num/256);
}
return res;
};
}();
var _md5=func(){
var K=[
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
];
var S=[
7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,
5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,
6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21
];
var idx=[
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,
5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,
0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9
];
var l=func(num,cx){
for(var i=0;i<cx;i+=1){
num=check(num*2);
}
return num;
}
var r=func(num,cx){
num=check(num);
for(var i=0;i<cx;i+=1){
num=num/2;
}
return floor(num);
}
var rol=func(num,cx){
return u32_bits_or(l(num,cx),r(num,32-cx));
}
# round 1
var F=func(x,y,z){
return u32_bits_or(
u32_bits_and(x,y),
u32_bits_and(u32_bits_not(x),z)
);
}
# round 2
var G=func(x,y,z){
return u32_bits_or(
u32_bits_and(x,z),
u32_bits_and(y,u32_bits_not(z))
);
}
# round 3
var H=func(x,y,z){
return u32_bits_xor(u32_bits_xor(x,y),z);
}
# round 4
var I=func(x,y,z){
return u32_bits_xor(
y,
u32_bits_or(x,u32_bits_not(z))
);
}
var functions=[
F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,
G,G,G,G,G,G,G,G,G,G,G,G,G,G,G,G,
H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,H,
I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I
];
return func(s){
var (s_size,len,res)=(size(s),size(s)*8,[]);
setsize(res,s_size);
for(var i=0;i<s_size;i+=1){
res[i]=s[i];
}
# +------len------+--1~512--+--64--+
# | text | fill | size |
# +---------------+---------+------+ N*512 bit
var (mod,res_size)=(s_size-floor(s_size/64)*64,0);
if(mod==56){
res_size=s_size+64;
}elsif(mod<56){
res_size=floor(s_size/64)*64+56;
}elsif(mod>56){
res_size=floor(s_size/64)*64+120; # 512+448=960 960/8=120
}
setsize(res,res_size);
res[s_size]=0x80;
for(var i=s_size+1;i<res_size;i+=1)
res[i]=0;
# little endian
setsize(res,size(res)+8);
var (s_size,lower32,higher32)=(size(res),check(len),check(len/math.pow(2,32)));
for(var i=4;i>0;i-=1){
res[s_size-4-i]=floor(lower32-floor(lower32/256)*256);
lower32=floor(lower32/256);
}
for(var i=4;i>0;i-=1){
res[s_size-i]=floor(higher32-floor(higher32/256)*256);
higher32=floor(higher32/256);
}
# 1 block=>16 uint32=>64 byte=>512 bit
# because using double to discribe number
# this may only work when string's length is under 1<<51
var tmp=[];
setsize(tmp,size(res)/4);
for(var i=0;i<size(res);i+=4){
tmp[i/4]=res[i+3]*math.pow(2,24)+
res[i+2]*math.pow(2,16)+
res[i+1]*math.pow(2,8)+
res[i];
}
res=tmp;
var A=0x67452301;
var B=0xefcdab89;
var C=0x98badcfe;
var D=0x10325476;
res_size=size(res);
for(var i=0;i<res_size;i+=16){
var (f,a,b,c,d)=(0,A,B,C,D);
for(var j=0;j<64;j+=1){
f=functions[j](b,c,d);
(a,b,c,d)=(d,check(b+rol(a+f+K[j]+res[i+idx[j]],S[j])),b,c);
}
(A,B,C,D)=(check(a+A),check(b+B),check(c+C),check(d+D));
}
return hex32str(A)~hex32str(B)~hex32str(C)~hex32str(D);
};
}();
# check if md5 runs correctly
var md5check=func(){
var test_set=[
"md5",
"github.com",
"helloworld",
"abc",
"https://www.github.com/ValKmjolnir/Nasal-Interpreter",
"https://github.com/andyross/nasal",
"var (lower32,higher32)=(check(len),check(len/math.pow(2,32)));",
"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
"let the bass kick",
"f499377c9ae8454c6c8a21ddba7f00de5817fccdc611333ed004d826abb17f4efdacad297f72956e0619002cecffc8e3d18d9b03b082f3cb114bc29173954043",
"you are our last hope"
];
var result=[
"1bc29b36f623ba82aaf6724fd3b16718",
"99cd2175108d157588c04758296d1cfc",
"fc5e038d38a57032085441e7fe7010b0",
"900150983cd24fb0d6963f7d28e17f72",
"6b3a7bbc2240046c4fb1b0b3a4ed8181",
"14a6afca5f3a7b239c56b5a9678c428e",
"f499377c9ae8454c6c8a21ddba7f00de",
"fdacad297f72956e0619002cecffc8e3",
"16eadccb9799dfb4c1ca512f40638bbb",
"a7916c5ce54e73b7ddf6a286b36d976d",
"ec6d5b197ba019db23c719112f3f70b7"
];
forindex(var i;test_set){
var res=_md5(test_set[i]);
if(cmp(res,result[i]))
println(
"md5 cannot work:\n",
" test \""~test_set[i]~"\"\n",
" result \""~result[i]~"\"\n",
" but get \""~res~"\"\n"
);
}
}
# check when loading md5.nas
md5check();

132
test/md5compare.nas Normal file
View File

@@ -0,0 +1,132 @@
import("test/md5.nas");
srand();
var progress_bar=func(){
var res=[];
setsize(res,51);
var (tmp,sp)=(" |"," | ");
res[0]=tmp~sp;
for(var i=1;i<=50;i+=1){
tmp~="#";
res[i]=tmp~substr(sp,i,52-i);
}
return res;
}();
var compare=func(){
var ch=[
"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","+",
"_","*","/","\'","\"",".",",",";",":","<",">","!","@","#","$","%",
"^","&","*","(",")","-","=","\\","|","[","]","{","}","`"," ","\t","?"
];
return func(begin,end){
var (total,prt_cnt,lastpercent,percent)=(end-begin,0,0,0);
for(var i=begin;i<end;i+=1){
var s="";
for(var j=0;j<i;j+=1){
s~=ch[rand()*size(ch)];
}
var res=md5(s);
if(cmp(res,_md5(s))){
die("error: "~str(i));
}
percent=int((i-begin+1)/total*100);
if(percent-lastpercent>=2){
prt_cnt+=1;
lastpercent=percent;
}
print(progress_bar[prt_cnt],percent,"% (",i-begin+1,"/",total,")\t",res," max byte: ",end-1," \r");
}
print('\n');
};
}();
var filechecksum=func(){
var getname=func(s){
var (len,ch)=(size(s),' '[0]);
for(var i=0;i<len and s[i]!=ch;i+=1);
return substr(s,0,i);
}
var files=[
"./stl/file.nas ",
"./stl/lib.nas ",
"./stl/list.nas ",
"./stl/module.nas ",
"./stl/queue.nas ",
"./stl/result.nas ",
"./stl/sort.nas ",
"./stl/stack.nas ",
"./test/ascii-art.nas ",
"./test/auto_crash.nas ",
"./test/bf.nas ",
"./test/bfcolored.nas ",
"./test/bfconvertor.nas ",
"./test/bfs.nas ",
"./test/bigloop.nas ",
"./test/bp.nas ",
"./test/calc.nas ",
"./test/choice.nas ",
"./test/class.nas ",
"./test/diff.nas ",
"./test/exception.nas ",
"./test/fib.nas ",
"./test/filesystem.nas ",
"./test/hexdump.nas ",
"./test/json.nas ",
"./test/leetcode1319.nas ",
"./test/lexer.nas ",
"./test/life.nas ",
"./test/loop.nas ",
"./test/mandel.nas ",
"./test/mandelbrot.nas ",
"./test/md5.nas ",
"./test/md5compare.nas ",
"./test/module_test.nas ",
"./test/nasal_test.nas ",
"./test/pi.nas ",
"./test/prime.nas ",
"./test/props_sim.nas ",
"./test/props.nas ",
"./test/qrcode.nas ",
"./test/quick_sort.nas ",
"./test/scalar.nas ",
"./test/snake.nas ",
"./test/tetris.nas ",
"./test/trait.nas ",
"./test/turingmachine.nas",
"./test/utf8chk.nas ",
"./test/wavecollapse.nas ",
"./test/ycombinator.nas ",
"LICENSE ",
"main.cpp ",
"makefile ",
"nasal_ast.h ",
"nasal_builtin.h ",
"nasal_codegen.h ",
"nasal_dbg.h ",
"nasal_err.h ",
"nasal_gc.h ",
"nasal_import.h ",
"nasal_lexer.h ",
"nasal_opt.h ",
"nasal_parse.h ",
"nasal_vm.h ",
"nasal.ebnf ",
"nasal.h ",
"README.md "
];
foreach(var i;files){
var f=io.fin(getname(i));
var (res0,res1)=(md5(f),_md5(f));
println(i,' ',res0,' ',!cmp(res0,res1),' ',size(f),' byte');
}
}
var randomchecksum=func(){
for(var i=0;i<4096;i+=512)
compare(i,i+512);
}
filechecksum();
randomchecksum();

View File

@@ -1,17 +1,44 @@
import("lib.nas");
var libfib=func(){
var dl=dylib.dlopen("./module/libfib."~(os.platform()=="windows"?"dll":"so"));
var fib=dylib.dlsym(dl,"fib");
var qfib=dylib.dlsym(dl,"quick_fib");
var call=dylib.dlcall;
return
{
fib: func(x){return call(fib,x)},
qfib:func(x){return call(qfib,x)}
};
var (dd,fib,qfib)=(nil,nil,nil);
return {
open:func(){
if(dd==nil){
dd=dylib.dlopen("./module/libfib.so");
fib=dylib.dlsym(dd,"fib");
qfib=dylib.dlsym(dd,"quick_fib");
}else{
println("[info ] already loaded.");
}
},
close:func(){
if(dd==nil){
println("[error ] already closed.");
return;
}
dylib.dlclose(dd);
(dd,fib,qfib)=(nil,nil,nil);
},
fib:func(x){
if(fib!=nil)
return dylib.dlcall(fib,x);
println("[error ] cannot call fib.");
return nil;
},
qfib:func(x){
if(qfib!=nil)
return dylib.dlcall(qfib,x);
println("[error ] cannot call qfib.");
return nil;
}
}
}();
println(libfib);
println(libfib.fib(29));
println(libfib.qfib(29));
println("[keys ] ",keys(libfib));
libfib.open();
libfib.open();
println("[result] ",libfib.fib(40));
println("[result] ",libfib.qfib(40));
libfib.close();
println("[result] ",libfib.fib(40));
println("[result] ",libfib.qfib(40));
libfib.close();

View File

@@ -1,6 +1,5 @@
# This is written for Nasal Intepreter
# Sidi Liang
import("lib.nas");
var w = 1;
var x = "hello";
var f = func(){

View File

@@ -1,5 +1,3 @@
import("lib.nas");
var (t,res)=(1,0);
for(var m=1;m<4e6;m+=2)
{

View File

@@ -1,5 +1,3 @@
import("lib.nas");
var is_prime=func(x){
for(var i=2;i<x;i+=1)
if(x/i==int(x/i))

View File

@@ -1,4 +1,26 @@
import("lib.nas");
var geodinfo=func(lat,lon){
return {};
}
var maketimer=func(interval,function){
return {
isRunning:0,
start:func(){
me.isRunning=1;
while(1){
unix.sleep(interval);
function();
}
},
stop:func(){
me.isRunning=0;
},
restart:func(interval){
},
singleShot:0,
simulatedTime:0
};
}
var props=
{

63
test/qrcode.nas Normal file
View File

@@ -0,0 +1,63 @@
var code=[
[1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1],
[1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1],
[1,0,1,1,1,0,1,0,0,0,0,0,0,0,1,0,1,1,1,0,1],
[1,0,1,1,1,0,1,0,0,0,0,0,0,0,1,0,1,1,1,0,1],
[1,0,1,1,1,0,1,0,0,0,0,0,0,0,1,0,1,1,1,0,1],
[1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1],
[1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0],
[1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
];
if(os.platform()=="windows")
system("chcp 65001");
var texture=[" ","██"];
for(var i=0;i<size(code);i+=1){
for(var j=0;j<size(code[i]);j+=1)
print(texture[code[i][j]]);
print('\n');
}
var transfer=func(s){
var mode=[0,1,0,0];
println(mode);
var len=size(s);
var vec=[0,0,0,0,0,0,0,0,0];
for(var i=8;i>=0;i-=1){
vec[i]=bits.bitand(1,len);
len=int(len/2);
}
println(vec);
var bitstr=[];
for(var i=0;i<size(s);i+=1){
var tmp=[0,0,0,0,0,0,0,0];
var c=s[i];
for(var j=7;j>=0;j-=1){
tmp[j]=bits.bitand(1,c);
c=int(c/2);
}
foreach(var j;tmp)
append(bitstr,j);
}
println(bitstr);
var end=[0,0,0,0];
println(end);
}
transfer("github.com/ValKmjolnir");

View File

@@ -1,4 +1,3 @@
import("lib.nas");
var sort=func(vec,left,right)
{
if(left>=right) return;

View File

@@ -1,5 +1,4 @@
# basic type
import("lib.nas");
nil;
2147483647;
0x7fffffff;
@@ -149,4 +148,56 @@ f1() or f2();
# print '1'
# this means that when using 'or' or 'and',
# if the result is clear when calculating,
# objects behind will not be calculated
# objects behind will not be calculated
print(
subvec([0,1,2,3],2),'\n',
subvec([0,1,2,3],2,1),'\n',
abs(1),'\n',
abs(-1),'\n',
systime(),'\n',
isfunc(func{}),' ',isfunc([]),'\n',
ishash({}),' ',ishash([]),'\n',
isint(114.514),' ',isint(114514),'\n',
isnum("0xaa55"),' ',isnum("?"),'\n',
isscalar(0.618),' ',isscalar("hello"),' ',isscalar([]),'\n',
isstr("hello"),' ',isstr(func{}),'\n',
isvec([]),' ',isvec("[]"),'\n',
vecindex([0,1,2,3,4],1),'\n',
vecindex(["apple","banana"],"apple")!=nil,'\n'
);
println(values({
a:1,
b:2,
c:3
}));
println(find("cd", "abcdef")); # prints 2
println(find("x", "abcdef")); # prints -1
println(find("cd", "abcdef")); # prints 2
var a={
new: func(x=0){
return {
x:x,
parents:[a]
};
},
new2: func(x=0){
return {
x:x,
parents:a
};
}
};
println(isa(a.new(),a)); # 1
println(isa(a.new2(),a));# 0
var a=[10,-10,0,1,2,3,nil,"string","hello",[],[0,1,2,3],{},{a:0,b:1,c:2},func{}];
println("type\tsize\tnum\tsrc");
foreach(var i;a){
println(typeof(i),'\t',size(i),'\t',num(i),'\t',i);
}
foreach(i;a){
;
}

216
test/snake.nas Normal file
View File

@@ -0,0 +1,216 @@
import("./module/libkey.nas");
var list=func(){
var (begin,end,len)=(nil,nil,0);
return{
push_back:func(elem){
var tmp={
elem:elem,
prev:nil,
next:nil
};
if(end!=nil){
end.next=tmp;
tmp.prev=end;
end=tmp;
}else{
begin=end=tmp;
}
len+=1;
},
push_front:func(elem){
var tmp={
elem:elem,
prev:nil,
next:nil
};
if(begin!=nil){
begin.prev=tmp;
tmp.next=begin;
begin=tmp;
}else{
begin=end=tmp;
}
len+=1;
},
pop_back:func(){
if(end!=nil)
end=end.prev;
if(end==nil)
begin=nil;
else
end.next=nil;
if(len)
len-=1;
},
pop_front:func(){
if(begin!=nil)
begin=begin.next;
if(begin==nil)
end=nil;
else
begin.prev=nil;
if(len)
len-=1;
},
front:func(){
if(begin!=nil)
return begin.elem;
},
back:func(){
if(end!=nil)
return end.elem;
},
length:func(){
return len;
}
};
}
var game=func(x,y){
rand(time(0));
var texture=[" ","██","\e[91m██\e[0m"];
var edge0="╔";
var edge1="╚";
for(var i=0;i<x;i+=1){
edge0~="══";
edge1~="══";
}
edge0~="╗\n";
edge1~="╝\n";
var vec=[];
setsize(vec,x);
for(var i=0;i<x;i+=1){
vec[i]=[];
setsize(vec[i],y);
for(var j=0;j<y;j+=1)
vec[i][j]=0;
}
var snake=list();
snake.push_back([int(x/2),int(y/3)]);
snake.push_back([int(x/2),int(y/3)+1]);
vec[int(x/2)][int(y/3)]=1;
vec[int(x/2)][int(y/3)+1]=1;
var move='w';
var gameover=0;
var setapple=func(){
var (cord_x,cord_y)=(int(rand()*x),int(rand()*y));
while(vec[cord_x][cord_y]!=0)
(cord_x,cord_y)=(int(rand()*x),int(rand()*y));
vec[cord_x][cord_y]=2;
}
setapple();
return {
print:func(){
var s="";
var (fx,fy)=snake.front();
for(var i=0;i<y;i+=1){
s~="║";
for(var j=0;j<x;j+=1){
if(fx==j and fy==i)
s~="\e[93m"~texture[vec[j][i]]~"\e[0m";
else
s~=texture[vec[j][i]];
}
s~='║\n';
}
print('\e[1;1H'~edge0~s~edge1);
},
next:func(){
var (fx,fy)=snake.front();
var eat=0;
if(move=="w" and fy-1>=0){
snake.push_front([fx,fy-1]);
if(vec[fx][fy-1]==1)
gameover=1;
elsif(vec[fx][fy-1]==2)
eat=1;
vec[fx][fy-1]=1;
}elsif(move=='a' and fx-1>=0){
snake.push_front([fx-1,fy]);
if(vec[fx-1][fy]==1)
gameover=1;
elsif(vec[fx-1][fy]==2)
eat=1;
vec[fx-1][fy]=1;
}elsif(move=='s' and fy+1<y){
snake.push_front([fx,fy+1]);
if(vec[fx][fy+1]==1)
gameover=1;
elsif(vec[fx][fy+1]==2)
eat=1;
vec[fx][fy+1]=1;
}elsif(move=='d' and fx+1<x){
snake.push_front([fx+1,fy]);
if(vec[fx+1][fy]==1)
gameover=1;
elsif(vec[fx+1][fy]==2)
eat=1;
vec[fx+1][fy]=1;
}else{
gameover=1;
}
if(!gameover and !eat){
var (bx,by)=snake.back();
vec[bx][by]=0;
snake.pop_back();
}
if(eat and snake.length()!=x*y)
setapple();
elsif(snake.length()==x*y)
gameover=2;
},
move:func(c){
if(c=='w' or c=='a' or c=='s' or c=='d')
move=c;
},
gameover:func(){
return gameover;
}
}
}
var main=func(){
if(os.platform()=="windows")
system("chcp 65001");
print("\ec");
libkey.init();
var g=game(15,10);
g.print();
print("\rpress any key to start...");
libkey.getch();
print("\r \r");
var counter=12;
while(1){
var ch=libkey.nonblock();
if(ch!=nil){
if(ch=='q'[0])
break;
elsif(ch=='p'[0]){
print("\rpress any key to continue...");
libkey.getch();
print("\r \r");
}
g.move(chr(ch));
}
unix.sleep(0.02);
counter-=1;
if(counter==0){
counter=20;
g.next();
if(g.gameover())
break;
g.print();
}
}
libkey.close();
println(g.gameover()<=1?"game over.":"you win!");
println("enter anything to quit.");
input();
}
main();

348
test/tetris.nas Normal file
View File

@@ -0,0 +1,348 @@
import("./module/libkey.nas");
var color=[
"\e[31m","\e[32m","\e[33m","\e[34m","\e[35m","\e[36m",
"\e[91m","\e[92m","\e[93m","\e[94m","\e[95m","\e[96m",
];
var blocktype=[
[0,1,2,3 ],
[4,5,6,7 ],
[8,9,10,11],
[12,13 ],
[14 ],
[15,16 ],
[17,18 ]
];
var blockshape=[
# [][] [] [][][]
# [] [] [] []
# [] [][][] [][]
[[0,0],[1,0],[0,1],[0,2]],
[[0,0],[0,1],[1,1],[2,1]],
[[0,0],[0,1],[0,2],[-1,2]],
[[0,0],[1,0],[2,0],[2,1]],
# [][] [][][] []
# [] [] [] []
# [] [][] [][][]
[[0,0],[1,0],[1,1],[1,2]],
[[0,0],[1,0],[2,0],[0,1]],
[[0,0],[0,1],[0,2],[1,2]],
[[0,0],[0,1],[-1,1],[-2,1]],
# [] [] [][][] []
# [][][] [][] [] [][]
# [] []
[[0,0],[0,1],[-1,1],[1,1]],
[[0,0],[0,1],[-1,1],[0,2]],
[[0,0],[-1,0],[1,0],[0,1]],
[[0,0],[0,1],[0,2],[1,1]],
# [] [][][][]
# []
# []
# []
[[0,0],[0,1],[0,2],[0,3]],
[[0,0],[1,0],[2,0],[3,0]],
# [][]
# [][]
[[0,0],[1,0],[0,1],[1,1]],
# [] [][]
# [][] [][]
# []
[[0,0],[0,1],[-1,1],[-1,2]],
[[0,0],[1,0],[1,1],[2,1]],
# [] [][]
# [][] [][]
# []
[[0,0],[0,1],[1,1],[1,2]],
[[0,0],[1,0],[0,1],[-1,1]]
];
var color_count=0;
var counter=0;
var package=[0,1,2,3,4,5,6];
var exchange=func(){
for(var i=6;i>=0;i-=1){
var index=int(i*rand());
(package[i],package[index])=(package[index],package[i]);
}
}
var block={
x:0,
y:0,
rotate:0,
type:nil,
shape:nil,
color:nil,
new:func(x=0,y=0){
(me.x,me.y)=(x,y);
me.rotate=0;
me.type=blocktype[package[counter]];
counter+=1;
if(counter==7){
exchange();
counter=0;
}
me.shape=blockshape[me.type[me.rotate]];
me.color=color_count;
color_count+=1;
if(color_count>=size(color))
color_count=0;
return {parents:[block]};
}
};
var mapgen=func(mapx,mapy){
var (score,gameover)=(0,0);
var (empty,unset,full)=(0,1,2);
if(mapx<1 or mapy<1)
die("map_x or map_y must be greater than 1");
# use in print
var line="";
for(var i=0;i<mapx;i+=1)
line~="══";
var head="\e[32m╔"~line~"╗\e[0m\n";
var tail="\e[32m╚"~line~"╝\e[0m\n";
# generate new map
var map=[];
for(var y=0;y<mapy;y+=1){
var tmp=[];
for(var x=0;x<mapx;x+=1)
append(tmp,empty);
append(map,tmp);
}
var blk=nil;
var new_block=func(){
blk=block.new(int(mapx/2),0);
# check if has enough place to place a new block
foreach(var i;blk.shape)
if(map[blk.y+i[1]][blk.x+i[0]]>=full){
gameover=1;
return;
}
# update map
foreach(var i;blk.shape)
map[blk.y+i[1]][blk.x+i[0]]=unset;
}
new_block(); # initialize the first block
# color print
var map_print=func(){
var s="\e[1;1H"~head;
for(var y=0;y<mapy;y+=1){
s~="\e[32m║\e[0m";
for(var x=0;x<mapx;x+=1){
var c=map[y][x];
if(c==empty)
s~=" ";
elsif(c==unset)
s~=color[blk.color]~"██\e[0m";
elsif(c>=full)
s~=color[c-full]~"██\e[0m";
}
s~="\e[32m║\e[0m\n";
}
s~=tail;
print(s,"\e[31ms\e[32mc\e[33mo\e[34mr\e[35me\e[36m: \e[0m",score,'\n');
}
var moveleft=func(){
var (x,y)=(blk.x-1,blk.y);
foreach(var i;blk.shape){
if(x+i[0]<0)
return;
if(map[y+i[1]][x+i[0]]>=full)
return;
}
# update block state and map
foreach(var i;blk.shape)
map[blk.y+i[1]][blk.x+i[0]]=empty;
blk.x=x;
foreach(var i;blk.shape)
map[blk.y+i[1]][blk.x+i[0]]=unset;
map_print();
}
var moveright=func(){
var (x,y)=(blk.x+1,blk.y);
foreach(var i;blk.shape){
if(x+i[0]>=mapx)
return;
if(map[y+i[1]][x+i[0]]>=full)
return;
}
# update block state and map
foreach(var i;blk.shape)
map[blk.y+i[1]][blk.x+i[0]]=empty;
blk.x=x;
foreach(var i;blk.shape)
map[blk.y+i[1]][blk.x+i[0]]=unset;
map_print();
}
var rotate=func(){
var (r,x,y)=(blk.rotate,blk.x,blk.y);
r=(r+1>=size(blk.type))?0:r+1;
var shape=blockshape[blk.type[r]];
foreach(var i;shape){
if(x+i[0]>=mapx or x+i[0]<0 or y+i[1]>=mapy or y+i[1]<0)
return;
if(map[y+i[1]][x+i[0]]>=full)
return;
}
# update block state and map
foreach(var i;blk.shape)
map[blk.y+i[1]][blk.x+i[0]]=empty;
blk.rotate=r;
blk.shape=shape;
foreach(var i;blk.shape)
map[blk.y+i[1]][blk.x+i[0]]=unset;
map_print();
}
var fall=func(){
var (x,y)=(blk.x,blk.y+1);
# check if falls to the edge of other blocks or map
var sethere=0;
foreach(var i;blk.shape)
if(y+i[1]>=mapy or map[y+i[1]][x+i[0]]>=full){
sethere=1;
break;
}
# set block here and generate a new block
if(sethere){
foreach(var i;blk.shape)
map[blk.y+i[1]][blk.x+i[0]]=blk.color+full;
checkmap();
new_block();
map_print();
return;
}
# update block state and map
foreach(var i;blk.shape)
map[blk.y+i[1]][blk.x+i[0]]=empty;
blk.y=y;
foreach(var i;blk.shape)
map[blk.y+i[1]][blk.x+i[0]]=unset;
map_print();
}
var checkmap=func(){
var lines=1;
for(var y=mapy-1;y>=0;y-=1){
# check if this line is full of blocks
var tmp=0;
for(var x=0;x<mapx;x+=1){
if(map[y][x]<full)
break;
tmp+=map[y][x];
}
# if is full, clear this line and
# all the lines above fall one block
if(x==mapx){
score+=lines*tmp;
lines*=2;
for(var t=y;t>=1;t-=1)
for(var x=0;x<mapx;x+=1)
map[t][x]=map[t-1][x];
for(var x=0;x<mapx;x+=1)
map[0][x]=empty;
y+=1;
}
}
map_print();
}
return {
print:map_print,
moveleft:moveleft,
moveright:moveright,
rotate:rotate,
fall:fall,
checkmap:checkmap,
gameover:func(){return gameover;}
};
}
var main=func(){
# windows use chcp 65001 to output unicode
if(os.platform()=="windows")
system("chcp 65001");
libkey.init();
print(
"\ec\e[1:1H",
"╔═════════════════════════╗\n",
"║ TETRIS ║\n",
"╠═════════════════════════╣\n",
"║ w:rotate, a:move left ║\n",
"║ s:fall, d:move right ║\n",
"║ p:pause, q:quit ║\n",
"╠═════════════════════════╣\n",
"║ press any key to start ║\n",
"╚═════════════════════════╝\n"
);
rand(time(0));
exchange();
var map=mapgen(mapx:12,mapy:18);
libkey.getch();
print("\ec");
var counter=30;
while(1){
# nonblock input one character
var ch=libkey.nonblock();
if(ch){
if(ch=='a'[0]) # move left
map.moveleft();
elsif(ch=='d'[0]) # move right
map.moveright();
elsif(ch=='w'[0]) # rotate
map.rotate();
elsif(ch=='s'[0]) # move down
map.fall();
elsif(ch=='q'[0]) # quit the game
break;
if(ch=='p'[0]){ # pause the game
print("\rpress any key to continue...");
libkey.getch();
print("\r ");
}
map.checkmap();
if(map.gameover())
break;
}
if(!counter){
# automatically fall one block and check
map.fall();
map.checkmap();
if(map.gameover())
break;
counter=30;
}
unix.sleep(0.02);
counter-=1;
}
libkey.close();
print(
map.gameover()?
"\e[31mg\e[32ma\e[33mm\e[34me \e[35mo\e[36mv\e[94me\e[31mr \e[32m~\e[0m\n":
"\e[31ms\e[32me\e[33me \e[34my\e[35mo\e[36mu \e[94m~\e[0m\n"
);
print(
"\e[31me\e[32mn\e[33mt\e[34me\e[35mr ",
"\e[36ma\e[94mn\e[95my\e[96mt\e[31mh\e[32mi\e[33mn\e[34mg ",
"\e[35mt\e[36mo \e[94mq\e[95mu\e[91mi\e[92mt\e[0m\n"
);
input();
};
main();

View File

@@ -1,4 +1,3 @@
import("lib.nas");
var trait={
get:func{return me.val;},

View File

@@ -1,4 +1,3 @@
import("lib.nas");
var table=[
['q0','0','1','R','q1'],
@@ -7,8 +6,44 @@ var table=[
['q2','0','1','R','q3'],
['q3',nil,nil,'S','q3']
];
var operand={
new:func(symbol,changed_symbol,move,next_state){
if(move!='L' and move!='R' and move!='S')
die("invalid move type:"+move);
return {
symbol:symbol,
changed_symbol:changed_symbol,
move:move,
next_state:next_state
};
}
};
var machine={
states:{},
add:func(state,operand){
if(!contains(me.states,state))
me.states[state]=[operand];
else{
foreach(var i;me.states[state])
if(i.symbol==operand.symbol or i.symbol==nil){
println(i);
die("conflict operand");
}
append(me.states[state],operand);
}
},
load:func(data){
foreach(var opr;data){
var (nstat,sym,csym,move,nextstat)=opr;
me.add(nstat,operand.new(sym,csym,move,nextstat));
}
}
};
var prt=func(state,pointer,paper,act=nil){
print(state,':',pointer,':',act!=nil?act:'','\n\t');
print(act!=nil?act:'','\n\t');
var s='';
foreach(var i;paper)
s~=i;
@@ -16,36 +51,50 @@ var prt=func(state,pointer,paper,act=nil){
for(var i=0;i<pointer;i+=1)
for(var j=0;j<size(paper[i]);j+=1)
s~=' ';
print(s,'^\n');
print(s,'^\n',state," ");
}
var run=func(table,node,start,stop){
var run=func(table,start,stop){
var paper=['0','1','1','1','0','1','0','a'];
var pointer=0;
foreach(var action;table){
if(!contains(node,action[0]))
node[action[0]]=nil;
if(!contains(node,action[4]))
node[action[4]]=nil;
}
print("nodes: ",keys(node),'\n');
if(!contains(node,start))
machine.load(table);
print("states: ",keys(machine.states),'\n');
if(!contains(machine.states,start))
die(start~" is not a valid node");
if(!contains(node,stop))
if(!contains(machine.states,stop))
die(stop~" is not a valid node");
var state=start;
var (state,pointer)=(start,0);
prt(state,pointer,paper);
while(state!=stop){
foreach(var action;table)
if(action[0]==state and (action[1]==paper[pointer] or action[1]==' ')){
paper[pointer]=action[2]==nil?paper[pointer]:action[2];
if(action[3]=='L') pointer-=1;
elsif(action[3]=='R') pointer+=1;
elsif(action[3]!='S') die("invalid action <"~action[3]~'>');
state=action[4];
if(!contains(machine.states,state))
die("no matching function for state:"~state);
var found=0;
foreach(var action;machine.states[state]){
var (sym,csym,move,next)=(
action.symbol,
action.changed_symbol,
action.move,
action.next_state
);
if(sym==paper[pointer] or sym==nil){
if(sym!=nil)
paper[pointer]=csym;
if(move=='L') pointer-=1;
elsif(move=='R') pointer+=1;
(state,found)=(next,1);
break;
}
prt(state,pointer,paper,action);
}
if(!found)
die("no matching function for state:"~state);
prt(state,pointer,paper,[sym,csym,move,next]);
}
}
run(table,{},'q0','q3');
run(table,'q0','q3');
print('\n');

32
test/utf8chk.nas Normal file
View File

@@ -0,0 +1,32 @@
var unicode测试=func(){
var 输出=print;
var 测试成功=[
"unicode: utf-8支持测试成功",
"目前仅支持utf-8以及ascii格式文件",
"注意: windows系统请开启chcp 65001代码页"
];
foreach(var 内容;测试成功)
输出(内容~"\n");
}
var emoji测试=func(){
var 💻=print;
var 🎤="\n";
var 🤣="🤣笑嘻了";
var 😅="😅差不多得了";
var 🤤="🤤收收味";
var 🥵="🥵太烧啦";
var 🥶="🥶捏麻麻滴冷死了";
var 🤢="🤢老八秘制小汉堡🍔";
var 🤓="🤓我是傻逼";
var 😭="😭你带我走吧😭😭😭";
var 👿="👿密麻麻石蜡";
var 🤡="🤡居然就是你";
var 💩="💩奥利给干了兄弟们";
var 🍾="🍾好似,开🍾咯";
var 🐘="🐘太🚬🐘了兄弟们";
var 📁=[🤣,😅,🤤,🥵,🥶,🤢,🤓,😭,👿,🤡,💩,🍾,🐘];
foreach(var 📄;📁)
💻(📄,🎤);
}
unicode测试();
emoji测试();

104
test/wavecollapse.nas Normal file
View File

@@ -0,0 +1,104 @@
# wave collapse function 2022/4/10
# by ValKmjolnir
srand();
var interval=1/60;
var table=[
# c ,w,a,s,d
["═",0,1,0,1],
["═",0,1,0,1],
["═",0,1,0,1],
["║",1,0,1,0],
["╔",0,0,1,1],
["╗",0,1,1,0],
["╚",1,0,0,1],
["╝",1,1,0,0],
# ["╠",1,0,1,1],
# ["╣",1,1,1,0],
# ["╦",0,1,1,1],
# ["╩",1,1,0,1],
# ["╬",1,1,1,1],
[" ",0,0,0,0],
[" ",0,0,0,0],
[" ",0,0,0,0],
[" ",0,0,0,0],
[" ",0,0,0,0],
[" ",0,0,0,0]
];
var map=func(){
var (vec,x,s)=(nil,nil,size(table));
var generator=func(){
var tmp=[];
foreach(var elem;table)
if(elem[1]==vec[0][0][3] and elem[2]==0)
append(tmp,elem);
vec[1][0]=tmp[rand()*size(tmp)];
for(var j=1;j<x;j+=1){
if(vec[0][j][3]==0 and vec[1][j-1][4]==0 and rand()>0.5){
vec[1][j]=table[-1];
continue;
}
tmp=[];
foreach(var elem;table)
if(elem[2]==vec[1][j-1][4] and elem[1]==vec[0][j][3]){
if((j==x-1 and elem[4]==0) or j<x-1)
append(tmp,elem);
}
vec[1][j]=tmp[rand()*size(tmp)];
}
}
return {
new:func(_x=10){
x=_x;
vec=[[],[]];
for(var i=0;i<2;i+=1){
setsize(vec[i],x);
for(var j=0;j<x;j+=1)
vec[i][j]=table[-1];
}
var tmp=[];
foreach(var elem;table)
if(elem[1]==0 and elem[2]==0)
append(tmp,elem);
vec[0][0]=tmp[rand()*size(tmp)];
for(var i=1;i<x;i+=1){
tmp=[];
foreach(var elem;table)
if(elem[2]==vec[0][i-1][4] and elem[1]==0){
if((i==x-1 and elem[4]==0) or i<x-1)
append(tmp,elem);
}
vec[0][i]=tmp[rand()*size(tmp)];
}
me.print(0);
generator();
},
print:func(index){
var str="";
foreach(var _x;vec[index])
str~=_x[0];
str~="\n";
print(str);
},
next:func(){
(vec[0],vec[1])=(vec[1],vec[0]);
generator();
}
}
}();
if(os.platform()=="windows")
system("chcp 65001");
map.new(80);
for(var iter=0;iter<100;iter+=1){
map.print(1);
map.next();
unix.sleep(interval);
}

View File

@@ -1,7 +1,4 @@
# Y combinator by ValKmjolnir
import("lib.nas");
var fib=func(f){
return f(f);
}(