43 Commits
v4.0 ... v5.0

Author SHA1 Message Date
Valk Richard Li
c4e6a89959 update test files and prepare the release of v5.0 2021-03-07 16:33:43 +08:00
Valk Richard Li
f60f674845 delete op_entry 2021-03-04 15:53:34 +08:00
Valk Richard Li
c21d40c466 change test files 2021-03-03 09:20:42 +08:00
Valk Richard Li
19b590f3bb add test files 2021-03-03 01:09:57 +08:00
Valk Richard Li
a421470715 change map to unordered_map 2021-03-01 15:54:58 +08:00
Valk Richard Li
79dc13f419 update 2021-02-27 22:45:51 +08:00
Valk Richard Li
2e8208a752 add getParent & getPath 2021-02-25 22:30:28 +08:00
Valk Richard Li
1c40cca673 add tutorial of how to add built-in function 2021-02-23 23:33:01 +08:00
Valk Richard Li
b1a5a5f6c0 clear memory footprint when codegen complete 2021-02-23 22:53:28 +08:00
Valk Richard Li
64961877de Add props lib & bug fixed(op_ret in foreach/index got SIGSEGV) 2021-02-18 23:49:29 +08:00
Valk Richard Li
9c9bb52818 codegen will not generate 'jmp' if 'if' and 'elsif' is the last condition 2021-02-18 11:45:47 +08:00
Valk Richard Li
02148f4766 bug fixed & more efficient function call
fixed a bug when different hash calling the same function,'me' will be set to the latest called hash's address.
changed the way of pushing the scope to the stack by copying a new scope from the function's scope address.
use map as the nasal_scop instead of list<map>,it'll be more efficient.
2021-02-17 19:31:44 +08:00
Valk Richard Li
767711c93a change identifier name to avoid misunderstanding 2021-02-15 15:29:55 +08:00
Valk Richard Li
78ba0641a6 change the way of calling built-in functions
change std::map to struct array,use index to call built-in functions.this may be more efficient.
2021-02-14 17:36:42 +08:00
Valk Richard Li
80683c381f bug fixed 2021-02-13 23:57:53 +08:00
Li Haokun
6aac46adaf Merge pull request #5 from sidi762/master
Added left, right, streq, cmp, chr to library functions
2021-02-13 07:24:17 -08:00
Sidi Liang
388ef66308 Library: added comment for chr 2021-02-13 21:43:07 +08:00
Sidi Liang
8faa4ef2db Library: Added core library function chr according to FlightGear Nasal 2021-02-13 21:40:10 +08:00
Sidi Liang
441c02d0fb Library: Added core library function streq and cmp according to FlightGear Nasal 2021-02-13 21:09:13 +08:00
Sidi Liang
953ad80482 Library: Added core library function left and right according to FlightGear Nasal 2021-02-13 20:19:49 +08:00
Valk Richard Li
e2ee9cff4c update 2021-02-13 14:37:21 +08:00
Valk Richard Li
996ac59c79 update parser to LL(1) 2021-02-13 13:28:20 +08:00
Valk Richard Li
944f713ee9 update 2021-02-13 11:09:31 +08:00
Valk Richard Li
7329c70492 identifiers' name changed 2021-02-12 23:48:51 +08:00
Valk Richard Li
b5514fd269 update 2021-02-12 22:27:41 +08:00
Valk Richard Li
3be50116fa update 2021-02-10 00:12:22 +08:00
Valk Richard Li
125d6d3a7d update 2021-01-23 19:21:37 +08:00
Valk Richard Li
bb746dfbfb update 2021-01-23 17:57:05 +08:00
Valk Richard Li
8069a1b659 update 2021-01-06 22:12:19 +08:00
Valk Richard Li
f0cb8b6ef3 update 2021-01-06 21:07:34 +08:00
Valk Richard Li
9474ac9ef0 update & bug fixed 2021-01-05 23:17:32 +08:00
Valk Richard Li
b862aa91eb update 2021-01-05 01:55:17 +08:00
Valk Richard Li
bc64d530be update 2021-01-02 23:57:21 +08:00
Valk Richard Li
ea5116e963 update 2020-12-29 19:09:20 +08:00
Valk Richard Li
cc4e697246 bug fixed 2020-12-26 19:05:04 +08:00
Valk Richard Li
515bef3f5d bug fixed 2020-12-25 22:06:42 +08:00
Valk Richard Li
05800fe518 bug fixed 2020-12-25 13:22:57 +08:00
Valk Richard Li
33d37771ce update 2020-12-24 23:53:31 +08:00
Valk Richard Li
89540475cf update 2020-12-20 20:18:02 +08:00
Valk Richard Li
e03da2f737 update 2020-12-20 13:39:24 +08:00
Valk Richard Li
4617eb8f17 update 2020-12-19 23:47:04 +08:00
Valk Richard Li
fed1e20085 update 2020-12-19 21:02:02 +08:00
Valk Richard Li
9f30440286 preparation for v5.0 2020-12-19 01:26:15 +08:00
43 changed files with 3735 additions and 7157 deletions

337
README.md
View File

@@ -1,48 +1,42 @@
# Nasal Interpreter
[![nasal_new_logo](pic/nasal.png?raw=true)](http://wiki.flightgear.org/File:Nasallogo3.png)
# Nasal script language
# Nasal Script Language
[Nasal](http://wiki.flightgear.org/Nasal_scripting_language) is a script language that used in [FlightGear](https://www.flightgear.org/).
There is a Nasal console in FlightGear but sometimes it is not so easy for every developer to use.
The interpreter is still in development(now it works well --2021/2/15). We really need your support!
So this is an interpreter for Nasal written by C++.
The interpreter is still in development.We really need your support!
Also,i am a member of [FGPRC](https://www.fgprc.org/), welcome to join us!
# Why Writing Nasal Interpreter
Nasal is a script language first used in Flightgear.
But in last summer holiday, members in FGPRC told me that it is hard to debug with nasal-console in Flightgear, especially when checking syntax error.
But in last summer holiday, members in FGPRC told me that it is hard to debug with nasal-console in Flightgear, especially when checking syntax errors.
So i tried to write a new interpreter to help them checking syntax error and even, runtime error.
I wrote the lexer, parser and runtime(nasal virtual machine/ast-runtime virtual machine) to help checking errors.
I wrote the lexer, parser and runtime(bytecode virtual machine/ast-runtime virtual machine) to help checking errors.
They found it easier for them to check errors before copying nasal-codes in nasal-console in Flightgear to test.
# How to Compile
> g++ -std=c++11 main.cpp -o main.exe
# Lexical Analysis
The flow chart of lexer is here:
[![nasal_lexer.png](pic/nasal_lexer.png?raw=true)](https://github.com/ValKmjolnir/Nasal-Interpreter/blob/master/pic/nasal_lexer.png)
This picture seems ugly. I will re-draw it later(maybe 1000 years later).
# Parser
## Version 3.0
LL(k) parser.
I refactored parser and make it easier to maintain.
```javascript
The EBNF is also refactored.
(var a,b,c)=[{b:nil},[1,2],func{return 0;}];
(a.b,b[0],c)=(1,2,3);
```
have the same first set,so LL(1) is useless for this language.
Maybe in the future i can refactor it to LL(1) with special checks.
# Abstract Syntax Tree
@@ -64,6 +58,12 @@ Now you can add your own functions as builtin-functions in this interpreter!
I decide to save the ast interpreter after releasing v4.0. Because it took me a long time to think and write...
## Version 5.0
I change my mind.AST interpreter leaves me too much things to do.
If i continue saving this interpreter,it will be harder for me to make the bytecode vm become more efficient.
# Byte Code Interpreter
## Version 4.0
@@ -77,21 +77,286 @@ Now i am trying to search hidden bugs in this interpreter.Hope you could help me
There's an example of byte code below:
```javascript
var (a,b,c)=(1,2,3);
for(var i=0;i<4000000;i+=1);
```
```asm
.number 0
.number 4e+006
.number 1
.number 2
.number 3
.symbol a
.symbol b
.symbol c
0x00000000: pone 0x00000000
0x00000001: load 0x00000000 (a)
0x00000002: pnum 0x00000001 (2)
0x00000003: load 0x00000001 (b)
0x00000004: pnum 0x00000002 (3)
0x00000005: load 0x00000002 (c)
0x00000006: nop 0x00000000
```
.symbol i
0x00000000: pzero 0x00000000
0x00000001: load 0x00000000 (i)
0x00000002: call 0x00000000 (i)
0x00000003: pnum 0x00000001 (4e+006)
0x00000004: less 0x00000000
0x00000005: jf 0x0000000b
0x00000006: pone 0x00000000
0x00000007: mcall 0x00000000 (i)
0x00000008: addeq 0x00000000
0x00000009: pop 0x00000000
0x0000000a: jmp 0x00000002
0x0000000b: nop 0x00000000
```
## Version 5.0
I decide to optimize bytecode vm in this version.
Because it takes more than 1.5s to count i from 0 to 4000000-1.This is not efficient at all!
2021/1/23 update: Now it can count from 0 to 4000000-1 in 1.5s.
# How to Use Nasal to Program
## basic value type
nasal has 6 value types.Number,string,vector,hash,function,nil.
Number has 3 formats.Dec,hex and oct;
String has 3 formats.But the third one is often used to declare a character.
Vector has unlimited length and can store all types of values.
Hash is a hashmap that stores values with strings/identifiers as the key.
Function is also a value type in nasal.
```javascript
var spc=nil;
var a=1;
var a=2.71828;
var a=2.147e16;
var a=1e-10;
var a=0x7fffffff;
var a=0xAA55;
var a=0o170001;
var b='str';
var b="another string";
var b=`c`;
var c=[];
var c=[0,nil,{},[],func(){return 0;}];
append(c,0,1,2);
var d={
member1:nil,
member2:'str',
'member3':'member\'s name can also be a string constant',
"member4":"also this",
function:func()
{
var a=me.member2~me.member3;
return a;
}
};
var f=func(x,y,z)
{
return nil;
}
var f=func
{
return 1024;
}
var f=func(x,y,z,default_parameter1=1,default_parameter2=2)
{
return x+y+z+default_parameter1+default_parameter2;
}
var f=func(x,y,z,dynamic_parameter...)
{
var sum=0;
foreach(var i;dynamic_parameter)
sum+=i;
return sum+x+y+z;
}
```
## operators
```javascript
1+2;
1-2;
1*2;
1/2;
'str1'~'str2';
(1+2)*(3+4)
1+1 and 0;
1+2*3 or 0;
1<0;
1>0;
1<=0;
1>=0;
1==0;
1!=0;
-1;
!0;
a=b=c=d=1;
a+=1;
a-=1;
a*=1;
a/=1;
a~='string';
```
## definition
```javascript
var a=1;
var (a,b,c)=[0,1,2];
var (a,b,c)=(0,1,2);
(var a,b,c)=[0,1,2];
(var a,b,c)=(0,1,2);
```
## multi-assignment
```javascript
(a,b[0],c.d)=[0,1,2];
(a,b[1],c.e)=(0,1,2);
```
## conditional expression
```javascript
if(1)
{
;
}
elsif(2)
{
;
}
else if(3)
{
;
}
else
{
;
}
```
## loop
```javascript
while(condition)
continue;
for(var i=0;i<10;i+=1)
break;
forindex(var i;elem)
print(elem[i]);
foreach(var i;elem)
print(i);
```
## subvec
Use index to search one element in the string will get the ascii number of this character.If you want to get the character,use built-in function chr().
```javascript
a[-1,1,0:2,0:,:3,:,nil:8,3:nil,nil:nil];
"hello world"[0];
```
## special function call
This is of great use but is not very efficient.
```javascript
a(x:0,y:1,z:2);
```
## closure
```javascript
var f=func()
{
var a=1;
return func(){return a;};
}
print(f()());
```
## built-in functions
Must import lib.nas or has these functions' definitions inside your code.
Also you could add builtin functions of your own(written in C/C++) to help you calculate things more quickly.(Advanced usage)
Check built-in functions in lib.nas!
If you want to add your own built-in functions,define the function in nasal_builtin.h.
Definition:
```C++
nasal_val* builtin_chr(nasal_val*,nasal_gc&);
```
Then complete this function using C++:
```C++
nasal_val* builtin_print(nasal_val* local_scope_addr,nasal_gc& gc)
{
// get arguments by using in_builtin_find
nasal_val* vector_value_addr=in_builtin_find("elements");
// main process
// also check type here,if get a type error,use builtin_error_occurred and return nullptr
nasal_vec& ref_vec=vector_value_addr->get_vector();
int size=ref_vec.size();
for(int i=0;i<size;++i)
{
nasal_val* tmp=ref_vec[i];
switch(tmp->get_type())
{
case vm_nil: std::cout<<"nil"; break;
case vm_num: std::cout<<tmp->get_number(); break;
case vm_str: std::cout<<tmp->get_string(); break;
case vm_vec: tmp->get_vector().print(); break;
case vm_hash: tmp->get_hash().print(); break;
case vm_func: std::cout<<"func(...){...}"; break;
}
}
// if a nasal value is not in use,use gc::del_reference to delete it
// if get a new reference of a nasal value,use gc::add_reference
// generate return value,use gc::gc_alloc(type) to make a new value
return gc.gc_alloc(vm_nil);
}
```
After that, write the built-in function's name(in nasal) and the function's pointer in this table:
```C++
struct FUNC_TABLE
{
std::string func_name;
nasal_val* (*func_pointer)(nasal_val* x,nasal_gc& gc);
} builtin_func_table[]=
{
{"nasal_call_builtin_std_cout",builtin_print},
{"",NULL}
};
```
At last,warp the 'nasal_call_builtin_std_cout' in a nasal file:
```javascript
var print=func(elements...)
{
nasal_call_builtin_std_cout(elements);
return nil;
};
```
In version 5.0,if you don't warp built-in function in a normal nasal function,this built-in function may cause a fault when searching arguments,which will cause SIGSEGV segmentation error(maybe).
Use import("") to get the nasal file including your biult-in functions,then you could use it.

90
lib.nas
View File

@@ -8,6 +8,12 @@ var print=func(elements...)
nasal_call_builtin_std_cout(elements);
return nil;
};
var println=func(elements...)
{
nasal_call_builtin_std_cout(elements);
print('\n');
return nil;
}
var append=func(vector,elements...)
{
nasal_call_builtin_push_back(vector,elements);
@@ -94,6 +100,26 @@ var substr=func(str,begin,length)
{
return nasal_call_builtin_substr(str,begin,length);
}
var streq=func(a,b)
{
return nasal_call_builtin_streq(a,b);
}
var left=func(string,length)
{
return nasal_call_builtin_left(string,length);
}
var right=func(string,length)
{
return nasal_call_builtin_right(string,length);
}
var cmp=func(a,b)
{
return nasal_call_builtin_cmp(a,b);
}
var chr=func(code) #//Unlike in FG, this chr does not support Extended ASCII
{
return nasal_call_builtin_chr(code);
}
var io=
{
@@ -110,58 +136,22 @@ var io=
var bits=
{
bitxor:func(a,b)
{
return nasal_call_builtin_xor(a,b);
},
bitand:func(a,b)
{
return nasal_call_builtin_and(a,b);
},
bitor:func(a,b)
{
return nasal_call_builtin_or(a,b);
},
bitnand:func(a,b)
{
return nasal_call_builtin_nand(a,b);
},
bitnot:func(a)
{
return nasal_call_builtin_not(a);
}
bitxor: func(a,b){return nasal_call_builtin_xor(a,b); },
bitand: func(a,b){return nasal_call_builtin_and(a,b); },
bitor: func(a,b){return nasal_call_builtin_or(a,b); },
bitnand: func(a,b){return nasal_call_builtin_nand(a,b);},
bitnot: func(a) {return nasal_call_builtin_not(a); }
};
var math=
{
e:2.7182818284590452354,
pi:3.14159265358979323846264338327950288,
sin:func(x)
{
return nasal_call_builtin_sin(x);
},
cos:func(x)
{
return nasal_call_builtin_cos(x);
},
tan:func(x)
{
return nasal_call_builtin_tan(x);
},
exp:func(x)
{
return nasal_call_builtin_exp(x);
},
ln:func(x)
{
return nasal_call_builtin_cpp_math_ln(x);
},
sqrt:func(x)
{
return nasal_call_builtin_cpp_math_sqrt(x);
},
atan2:func(x,y)
{
return nasal_call_builtin_cpp_atan2(x,y);
},
e: 2.7182818284590452354,
pi: 3.14159265358979323846264338327950288,
sin: func(x) {return nasal_call_builtin_sin(x); },
cos: func(x) {return nasal_call_builtin_cos(x); },
tan: func(x) {return nasal_call_builtin_tan(x); },
exp: func(x) {return nasal_call_builtin_exp(x); },
ln: func(x) {return nasal_call_builtin_cpp_math_ln(x); },
sqrt: func(x) {return nasal_call_builtin_cpp_math_sqrt(x);},
atan2: func(x,y){return nasal_call_builtin_cpp_atan2(x,y); }
};

View File

@@ -4,51 +4,51 @@ nasal_lexer lexer;
nasal_parse parse;
nasal_import import;
std::string inputfile="null";
nasal_runtime runtime;
nasal_codegen code_generator;
nasal_bytecode_vm bytevm;
nasal_vm vm;
void help()
{
std::cout<<">> [\"file\"] input a file name.\n";
std::cout<<">> [help ] show help.\n";
std::cout<<">> [clear ] clear the screen.\n";
std::cout<<">> [del ] clear the input filename.\n";
std::cout<<">> [lex ] use lexer to turn code into tokens.\n";
std::cout<<">> [ast ] do parsing and check the abstract syntax tree.\n";
std::cout<<">> [run ] run abstract syntax tree.\n";
std::cout<<">> [code ] show byte code.\n";
std::cout<<">> [exec ] execute program on bytecode vm.\n";
std::cout<<">> [logo ] print logo of nasal .\n";
std::cout<<">> [exit ] quit nasal interpreter.\n";
std::cout
<<">> [\"file\"] input a file name.\n"
<<">> [help ] show help.\n"
<<">> [clear ] clear the screen.\n"
<<">> [lex ] use lexer to turn code into tokens.\n"
<<">> [ast ] do parsing and check the abstract syntax tree.\n"
<<">> [code ] show byte code.\n"
<<">> [exec ] execute program on bytecode vm.\n"
<<">> [logo ] print logo of nasal .\n"
<<">> [exit ] quit nasal interpreter.\n";
return;
}
void logo()
{
std::cout<<" __ _ \n";
std::cout<<" /\\ \\ \\__ _ ___ __ _| | \n";
std::cout<<" / \\/ / _` / __|/ _` | | \n";
std::cout<<" / /\\ / (_| \\__ \\ (_| | | \n";
std::cout<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n";
std::cout
<<" __ _ \n"
<<" /\\ \\ \\__ _ ___ __ _| | \n"
<<" / \\/ / _` / __|/ _` | | \n"
<<" / /\\ / (_| \\__ \\ (_| | | \n"
<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n";
return;
}
void del_func()
{
lexer.clear();
parse.clear();
inputfile="null";
std::cout<<">> [Delete] complete.\n";
return;
}
void die(std::string stage,std::string filename)
{
std::cout<<">> ["<<stage<<"] in <\""<<filename<<"\">: error(s) occurred,stop.\n";
return;
}
void clear()
{
// this will clear the data in lexer/parser/import modules
// to reduce memory footprint
lexer.get_token_list().clear();
parse.get_root().clear();
import.get_root().clear();
return;
}
void lex_func()
{
lexer.openfile(inputfile);
@@ -59,6 +59,7 @@ void lex_func()
return;
}
lexer.print_token();
clear();
return;
}
@@ -79,33 +80,7 @@ void ast_print()
return;
}
parse.get_root().print_ast(0);
return;
}
void runtime_start()
{
lexer.openfile(inputfile);
lexer.scanner();
if(lexer.get_error())
{
die("lexer",inputfile);
return;
}
parse.set_toklist(lexer.get_token_list());
parse.main_process();
if(parse.get_error())
{
die("parse",inputfile);
return;
}
import.link(parse.get_root());
if(import.get_error())
{
die("import",inputfile);
return;
}
runtime.set_root(import.get_root());
runtime.run();
clear();
return;
}
@@ -132,6 +107,7 @@ void show_bytecode()
return;
}
code_generator.main_progress(import.get_root());
clear();
code_generator.print_byte_code();
return;
}
@@ -159,7 +135,8 @@ void execute()
return;
}
code_generator.main_progress(import.get_root());
bytevm.run(
clear();
vm.run(
code_generator.get_string_table(),
code_generator.get_number_table(),
code_generator.get_exec_code()
@@ -176,7 +153,7 @@ int main()
system("cls");
#endif
logo();
std::cout<<">> Nasal interpreter ver 3.0 .\n";
std::cout<<">> Nasal interpreter ver 5.0 .\n";
std::cout<<">> Code: https://github.com/ValKmjolnir/Nasal-Interpreter\n";
std::cout<<">> Info: http://wiki.flightgear.org/Nasal_scripting_language\n";
std::cout<<">> Input \"help\" to get help .\n";
@@ -198,14 +175,10 @@ int main()
system("clear");
#endif
}
else if(command=="del")
del_func();
else if(command=="lex")
lex_func();
else if(command=="ast")
ast_print();
else if(command=="run")
runtime_start();
else if(command=="code")
show_bytecode();
else if(command=="exec")

View File

@@ -19,7 +19,7 @@
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <unordered_map>
/*
check if a string can be converted to a number
@@ -133,8 +133,7 @@ std::string trans_number_to_string(double number)
#include "nasal_import.h"
#include "nasal_gc.h"
#include "nasal_builtin.h"
#include "nasal_runtime.h"
#include "nasal_codegen.h"
#include "nasal_bytecode_vm.h"
#include "nasal_vm.h"
#endif

View File

@@ -4,17 +4,17 @@
enum ast_node
{
ast_null=0,ast_root,ast_block,
ast_nil,ast_number,ast_string,ast_identifier,ast_function,ast_hash,ast_vector,
ast_hashmember,ast_call,ast_call_hash,ast_call_vec,ast_call_func,ast_subvec,
ast_nil,ast_num,ast_str,ast_id,ast_func,ast_hash,ast_vec,
ast_hashmember,ast_call,ast_callh,ast_callv,ast_callf,ast_subvec,
ast_args,ast_default_arg,ast_dynamic_id,
ast_and,ast_or,
ast_equal,ast_add_equal,ast_sub_equal,ast_mult_equal,ast_div_equal,ast_link_equal,
ast_cmp_equal,ast_cmp_not_equal,
ast_less_than,ast_less_equal,
ast_greater_than,ast_greater_equal,
ast_equal,ast_addeq,ast_subeq,ast_multeq,ast_diveq,ast_lnkeq,
ast_cmpeq,ast_neq,
ast_less,ast_leq,
ast_grt,ast_geq,
ast_add,ast_sub,ast_mult,ast_div,ast_link,
ast_unary_sub,ast_unary_not,
ast_trinocular,
ast_neg,ast_not,
ast_trino,
ast_for,ast_forindex,ast_foreach,ast_while,ast_new_iter,
ast_conditional,ast_if,ast_elsif,ast_else,
ast_multi_id,ast_multi_scalar,
@@ -22,70 +22,69 @@ enum ast_node
ast_continue,ast_break,ast_return
};
std::string ast_str(int type)
std::string ast_name(int type)
{
std::string str;
switch(type)
{
case ast_null: str="null";break;
case ast_root: str="root";break;
case ast_block: str="block";break;
case ast_nil: str="nil";break;
case ast_number: str="number";break;
case ast_string: str="string";break;
case ast_identifier: str="id";break;
case ast_function: str="function";break;
case ast_hash: str="hash";break;
case ast_vector: str="vector";break;
case ast_hashmember: str="hashmember";break;
case ast_call: str="call";break;
case ast_call_hash: str="call_hash";break;
case ast_call_vec: str="call_vector";break;
case ast_call_func: str="call_func";break;
case ast_subvec: str="subvec";break;
case ast_args: str="arguments";break;
case ast_default_arg: str="default_arg";break;
case ast_dynamic_id: str="dynamic_id";break;
case ast_and: str="and";break;
case ast_or: str="or";break;
case ast_equal: str="=";break;
case ast_add_equal: str="+=";break;
case ast_sub_equal: str="-=";break;
case ast_mult_equal: str="*=";break;
case ast_div_equal: str="/=";break;
case ast_link_equal: str="~=";break;
case ast_cmp_equal: str="==";break;
case ast_cmp_not_equal:str="!=";break;
case ast_less_than: str="<";break;
case ast_less_equal: str="<=";break;
case ast_greater_than: str=">";break;
case ast_greater_equal:str=">=";break;
case ast_add: str="+";break;
case ast_sub: str="-";break;
case ast_mult: str="*";break;
case ast_div: str="/";break;
case ast_link: str="~";break;
case ast_unary_sub: str="unary-";break;
case ast_unary_not: str="unary!";break;
case ast_trinocular: str="trinocular";break;
case ast_for: str="for";break;
case ast_forindex: str="forindex";break;
case ast_foreach: str="foreach";break;
case ast_while: str="while";break;
case ast_new_iter: str="new_iterator";break;
case ast_conditional: str="conditional";break;
case ast_if: str="if";break;
case ast_elsif: str="elsif";break;
case ast_else: str="else";break;
case ast_multi_id: str="multi_id";break;
case ast_multi_scalar: str="multi_scalar";break;
case ast_definition: str="definition";break;
case ast_multi_assign: str="multi_assignment";break;
case ast_continue: str="continue";break;
case ast_break: str="break";break;
case ast_return: str="return";break;
case ast_null: return "null";
case ast_root: return "root";
case ast_block: return "block";
case ast_nil: return "nil";
case ast_num: return "number";
case ast_str: return "string";
case ast_id: return "id";
case ast_func: return "function";
case ast_hash: return "hash";
case ast_vec: return "vector";
case ast_hashmember: return "hashmember";
case ast_call: return "call";
case ast_callh: return "callh";
case ast_callv: return "callv";
case ast_callf: return "callf";
case ast_subvec: return "subvec";
case ast_args: return "args";
case ast_default_arg: return "deflt_arg";
case ast_dynamic_id: return "dyn_id";
case ast_and: return "and";
case ast_or: return "or";
case ast_equal: return "=";
case ast_addeq: return "+=";
case ast_subeq: return "-=";
case ast_multeq: return "*=";
case ast_diveq: return "/=";
case ast_lnkeq: return "~=";
case ast_cmpeq: return "==";
case ast_neq: return "!=";
case ast_less: return "<";
case ast_leq: return "<=";
case ast_grt: return ">";
case ast_geq: return ">=";
case ast_add: return "+";
case ast_sub: return "-";
case ast_mult: return "*";
case ast_div: return "/";
case ast_link: return "~";
case ast_neg: return "unary-";
case ast_not: return "unary!";
case ast_trino: return "trino";
case ast_for: return "for";
case ast_forindex: return "forindex";
case ast_foreach: return "foreach";
case ast_while: return "while";
case ast_new_iter: return "iter";
case ast_conditional: return "conditional";
case ast_if: return "if";
case ast_elsif: return "elsif";
case ast_else: return "else";
case ast_multi_id: return "multi_id";
case ast_multi_scalar: return "multi_scalar";
case ast_definition: return "def";
case ast_multi_assign: return "multi_assign";
case ast_continue: return "continue";
case ast_break: return "break";
case ast_return: return "return";
}
return str;
return "null";
}
class nasal_ast
@@ -217,13 +216,13 @@ void nasal_ast::print_ast(int depth)
{
std::string indentation="";
for(int i=0;i<depth;++i) indentation+="| ";
indentation+=ast_str(this->type);
indentation+=ast_name(this->type);
std::cout<<indentation;
if(this->type==ast_string || this->type==ast_identifier || this->type==ast_dynamic_id || this->type==ast_call_hash)
if(this->type==ast_str || this->type==ast_id || this->type==ast_dynamic_id || this->type==ast_callh)
std::cout<<":"<<this->str;
else if(this->type==ast_number)
else if(this->type==ast_num)
std::cout<<":"<<this->num;
std::cout<<std::endl;
std::cout<<'\n';
int child_size=this->children.size();
for(int i=0;i<child_size;++i)
this->children[i].print_ast(depth+1);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -10,28 +10,17 @@ private:
std::vector<std::string> filename_table;
int error;
void die(std::string,std::string);
void init();
bool check_import(nasal_ast&);
bool check_exist(std::string);
void linker(nasal_ast&,nasal_ast&);
nasal_ast file_import(nasal_ast&);
nasal_ast load(nasal_ast&);
public:
nasal_import();
int get_error();
void link(nasal_ast&);
nasal_ast& get_root();
};
nasal_import::nasal_import()
{
import_lex.clear();
import_par.clear();
import_ast.clear();
filename_table.clear();
return;
}
void nasal_import::die(std::string filename,std::string error_stage)
{
++error;
@@ -39,13 +28,6 @@ void nasal_import::die(std::string filename,std::string error_stage)
return;
}
void nasal_import::init()
{
import_lex.clear();
import_par.clear();
return;
}
bool nasal_import::check_import(nasal_ast& node)
{
/*
@@ -63,9 +45,9 @@ bool nasal_import::check_import(nasal_ast& node)
return false;
if(ref_vec[0].get_str()!="import")
return false;
if(ref_vec[1].get_type()!=ast_call_func)
if(ref_vec[1].get_type()!=ast_callf)
return false;
if(ref_vec[1].get_children().size()!=1 || ref_vec[1].get_children()[0].get_type()!=ast_string)
if(ref_vec[1].get_children().size()!=1 || ref_vec[1].get_children()[0].get_type()!=ast_str)
return false;
return true;
}
@@ -94,15 +76,11 @@ void nasal_import::linker(nasal_ast& root,nasal_ast& add_root)
nasal_ast nasal_import::file_import(nasal_ast& node)
{
// initializing
nasal_ast tmp;
tmp.set_line(0);
tmp.set_type(ast_root);
init();
nasal_ast tmp(0,ast_root);
// get filename and set node to ast_null
std::string filename=node.get_children()[1].get_children()[0].get_str();
node.clear();
node.set_type(ast_null);
// avoid infinite loading loop
if(check_exist(filename))
@@ -131,9 +109,7 @@ nasal_ast nasal_import::file_import(nasal_ast& node)
nasal_ast nasal_import::load(nasal_ast& root)
{
nasal_ast new_root;
new_root.set_line(0);
new_root.set_type(ast_root);
nasal_ast new_root(0,ast_root);
std::vector<nasal_ast>& ref_vec=root.get_children();
int size=ref_vec.size();
@@ -148,7 +124,6 @@ nasal_ast nasal_import::load(nasal_ast& root)
}
// add root to the back of new_root
linker(new_root,root);
// oops,i think it is not efficient if the root is too ... large?
return new_root;
}

View File

@@ -7,7 +7,7 @@
#define IS_DIGIT(c) ('0'<=c&&c<='9')
#define IS_STRING(c) (c=='\''||c=='\"'||c=='`')
// single operators have only one character
#define IS_SINGLE_OPRATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\
#define IS_SINGLE_OPERATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\
c=='?'||c=='`'||c=='&'||c=='@'||c=='%'||c=='$'||c=='^'||c=='\\')
// calculation operators may have two chars, for example: += -= *= /= ~= != == >= <=
#define IS_CALC_OPERATOR(c) (c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~')
@@ -16,18 +16,19 @@
enum token_type
{
tok_null=0,
tok_number,tok_string,tok_identifier,
tok_num,tok_str,tok_id,
tok_for,tok_forindex,tok_foreach,tok_while,
tok_var,tok_func,tok_break,tok_continue,
tok_return,tok_if,tok_elsif,tok_else,tok_nil,
tok_left_curve,tok_right_curve,
tok_left_bracket,tok_right_bracket,
tok_left_brace,tok_right_brace,
tok_ret,tok_if,tok_elsif,tok_else,tok_nil,
tok_lcurve,tok_rcurve,
tok_lbracket,tok_rbracket,
tok_lbrace,tok_rbrace,
tok_semi,tok_and,tok_or,tok_comma,tok_dot,tok_ellipsis,tok_quesmark,
tok_colon,tok_add,tok_sub,tok_mult,tok_div,tok_link,tok_not,
tok_equal,
tok_add_equal,tok_sub_equal,tok_mult_equal,tok_div_equal,tok_link_equal,
tok_cmp_equal,tok_cmp_not_equal,tok_less_than,tok_less_equal,tok_greater_than,tok_greater_equal
tok_eq,
tok_addeq,tok_subeq,tok_multeq,tok_diveq,tok_lnkeq,
tok_cmpeq,tok_neq,tok_less,tok_leq,tok_grt,tok_geq,
tok_eof
};
struct
@@ -36,52 +37,52 @@ struct
int tok_type;
}token_table[]=
{
{"for" ,tok_for },
{"forindex",tok_forindex },
{"foreach" ,tok_foreach },
{"while" ,tok_while },
{"var" ,tok_var },
{"func" ,tok_func },
{"break" ,tok_break },
{"continue",tok_continue },
{"return" ,tok_return },
{"if" ,tok_if },
{"elsif" ,tok_elsif },
{"else" ,tok_else },
{"nil" ,tok_nil },
{"(" ,tok_left_curve },
{")" ,tok_right_curve },
{"[" ,tok_left_bracket },
{"]" ,tok_right_bracket},
{"{" ,tok_left_brace },
{"}" ,tok_right_brace },
{";" ,tok_semi },
{"and" ,tok_and },
{"or" ,tok_or },
{"," ,tok_comma },
{"." ,tok_dot },
{"..." ,tok_ellipsis },
{"?" ,tok_quesmark },
{":" ,tok_colon },
{"+" ,tok_add },
{"-" ,tok_sub },
{"*" ,tok_mult },
{"/" ,tok_div },
{"~" ,tok_link },
{"!" ,tok_not },
{"=" ,tok_equal },
{"+=" ,tok_add_equal },
{"-=" ,tok_sub_equal },
{"*=" ,tok_mult_equal },
{"/=" ,tok_div_equal },
{"~=" ,tok_link_equal },
{"==" ,tok_cmp_equal },
{"!=" ,tok_cmp_not_equal},
{"<" ,tok_less_than },
{"<=" ,tok_less_equal },
{">" ,tok_greater_than },
{">=" ,tok_greater_equal},
{NULL ,-1 }
{"for" ,tok_for },
{"forindex",tok_forindex },
{"foreach" ,tok_foreach },
{"while" ,tok_while },
{"var" ,tok_var },
{"func" ,tok_func },
{"break" ,tok_break },
{"continue",tok_continue },
{"return" ,tok_ret },
{"if" ,tok_if },
{"elsif" ,tok_elsif },
{"else" ,tok_else },
{"nil" ,tok_nil },
{"(" ,tok_lcurve },
{")" ,tok_rcurve },
{"[" ,tok_lbracket },
{"]" ,tok_rbracket },
{"{" ,tok_lbrace },
{"}" ,tok_rbrace },
{";" ,tok_semi },
{"and" ,tok_and },
{"or" ,tok_or },
{"," ,tok_comma },
{"." ,tok_dot },
{"..." ,tok_ellipsis },
{"?" ,tok_quesmark },
{":" ,tok_colon },
{"+" ,tok_add },
{"-" ,tok_sub },
{"*" ,tok_mult },
{"/" ,tok_div },
{"~" ,tok_link },
{"!" ,tok_not },
{"=" ,tok_eq },
{"+=" ,tok_addeq },
{"-=" ,tok_subeq },
{"*=" ,tok_multeq },
{"/=" ,tok_diveq },
{"~=" ,tok_lnkeq },
{"==" ,tok_cmpeq },
{"!=" ,tok_neq },
{"<" ,tok_less },
{"<=" ,tok_leq },
{">" ,tok_grt },
{">=" ,tok_geq },
{NULL ,-1 }
};
struct token
@@ -89,6 +90,7 @@ struct token
int line;
int type;
std::string str;
token(int l=0,int t=tok_null,std::string s=""){line=l;type=t;str=s;return;}
};
class nasal_lexer
@@ -101,31 +103,19 @@ private:
std::string line_code;
std::vector<char> res;
std::vector<token> token_list;
int get_token_type(std::string);
void die(std::string,std::string,int,int);
std::string identifier_gen();
std::string number_gen();
std::string string_gen();
public:
void clear();
void openfile(std::string);
void die(std::string,int,int);
void scanner();
void print_token();
int get_error();
std::vector<token>& get_token_list();
};
void nasal_lexer::clear()
{
error=0;
res_size=0;
line=0;
ptr=0;
line_code="";
res.clear();
token_list.clear();
return;
}
void nasal_lexer::openfile(std::string filename)
{
error=0;
@@ -150,10 +140,21 @@ void nasal_lexer::openfile(std::string filename)
return;
}
void nasal_lexer::die(std::string error_info,int line=-1,int column=-1)
int nasal_lexer::get_token_type(std::string tk_str)
{
for(int i=0;token_table[i].str;++i)
if(tk_str==token_table[i].str)
return token_table[i].tok_type;
return tok_null;
}
void nasal_lexer::die(std::string code,std::string error_info,int line=-1,int column=-1)
{
++error;
std::cout<<">> [lexer] line "<<line<<" column "<<column<<": "<<error_info<<"\n";
std::cout<<">> [lexer] line "<<line<<" column "<<column<<": \n"<<code<<"\n";
for(int i=0;i<column-1;++i)
std::cout<<(code[i]=='\t'?'\t':' ');
std::cout<<"^ "<<error_info<<'\n';
return;
}
@@ -172,7 +173,7 @@ std::string nasal_lexer::number_gen()
bool scientific_notation=false;// numbers like 1e8 are scientific_notation
std::string token_str="";
// generate hex number
if(res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='x')
if(ptr+1<res_size && res[ptr]=='0' && res[ptr+1]=='x')
{
token_str="0x";
ptr+=2;
@@ -181,13 +182,13 @@ std::string nasal_lexer::number_gen()
line_code+=token_str;
if(token_str=="0x")
{
die("["+line_code+"_] incorrect number.",line,line_code.length());
die(line_code,"incorrect number.",line,line_code.length());
return "0";
}
return token_str;
}
// generate oct number
else if(res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='o')
else if(ptr+1<res_size && res[ptr]=='0' && res[ptr+1]=='o')
{
token_str="0o";
ptr+=2;
@@ -196,7 +197,7 @@ std::string nasal_lexer::number_gen()
line_code+=token_str;
if(token_str=="0o")
{
die("["+line_code+"_] incorrect number.",line,line_code.length());
die(line_code,"incorrect number.",line,line_code.length());
return "0";
}
return token_str;
@@ -212,7 +213,7 @@ std::string nasal_lexer::number_gen()
if(ptr>=res_size)
{
line_code+=token_str;
die("["+line_code+"_] incorrect number.",line,line_code.length());
die(line_code,"incorrect number.",line,line_code.length());
return "0";
}
while(ptr<res_size && IS_DIGIT(res[ptr]))
@@ -221,7 +222,7 @@ std::string nasal_lexer::number_gen()
if(token_str.back()=='.')
{
line_code+=token_str;
die("["+line_code+"_] incorrect number.",line,line_code.length());
die(line_code,"incorrect number.",line,line_code.length());
return "0";
}
}
@@ -232,7 +233,7 @@ std::string nasal_lexer::number_gen()
if(ptr>=res_size)
{
line_code+=token_str;
die("["+line_code+"_] incorrect number.",line,line_code.length());
die(line_code,"incorrect number.",line,line_code.length());
return "0";
}
if(ptr<res_size && (res[ptr]=='-' || res[ptr]=='+'))
@@ -240,18 +241,16 @@ std::string nasal_lexer::number_gen()
if(ptr>=res_size)
{
line_code+=token_str;
die("["+line_code+"_] incorrect number.",line,line_code.length());
die(line_code,"incorrect number.",line,line_code.length());
return "0";
}
if(ptr<res_size && res[ptr]=='0')
token_str+=res[ptr++];
while(ptr<res_size && IS_DIGIT(res[ptr]))
token_str+=res[ptr++];
// "xxxe(-|+)" is not a correct number
if(token_str.back()=='e' || token_str.back()=='E' || token_str.back()=='-' || token_str.back()=='+')
{
line_code+=token_str;
die("["+line_code+"_] incorrect number.",line,line_code.length());
die(line_code,"incorrect number.",line,line_code.length());
return "0";
}
}
@@ -262,9 +261,9 @@ std::string nasal_lexer::number_gen()
std::string nasal_lexer::string_gen()
{
std::string token_str="";
line_code+=res[ptr];
char str_begin=res[ptr++];
while(ptr<res_size && res[ptr]!=str_begin)
char str_begin=res[ptr];
line_code+=str_begin;
while(++ptr<res_size && res[ptr]!=str_begin)
{
line_code+=res[ptr];
if(res[ptr]=='\n')
@@ -274,8 +273,7 @@ std::string nasal_lexer::string_gen()
}
if(res[ptr]=='\\' && ptr+1<res_size)
{
++ptr;
line_code+=res[ptr];
line_code+=res[++ptr];
switch(res[ptr])
{
case 'a':token_str.push_back('\a');break;
@@ -292,15 +290,13 @@ std::string nasal_lexer::string_gen()
case '\"':token_str.push_back('\"');break;
default: token_str.push_back(res[ptr]);break;
}
continue;
}
else
token_str+=res[ptr];
++ptr;
token_str+=res[ptr];
}
// check if this string ends with a " or '
if(ptr>=res_size)
die("["+line_code+"_] get EOF when generating string.",line,line_code.length());
++ptr;
if(ptr++>=res_size)
die(line_code,"get EOF when generating string.",line,line_code.length());
return token_str;
}
@@ -318,66 +314,41 @@ void nasal_lexer::scanner()
{
// these characters will be ignored, and '\n' will cause ++line
line_code+=res[ptr];
if(res[ptr]=='\n')
if(res[ptr++]=='\n')
{
++line;
line_code="";
}
++ptr;
}
if(ptr>=res_size) break;
if(IS_IDENTIFIER(res[ptr]))
{
token_str=identifier_gen();
token new_token;
new_token.line=line;
new_token.str=token_str;
new_token.type=0;
for(int i=0;token_table[i].str;++i)
if(token_str==token_table[i].str)
{
new_token.type=token_table[i].tok_type;
break;
}
token new_token(line,get_token_type(token_str),token_str);
if(!new_token.type)
new_token.type=tok_identifier;
new_token.type=tok_id;
token_list.push_back(new_token);
}
else if(IS_DIGIT(res[ptr]))
{
token_str=number_gen();
token new_token;
new_token.line=line;
new_token.str=token_str;
new_token.type=tok_number;
token new_token(line,tok_num,token_str);
token_list.push_back(new_token);
}
else if(IS_STRING(res[ptr]))
{
token_str=string_gen();
token new_token;
new_token.line=line;
new_token.type=tok_string;
new_token.str=token_str;
token new_token(line,tok_str,token_str);
token_list.push_back(new_token);
}
else if(IS_SINGLE_OPRATOR(res[ptr]))
else if(IS_SINGLE_OPERATOR(res[ptr]))
{
token_str="";
token_str+=res[ptr];
line_code+=res[ptr];
token new_token;
new_token.line=line;
new_token.str=token_str;
new_token.type=-1;
for(int i=0;token_table[i].str;++i)
if(token_str==token_table[i].str)
{
new_token.type=token_table[i].tok_type;
break;
}
if(new_token.type<0)
die("["+line_code+"_] incorrect operator.",line,line_code.length());
token new_token(line,get_token_type(token_str),token_str);
if(!new_token.type)
die(line_code,"incorrect operator.",line,line_code.length());
token_list.push_back(new_token);
++ptr;
}
@@ -394,53 +365,29 @@ void nasal_lexer::scanner()
++ptr;
}
line_code+=token_str;
token new_token;
new_token.line=line;
new_token.str=token_str;
for(int i=0;token_table[i].str;++i)
if(token_str==token_table[i].str)
{
new_token.type=token_table[i].tok_type;
break;
}
token new_token(line,get_token_type(token_str),token_str);
token_list.push_back(new_token);
}
else if(IS_CALC_OPERATOR(res[ptr]))
{
// get calculation operator
token_str=res[ptr];
++ptr;
if(ptr<res.size() && res[ptr]=='=')
{
token_str+=res[ptr];
++ptr;
}
token_str=res[ptr++];
if(ptr<res_size && res[ptr]=='=')
token_str+=res[ptr++];
line_code+=token_str;
token new_token;
new_token.line=line;
new_token.str=token_str;
for(int i=0;token_table[i].str;++i)
if(token_str==token_table[i].str)
{
new_token.type=token_table[i].tok_type;
break;
}
token new_token(line,get_token_type(token_str),token_str);
token_list.push_back(new_token);
}
else if(IS_NOTE(res[ptr]))
{
// avoid note
while(ptr<res_size && res[ptr]!='\n') ++ptr;
// after this process ptr will point to a '\n'
// don't ++ptr then the counter for line can work correctly
}
else if(IS_NOTE(res[ptr]))// avoid note, after this process ptr will point to a '\n', so next loop line counter+1
while(++ptr<res_size && res[ptr]!='\n');
else
{
line_code+=res[ptr];
die("["+line_code+"_] unknown character.",line,line_code.length());
++ptr;
line_code+=res[ptr++];
die(line_code,"unknown character.",line,line_code.length());
}
}
token tk(line,tok_eof,"");
token_list.push_back(tk);
return;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1183
nasal_vm.h Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

152
props.nas Normal file
View File

@@ -0,0 +1,152 @@
import("lib.nas");
var props=
{
globals:nil,
Node:nil,
getNode:func(path,index)
{
path=split('/',path);
var tmp=me.globals;
var path_size=size(path);
for(var i=0;i<path_size-1;i+=1)
tmp=tmp.val[path[i]];
if(path_size>0)
{
if(contains(tmp.val,path[i]~'['~index~']'))
return tmp.val[path[i]~'['~index~']'];
else
return tmp.val[path[i]];
}
return tmp;
}
};
props.Node=
{
new:func(values=nil)
{
var result={
parents:[props.Node],
val:{},
type:'GHOST',
parent:nil
};
if(typeof(values)=="hash")
result.val=values;
return result;
},
addChild:func(name)
{
if(!contains(me.val,name))
{
me.val[name]=props.Node.new();
me.val[name].parent=me;
return 1;
}
return 0;
},
addChildren:func(name,cnt=0)
{
for(var i=0;i<cnt;i+=1)
{
var label=name~'['~i~']';
me.val[label]=props.Node.new();
me.val[label].parent=me;
}
return;
},
setValue:func(path,val)
{
path=split('/',path);
var tmp=me;
foreach(var label;path)
tmp=tmp.val[label];
tmp.val=val;
if(typeof(val)=='string')
{
if(val=='true' or val=='false')
tmp.type='BOOL';
else
tmp.type='STRING';
}
elsif(typeof(val)=='number')
tmp.type='DOUBLE';
return;
},
setIntValue:func(num)
{
me.val=num;
me.type='INT';
return;
},
setBoolValue:func(state)
{
me.val=state;
me.type='BOOL';
return;
},
setDoubleValue:func(num)
{
me.val=num;
me.type='DOUBLE';
return;
},
getValue:func(){return me.val;},
getName:func()
{
var val=me.parent.val;
var key=keys(val);
foreach(var k;key)
if(val[k]==me)
return k;
return '';
},
getParent:func()
{
return me.parent;
},
getPath:func()
{
if(me.parent==nil) return '';
return me.parent.getPath()~'/'~me.getName();
},
equals:func(node){return me==node;},
debug:func(s='')
{
if(typeof(me.val)=='hash')
{
var key=keys(me.val);
println('{');
foreach(var k;key)
{
print(s~' ',k,':');
me.val[k].debug(s~' ');
}
println(s,'}');
}
else
println(me.val,' (',me.type,')');
return;
}
};
props.globals=props.Node.new();
var c=['aircraft','ai','models','position','orientation','controls','sim'];
foreach(var i;c)
props.getNode('/',1).addChild(i);
props.getNode('/ai',1).addChildren('ai',4);
props.getNode('/aircraft',1).setValue('/','IDG MD-11');
for(var i=0;i<4;i+=1)
props.getNode('/ai/ai['~i~']',1).setBoolValue('true');
props.getNode('/models',1).addChildren('building',4);
for(var i=0;i<4;i+=1)
props.getNode('/models/building['~i~']',1).setIntValue(i);
props.getNode('/',1).addChild('test');
props.getNode('/test',1).addChildren('in',4);
props.getNode('/test/in',0).setValue('/','true');
props.getNode('/test/in',1).setValue('/','false');
props.getNode('/test/in',2).setValue('/','welcome aboard,need help? use help->tutorial');
props.getNode('/test/in',3).setValue('/',2147483648);
props.globals.debug();
println(props.getNode('/test/in',3).getPath());

View File

@@ -1,96 +0,0 @@
# NasNeuron lib written by ValKmjolnir
# Basic Class NasMatrix
# NasMatGen : generate a new matrix
# NasMatAdd : add two matrixes
# NasMatSub : sub two matrixes
# NasMatMul : multiply two matrix
# NasMatTrans: transpose a matrix
# NasMatPrt : print a matrix
var NasMatrix=
{
NasMatGen:func(row,col)
{
var GenMat={Row:row,Col:col,Elem:[]};
for(var i=0;i<row;i+=1)
{
var TmpVec=[];
for(var j=0;j<col;j+=1)
append(TmpVec,0);
append(GenMat.Elem,TmpVec);
}
return GenMat;
},
NasMatAdd:func(mat1,mat2)
{
var ResultMat=nil;
if(mat1.Row==mat2.Row and mat1.Col==mat2.Col)
{
ResultMat=me.NasMatGen(mat1.Row,mat1.Col);
for(var i=0;i<ResultMat.Row;i+=1)
for(var j=0;j<ResultMat.Col;j+=1)
ResultMat.Elem[i][j]=mat1.Elem[i][j]+mat2.Elem[i][j];
}
else
print("NasNeuron: Mat1 and Mat2 have different rows and cols.");
return ResultMat;
},
NasMatSub:func(mat1,mat2)
{
var ResultMat=nil;
if(mat1.Row==mat2.Row and mat1.Col==mat2.Col)
{
ResultMat=me.NasMatGen(mat1.Row,mat1.Col);
for(var i=0;i<ResultMat.Row;i+=1)
for(var j=0;j<ResultMat.Col;j+=1)
ResultMat.Elem[i][j]=mat1.Elem[i][j]-mat2.Elem[i][j];
}
else
print("NasNeuron: Mat1 and Mat2 have different rows and cols.");
return ResultMat;
},
NasMatMul:func(mat1,mat2)
{
var ResultMat=nil;
if(mat1.Col==mat2.Row)
{
ResultMat=me.NasMatGen(mat1.Row,mat2.Col);
for(var i=0;i<ResultMat.Row;i+=1)
for(var j=0;j<ResultMat.Col;j+=1)
{
var sum=0;
for(var k=0;k<mat1.Col;k+=1)
sum+=mat1.Elem[i][k]*mat2.Elem[k][j];
ResultMat.Elem[i][j]=sum;
}
}
else
print("NasNeuron: Mat1's Col is different from Mat2's Row.");
return ResultMat;
},
NasMatTrans:func(mat)
{
var ResultMat=nil;
ResultMat=me.NasMatGen(mat.Col,mat.Row);
for(var i=0;i<ResultMat.Row;i+=1)
for(var j=0;j<ResultMat.Col;j+=1)
ResultMat.Elem[i][j]=mat.Elem[j][i];
return ResultMat;
},
NasMatPrt:func(mat)
{
for(var i=0;i<mat.Row;i+=1)
{
for(var j=0;j<mat.Col;j+=1)
print(mat.Elem[i][j],' ');
print('\n');
}
return nil;
}
};
NasMatrix.NasMatPrt(
NasMatrix.NasMatGen(
10,100
)
);

View File

@@ -329,7 +329,4 @@ var main=func()
return nil;
}
# var (a,b,c)=[1,2,3];
# (a,b,c)=(b,c,a);
# print(a,b,c);
main();

View File

@@ -45,7 +45,7 @@ var trans_ttf=func(string)
str[j]~=char_ttf[0][j];
}
foreach(var i;str)
print(i);
println(i);
return;
}
var curve1=func()
@@ -100,7 +100,7 @@ var curve4=func()
{
forindex(var i;s)
{
print(s[i]);
println(s[i]);
s[i]='';
}
cnt=0;
@@ -123,11 +123,12 @@ var curve5=func()
var s="";
for(var i=0;i<size(arr);i+=1)
s~=shadow[arr[i]];
print(s);
println(s);
}
return;
}
trans_ttf("just for test");
trans_ttf("ValKmjolnir");
curve1();
curve2();
curve3();

View File

@@ -20,7 +20,7 @@ var prt=func()
s~=map[i][j];
s~='\n';
}
print(s);
print(s,'\n');
}
var bfs=func(begin,end)
@@ -50,16 +50,12 @@ var bfs=func(begin,end)
}
prt();
}
print("cannot reach.");
print("cannot reach.\n");
return;
}
prt();
var x=num(input());
var y=num(input());
var begin=[x,y];
x=num(input());
y=num(input());
var end=[x,y];
var begin=[input(),input()];
var end=[input(),input()];
bfs(begin,end);
prt();

1
test/bigloop.nas Normal file
View File

@@ -0,0 +1 @@
for(var i=0;i<4000000;i+=1);

View File

@@ -125,8 +125,9 @@ var backward=func(x)
}
var cnt=0;
var show=0;
var error=1e8;
while(error>0.01)
while(error>0.0005)
{
error=0;
for(var i=0;i<4;i+=1)
@@ -136,18 +137,22 @@ while(error>0.01)
backward(i);
}
cnt+=1;
print('epoch ',cnt,':',error);
show+=1;
if(show==200)
{
show=0;
print('epoch ',cnt,':',error,'\r');
}
}
print('\afinished.');
while(1)
print('finished after ',cnt,' epoch.\n');
var vec=[
[0,0],
[0,1],
[1,0],
[1,1]
];
foreach(var v;vec)
{
var vec=[];
var command=input();
if(command=="exit")break;
append(vec,num(command));
command=input();
if(command=="exit")break;
append(vec,num(command));
run(vec);
print(output[0].out);
run(v);
print(v,': ',output[0].out,'\n');
}

30
test/calc.nas Normal file
View File

@@ -0,0 +1,30 @@
import("lib.nas");
func(){
var filename=[
"main.cpp",
"nasal_ast.h",
"nasal_builtin.h",
"nasal_codegen.h",
"nasal_gc.h",
"nasal_import.h",
"nasal_lexer.h",
"nasal_parse.h",
"nasal_vm.h",
"nasal.h"
];
var max_size=size('nasal_codegen.h');
var (cnt,semi)=[0,0];
foreach(var file;filename)
{
var s=io.fin(file);
var name=file;
for(var i=size(name);i<max_size;i+=1)
name~=' ';
var line_cnt=size(split('\n',s));
var semi_cnt=size(split(';' ,s))-1;
println(name,'| ',line_cnt,' \tline | ',semi_cnt,' \tsemi');
cnt +=line_cnt;
semi+=semi_cnt;
}
println('total: ',cnt,' line | ',semi,' semi');
}();

View File

@@ -1,38 +0,0 @@
if(this_token.type==__if)
{
parse.push(this_token);
return;
}
elsif(this_token.type==__elsif)
{
parse.push(this_token);
return;
}
else if(this_token.type!=__else)
{
exit(0);
}
elsif(this_token.type==__elsif)
{
parse.push(this_token);
return;
}
elsif(this_token.type==__elsif)
{
parse.push(this_token);
return;
}
else if(this==(1+2+3*1))
{
return nil;
}
else
{
parse.push(this_token);
return;
}
if(!id)
{
exit(0);
}

19
test/class.nas Normal file
View File

@@ -0,0 +1,19 @@
import("lib.nas");
var student=
{
new:func(name,age)
{
return {
parents:[student],
name:name,
age:age
};
},
print_info:func(){println(me.name,' ',me.age);},
get_age:func(){return me.age;},
get_name:func(){return me.name;}
};
var s=student.new('tiansuohaoer',24);
s.print_info();
println(s.get_age(),' ',s.get_name());

27
test/fib.nas Normal file
View File

@@ -0,0 +1,27 @@
var print=func(elements...)
{
nasal_call_builtin_std_cout(elements);
return nil;
};
var setsize=func(vector,size)
{
nasal_call_builtin_set_size(vector,size);
return nil;
}
var fib=func(x)
{
if(x<2) return x;
return fib(x-1)+fib(x-2);
}
print(fib(30),'\n');
var m=[0,1,1,2,3,5,8];
setsize(m,101);
var fib=func(n)
{
if(m[n]!=nil) return m[n];
var t=fib(n-1)+fib(n-2);
m[n]=t;
return t;
}
print(fib(100),'\n');

View File

@@ -1,6 +0,0 @@
print("hello world!\n");
print("This is the first program for nasal--\n");
var cnt=0;
for(var i=1;i<101;i+=1)
cnt+=i;
print(cnt);

View File

@@ -1,10 +0,0 @@
var f=func(n,m,dynamic...)
{
print(n+m," ",dynamic);
n=dynamic;
m=dynamic;
n+=m;
return dynamic;
};
print(f(1,1,0,0,0,0,0,(1+2+3+(1+2+3+4)))[3]);
function([0,1,2,3],{str:"str"});

32
test/leetcode1319.nas Normal file
View File

@@ -0,0 +1,32 @@
import("lib.nas");
# 并查集
var n=4;
var input=[[0,1],[0,2],[1,2]];
var find_root=func(x,parent)
{
while(parent[x]!=nil)
x=parent[x];
return x;
}
var union_root=func(x,y,parent)
{
var x_root=find_root(x,parent);
var y_root=find_root(y,parent);
if(x_root==y_root) return 0;
else parent[x_root]=y_root;
return 1;
}
var makeConnect=func(n,connections)
{
if(size(connections)<n-1) return -1;
var cnt=n-1;
var parent=[];
setsize(parent,n);
for(var i=0;i<size(connections);i+=1)
if(union_root(connections[i][0],connections[i][1],parent))
cnt-=1;
return cnt;
}
print(makeConnect(n,input));

View File

@@ -1,7 +1,6 @@
import("lib.nas");
var s=io.fin("a.nas");
s=split('',s);
var s=split('',io.fin(input()));
var len=size(s);
var ptr=0;
@@ -59,7 +58,7 @@ var generate_str=func()
ptr+=1;
}
if(ptr>=len)
print("read eof when generating string.");
print("read eof when generating string.\n");
ptr+=1;
return tok_str;
}
@@ -178,6 +177,6 @@ while(ptr<len)
}
foreach(var i;token)
{
print("(",cnt," | ",i,")");
print("(",cnt," | ",i,")\n");
cnt+=1;
}

View File

@@ -8,6 +8,12 @@ var print=func(elements...)
nasal_call_builtin_std_cout(elements);
return nil;
};
var println=func(elements...)
{
nasal_call_builtin_std_cout(elements);
print('\n');
return nil;
}
var append=func(vector,elements...)
{
nasal_call_builtin_push_back(vector,elements);
@@ -94,6 +100,26 @@ var substr=func(str,begin,length)
{
return nasal_call_builtin_substr(str,begin,length);
}
var streq=func(a,b)
{
return nasal_call_builtin_streq(a,b);
}
var left=func(string,length)
{
return nasal_call_builtin_left(string,length);
}
var right=func(string,length)
{
return nasal_call_builtin_right(string,length);
}
var cmp=func(a,b)
{
return nasal_call_builtin_cmp(a,b);
}
var chr=func(code) #//Unlike in FG, this chr does not support Extended ASCII
{
return nasal_call_builtin_chr(code);
}
var io=
{
@@ -110,58 +136,22 @@ var io=
var bits=
{
bitxor:func(a,b)
{
return nasal_call_builtin_xor(a,b);
},
bitand:func(a,b)
{
return nasal_call_builtin_and(a,b);
},
bitor:func(a,b)
{
return nasal_call_builtin_or(a,b);
},
bitnand:func(a,b)
{
return nasal_call_builtin_nand(a,b);
},
bitnot:func(a)
{
return nasal_call_builtin_not(a);
}
bitxor: func(a,b){return nasal_call_builtin_xor(a,b); },
bitand: func(a,b){return nasal_call_builtin_and(a,b); },
bitor: func(a,b){return nasal_call_builtin_or(a,b); },
bitnand: func(a,b){return nasal_call_builtin_nand(a,b);},
bitnot: func(a) {return nasal_call_builtin_not(a); }
};
var math=
{
e:2.7182818284590452354,
pi:3.14159265358979323846,
sin:func(x)
{
return nasal_call_builtin_sin(x);
},
cos:func(x)
{
return nasal_call_builtin_cos(x);
},
tan:func(x)
{
return nasal_call_builtin_tan(x);
},
exp:func(x)
{
return nasal_call_builtin_exp(x);
},
ln:func(x)
{
return nasal_call_builtin_cpp_math_ln(x);
},
sqrt:func(x)
{
return nasal_call_builtin_cpp_math_sqrt(x);
},
atan2:func(x,y)
{
return nasal_call_builtin_cpp_atan2(x,y);
},
e: 2.7182818284590452354,
pi: 3.14159265358979323846264338327950288,
sin: func(x) {return nasal_call_builtin_sin(x); },
cos: func(x) {return nasal_call_builtin_cos(x); },
tan: func(x) {return nasal_call_builtin_tan(x); },
exp: func(x) {return nasal_call_builtin_exp(x); },
ln: func(x) {return nasal_call_builtin_cpp_math_ln(x); },
sqrt: func(x) {return nasal_call_builtin_cpp_math_sqrt(x);},
atan2: func(x,y){return nasal_call_builtin_cpp_atan2(x,y); }
};

64
test/life.nas Normal file
View File

@@ -0,0 +1,64 @@
import("lib.nas");
var map=nil;
var check=func(x,y)
{
if(x>=30) x=0;
if(x<0) x=19;
if(y>=40) y=0;
if(y<0) y=39;
return map[x][y];
}
var new_map=func()
{
var tmp=[];
setsize(tmp,30);
forindex(var i;tmp)
{
tmp[i]=[];
setsize(tmp[i],40);
}
return tmp;
}
var prt=func()
{
var s='';
foreach(var line;map)
{
foreach(var elem;line)
s~=elem~' ';
s~='\n';
}
system("cls");
print(s);
}
func()
{
rand(time(0));
map=new_map();
forindex(var i;map)
forindex(var j;map[i])
map[i][j]=rand()>0.7?'O':' ';
var calc=[[0,1],[1,0],[0,-1],[-1,0],[1,1],[1,-1],[-1,-1],[-1,1]];
for(var r=0;r<200;r+=1)
{
prt(map);
var tmp=new_map();
forindex(var i;map)
forindex(var j;map[i])
{
var cnt=0;
foreach(var k;calc)
cnt+=(check(i+k[0],j+k[1])=='O');
if(cnt==2) tmp[i][j]=map[i][j];
elsif(cnt==3) tmp[i][j]='O';
else tmp[i][j]=' ';
}
map=tmp;
}
return;
}();

View File

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

View File

@@ -1,382 +0,0 @@
# game left in corner by ValKmjolnir
# 2020
# lib function defined here
var print=func(elements...)
{
nasal_call_builtin_std_cout(elements);
return nil;
};
var append=func(vector,elements...)
{
nasal_call_builtin_push_back(vector,elements);
return nil;
}
var setsize=func(vector,size)
{
nasal_call_builtin_set_size(vector,size);
return nil;
}
var system=func(str)
{
nasal_call_builtin_system(str);
return;
}
var sleep=func(duration)
{
nasal_call_builtin_sleep(duration);
return;
}
var input=func()
{
return nasal_call_builtin_input();
}
var io=
{
fin:func(filename)
{
return nasal_call_builtin_finput(filename);
},
fout:func(filename,str)
{
nasal_call_builtin_foutput(filename,str);
return;
}
};
var int=func(str)
{
return str+0;
}
var str=func(num)
{
return num~'';
}
# string split
# game elements defined here
var role_property=
{
health:100,
mood:100,
satiety:100,
thirst:100,
health_change:func(x)
{
me.health+=x;
if(me.health<0)
me.health=0;
elsif(me.health>100)
me.health=100;
return nil;
},
mood_change:func(x)
{
me.mood+=x;
if(me.mood<0)
me.mood=0;
elsif(me.mood>100)
me.mood=100;
return nil;
},
satiety_change:func(x)
{
me.satiety+=x;
if(me.satiety<0)
me.satiety=0;
elsif(me.satiety>100)
me.satiety=100;
return nil;
},
thirst_change:func(x)
{
me.thirst+=x;
if(me.thirst<0)
me.thirst=0;
elsif(me.thirst>100)
me.thirst=100;
return nil;
}
};
var screen=
{
picture:[],
info_below_left:[],
info_below_right:[],
clear:func()
{
me.picture=[];
me.info_below_left=[];
me.info_below_right=[];
return;
},
pic_addline:func(_str)
{
append(me.picture,_str);
return;
},
left_add:func(_str)
{
append(me.info_below_left,_str);
return;
},
right_add:func(_str)
{
append(me.info_below_right,_str);
return;
},
prt_screen:func()
{
foreach(var i;me.picture)
print(i);
forindex(var i;me.info_below_left)
print(me.info_below_left[i]~me.info_below_right[i]);
return;
}
};
var first_shown_info=func()
{
system("cls");
var str_list=[
"+-----------------------------------------------+",
"| |",
"| |",
"| Let me tell you a story... |",
"| A story that really happened many years ago...|",
"| Nearly no one knows and cares about it... |",
"| But some children may still suffer from... |",
"| This kind of stories... |",
"| And this kind of stories never stop hurting...|",
"| People that are still alive... |",
"| |",
"| |",
"+-----------------------------------------------+"
];
foreach(var i;str_list)
print(i);
return;
}
var generate_role_property=func()
{
screen.left_add("+-----------------------+");
var str="";
for(var i=10;i<=100;i+=10)
{
if(i<=role_property.health)
str~="=";
else
str~=" ";
}
screen.left_add("|[health ]:"~str~" |");
str="";
for(var i=10;i<=100;i+=10)
{
if(i<=role_property.mood)
str~="=";
else
str~=" ";
}
screen.left_add("|[mood ]:"~str~" |");
str="";
for(var i=10;i<=100;i+=10)
{
if(i<=role_property.satiety)
str~="=";
else
str~=" ";
}
screen.left_add("|[satiety]:"~str~" |");
str="";
for(var i=10;i<=100;i+=10)
{
if(i<=role_property.thirst)
str~="=";
else
str~=" ";
}
screen.left_add("|[thirst ]:"~str~" |");
screen.left_add("+-----------------------+");
return;
}
var generate_choose_list=func()
{
var str_list=[
"-----------------------+",
"[1]| next step |",
"[2]| restart |",
"[3]| store game |",
"[4]| exit |",
"-----------------------+"
];
foreach(var i;str_list)
screen.right_add(i);
return;
}
var next_step=func()
{
role_property.health_change(-1);
role_property.mood_change(-1);
role_property.satiety_change(-1);
role_property.thirst_change(-10);
var str_list=[
"+-----------------------------------------------+",
"| |",
"| |",
"| |",
"| |",
"| |",
"| |",
"| |",
"| |",
"| |",
"| |",
"| |",
"+-----------------------------------------------+"
];
foreach(var i;str_list)
screen.pic_addline(i);
return;
}
var restart=func()
{
role_property.health=100;
role_property.mood=100;
role_property.satiety=100;
role_property.thirst=100;
var str_list=[
"+-----------------------------------------------+",
"| |",
"| |",
"| |",
"| |",
"| |",
"| |",
"| |",
"| |",
"| |",
"| |",
"| |",
"+-----------------------------------------------+"
];
foreach(var i;str_list)
screen.pic_addline(i);
return;
}
var generate_incorrect_choice_screen=func()
{
var str_list=[
"+-----------------------------------------------+",
"| |",
"| |",
"| |",
"| |",
"| |",
"| make a correct choice. |",
"| |",
"| |",
"| |",
"| |",
"| |",
"+-----------------------------------------------+"
];
foreach(var i;str_list)
screen.pic_addline(i);
}
var generate_goodbye_screen=func()
{
var str_list=[
"+-----------------------------------------------+",
"| |",
"| |",
"| |",
"| |",
"| |",
"| see you next life. |",
"| |",
"| |",
"| |",
"| |",
"| |",
"+-----------------------------------------------+"
];
foreach(var i;str_list)
screen.pic_addline(i);
}
var store_file=func()
{
var str=role_property.health~'\n'~role_property.mood~'\n'~role_property.satiety~'\n'~role_property.thirst~'\n';
io.fout("game-left-in-corner.glic",str);
var str_list=[
"+-----------------------------------------------+",
"| |",
"| |",
"| |",
"| |",
"| |",
"| data stored. |",
"| |",
"| |",
"| |",
"| |",
"| |",
"+-----------------------------------------------+"
];
foreach(var i;str_list)
screen.pic_addline(i);
return;
}
var get_file=func()
{
var str=io.fin("game-left-in-corner.glic");
print(str);
return;
}
var game_main=func()
{
first_shown_info();
screen.clear();
generate_role_property();
generate_choose_list();
screen.prt_screen();
while(1)
{
screen.clear();
print("|your choice[1|2|3|4]: |");
var choice=input();
if((choice!='1') and (choice!='2') and (choice!='3') and (choice!='4'))
generate_incorrect_choice_screen();
elsif(choice=='1')
next_step();
elsif(choice=='2')
restart();
elsif(choice=='3')
store_file();
elsif(choice=='4')
{
system("cls");
screen.clear();
generate_goodbye_screen();
generate_role_property();
generate_choose_list();
screen.prt_screen();
break;
}
system("cls");
generate_role_property();
generate_choose_list();
screen.prt_screen();
if(role_property.health==0 or role_property.mood==0 or role_property.satiety==0 or role_property.thirst==0)
{
print("|you died. |");
print("+-----------------------------------------------+");
system("pause");
screen.clear();
restart();
system("cls");
generate_role_property();
generate_choose_list();
screen.prt_screen();
}
}
return;
}
game_main();

View File

@@ -13,16 +13,16 @@ var film_node=[];
for(var i=0;i<1000;i+=1)
append(film_node,node("film"));
var director_node=[];
for(var i=0;i<400;i+=1)
for(var i=0;i<200;i+=1)
append(director_node,node("direct"));
var actor_node=[];
for(var i=0;i<2000;i+=1)
for(var i=0;i<400;i+=1)
append(actor_node,node("actor"));
var writer_node=[];
for(var i=0;i<300;i+=1)
for(var i=0;i<100;i+=1)
append(writer_node,node("writer"));
var type_node=[];
for(var i=0;i<20;i+=1)
for(var i=0;i<40;i+=1)
append(type_node,node("type"));
var lang_node=[];
for(var i=0;i<120;i+=1)
@@ -40,14 +40,14 @@ func()
var lang_size=size(lang_node);
var country_size=size(country_node);
var director_link=int(1+rand()*2);
var actor_link=int(1+rand()*10);
var writer_link=int(1+rand());
var type_link=int(1+rand()*3);
var lang_link=int(1+rand()*4);
var country_link=int(1+rand()*2);
foreach(var film;film_node)
{
var director_link=int(1+rand()*2);
var actor_link=int(1+rand()*20);
var writer_link=int(1+rand()*2);
var type_link=int(1+rand()*5);
var lang_link=int(1+rand()*4);
var country_link=int(1+rand()*4);
for(var i=0;i<director_link;i+=1)
{
var director=director_node[rand()*director_size];
@@ -118,18 +118,9 @@ var sort_list=func(begin,end)
return;
}
while(1)
var get_next=func(index)
{
var list_size=size(film_list);
list_size=list_size>10?10:list_size;
for(var i=0;i<list_size;i+=1)
print(i,'\t:',film_list[i].name,'\t',count_list[i]);
var choose=input();
if(choose=="exit")
break;
if(num(choose)>=list_size)
die("choose a correct index");
var label_list=film_node[num(choose)].next;
var label_list=film_list[index].next;
film_list=[];
count_list=[];
foreach(var label;label_list)
@@ -140,7 +131,7 @@ while(1)
if(film_list[i].name==film.name)
{
has=1;
count_list[i]+=rand();
count_list[i]+=1;
break;
}
if(has==0)
@@ -150,6 +141,21 @@ while(1)
}
}
sort_list(0,size(film_list));
return;
}
while(1)
{
var list_size=size(film_list);
list_size=list_size>10?10:list_size;
for(var i=1;i<list_size;i+=1)
println('| ',i,'\t:',film_list[i].name,'\t',count_list[i]);
var choose=input();
if(choose=="exit")
break;
if(num(choose)==0 or num(choose)>=list_size)
die("choose a correct index");
get_next(num(choose));
}
foreach(var film;film_node)

View File

@@ -1,246 +0,0 @@
import("lib.nas");
var property_tree=
{
accelerations:
{
'n-z-cg-fps_sec':0,
ned:
{
'down-accel-fps_sec':0,
'east-accel-fps_sec':0,
'north-accel-fps_sec':0,
},
nlf:0,
pilot:
{
'x-accel-fps_sec':0,
'y-accel-fps_sec':0,
'z-accel-fps_sec':0,
},
'pilot-g':1,
'pilot-gdamped':1
},
ai:
{
models:
{
carrier:
{
callsign:'',
controls:{},
environment:{},
id:2,
name:'Nimitz',
navaids:{},
orientation:{},
position:{},
radar:{},
sign:'CVN-68',
sim:{},
subID:0,
submodels:
{
path:'',
serviceable:1
},
'surface-positions':{},
type:'AI',
valid:1,
velocities:{},
waypoint:{}
},
'carrier[1]':
{
callsign:'',
controls:{},
environment:{},
id:3,
name:'Eisenhower',
navaids:{},
orientation:{},
position:{},
radar:{},
sign:'CVN-69',
sim:{},
subID:0,
submodels:
{
path:'',
serviceable:0
},
'surface-positions':{},
type:'AI',
valid:1,
velocities:{},
waypoint:{}
},
count:2,
'model-added':'/ai[0]/models[0]/carrier[1]',
'model-removed':nil,
'num-players':0
},
submodels:
{
contrails:0
},
},
aircraft:
{
icao:
{
equipment:'SDFGY',
surveillance:'S',
type:'ZZZZ',
'wake-turbulence-category':'L'
},
performance:
{
approach:
{
'airspeed-knots':150,
},
climb:'\n\t\t\t\n\t\t\t',
cruise:
{
'airspeed-knots':1000,
'altitude-ft':4500,
},
descent:'\n\t\t\t\n\t\t\t',
maximum:'\n\t\t\t\n\t\t\t',
minimum:'\n\t\t\t\n\t\t\t',
},
settings:
{
fuel_persistent:0,
ground_services_persistent:0,
radio_persistent:0,
tooltips:1,
weight_persistent:0
}
},
autopilot:
{
internal:{},
locks:{},
'route-manager':{},
settings:{},
'target-tracking':{},
},
canvas:
{
'by-index':
{
texture:
{
background:'rgba(0,0,0,0)',
group:{},
name:'Tooltip',
placement:{},
size:600,
'size[1]':200,
status:0,
'status-msg':'OK',
view:300,
'view[1]':100
},
'texture[1]':
{
background:'rgba(0,0,0,0)',
group:{},
mipmapping:1,
name:'SymbolCache1024x1024',
placement:{},
size:1024,
'size[1]':1024,
status:0,
'status-msg':'OK',
view:1024,
'view[1]':1024
},
'texture[2]':
{
background:'rgba(0,0,0,0)',
group:{},
mipmapping:1,
name:'SymbolCache1024x1024',
placement:{},
size:1024,
'size[1]':1024,
status:0,
'status-msg':'OK',
view:1024,
'view[1]':1024
},
}
},
command:{},
consumables:{},
controls:{},
cursor:'Aircraft/ufo/Models/cursor.ac',
devices:{},
earthview:{},
engines:{},
environment:{},
ephemeris:{},
fdm:{},
gear:{},
hazards:{},
input:{},
instrumentation:{},
'local-weather':{},
logging:{},
models:{},
nasal:{},
orientation:{},
position:{},
rendering:{},
scenery:{},
sim:{},
source:'Models',
'surface-positions':{},
systems:{},
velocities:{},
};
var setprop=func(prop,value)
{
if(type(prop)!="string")
die("setprop: prop is not a string");
var path=split('/',prop);
var tmp=property_tree;
var path_size=size(path);
for(var i=0;i<path_size-1;i+=1)
tmp=tmp[path[i]];
tmp[path[path_size-1]]=value;
return;
}
var getprop=func(prop)
{
if(type(prop)!="string")
die("getprop: prop is not a string");
var path=split('/',prop);
var tmp=property_tree;
foreach(var i;path)
tmp=tmp[i];
return tmp;
}
setprop("aircraft/icao/type",'IDG MD-11');
var print_prop=func(depth,prop)
{
var s='';
for(var i=0;i<depth;i+=1)
s~='| ';
if(type(prop)!="hash")
return;
var m=keys(prop);
foreach(var elem;m)
{
print(s,elem,':',prop[elem]);
print_prop(depth+1,prop[elem]);
}
return;
}
print_prop(0,property_tree);

View File

@@ -9,6 +9,24 @@
# local node, there is no equivalent of the "relative path" variants
# available in C++; just use node.getNode(path).whatever() instead.
#
##
# Utility. Turns any ghosts it finds (either solo, or in an
# array) into Node objects.
#
var wrap = func(node) {
var argtype = typeof(node);
if(argtype == "ghost") {
return wrapNode(node);
} elsif(argtype == "vector") {
var v = node;
var n = size(v);
for(var i=0; i<n; i+=1) { v[i] = wrapNode(v[i]); }
return v;
}
return node;
}
var Node = {
getNode : func wrap(_getNode(me._g, arg)),
getParent : func wrap(_getParent(me._g, arg)),
@@ -166,23 +184,6 @@ var copy = func(src, dest, attr = 0) {
if(attr) dest.setAttribute(src.getAttribute());
}
##
# Utility. Turns any ghosts it finds (either solo, or in an
# array) into Node objects.
#
var wrap = func(node) {
var argtype = typeof(node);
if(argtype == "ghost") {
return wrapNode(node);
} elsif(argtype == "vector") {
var v = node;
var n = size(v);
for(var i=0; i<n; i+=1) { v[i] = wrapNode(v[i]); }
return v;
}
return node;
}
##
# Utility. Returns a new object with its superclass/parent set to the
# Node object and its _g (ghost) field set to the specified object.

View File

@@ -1,35 +1,40 @@
# lib queue.nas
var block_alloc=func()
{
return {elem:nil,next:nil};
}
# valkmjolnir 2021/3/3
var new_queue=func()
{
return {next:nil};
return {begin:nil,end:nil};
}
var queue_push=func(queue,elem)
var queue_push=func(queue_head,elem)
{
var tmp=queue;
while(tmp.next!=nil)
tmp=tmp.next;
tmp.next=block_alloc();
tmp.next.elem=elem;
}
var queue_pop=func(queue)
{
var tmp=queue.next;
if(tmp!=nil)
queue.next=tmp.next;
var new_node=
{
elem:elem,
next:nil
};
if(queue_head.begin==nil)
queue_head.begin=queue_head.end=new_node;
else
{
queue_head.end.next=new_node;
queue_head.end=new_node;
}
return;
}
var queue_front=func(queue)
var queue_pop=func(queue_head)
{
var tmp=queue.next;
if(tmp!=nil)
return tmp.elem;
var t=queue_head.begin;
queue_head.begin=queue_head.begin.next;
if(queue_head.begin==nil)
queue_head.end=nil;
return t;
}
var queue_front=func(queue_head)
{
if(queue_head.begin!=nil)
return queue_head.begin.elem;
return nil;
}
var queue_empty=func(queue)
var queue_empty=func(queue_head)
{
return queue.next==nil;
return queue_head.begin==nil;
}

View File

@@ -1,4 +1,5 @@
# basic type
import("lib.nas");
nil;
2147483647;
0x7fffffff;
@@ -54,7 +55,7 @@ var hash_4={
# function
var func_1=func(){return 1;}
var prt=func(x){print(x);return nil;}
var prt=func(x){println(x);return nil;}
var func_with_dynamic_id=func(a,b,c,d...){return [a,b,c,d];}
var func_with_lack_para=func(a,b,c=1,d=2){return a+b+c+d;}
var func_with_func_para=func(a,f){return f(a);}
@@ -72,21 +73,21 @@ var source={
member_1: func func_1(), # this will get a number
member_2: func {return 2.71828;} # this will get a function
};
print(source['member_2']());
print(source.member_2());
println(source['member_2']());
println(source.member_2());
var test_func=func{return 1;}
print(func test_func()); # 1
print(test_func()); # 1
print(func test_func); # nothing
print(test_func); # nothing
print(([0,1,2,3])[1]); # 1
print(({str:"what?"})["str"]); # what?
print(({str:"what?"}).str); # what?
println(func test_func()); # 1
println(test_func()); # 1
println(func test_func); # nothing
println(test_func); # nothing
println(([0,1,2,3])[1]); # 1
println(({str:"what?"})["str"]); # what?
println(({str:"what?"}).str); # what?
# lambda
(func(x){return x>0? x:0;})(12);
(func{print("hello world");})();
(func{println("hello world");})();
(((func(x){return 1.0/math.exp(x);})))(0);
# flexible definition & assignment
@@ -123,4 +124,29 @@ nil and 1+7*8;
(number_1 or number_2) and (number_3 or number_4-number_4*1);
[0,1,4,3,2][4]*2-4+1*2*2*2*2*2/8;
{num:0}.num or {what_is_the_secret_of_universe:42}["what_is_the_secret_of_universe"];
"123"~"456"-123456*2/2;
"123"~"456"-123456*2/2;
var hash={str:'hello',f:func{return me.str;}};
var tmp_f=hash.f;
hash=1;
print(tmp_f());
# undefined symbol 'me'
# this means that
# when generating local_scope for function f,
# nasal_gc will not count 'me' as one reference of this hash
var h1={str:'hello',f:func{return me.str;}};
var h2={str:'world',f:func{return nil;}};
h2.f=h1.f;
print(h2.f());
# print 'world'
# this means that 'me' in hash's functions
# only points to the hash this function belongs to
var f1=func(){print(1);return 1;}
var f2=func(){print(2);return 0;}
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

View File

@@ -1,3 +1,4 @@
import("lib.nas");
var global_value=0;
var global_hash=
{
@@ -5,16 +6,16 @@ var global_hash=
var2:2,
var3:func(){return me.var2;}
};
print(global_value);
print(global_hash.var3());
println(global_value);
println(global_hash.var3());
var func1=func()
{
global_value=1;
print(global_value);
println(global_value);
var closure_value=1;
var temp_value=1;
print(temp_value);
println(temp_value);
return func{return closure_value;};
}
@@ -23,10 +24,9 @@ var func2=func()
for(var temp_value=0;temp_value<100;temp_value+=1)
{
if(temp_value<10)
print(temp_value,"< 10");
println(temp_value,"< 10");
elsif(10<=temp_value and temp_value<50)
print(temp_value,"< 50");
temp_value=10;
println(temp_value,"< 50");
}
return;
}
@@ -41,9 +41,9 @@ var func3=func()
};
}
func1()();
println(func1()());
func2();
func3()();
println(func3()());
if(!global_value)
{

View File

@@ -1,5 +0,0 @@
import("lib.nas");
var filename="";
filename=input();
print(filename[0]);