forked from xxq250/Nasal-Interpreter
Compare commits
85 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d567f5abf8 | ||
|
|
f8692f1e4e | ||
|
|
712a047a43 | ||
|
|
396d55a207 | ||
|
|
c5171c735a | ||
|
|
07857d980c | ||
|
|
51a1279110 | ||
|
|
de262980cc | ||
|
|
23a5c1b1ad | ||
|
|
fd8a148d0c | ||
|
|
9c7f5f1a6e | ||
|
|
f049e1f9fb | ||
|
|
c4b7712e53 | ||
|
|
7417d5e635 | ||
|
|
785572634b | ||
|
|
2dc8459cbf | ||
|
|
6e035d1951 | ||
|
|
4f5fd3de33 | ||
|
|
fc25dd69e1 | ||
|
|
ca073499ae | ||
|
|
022460755f | ||
|
|
b6f174e869 | ||
|
|
7b160c4589 | ||
|
|
4503239731 | ||
|
|
c12e812651 | ||
|
|
87cff700e8 | ||
|
|
bf5737ecfd | ||
|
|
651ae4ef77 | ||
|
|
e846e51175 | ||
|
|
399b2f0ce9 | ||
|
|
aed5e27409 | ||
|
|
a2b51fe212 | ||
|
|
92b684624d | ||
|
|
83a8632e8e | ||
|
|
41b5304712 | ||
|
|
c5a12ade5c | ||
|
|
7a939b417d | ||
|
|
dd7740f1fd | ||
|
|
617ad03d33 | ||
|
|
b66ebbef4b | ||
|
|
7f22b25909 | ||
|
|
86f6296268 | ||
|
|
cf722fd98c | ||
|
|
1dd3fd445c | ||
|
|
27e25f84ec | ||
|
|
e6457651d3 | ||
|
|
c4d52a88cd | ||
|
|
9bcad59e45 | ||
|
|
9a099f66cb | ||
|
|
b79d60fab5 | ||
|
|
82e9e97a26 | ||
|
|
6a1338bb23 | ||
|
|
3b8a092f36 | ||
|
|
3d86a32b12 | ||
|
|
f26719e1d3 | ||
|
|
e54ef9620f | ||
|
|
d8156e839b | ||
|
|
61666d275d | ||
|
|
99f595e16f | ||
|
|
debe32b187 | ||
|
|
ca9b8581b4 | ||
|
|
a0b341deb5 | ||
|
|
d3df356299 | ||
|
|
cd808a5e6d | ||
|
|
40f61a9dd4 | ||
|
|
f312250d27 | ||
|
|
3fac8aa665 | ||
|
|
243aafd417 | ||
|
|
6bc03601d9 | ||
|
|
f05acaecc7 | ||
|
|
9456a903d7 | ||
|
|
984deed883 | ||
|
|
557cb2ebcf | ||
|
|
9c055a9a23 | ||
|
|
13a09343e6 | ||
|
|
8c67e04cc4 | ||
|
|
e77bb73a82 | ||
|
|
05fc5db337 | ||
|
|
a4738e8c7d | ||
|
|
5f6051e333 | ||
|
|
51afe3dacd | ||
|
|
0291908675 | ||
|
|
5fba784d05 | ||
|
|
9139e34c0b | ||
|
|
e7f503fae1 |
156
lib.nas
156
lib.nas
@@ -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");
|
||||
}
|
||||
74
main.cpp
74
main.cpp
@@ -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();
|
||||
}
|
||||
|
||||
73
makefile
73
makefile
@@ -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
|
||||
|
||||
@@ -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
74
module/keyboard.cpp
Normal 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
13
module/libfib.nas
Normal 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
47
module/libkey.nas
Normal 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);
|
||||
}
|
||||
}
|
||||
}();
|
||||
@@ -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
77
nasal.h
@@ -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"
|
||||
|
||||
13
nasal_ast.h
13
nasal_ast.h
@@ -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)
|
||||
|
||||
742
nasal_builtin.h
742
nasal_builtin.h
File diff suppressed because it is too large
Load Diff
274
nasal_codegen.h
274
nasal_codegen.h
@@ -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);
|
||||
}
|
||||
|
||||
47
nasal_dbg.h
47
nasal_dbg.h
@@ -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, &¶, &&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 );
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
246
nasal_gc.h
246
nasal_gc.h
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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;}
|
||||
|
||||
458
nasal_vm.h
458
nasal_vm.h
@@ -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, &¶, &&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
BIN
pic/mandelbrot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 111 KiB |
26
stl/file.nas
Normal file
26
stl/file.nas
Normal 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);}
|
||||
};
|
||||
}
|
||||
};
|
||||
156
stl/lib.nas
156
stl/lib.nas
@@ -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
43
stl/module.nas
Normal 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);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -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();
|
||||
@@ -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;
|
||||
|
||||
22
test/bf.nas
22
test/bf.nas
@@ -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
242
test/bfcolored.nas
Normal 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);
|
||||
@@ -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]);
|
||||
|
||||
13
test/bfs.nas
13
test/bfs.nas
@@ -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]);
|
||||
@@ -1 +1 @@
|
||||
for(var i=0;i<4e6;i+=1);
|
||||
for(var i=0;i<4e6;i+=1);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import("lib.nas");
|
||||
|
||||
rand(time(0));
|
||||
|
||||
var new_neuron=func()
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import("lib.nas");
|
||||
var condition_true=1;
|
||||
var condition_false=0;
|
||||
if(condition_true)
|
||||
|
||||
@@ -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
129
test/diff.nas
Normal 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);
|
||||
@@ -1,5 +1,3 @@
|
||||
import("lib.nas");
|
||||
|
||||
var ResultTrait={
|
||||
Ok:func(val){
|
||||
me.ok=val;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import("lib.nas");
|
||||
var fib=func(x)
|
||||
{
|
||||
if(x<2) return x;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import("lib.nas");
|
||||
|
||||
var fd=io.open("test/filesystem.nas");
|
||||
while((var line=io.readln(fd))!=nil)
|
||||
println(line);
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# hexdump.nas by ValKmjolnir
|
||||
# 2021/8/13
|
||||
|
||||
import("lib.nas");
|
||||
|
||||
# init
|
||||
var hex_num=[
|
||||
'0','1','2','3',
|
||||
|
||||
476
test/json.nas
476
test/json.nas
@@ -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));
|
||||
@@ -1,4 +1,3 @@
|
||||
import("lib.nas");
|
||||
# union set
|
||||
var n=4;
|
||||
var input=[[0,1],[0,2],[1,2]];
|
||||
|
||||
@@ -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');
|
||||
@@ -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)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import("lib.nas");
|
||||
for(;;)break;
|
||||
for(;;)
|
||||
{
|
||||
|
||||
257
test/mandel.nas
257
test/mandel.nas
@@ -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;
|
||||
|
||||
@@ -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
247
test/md5.nas
Normal 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
132
test/md5compare.nas
Normal 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();
|
||||
@@ -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();
|
||||
@@ -1,6 +1,5 @@
|
||||
# This is written for Nasal Intepreter
|
||||
# Sidi Liang
|
||||
import("lib.nas");
|
||||
var w = 1;
|
||||
var x = "hello";
|
||||
var f = func(){
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import("lib.nas");
|
||||
|
||||
var (t,res)=(1,0);
|
||||
for(var m=1;m<4e6;m+=2)
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
63
test/qrcode.nas
Normal 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");
|
||||
@@ -1,4 +1,3 @@
|
||||
import("lib.nas");
|
||||
var sort=func(vec,left,right)
|
||||
{
|
||||
if(left>=right) return;
|
||||
|
||||
@@ -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
216
test/snake.nas
Normal 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
348
test/tetris.nas
Normal 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();
|
||||
@@ -1,4 +1,3 @@
|
||||
import("lib.nas");
|
||||
|
||||
var trait={
|
||||
get:func{return me.val;},
|
||||
|
||||
@@ -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
32
test/utf8chk.nas
Normal 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
104
test/wavecollapse.nas
Normal 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);
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
# Y combinator by ValKmjolnir
|
||||
|
||||
import("lib.nas");
|
||||
|
||||
var fib=func(f){
|
||||
return f(f);
|
||||
}(
|
||||
|
||||
Reference in New Issue
Block a user