forked from xxq250/Nasal-Interpreter
Compare commits
170 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d71b4f09e2 | ||
|
|
13d40e886e | ||
|
|
618ce59233 | ||
|
|
071d8bd1ce | ||
|
|
c498d5c8c4 | ||
|
|
11971267dc | ||
|
|
418531a44a | ||
|
|
59dc0d1423 | ||
|
|
385f0af17e | ||
|
|
ef9b781961 | ||
|
|
80cc8e9db7 | ||
|
|
b2be386be8 | ||
|
|
e4c598cae6 | ||
|
|
5fe6681b0d | ||
|
|
35fc848672 | ||
|
|
e3f3bd7387 | ||
|
|
638ec1c3a3 | ||
|
|
90ac468aa9 | ||
|
|
65dfef0a33 | ||
|
|
76a2548e95 | ||
|
|
40b690b67b | ||
|
|
2b17f3d702 | ||
|
|
5b6c78783e | ||
|
|
fa618eb97f | ||
|
|
d0616ef028 | ||
|
|
91771297d3 | ||
|
|
4e1a3c5f2d | ||
|
|
df634cb1b2 | ||
|
|
aa797142d1 | ||
|
|
816be43a98 | ||
|
|
9ebabfe737 | ||
|
|
884b56ac09 | ||
|
|
61677101e4 | ||
|
|
7a93f5b89b | ||
|
|
9fe7a86a3b | ||
|
|
9da029b8fe | ||
|
|
8b8e72c879 | ||
|
|
590c595522 | ||
|
|
57d6bcdc52 | ||
|
|
0b2fe61e6e | ||
|
|
706659ba3d | ||
|
|
3c9a10d710 | ||
|
|
fd57e9a47c | ||
|
|
ab99d2d1ed | ||
|
|
ae0dae5956 | ||
|
|
00c6e3b4fd | ||
|
|
cdf7b92a8e | ||
|
|
0e979a6e7b | ||
|
|
dd144305da | ||
|
|
4f3ddf803a | ||
|
|
de305d26ad | ||
|
|
9f30f45774 | ||
|
|
1ae47807eb | ||
|
|
3deea632f8 | ||
|
|
9f2c31149a | ||
|
|
b25a1bc3f4 | ||
|
|
fd7677f94f | ||
|
|
2e31a70406 | ||
|
|
8e29a3ec5b | ||
|
|
a68bf85f04 | ||
|
|
aae9395d66 | ||
|
|
a463af53b7 | ||
|
|
6adb991c04 | ||
|
|
c5f4736984 | ||
|
|
1a233fbe15 | ||
|
|
a7d6518bff | ||
|
|
0700ce14f7 | ||
|
|
c88620920b | ||
|
|
125fc8a9fe | ||
|
|
b06e1bb5dd | ||
|
|
c7316e9780 | ||
|
|
be1bcdfe2c | ||
|
|
144e6f45da | ||
|
|
569d5c6c6a | ||
|
|
7087c67d79 | ||
|
|
c4e6a89959 | ||
|
|
f60f674845 | ||
|
|
c21d40c466 | ||
|
|
19b590f3bb | ||
|
|
a421470715 | ||
|
|
79dc13f419 | ||
|
|
2e8208a752 | ||
|
|
1c40cca673 | ||
|
|
b1a5a5f6c0 | ||
|
|
64961877de | ||
|
|
9c9bb52818 | ||
|
|
02148f4766 | ||
|
|
767711c93a | ||
|
|
78ba0641a6 | ||
|
|
80683c381f | ||
|
|
6aac46adaf | ||
|
|
388ef66308 | ||
|
|
8faa4ef2db | ||
|
|
441c02d0fb | ||
|
|
953ad80482 | ||
|
|
e2ee9cff4c | ||
|
|
996ac59c79 | ||
|
|
944f713ee9 | ||
|
|
7329c70492 | ||
|
|
b5514fd269 | ||
|
|
3be50116fa | ||
|
|
125d6d3a7d | ||
|
|
bb746dfbfb | ||
|
|
8069a1b659 | ||
|
|
f0cb8b6ef3 | ||
|
|
9474ac9ef0 | ||
|
|
b862aa91eb | ||
|
|
bc64d530be | ||
|
|
ea5116e963 | ||
|
|
cc4e697246 | ||
|
|
515bef3f5d | ||
|
|
05800fe518 | ||
|
|
33d37771ce | ||
|
|
89540475cf | ||
|
|
e03da2f737 | ||
|
|
4617eb8f17 | ||
|
|
fed1e20085 | ||
|
|
9f30440286 | ||
|
|
99189d4f95 | ||
|
|
ae16f36baa | ||
|
|
19ce1c5f34 | ||
|
|
7c026b62b7 | ||
|
|
9eb72f8754 | ||
|
|
73c9f98f4f | ||
|
|
09e5b3fa90 | ||
|
|
d8ce203ab3 | ||
|
|
71f501a323 | ||
|
|
a5825e0e92 | ||
|
|
230bbd5eb5 | ||
|
|
c9aa6cb6c4 | ||
|
|
789300e5f6 | ||
|
|
7f6a521ad7 | ||
|
|
14852bfc2e | ||
|
|
d0206abb8d | ||
|
|
35cd1bd1e2 | ||
|
|
1d941354ca | ||
|
|
2bb0f0bf47 | ||
|
|
c5d700d0bc | ||
|
|
33e544387e | ||
|
|
f336e5c3ae | ||
|
|
fce34c12b3 | ||
|
|
bbf5217374 | ||
|
|
ffdc8993c4 | ||
|
|
ab28657c78 | ||
|
|
f811368491 | ||
|
|
e9fd953273 | ||
|
|
4a5083f5cf | ||
|
|
1625f241fa | ||
|
|
d7f1de5d7f | ||
|
|
a0a22f701d | ||
|
|
5aabbd8d42 | ||
|
|
dc81773e7d | ||
|
|
405172b317 | ||
|
|
5c253bac88 | ||
|
|
2b4b1af72c | ||
|
|
a09b748093 | ||
|
|
fd8d3acfed | ||
|
|
b9a53b3c4a | ||
|
|
155ce6fc0d | ||
|
|
6f5143657e | ||
|
|
269d81ae5b | ||
|
|
2923d24e6c | ||
|
|
b612f73ff7 | ||
|
|
ab8db5dd62 | ||
|
|
e806b5f0a2 | ||
|
|
9a9277c505 | ||
|
|
67ae3505fb | ||
|
|
6daae85740 | ||
|
|
cc05fbb597 | ||
|
|
9958431b58 |
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 ValKmjolnir
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
910
README.md
910
README.md
@@ -1,72 +1,910 @@
|
||||
# Nasal Interpreter
|
||||
# Nasal Script Language
|
||||
|
||||
[](http://wiki.flightgear.org/File:Nasallogo3.png)
|
||||
|
||||
# Nasal script language
|
||||
## Introduction
|
||||
|
||||
[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 totally rewritten by ValKmjolnir using C++(standard c++11) without reusing the code in Andy Ross's nasal interpreter(<https://github.com/andyross/nasal>). But we really appreciate that Andy created this amazing programming language and his interpreter project.
|
||||
|
||||
So this is an interpreter for Nasal written by C++.
|
||||
The interpreter is still in development(now it works well --2021/2/15). We really need your support!
|
||||
|
||||
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
|
||||
(2021/5/4) Now this project uses MIT license.Edit it if you want, use this project to learn or create more interesting things(But don't forget me XD).
|
||||
|
||||
Nasal is a script language first used in Flightgear.
|
||||
## Why Writing Nasal Interpreter
|
||||
|
||||
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.
|
||||
Nasal is a script language first used in Flightgear, created by Andy Ross(<https://github.com/andyross>).
|
||||
|
||||
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 runtimebytecode virtual machine(there was an ast-interpreter,but i deleted it after version4.0) to help checking errors.
|
||||
|
||||
They found it easier for them to check errors before copying nasal-codes in nasal-console in Flightgear to test.
|
||||
|
||||
# Lexical Analysis
|
||||
They found it much easier to check syntax and runtime errors before copying nasal-codes in nasal-console in Flightgear to test.
|
||||
|
||||
The flow chart of lexer is here:
|
||||
Also, you could use this language to write some interesting programs and run them without the lib of Flightgear.
|
||||
|
||||
[](https://github.com/ValKmjolnir/Nasal-Interpreter/blob/master/pic/nasal_lexer.png)
|
||||
You could add your own built-in functions to change this interpreter to a useful tool in your own projects(such as a script in your own game).
|
||||
|
||||
# Parser
|
||||
## How to Compile
|
||||
|
||||
Better choose the latest update of the interpreter.
|
||||
|
||||
MUST USE -O2/-O3 if want to optimize the interpreter!
|
||||
|
||||
Also remember to use g++ or clang++.
|
||||
|
||||
> [cpp compiler] -std=c++11 -O2 main.cpp -o nasal.exe
|
||||
|
||||
Or use this in linux/macOS/Unix
|
||||
|
||||
> [cpp compiler] -std=c++11 -O2 main.cpp -o nasal
|
||||
|
||||
## How to Use?
|
||||
|
||||
Input this command to run scripts directly:
|
||||
|
||||
> ./nasal filename
|
||||
|
||||
Use these commands to get version of interpreter:
|
||||
|
||||
> ./nasal -v | --version
|
||||
|
||||
Use these commands to get help(see more debug commands in help):
|
||||
|
||||
> ./nasal -h | --help
|
||||
|
||||
If your system is Windows and you want to output unicode,please use this command before running nasal interpreter:
|
||||
|
||||
> chcp 65001
|
||||
|
||||
The interpreter's interactive mode will do this automatically,so you don't need to run this command if you use the interactive interpreter.
|
||||
|
||||
## Parser
|
||||
|
||||
LL(k) parser.
|
||||
|
||||
## In __version 2.0__
|
||||
```javascript
|
||||
(var a,b,c)=(1,2,3);
|
||||
var (r,g,b)=color;
|
||||
(var a,b,c)=[{b:nil},[1,2],func return 0;];
|
||||
(a.b,b[0],c)=(1,2,3);
|
||||
```
|
||||
These two types of statements are both definition_expr.
|
||||
|
||||
These two expressions 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.
|
||||
|
||||
Problems mentioned above have been solved for a long time, but recently i found a new problem here:
|
||||
|
||||
```javascript
|
||||
(a,b,c)=(1,2,3);
|
||||
var f=func(x,y,z){return x+y+z}
|
||||
(a,b,c)=(0,1,2);
|
||||
```
|
||||
|
||||
This will be recognized as this:
|
||||
|
||||
```javascript
|
||||
var f=func(x,y,z){return x+y+z}(a,b,c)
|
||||
=(0,1,2);
|
||||
```
|
||||
|
||||
and causes fatal syntax error.
|
||||
And i tried this program in flightgear nasal console.
|
||||
It also found this is a syntax error.
|
||||
I think this is a serious design fault.
|
||||
To avoid this syntax error, change program like this, just add a semicolon:
|
||||
|
||||
```javascript
|
||||
var f=func(x,y,z){return x+y+z};
|
||||
^ here
|
||||
(a,b,c)=(0,1,2);
|
||||
```
|
||||
|
||||
### version 1.0(last update 2019/10/14)
|
||||
|
||||
First fully functional version of nasal_parser.
|
||||
|
||||
Before version 1.0,i tried many times to create a correct parser.
|
||||
|
||||
Finally i learned LL(1) and LL(k) and wrote a parser for math formulas in version 0.16(last update 2019/9/14).
|
||||
|
||||
In version 0.17(2019/9/15) 0.18(2019/9/18) 0.19(2019/10/1)i was playing the parser happily and after that i wrote version 1.0.
|
||||
|
||||
This project began at 2019/8/31.
|
||||
|
||||
## Abstract Syntax Tree
|
||||
|
||||
### Version 1.2(last update 2019/10/31)
|
||||
|
||||
The ast has been completed in this version.
|
||||
|
||||
### Version 2.0(last update 2020/8/31)
|
||||
|
||||
A completed ast-interpreter with unfinished lib functions.
|
||||
|
||||
### Version 3.0(last update 2020/10/23)
|
||||
|
||||
The ast is refactored and is now easier to read and maintain.
|
||||
|
||||
Ast-interpreter uses new techniques so it can run codes more efficiently.
|
||||
|
||||
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(last update 2021/3/7)
|
||||
|
||||
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 (last update 2020/12/17)
|
||||
|
||||
I have just finished the first version of byte-code-interpreter.
|
||||
|
||||
This interpreter is still in test.After this test,i will release version 4.0!
|
||||
|
||||
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
|
||||
for(var i=0;i<4000000;i+=1);
|
||||
```
|
||||
|
||||
```asm
|
||||
.number 0
|
||||
.number 4e+006
|
||||
.number 1
|
||||
.symbol i
|
||||
0x00000000: pzero 0x00000000
|
||||
0x00000001: loadg 0x00000000 (i)
|
||||
0x00000002: callg 0x00000000 (i)
|
||||
0x00000003: pnum 0x00000001 (4e+006)
|
||||
0x00000004: less 0x00000000
|
||||
0x00000005: jf 0x0000000b
|
||||
0x00000006: pone 0x00000000
|
||||
0x00000007: mcallg 0x00000000 (i)
|
||||
0x00000008: addeq 0x00000000
|
||||
0x00000009: pop 0x00000000
|
||||
0x0000000a: jmp 0x00000002
|
||||
0x0000000b: nop 0x00000000
|
||||
```
|
||||
|
||||
### Version 5.0 (last update 2021/3/7)
|
||||
|
||||
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.
|
||||
|
||||
### Version 6.0 (last update 2021/6/1)
|
||||
|
||||
Use loadg loadl callg calll mcallg mcalll to avoid branches.
|
||||
|
||||
Delete type vm_scop.
|
||||
|
||||
Use const vm_num to avoid frequently new & delete.
|
||||
|
||||
Change garbage collector from reference-counting to mark-sweep.
|
||||
|
||||
Vapp and newf operand use .num to reduce the size of exec_code.
|
||||
|
||||
2021/4/3 update: Now it can count from 0 to 4000000-1 in 0.8s.
|
||||
|
||||
2021/4/19 update: Now it can count from 0 to 4e6-1 in 0.4s.
|
||||
|
||||
In this update i changed global and local scope from unordered_map to vector.
|
||||
|
||||
So the bytecode generator changed a lot.
|
||||
|
||||
```javascript
|
||||
for(var i=0;i<4000000;i+=1);
|
||||
```
|
||||
|
||||
```asm
|
||||
.number 4e+006
|
||||
0x00000000: intg 0x00000001
|
||||
0x00000001: pzero 0x00000000
|
||||
0x00000002: loadg 0x00000000
|
||||
0x00000003: callg 0x00000000
|
||||
0x00000004: pnum 0x00000000 (4e+006)
|
||||
0x00000005: less 0x00000000
|
||||
0x00000006: jf 0x0000000c
|
||||
0x00000007: pone 0x00000000
|
||||
0x00000008: mcallg 0x00000000
|
||||
0x00000009: addeq 0x00000000
|
||||
0x0000000a: pop 0x00000000
|
||||
0x0000000b: jmp 0x00000003
|
||||
0x0000000c: nop 0x00000000
|
||||
```
|
||||
|
||||
### Version 6.5 (last update 2021/6/24)
|
||||
|
||||
2021/5/31 update: Now gc can collect garbage correctly without re-collecting,which will cause fatal error.
|
||||
|
||||
Add builtin_alloc to avoid mark-sweep when running a built-in function,which will mark useful items as useless garbage to collect.
|
||||
|
||||
Better use setsize and assignment to get a big array,append is very slow in this situation.
|
||||
|
||||
2021/6/3 update: Fixed a bug that gc still re-collects garbage,this time i use three mark states to make sure garbage is ready to be collected.
|
||||
|
||||
Change callf to callfv and callfh.And callfv fetches arguments from val_stack directly instead of using vm_vec,a not very efficient way.
|
||||
|
||||
Better use callfv instead of callfh,callfh will fetch a vm_hash from stack and parse it,making this process slow.
|
||||
|
||||
```javascript
|
||||
var f=func(x,y){return x+y;}
|
||||
f(1024,2048);
|
||||
```
|
||||
|
||||
```asm
|
||||
.number 1024
|
||||
.number 2048
|
||||
.symbol x
|
||||
.symbol y
|
||||
0x00000000: intg 0x00000001
|
||||
0x00000001: newf 0x00000007
|
||||
0x00000002: intl 0x00000003
|
||||
0x00000003: offset 0x00000001
|
||||
0x00000004: para 0x00000000 (x)
|
||||
0x00000005: para 0x00000001 (y)
|
||||
0x00000006: jmp 0x0000000b
|
||||
0x00000007: calll 0x00000001
|
||||
0x00000008: calll 0x00000002
|
||||
0x00000009: add 0x00000000
|
||||
0x0000000a: ret 0x00000000
|
||||
0x0000000b: loadg 0x00000000
|
||||
0x0000000c: callg 0x00000000
|
||||
0x0000000d: pnum 0x00000000 (1024)
|
||||
0x0000000e: pnum 0x00000001 (2048)
|
||||
0x0000000f: callfv 0x00000002
|
||||
0x00000010: pop 0x00000000
|
||||
0x00000011: nop 0x00000000
|
||||
```
|
||||
|
||||
2021/6/21 update: Now gc will not collect nullptr.And the function of assignment is complete,now these kinds of assignment is allowed:
|
||||
|
||||
```javascript
|
||||
var f=func()
|
||||
{
|
||||
var _=[{_:0},{_:1}];
|
||||
return func(x)
|
||||
{
|
||||
return _[x];
|
||||
}
|
||||
}
|
||||
var m=f();
|
||||
m(0)._=m(1)._=10;
|
||||
|
||||
[0,1,2][1:2][0]=0;
|
||||
```
|
||||
|
||||
In the old version,parser will check this left-value and tells that these kinds of left-value are not allowed(bad lvalue).
|
||||
|
||||
But now it can work.And you could see its use by reading the code above.To make sure this assignment works correctly,codegen will generate byte code by nasal_codegen::call_gen() instead of nasal_codegen::mcall_gen(),and the last child of the ast will be generated by nasal_codegen::mcall_gen().So the bytecode is totally different now:
|
||||
|
||||
```asm
|
||||
.number 10
|
||||
.number 2
|
||||
.symbol _
|
||||
.symbol x
|
||||
0x00000000: intg 0x00000002
|
||||
0x00000001: newf 0x00000005
|
||||
0x00000002: intl 0x00000002
|
||||
0x00000003: offset 0x00000001
|
||||
0x00000004: jmp 0x00000017
|
||||
0x00000005: newh 0x00000000
|
||||
0x00000006: pzero 0x00000000
|
||||
0x00000007: happ 0x00000000 (_)
|
||||
0x00000008: newh 0x00000000
|
||||
0x00000009: pone 0x00000000
|
||||
0x0000000a: happ 0x00000000 (_)
|
||||
0x0000000b: newv 0x00000002
|
||||
0x0000000c: loadl 0x00000001
|
||||
0x0000000d: newf 0x00000012
|
||||
0x0000000e: intl 0x00000003
|
||||
0x0000000f: offset 0x00000002
|
||||
0x00000010: para 0x00000001 (x)
|
||||
0x00000011: jmp 0x00000016
|
||||
0x00000012: calll 0x00000001
|
||||
0x00000013: calll 0x00000002
|
||||
0x00000014: callv 0x00000000
|
||||
0x00000015: ret 0x00000000
|
||||
0x00000016: ret 0x00000000
|
||||
0x00000017: loadg 0x00000000
|
||||
0x00000018: callg 0x00000000
|
||||
0x00000019: callfv 0x00000000
|
||||
0x0000001a: loadg 0x00000001
|
||||
0x0000001b: pnum 0x00000000 (10.000000)
|
||||
0x0000001c: callg 0x00000001
|
||||
0x0000001d: pone 0x00000000
|
||||
0x0000001e: callfv 0x00000001
|
||||
0x0000001f: mcallh 0x00000000 (_)
|
||||
0x00000020: meq 0x00000000
|
||||
0x00000021: callg 0x00000001
|
||||
0x00000022: pzero 0x00000000
|
||||
0x00000023: callfv 0x00000001
|
||||
0x00000024: mcallh 0x00000000 (_)
|
||||
0x00000025: meq 0x00000000
|
||||
0x00000026: pop 0x00000000
|
||||
0x00000027: pzero 0x00000000
|
||||
0x00000028: pzero 0x00000000
|
||||
0x00000029: pone 0x00000000
|
||||
0x0000002a: pnum 0x00000001 (2.000000)
|
||||
0x0000002b: newv 0x00000003
|
||||
0x0000002c: slcbeg 0x00000000
|
||||
0x0000002d: pone 0x00000000
|
||||
0x0000002e: pnum 0x00000001 (2.000000)
|
||||
0x0000002f: slc2 0x00000000
|
||||
0x00000030: slcend 0x00000000
|
||||
0x00000031: pzero 0x00000000
|
||||
0x00000032: mcallv 0x00000000
|
||||
0x00000033: meq 0x00000000
|
||||
0x00000034: pop 0x00000000
|
||||
0x00000035: nop 0x00000000
|
||||
```
|
||||
|
||||
As you could see from the bytecode above,mcall/mcallv/mcallh operands' using frequency will reduce,call/callv/callh/callfv/callfh at the opposite.
|
||||
|
||||
And because of the new structure of mcall, addr_stack, a stack used to store the memory address, is deleted from nasal_vm, and now nasal_vm use nasal_val** mem_addr to store the memory address. This will not cause fatal errors because the memory address is used __immediately__ after getting it.
|
||||
|
||||
### version 7.0 (latest)
|
||||
|
||||
2021/6/26 update:
|
||||
|
||||
Instruction dispatch is changed from call-threading to computed-goto(with inline function).After changing the way of instruction dispatch,there is a great improvement in nasal_vm.Now vm can run test/bigloop and test/pi in 0.2s!And vm runs test/fib in 0.8s on linux.You could see the time use data below,in Test data section.
|
||||
|
||||
This version uses g++ extension "labels as values", which is also supported by clang++.(But i don't know if MSVC supports this)
|
||||
|
||||
There is also a change in nasal_gc: std::vector global is deleted,now the global values are all stored on stack(from val_stack+0 to val_stack+intg-1).
|
||||
|
||||
2021/6/29 update:
|
||||
|
||||
Add some instructions that execute const values:op_addc,op_subc,op_mulc,op_divc,op_lnkc,op_addeqc,op_subeqc,op_muleqc,op_diveqc,op_lnkeqc.
|
||||
|
||||
Now the bytecode of test/bigloop.nas seems like this:
|
||||
|
||||
```asm
|
||||
.number 4e+006
|
||||
.number 1
|
||||
0x00000000: intg 0x00000001
|
||||
0x00000001: pzero 0x00000000
|
||||
0x00000002: loadg 0x00000000
|
||||
0x00000003: callg 0x00000000
|
||||
0x00000004: pnum 0x00000000 (4000000)
|
||||
0x00000005: less 0x00000000
|
||||
0x00000006: jf 0x0000000b
|
||||
0x00000007: mcallg 0x00000000
|
||||
0x00000008: addeqc 0x00000001 (1)
|
||||
0x00000009: pop 0x00000000
|
||||
0x0000000a: jmp 0x00000003
|
||||
0x0000000b: nop 0x00000000
|
||||
```
|
||||
|
||||
And this test file runs in 0.1s after this update.Most of the calculations are accelerated.
|
||||
|
||||
Also, assignment bytecode has changed a lot. Now the first identifier that called in assignment will use op_load to assign, instead of op_meq,op_pop.
|
||||
|
||||
```javascript
|
||||
var (a,b)=(1,2);
|
||||
a=b=0;
|
||||
```
|
||||
|
||||
```asm
|
||||
.number 2
|
||||
0x00000000: intg 0x00000002
|
||||
0x00000001: pone 0x00000000
|
||||
0x00000002: loadg 0x00000000
|
||||
0x00000003: pnum 0x00000000 (2)
|
||||
0x00000004: loadg 0x00000001
|
||||
0x00000005: pzero 0x00000000
|
||||
0x00000006: mcallg 0x00000001
|
||||
0x00000007: meq 0x00000000 (b=2 use meq,pop->a)
|
||||
0x00000008: loadg 0x00000000 (a=b use loadg)
|
||||
0x00000009: nop 0x00000000
|
||||
```
|
||||
|
||||
## Test data
|
||||
|
||||
### version 6.5(i5-8250U windows10 2021/6/19)
|
||||
|
||||
running time and gc time:
|
||||
|
||||
|file|call gc|total time|gc time|
|
||||
|:----|:----|:----|:----|
|
||||
|pi.nas|12000049|0.593s|0.222s|
|
||||
|fib.nas|10573747|2.838s|0.187s|
|
||||
|bp.nas|4419829|1.99s|0.18s|
|
||||
|bigloop.nas|4000000|0.419s|0.039s|
|
||||
|mandelbrot.nas|1044630|0.433s|0.041s|
|
||||
|life.nas|817112|8.557s|0.199s|
|
||||
|ascii-art.nas|45612|0.48s|0.027s|
|
||||
|calc.nas|8089|0.068s|0.006s|
|
||||
|quick_sort.nas|2768|0.107s|0s|
|
||||
|bfs.nas|2471|1.763s|0.003s|
|
||||
|
||||
operands calling frequency:
|
||||
|
||||
|file|1st|2nd|3rd|4th|5th|
|
||||
|:----|:----|:----|:----|:----|:----|
|
||||
|pi.nas|callg|pop|mcallg|pnum|pone|
|
||||
|fib.nas|calll|pnum|callg|less|jf|
|
||||
|bp.nas|calll|callg|pop|callv|addeq|
|
||||
|bigloop.nas|pnum|less|jf|callg|pone|
|
||||
|mandelbrot.nas|callg|mult|loadg|pnum|pop|
|
||||
|life.nas|calll|callv|pnum|jf|callg|
|
||||
|ascii-art.nas|calll|pop|mcalll|callg|callb|
|
||||
|calc.nas|calll|pop|pstr|mcalll|jmp|
|
||||
|quick_sort.nas|calll|pop|jt|jf|less|
|
||||
|bfs.nas|calll|pop|callv|mcalll|jf|
|
||||
|
||||
operands calling total times:
|
||||
|
||||
|file|1st|2nd|3rd|4th|5th|
|
||||
|:----|:----|:----|:----|:----|:----|
|
||||
|pi.nas|6000004|6000003|6000000|4000005|4000002|
|
||||
|fib.nas|17622792|10573704|7049218|7049155|7049155|
|
||||
|bp.nas|7081480|4227268|2764676|2617112|2065441|
|
||||
|bigloop.nas|4000001|4000001|4000001|4000001|4000000|
|
||||
|mandelbrot.nas|1519632|563856|290641|286795|284844|
|
||||
|life.nas|2114371|974244|536413|534794|489743|
|
||||
|ascii-art.nas|37906|22736|22402|18315|18292|
|
||||
|calc.nas|191|124|109|99|87|
|
||||
|quick_sort.nas|16226|5561|4144|3524|2833|
|
||||
|bfs.nas|24707|16297|14606|14269|8672|
|
||||
|
||||
### version 7.0(i5-8250U ubuntu-WSL on windows10 2021/6/29)
|
||||
|
||||
running time:
|
||||
|
||||
|file|total time|info|
|
||||
|:----|:----|:----|
|
||||
|pi.nas|0.15625s|great improvement|
|
||||
|fib.nas|0.75s|great improvement|
|
||||
|bp.nas|0.4218s(7162 epoch)|good improvement|
|
||||
|bigloop.nas|0.09375s|great improvement|
|
||||
|mandelbrot.nas|0.0312s|great improvement|
|
||||
|life.nas|8.80s(windows) 1.25(ubuntu WSL)|little improvement|
|
||||
|ascii-art.nas|0.015s|little improvement|
|
||||
|calc.nas|0.0468s|little improvement|
|
||||
|quick_sort.nas|0s|great improvement|
|
||||
|bfs.nas|0.0156s|great improvement|
|
||||
|
||||
## 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_para1=1,default_para2=2)
|
||||
{
|
||||
return x+y+z+default_para1+default_para2;
|
||||
}
|
||||
var f=func(x,y,z,dynamic_para...)
|
||||
{
|
||||
var sum=0;
|
||||
foreach(var i;dynamic_para)
|
||||
sum+=i;
|
||||
return sum+x+y+z;
|
||||
}
|
||||
```
|
||||
|
||||
### operators
|
||||
|
||||
```javascript
|
||||
1+2-1*2/1;
|
||||
'str1'~'str2';
|
||||
(1+2)*(3+4)
|
||||
|
||||
1+1 and 0;
|
||||
1<0 or 1>0;
|
||||
1<=0 and 1>=0;
|
||||
1==0 or 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);
|
||||
(a,b)=(b,a);
|
||||
```
|
||||
This type of statement is multi_assignment.
|
||||
|
||||
And to check if an expr in '(' ')' is multi_scalar or multi_id.
|
||||
### conditional expression
|
||||
|
||||
i used bool nasal_parse::check_multi_scalar() and bool nasal_parse::check_multi_assignment().
|
||||
```javascript
|
||||
if(1){
|
||||
;
|
||||
}elsif(2){
|
||||
;
|
||||
}else if(3){
|
||||
;
|
||||
}else{
|
||||
;
|
||||
}
|
||||
```
|
||||
|
||||
## In __version 3.0__
|
||||
### loop
|
||||
|
||||
I refactored parser and make it easier to maintain.
|
||||
```javascript
|
||||
while(condition)
|
||||
continue;
|
||||
|
||||
the EBNF is also refactored.
|
||||
for(var i=0;i<10;i+=1)
|
||||
break;
|
||||
|
||||
# Abstract Syntax Tree
|
||||
forindex(var i;elem)
|
||||
print(elem[i]);
|
||||
|
||||
In __version 1.2__ the ast has been completed.
|
||||
foreach(var i;elem)
|
||||
print(i);
|
||||
```
|
||||
|
||||
In __version 3.0__ the ast is refactored and is now easier to read and maintain.
|
||||
### subvec
|
||||
|
||||
# Version 2.0
|
||||
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().
|
||||
|
||||
a completed ast-interpreter with unfinished lib functions.
|
||||
```javascript
|
||||
a[-1,1,0:2,0:,:3,:,nil:8,3:nil,nil:nil];
|
||||
"hello world"[0];
|
||||
```
|
||||
|
||||
# Version 3.0
|
||||
### special function call
|
||||
|
||||
ast-interpreter uses new techniques so it can run codes more efficiently.
|
||||
This is of great use but is not very efficient(because hashmap use string as the key to compare).
|
||||
|
||||
byte-code-interpreter is in progress(i need a lot of time to learn that :( ).
|
||||
```javascript
|
||||
a(x:0,y:1,z:2);
|
||||
```
|
||||
|
||||
### lambda
|
||||
|
||||
Also functions have this kind of use:
|
||||
|
||||
```javascript
|
||||
func(x,y){return x+y}(0,1);
|
||||
func(x){return 1/(1+math.exp(-x));}(0.5);
|
||||
```
|
||||
|
||||
### closure
|
||||
|
||||
Use closure to OOP.
|
||||
|
||||
```javascript
|
||||
var f=func()
|
||||
{
|
||||
var a=1;
|
||||
return func(){return a;};
|
||||
}
|
||||
print(f()());
|
||||
|
||||
var student=func(name,age)
|
||||
{
|
||||
var val={
|
||||
name:name,
|
||||
age:age
|
||||
};
|
||||
return {
|
||||
print_info:func(){println(val.name,' ',val.age);},
|
||||
set_age: func(age){val.age=age;},
|
||||
get_age: func(){return val.age;},
|
||||
set_name: func(name){val.name=name;},
|
||||
get_name: func(){return val.name;}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 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(std::vector<nasal_val*>&,nasal_gc&);
|
||||
```
|
||||
|
||||
Then complete this function using C++:
|
||||
|
||||
```C++
|
||||
nasal_val* builtin_print(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
|
||||
{
|
||||
// get arguments by using builtin_find
|
||||
// find value with index begin from 1
|
||||
// because local_scope[0] is reserved for value 'me'
|
||||
nasal_val* vector_value=local_scope[1];
|
||||
// main process
|
||||
// also check number of arguments and type here
|
||||
// if get a type error,use builtin_err and return nullptr
|
||||
for(auto i:vec_addr->ptr.vec->elems)
|
||||
switch(i->type)
|
||||
{
|
||||
case vm_nil: std::cout<<"nil"; break;
|
||||
case vm_num: std::cout<<i->ptr.num; break;
|
||||
case vm_str: std::cout<<*i->ptr.str; break;
|
||||
case vm_vec: i->ptr.vec->print(); break;
|
||||
case vm_hash: i->ptr.hash->print(); break;
|
||||
case vm_func: std::cout<<"func(...){...}"; break;
|
||||
}
|
||||
std::cout<<std::flush;
|
||||
// if a nasal value is not in use,use gc::del_reference to delete it
|
||||
// generate return value,use gc::gc_alloc(type) to make a new value
|
||||
// or use reserved reference gc.nil_addr/gc.one_addr/gc.zero_addr
|
||||
return gc.nil_addr;
|
||||
}
|
||||
```
|
||||
|
||||
After that, write the built-in function's name(in nasal) and the function's pointer in this table:
|
||||
|
||||
```C++
|
||||
struct FUNC_TABLE
|
||||
{
|
||||
const char* name;
|
||||
nasal_val* (*func)(std::vector<nasal_val*>&,nasal_gc&);
|
||||
} builtin_func[]=
|
||||
{
|
||||
{"__builtin_print",builtin_print},
|
||||
{nullptr, nullptr }
|
||||
};
|
||||
```
|
||||
|
||||
At last,warp the '__builtin_print' in a nasal file:
|
||||
|
||||
```javascript
|
||||
var print=func(elems...)
|
||||
{
|
||||
return __builtin_print(elems);
|
||||
};
|
||||
```
|
||||
|
||||
In fact the arguments that '__builtin_print' uses is not necessary,So writting it like this is also right:
|
||||
|
||||
```javascript
|
||||
var print=func(elems...)
|
||||
{
|
||||
return __builtin_print;
|
||||
};
|
||||
```
|
||||
|
||||
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 built-in functions,then you could use it.
|
||||
|
||||
version 6.5 update:
|
||||
|
||||
Use nasal_gc::builtin_alloc in builtin function if this function uses alloc more than one time.
|
||||
|
||||
When running a builtin function,alloc will run more than one time,this may cause mark-sweep in gc_alloc.
|
||||
|
||||
The value got before will be collected,but stil in use in this builtin function,this is a fatal error.
|
||||
|
||||
So use builtin_alloc in builtin functions like this:
|
||||
|
||||
```C++
|
||||
nasal_val* builtin_keys(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
|
||||
{
|
||||
nasal_val* hash_addr=local_scope[1];
|
||||
if(hash_addr->type!=vm_hash)
|
||||
{
|
||||
builtin_err("keys","\"hash\" must be hash");
|
||||
return nullptr;
|
||||
}
|
||||
nasal_val* ret_addr=gc.builtin_alloc(vm_vec);
|
||||
std::vector<nasal_val*>& ref_vec=ret_addr->ptr.vec->elems;
|
||||
for(auto iter:hash_addr->ptr.hash->elems)
|
||||
{
|
||||
nasal_val* str_addr=gc.builtin_alloc(vm_str);
|
||||
*str_addr->ptr.str=iter.first;
|
||||
ref_vec.push_back(str_addr);
|
||||
}
|
||||
return ret_addr;
|
||||
}
|
||||
```
|
||||
|
||||
## Difference Between Andy's Nasal Interpreter and This Interpreter
|
||||
|
||||
This interpreter uses more strict syntax to make sure it is easier for you to program and debug.
|
||||
|
||||
In Andy's interpreter:
|
||||
|
||||
```javascript
|
||||
foreach(i;[0,1,2,3])
|
||||
print(i)
|
||||
```
|
||||
|
||||
This program can run normally with output 0 1 2 3.
|
||||
But take a look at the iterator 'i',this symbol is defined in foreach without using keyword 'var'.
|
||||
I think this design will make programmers filling confused.
|
||||
This is ambiguous that programmers maybe difficult to find the 'i' is defined here.
|
||||
Without 'var',programmers may think this 'i' is defined anywhere else.
|
||||
|
||||
So in this new interpreter i use a more strict syntax to force users to use 'var' to define iterator of forindex and foreach.
|
||||
If you forget to add the keyword 'var', and you haven't defined this symbol before, you will get this:
|
||||
|
||||
```javascript
|
||||
[code] <test.nas> line 1: undefined symbol "i".
|
||||
[codegen] in <test.nas>: error(s) occurred,stop.
|
||||
```
|
||||
|
||||
Also there's another difference.
|
||||
In Andy's interpreter:
|
||||
|
||||
```javascript
|
||||
var a=func {print(b);}
|
||||
var b=1;
|
||||
a();
|
||||
```
|
||||
|
||||
This program runs normally with output 1.
|
||||
But in this new interpreter, it will get:
|
||||
|
||||
```javascript
|
||||
[code] <test.nas> line 1: undefined symbol "b".
|
||||
[codegen] in <test.nas>: error(s) occurred,stop.
|
||||
```
|
||||
|
||||
(outdated)This difference is caused by different kinds of ways of lexical analysis.
|
||||
In most script language interpreters, they use dynamic analysis to check if this symbol is defined yet.
|
||||
However, this kind of analysis is at the cost of lower efficiency.
|
||||
To make sure the interpreter runs at higher efficiency, i choose static analysis to manage the memory space of each symbol.
|
||||
By this way, runtime will never need to check if a symbol exists or not.
|
||||
But this causes a difference.
|
||||
You will get an error of 'undefined symbol', instead of nothing happening in most script language interpreters.
|
||||
|
||||
This change is __controversial__ among FGPRC's members.
|
||||
So maybe in the future i will use dynamic analysis again to cater to the habits of senior programmers.
|
||||
|
||||
(2021/8/3 update) __Now i use scanning ast twice to reload symbols.
|
||||
So this difference does not exist from this update.__
|
||||
But a new difference is that if you call a variable before defining it, you'll get nil instead of 'undefined error'.
|
||||
|
||||
In this new interpreter, function doesn't put dynamic arguments into vector 'arg' automatically.
|
||||
So if you use 'arg' without definition, you'll get an error of 'undefined symbol'.
|
||||
|
||||
## Trace Back Info
|
||||
|
||||
Now when the interpreter crashes,it will print trace back information:
|
||||
|
||||
```javascript
|
||||
func()
|
||||
{
|
||||
println("hello");
|
||||
die("error occurred this line");
|
||||
return;
|
||||
}();
|
||||
```
|
||||
|
||||
Function 'die' is used to throw error and crash.
|
||||
|
||||
```javascript
|
||||
hello
|
||||
[vm] error: error occurred this line
|
||||
[vm] error at 0x000000b0: native function error.
|
||||
trace back:
|
||||
0x000000b0: callb 0x00000021:__builtin_die (lib.nas line 85)
|
||||
0x0000017f: callfv 0x00000001 (a.nas line 19)
|
||||
0x00000183: callfv 0x00000000 (a.nas line 21)
|
||||
vm stack(limit 10):
|
||||
0x0 nullptr
|
||||
0x7fa5f8e19c80 func | func(1 para){..}
|
||||
0x7fa5f8e1a780 func | func(0 para){..}
|
||||
0x7fa5f8c0c040 num | 0.017453
|
||||
0x7fa5f8e33370 hash | {9 member}
|
||||
0x7fa5f8e33330 hash | {5 member}
|
||||
0x7fa5f8e332e0 hash | {2 member}
|
||||
0x7fa5f8e1a000 func | func(1 para){..}
|
||||
0x7fa5f8e19f80 func | func(2 para){..}
|
||||
0x7fa5f8e19f00 func | func(2 para){..}
|
||||
```
|
||||
|
||||
Here is an example of stack overflow:
|
||||
|
||||
```javascript
|
||||
func(f){
|
||||
return f(f);
|
||||
}(
|
||||
func(f){
|
||||
f(f);
|
||||
}
|
||||
)();
|
||||
```
|
||||
|
||||
And the trace back info:
|
||||
|
||||
```javascript
|
||||
[vm] stack overflow
|
||||
trace back:
|
||||
0x00000011: callfv 0x00000001 (a.nas line 5)
|
||||
0x00000011: 4076 same call(s) ...
|
||||
0x00000008: callfv 0x00000001 (a.nas line 2)
|
||||
0x00000015: callfv 0x00000001 (a.nas line 3)
|
||||
vm stack(limit 10):
|
||||
0x7fcc3110ad00 func | func(1 para){..}
|
||||
0x7fcc3110ad00 ... | 9 same value(s)
|
||||
```
|
||||
195
lib.nas
195
lib.nas
@@ -1,163 +1,162 @@
|
||||
var import=func(filename)
|
||||
{
|
||||
nasal_call_import(filename);
|
||||
return nil;
|
||||
return __builtin_import(filename);
|
||||
}
|
||||
var print=func(elements...)
|
||||
var print=func(elems...)
|
||||
{
|
||||
nasal_call_builtin_std_cout(elements);
|
||||
return nil;
|
||||
return __builtin_print(elems);
|
||||
};
|
||||
var append=func(vector,elements...)
|
||||
var println=func(elems...)
|
||||
{
|
||||
nasal_call_builtin_push_back(vector,elements);
|
||||
return nil;
|
||||
__builtin_print(elems);
|
||||
elems=['\n'];
|
||||
return __builtin_print(elems);
|
||||
}
|
||||
var setsize=func(vector,size)
|
||||
var append=func(vec,elems...)
|
||||
{
|
||||
nasal_call_builtin_set_size(vector,size);
|
||||
return nil;
|
||||
return __builtin_append(vec,elems);
|
||||
}
|
||||
var setsize=func(vec,size)
|
||||
{
|
||||
return __builtin_setsize(vec,size);
|
||||
}
|
||||
var system=func(str)
|
||||
{
|
||||
nasal_call_builtin_system(str);
|
||||
return;
|
||||
return __builtin_system(str);
|
||||
}
|
||||
var input=func()
|
||||
{
|
||||
return nasal_call_builtin_input();
|
||||
return __builtin_input();
|
||||
}
|
||||
var sleep=func(duration)
|
||||
{
|
||||
nasal_call_builtin_sleep(duration);
|
||||
return;
|
||||
return __builtin_sleep(duration);
|
||||
}
|
||||
var split=func(delimeter,string)
|
||||
var split=func(deli,str)
|
||||
{
|
||||
return nasal_call_builtin_split(delimeter,string);
|
||||
return __builtin_split(deli,str);
|
||||
}
|
||||
var rand=func(seed=nil)
|
||||
{
|
||||
return nasal_call_builtin_rand(seed);
|
||||
return __builtin_rand(seed);
|
||||
}
|
||||
var id=func(thing)
|
||||
var id=func(object)
|
||||
{
|
||||
return nasal_call_builtin_get_id(thing);
|
||||
return __builtin_id(object);
|
||||
}
|
||||
var int=func(value)
|
||||
var int=func(val)
|
||||
{
|
||||
return nasal_call_builtin_trans_int(value);
|
||||
return __builtin_int(val);
|
||||
}
|
||||
var num=func(value)
|
||||
var num=func(val)
|
||||
{
|
||||
return nasal_call_builtin_trans_num(value);
|
||||
return __builtin_num(val);
|
||||
}
|
||||
var pop=func(vector)
|
||||
var pop=func(vec)
|
||||
{
|
||||
return nasal_call_builtin_pop_back(vector);
|
||||
return __builtin_pop(vec);
|
||||
}
|
||||
var str=func(number)
|
||||
var str=func(num)
|
||||
{
|
||||
return nasal_call_builtin_trans_str(number);
|
||||
return __builtin_str(num);
|
||||
}
|
||||
var size=func(object)
|
||||
{
|
||||
return nasal_call_builtin_size(object);
|
||||
return __builtin_size(object);
|
||||
}
|
||||
var contains=func(hash,key)
|
||||
{
|
||||
return nasal_call_builtin_contains(hash,key);
|
||||
return __builtin_contains(hash,key);
|
||||
}
|
||||
var delete=func(hash,key)
|
||||
{
|
||||
nasal_call_builtin_delete(hash,key);
|
||||
return;
|
||||
return __builtin_delete(hash,key);
|
||||
}
|
||||
var keys=func(hash)
|
||||
{
|
||||
return nasal_call_builtin_get_keys(hash);
|
||||
return __builtin_keys(hash);
|
||||
}
|
||||
var time=func(begin_time)
|
||||
{
|
||||
return nasal_call_builtin_time(begin_time);
|
||||
return __builtin_time(begin_time);
|
||||
}
|
||||
var die=func(str)
|
||||
{
|
||||
nasal_call_builtin_die(str);
|
||||
return nil;
|
||||
return __builtin_die(str);
|
||||
}
|
||||
var type=func(object)
|
||||
var typeof=func(object)
|
||||
{
|
||||
return nasal_call_builtin_type(object);
|
||||
return __builtin_type(object);
|
||||
}
|
||||
var substr=func(str,begin,len)
|
||||
{
|
||||
return __builtin_substr(str,begin,len);
|
||||
}
|
||||
var streq=func(a,b)
|
||||
{
|
||||
return __builtin_streq(a,b);
|
||||
}
|
||||
var left=func(str,len)
|
||||
{
|
||||
return __builtin_left(str,len);
|
||||
}
|
||||
var right=func(str,len)
|
||||
{
|
||||
return __builtin_right(str,len);
|
||||
}
|
||||
var cmp=func(a,b)
|
||||
{
|
||||
return __builtin_cmp(a,b);
|
||||
}
|
||||
var chr=func(code)
|
||||
{
|
||||
return __builtin_chr(code);
|
||||
}
|
||||
|
||||
var io=
|
||||
{
|
||||
fin:func(filename)
|
||||
{
|
||||
return nasal_call_builtin_finput(filename);
|
||||
},
|
||||
fout:func(filename,str)
|
||||
{
|
||||
nasal_call_builtin_foutput(filename,str);
|
||||
return;
|
||||
}
|
||||
fin: func(filename){return __builtin_fin(filename);},
|
||||
fout:func(filename,str){return __builtin_fout(filename,str);}
|
||||
};
|
||||
|
||||
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 __builtin_xor(a,b); },
|
||||
bitand: func(a,b){return __builtin_and(a,b); },
|
||||
bitor: func(a,b){return __builtin_or(a,b); },
|
||||
bitnand: func(a,b){return __builtin_nand(a,b);},
|
||||
bitnot: func(a) {return __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 __builtin_sin(x); },
|
||||
cos: func(x) {return __builtin_cos(x); },
|
||||
tan: func(x) {return __builtin_tan(x); },
|
||||
exp: func(x) {return __builtin_exp(x); },
|
||||
ln: func(x) {return __builtin_ln(x); },
|
||||
sqrt: func(x) {return __builtin_sqrt(x); },
|
||||
atan2: func(x,y){return __builtin_atan2(x,y);},
|
||||
inf: 1/0,
|
||||
nan: 0/0,
|
||||
isnan: func(x) {return __builtin_isnan(x); }
|
||||
};
|
||||
|
||||
var D2R=math.pi/180;
|
||||
var FPS2KT=0.5925;
|
||||
var FT2M=0.3048;
|
||||
var GAL2L=3.7854;
|
||||
var IN2M=0.0254;
|
||||
var KG2LB=2.2046;
|
||||
var KT2FPS=1.6878;
|
||||
var KT2MPS=0.5144;
|
||||
var L2GAL=0.2642;
|
||||
var LB2KG=0.4536;
|
||||
var M2FT=3.2808;
|
||||
var M2IN=39.3701;
|
||||
var M2NM=0.00054;
|
||||
var MPS2KT=1.9438;
|
||||
var NM2M=1852;
|
||||
var R2D=180/math.pi;
|
||||
356
main.cpp
356
main.cpp
@@ -1,248 +1,144 @@
|
||||
#include "nasal.h"
|
||||
|
||||
nasal_resource resource;
|
||||
nasal_lexer lexer;
|
||||
nasal_parse parse;
|
||||
nasal_import preprocessor;
|
||||
nasal_codegen code_generator;
|
||||
std::string command;
|
||||
std::string inputfile="null";
|
||||
nasal_runtime runtime;
|
||||
|
||||
void help()
|
||||
void help_cmd()
|
||||
{
|
||||
std::cout<<">> [\"file\"] input a file name.\n";
|
||||
std::cout<<">> [clear ] clear the screen.\n";
|
||||
std::cout<<">> [del ] clear the input filename.\n";
|
||||
std::cout<<">> [rs ] print source code.\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<<">> [exec ] generate byte code.\n";
|
||||
std::cout<<">> [erun ] run byte code.\n";
|
||||
std::cout<<">> [logo ] print logo of nasal .\n";
|
||||
std::cout<<">> [exit ] quit nasal interpreter.\n";
|
||||
return;
|
||||
std::cout
|
||||
#ifdef _WIN32
|
||||
<<"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"
|
||||
<<"nasal [file]\n"
|
||||
<<"file:\n"
|
||||
<<" input file name to execute script file.\n\n"
|
||||
<<"nasal [option] [file]\n"
|
||||
<<"option:\n"
|
||||
<<" -l, --lex | view token info.\n"
|
||||
<<" -a, --ast | view abstract syntax tree.\n"
|
||||
<<" -c, --code | view bytecode.\n"
|
||||
<<" -e, --exec | execute script file.\n"
|
||||
<<" -t, --time | execute and get the running time.\n"
|
||||
<<" -o, --opcnt | count operands while running.\n"
|
||||
<<"file:\n"
|
||||
<<" input file name to execute script file.\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"
|
||||
<<"nasal interpreter ver 7.0\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"
|
||||
<<"lang info : http://wiki.flightgear.org/Nasal_scripting_language\n"
|
||||
<<"input \"nasal -h\" to get help .\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void del_func()
|
||||
void die(const char* stage,const std::string& filename)
|
||||
{
|
||||
resource.clear();
|
||||
lexer.clear();
|
||||
parse.clear();
|
||||
inputfile="null";
|
||||
std::cout<<">> [Delete] complete.\n";
|
||||
return;
|
||||
std::cout<<"["<<stage<<"] in <"<<filename<<">: error(s) occurred,stop.\n";
|
||||
std::exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
void die(std::string stage,std::string filename)
|
||||
void execute(const std::string& file,const std::string& command)
|
||||
{
|
||||
std::cout<<">> ["<<stage<<"] in <\""<<filename<<"\">: error(s) occurred,stop.\n";
|
||||
return;
|
||||
nasal_lexer lexer;
|
||||
nasal_parse parse;
|
||||
nasal_import import;
|
||||
nasal_codegen codegen;
|
||||
nasal_vm vm;
|
||||
lexer.openfile(file);
|
||||
lexer.scanner();
|
||||
if(lexer.get_error())
|
||||
die("lexer",file);
|
||||
if(command=="--lex" || command=="-l")
|
||||
{
|
||||
lexer.print_token();
|
||||
return;
|
||||
}
|
||||
parse.main_process(lexer.get_token_list());
|
||||
if(parse.get_error())
|
||||
die("parse",file);
|
||||
if(command=="--ast" || command=="-a")
|
||||
{
|
||||
parse.get_root().print_ast(0);
|
||||
return;
|
||||
}
|
||||
// first used file is itself
|
||||
import.link(parse.get_root(),file);
|
||||
if(import.get_error())
|
||||
die("import",file);
|
||||
codegen.main_progress(import.get_root(),import.get_file());
|
||||
if(codegen.get_error())
|
||||
die("code",file);
|
||||
if(command=="--code" || command=="-c")
|
||||
{
|
||||
codegen.print_byte_code();
|
||||
return;
|
||||
}
|
||||
vm.init(
|
||||
codegen.get_str_table(),
|
||||
codegen.get_num_table(),
|
||||
import.get_file()
|
||||
);
|
||||
if(command=="--exec" || command=="-e" || command=="--opcnt" || command=="-o")
|
||||
vm.run(codegen.get_exec_code(),command=="--opcnt" || command=="-o");
|
||||
else if(command=="--time" || command=="-t")
|
||||
{
|
||||
clock_t begin=clock();
|
||||
vm.run(codegen.get_exec_code(),false);
|
||||
std::cout<<"process exited after "<<((double)(clock()-begin))/CLOCKS_PER_SEC<<"s.\n";
|
||||
}
|
||||
vm.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void lex_func()
|
||||
int main(int argc,const char* argv[])
|
||||
{
|
||||
if(!resource.input_file(inputfile))
|
||||
{
|
||||
die("resource",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.scanner(resource.get_file());
|
||||
if(lexer.get_error())
|
||||
{
|
||||
die("lexer",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.print_token();
|
||||
return;
|
||||
}
|
||||
|
||||
void ast_print()
|
||||
{
|
||||
if(!resource.input_file(inputfile))
|
||||
{
|
||||
die("resource",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.scanner(resource.get_file());
|
||||
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;
|
||||
}
|
||||
parse.get_root().print_ast(0);
|
||||
return;
|
||||
}
|
||||
void runtime_start()
|
||||
{
|
||||
if(!resource.input_file(inputfile))
|
||||
{
|
||||
die("resource",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.scanner(resource.get_file());
|
||||
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;
|
||||
}
|
||||
preprocessor.preprocessing(parse.get_root());
|
||||
if(preprocessor.get_error())
|
||||
{
|
||||
die("import",inputfile);
|
||||
return;
|
||||
}
|
||||
runtime.set_root(preprocessor.get_root());
|
||||
runtime.run();
|
||||
return;
|
||||
}
|
||||
|
||||
void codegen_start()
|
||||
{
|
||||
if(!resource.input_file(inputfile))
|
||||
{
|
||||
die("resource",inputfile);
|
||||
return;
|
||||
}
|
||||
lexer.scanner(resource.get_file());
|
||||
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;
|
||||
}
|
||||
preprocessor.preprocessing(parse.get_root());
|
||||
if(preprocessor.get_error())
|
||||
{
|
||||
die("import",inputfile);
|
||||
return;
|
||||
}
|
||||
runtime.set_root(preprocessor.get_root());
|
||||
code_generator.output_exec(inputfile+".naexec",preprocessor.get_root());
|
||||
if(code_generator.get_error())
|
||||
{
|
||||
die("code",inputfile);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void execution_start()
|
||||
{
|
||||
code_generator.load_exec(inputfile,preprocessor.get_root());
|
||||
if(code_generator.get_error())
|
||||
{
|
||||
die("code",inputfile);
|
||||
return;
|
||||
}
|
||||
runtime.set_root(preprocessor.get_root());
|
||||
runtime.run();
|
||||
return;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// use chcp 65001 to use unicode io
|
||||
system("chcp 65001");
|
||||
system("cls");
|
||||
#endif
|
||||
logo();
|
||||
#ifdef _WIN32
|
||||
std::cout<<">> [system] Windows system.\n";
|
||||
#endif
|
||||
#ifdef _linux_
|
||||
std::cout<<">> [system] Linux system.\n";
|
||||
#endif
|
||||
#ifdef TARGET_OS_MAC
|
||||
std::cout<<">> [system] MacOS system.\n";
|
||||
#endif
|
||||
|
||||
std::cout<<">> Nasal interpreter ver 3.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";
|
||||
while(1)
|
||||
{
|
||||
std::cout<<">> ";
|
||||
std::cin>>command;
|
||||
if(command=="help")
|
||||
help();
|
||||
else if(command=="clear")
|
||||
{
|
||||
#ifdef _WIN32
|
||||
system("cls");
|
||||
#endif
|
||||
#ifdef _linux_
|
||||
system("clear");
|
||||
#endif
|
||||
#ifdef TARGET_OS_MAC
|
||||
system("clear");
|
||||
#endif
|
||||
}
|
||||
else if(command=="del")
|
||||
del_func();
|
||||
else if(command=="rs")
|
||||
{
|
||||
if(resource.input_file(inputfile))
|
||||
resource.print_file();
|
||||
}
|
||||
else if(command=="lex")
|
||||
lex_func();
|
||||
else if(command=="ast")
|
||||
ast_print();
|
||||
else if(command=="run")
|
||||
runtime_start();
|
||||
else if(command=="exec")
|
||||
codegen_start();
|
||||
else if(command=="erun")
|
||||
execution_start();
|
||||
else if(command=="logo")
|
||||
logo();
|
||||
else if(command=="exit")
|
||||
break;
|
||||
else
|
||||
{
|
||||
inputfile=command;
|
||||
std::ifstream fin(command);
|
||||
if(fin.fail())
|
||||
{
|
||||
std::cout<<">> [file] cannot open file \""<<command<<"\".\n";
|
||||
inputfile="null";
|
||||
}
|
||||
fin.close();
|
||||
}
|
||||
}
|
||||
std::string command,file;
|
||||
if(argc==2 && (!strcmp(argv[1],"-v") || !strcmp(argv[1],"--version")))
|
||||
logo();
|
||||
else if(argc==2 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help")))
|
||||
help_cmd();
|
||||
else if(argc==2 && argv[1][0]!='-')
|
||||
{
|
||||
file=argv[1];
|
||||
command="-e";
|
||||
execute(file,command);
|
||||
}
|
||||
else if(argc==3 &&
|
||||
(!strcmp(argv[1],"--lex") ||
|
||||
!strcmp(argv[1],"-l") ||
|
||||
!strcmp(argv[1],"--ast") ||
|
||||
!strcmp(argv[1],"-a") ||
|
||||
!strcmp(argv[1],"--code") ||
|
||||
!strcmp(argv[1],"-c") ||
|
||||
!strcmp(argv[1],"--exec") ||
|
||||
!strcmp(argv[1],"-e") ||
|
||||
!strcmp(argv[1],"--opcnt")||
|
||||
!strcmp(argv[1],"-o") ||
|
||||
!strcmp(argv[1],"--time") ||
|
||||
!strcmp(argv[1],"-t")))
|
||||
{
|
||||
file=argv[2];
|
||||
command=argv[1];
|
||||
execute(file,command);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout
|
||||
<<"invalid argument(s).\n"
|
||||
<<"use nasal -h to get help.\n";
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
20
nasal.ebnf
20
nasal.ebnf
@@ -20,7 +20,7 @@ hashmember::=
|
||||
id|string ':' calculation
|
||||
;
|
||||
function::=
|
||||
func argument_list expressions
|
||||
func {argument_list} exprs|expr
|
||||
;
|
||||
argument_list::=
|
||||
'(' [{id ','} ([id '...']|{id '=' scalar ','})] ')'
|
||||
@@ -35,7 +35,7 @@ expr::=
|
||||
|continue_expr
|
||||
|break_expr
|
||||
;
|
||||
expressions::=
|
||||
exprs::=
|
||||
'{' {expr} '}'
|
||||
;
|
||||
calculation::=
|
||||
@@ -59,15 +59,15 @@ multive_expr::=
|
||||
(unary|scalar) ('*' | '/') (unary|scalar)
|
||||
;
|
||||
unary::=
|
||||
('-'|'!') scalar
|
||||
('-'|'!') (unary|scalar)
|
||||
;
|
||||
scalar::=
|
||||
function {call_scalar}
|
||||
|identifier {call_scalar}
|
||||
|vector {call_scalar}
|
||||
|hash {call_scalar}
|
||||
|number
|
||||
|string
|
||||
|nil
|
||||
|'(' calculation ')' {call_scalar}
|
||||
;
|
||||
call_scalar::=
|
||||
@@ -108,18 +108,18 @@ loop::=
|
||||
|forei_loop
|
||||
;
|
||||
while_loop::=
|
||||
while '(' calculation ')' expressions
|
||||
while '(' calculation ')' exprs
|
||||
;
|
||||
for_loop::=
|
||||
for '(' [definition|calculation] ';' [calculation] ';' [calculation] ')' expressions
|
||||
for '(' [definition|calculation] ';' [calculation] ';' [calculation] ')' exprs
|
||||
;
|
||||
forei_loop::=
|
||||
(forindex | foreach) '(' (definition | calculation) ';' calculation ')' expressions
|
||||
(forindex | foreach) '(' (definition | calculation) ';' calculation ')' exprs
|
||||
;
|
||||
conditional::=
|
||||
if '(' calculation ')' expressions
|
||||
{elsif '(' calculation ')' expressions}
|
||||
[else expressions]
|
||||
if '(' calculation ')' exprs
|
||||
{elsif '(' calculation ')' exprs}
|
||||
[else exprs]
|
||||
;
|
||||
continue_expr::=
|
||||
continue
|
||||
|
||||
119
nasal.h
119
nasal.h
@@ -1,34 +1,137 @@
|
||||
#ifndef __NASAL_H__
|
||||
#define __NASAL_H__
|
||||
|
||||
#pragma GCC optimize(2)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
/* if thread is used, don't forget to add -std=c++11 or higher standard before executing */
|
||||
// #include <thread>
|
||||
#include <list>
|
||||
#include <stack>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "nasal_enum.h"
|
||||
#include "nasal_misc.h"
|
||||
#include "nasal_resource.h"
|
||||
/*
|
||||
check if a string can be converted to a number
|
||||
if this string cannot be converted to a number,it will return nan
|
||||
*/
|
||||
inline double hex_to_double(const char* str)
|
||||
{
|
||||
double ret=0;
|
||||
for(;*str;++str)
|
||||
{
|
||||
ret*=16;
|
||||
if('0'<=*str && *str<='9')
|
||||
ret+=(*str-'0');
|
||||
else if('a'<=*str && *str<='f')
|
||||
ret+=(*str-'a'+10);
|
||||
else if('A'<=*str && *str<='F')
|
||||
ret+=(*str-'A'+10);
|
||||
else
|
||||
return nan("");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
inline double oct_to_double(const char* str)
|
||||
{
|
||||
double ret=0;
|
||||
for(;*str;++str)
|
||||
{
|
||||
ret*=8;
|
||||
if('0'<=*str && *str<'8')
|
||||
ret+=(*str-'0');
|
||||
else
|
||||
return nan("");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
inline double dec_to_double(const char* str)
|
||||
{
|
||||
double ret=0,negative=1,num_pow=0;
|
||||
while('0'<=*str && *str<='9')
|
||||
ret=ret*10+(*str++-'0');
|
||||
if(!*str) return ret;
|
||||
if(*str=='.')
|
||||
{
|
||||
if(!*++str) return nan("");
|
||||
num_pow=0.1;
|
||||
while('0'<=*str && *str<='9')
|
||||
{
|
||||
ret+=num_pow*(*str++-'0');
|
||||
num_pow*=0.1;
|
||||
}
|
||||
if(!*str) return ret;
|
||||
}
|
||||
if(*str!='e' && *str!='E')
|
||||
return nan("");
|
||||
if(!*++str) return nan("");
|
||||
if(*str=='-' || *str=='+')
|
||||
negative=(*str++=='-'? -1:1);
|
||||
if(!*str) return nan("");
|
||||
num_pow=0;
|
||||
for(;*str;++str)
|
||||
{
|
||||
if('0'<=*str && *str<='9')
|
||||
num_pow=num_pow*10+(*str-'0');
|
||||
else
|
||||
return nan("");
|
||||
}
|
||||
return ret*std::pow(10,negative*num_pow);
|
||||
}
|
||||
double str2num(const char* str)
|
||||
{
|
||||
bool is_negative=false;
|
||||
double ret_num=0;
|
||||
if(*str=='-' || *str=='+')
|
||||
is_negative=(*str++=='-');
|
||||
if(!*str)
|
||||
return nan("");
|
||||
if(str[0]=='0' && str[1]=='x')
|
||||
ret_num=hex_to_double(str+2);
|
||||
else if(str[0]=='0' && str[1]=='o')
|
||||
ret_num=oct_to_double(str+2);
|
||||
else
|
||||
ret_num=dec_to_double(str);
|
||||
return is_negative?-ret_num:ret_num;
|
||||
}
|
||||
|
||||
/*
|
||||
show raw string
|
||||
*/
|
||||
void raw_string(const std::string& str)
|
||||
{
|
||||
for(auto i:str)
|
||||
switch(i)
|
||||
{
|
||||
case '\a': std::cout<<"\\a";break;
|
||||
case '\b': std::cout<<"\\b";break;
|
||||
case '\f': std::cout<<"\\f";break;
|
||||
case '\n': std::cout<<"\\n";break;
|
||||
case '\r': std::cout<<"\\r";break;
|
||||
case '\t': std::cout<<"\\t";break;
|
||||
case '\v': std::cout<<"\\v";break;
|
||||
case '\0': std::cout<<"\\0";break;
|
||||
default: std::cout<<i; break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#include "nasal_lexer.h"
|
||||
#include "nasal_ast.h"
|
||||
#include "nasal_parse.h"
|
||||
#include "nasal_import.h"
|
||||
#include "nasal_codegen.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "nasal_runtime.h"
|
||||
#include "nasal_builtin.h"
|
||||
#include "nasal_codegen.h"
|
||||
#include "nasal_vm.h"
|
||||
|
||||
#endif
|
||||
|
||||
209
nasal_ast.h
209
nasal_ast.h
@@ -1,128 +1,153 @@
|
||||
#ifndef __NASAL_AST_H__
|
||||
#define __NASAL_AST_H__
|
||||
|
||||
enum ast_node
|
||||
{
|
||||
ast_null=0,
|
||||
ast_root,ast_block,
|
||||
ast_file, // ast_file is only used to store which file the subtree is on,codegen will generate nothing
|
||||
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_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_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,
|
||||
ast_def,ast_multi_assign,
|
||||
ast_continue,ast_break,ast_ret
|
||||
};
|
||||
|
||||
const char* ast_name[]=
|
||||
{
|
||||
"null",
|
||||
"root","block",
|
||||
"file",
|
||||
"nil","num","str","id","func","hash","vec",
|
||||
"hashmember","call","callh","callv","callf","subvec",
|
||||
"args","deflt_arg","dyn_id",
|
||||
"and","or",
|
||||
"=","+=","-=","*=","/=","~=",
|
||||
"==","!=",
|
||||
"<","<=",
|
||||
">",">=",
|
||||
"+","-","*","/","~",
|
||||
"unary-","unary!",
|
||||
"trino",
|
||||
"for","forindex","foreach","while","iter",
|
||||
"conditional","if","elsif","else",
|
||||
"multi_id","multi_scalar",
|
||||
"def","multi_assign",
|
||||
"continue","break","return"
|
||||
};
|
||||
|
||||
class nasal_ast
|
||||
{
|
||||
private:
|
||||
int line;
|
||||
int type;
|
||||
int line;
|
||||
int type;
|
||||
double num;
|
||||
std::string str;
|
||||
std::vector<nasal_ast> children;
|
||||
public:
|
||||
nasal_ast();
|
||||
nasal_ast(){line=0;type=ast_null;}
|
||||
nasal_ast(const int l,const int t){line=l;type=t;}
|
||||
nasal_ast(const nasal_ast&);
|
||||
~nasal_ast();
|
||||
nasal_ast(nasal_ast&&);
|
||||
nasal_ast& operator=(const nasal_ast&);
|
||||
void clear();
|
||||
void set_line(int);
|
||||
void set_type(int);
|
||||
void set_str(std::string&);
|
||||
void add_child(nasal_ast);
|
||||
int get_line();
|
||||
int get_type();
|
||||
std::string get_str();
|
||||
std::vector<nasal_ast>& get_children();
|
||||
void print_ast(int);
|
||||
};
|
||||
nasal_ast& operator=(nasal_ast&&);
|
||||
void print_ast(const int);
|
||||
void clear();
|
||||
void add_child(nasal_ast&& ast){children.push_back(std::move(ast));}
|
||||
void add_child(const nasal_ast& ast){children.push_back(ast);}
|
||||
void set_line(const int l){line=l;}
|
||||
void set_type(const int t){type=t;}
|
||||
void set_str(const std::string& s){str=s;}
|
||||
void set_num(const double n){num=n;}
|
||||
int get_line(){return line;}
|
||||
int get_type(){return type;}
|
||||
double get_num() {return num;}
|
||||
std::string& get_str(){return str;}
|
||||
std::vector<nasal_ast>& get_children(){return children;}
|
||||
|
||||
nasal_ast::nasal_ast()
|
||||
{
|
||||
this->line=0;
|
||||
this->type=ast_null;
|
||||
this->str="";
|
||||
return;
|
||||
}
|
||||
int get_line() const {return line;}
|
||||
int get_type() const {return type;}
|
||||
double get_num() const {return num;}
|
||||
const std::string& get_str() const {return str;}
|
||||
const std::vector<nasal_ast>& get_children() const {return children;}
|
||||
};
|
||||
|
||||
nasal_ast::nasal_ast(const nasal_ast& tmp)
|
||||
{
|
||||
this->line=tmp.line;
|
||||
this->type=tmp.type;
|
||||
this->str=tmp.str;
|
||||
this->children=tmp.children;
|
||||
line=tmp.line;
|
||||
type=tmp.type;
|
||||
num =tmp.num;
|
||||
str =tmp.str;
|
||||
children=tmp.children;
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast::~nasal_ast()
|
||||
nasal_ast::nasal_ast(nasal_ast&& tmp)
|
||||
{
|
||||
this->str.clear();
|
||||
this->children.clear();
|
||||
line=tmp.line;
|
||||
type=tmp.type;
|
||||
num =tmp.num;
|
||||
str.swap(tmp.str);
|
||||
children.swap(tmp.children);
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast& nasal_ast::operator=(const nasal_ast& tmp)
|
||||
{
|
||||
this->line=tmp.line;
|
||||
this->type=tmp.type;
|
||||
this->str=tmp.str;
|
||||
this->children=tmp.children;
|
||||
line=tmp.line;
|
||||
type=tmp.type;
|
||||
num=tmp.num;
|
||||
str=tmp.str;
|
||||
children=tmp.children;
|
||||
return *this;
|
||||
}
|
||||
|
||||
nasal_ast& nasal_ast::operator=(nasal_ast&& tmp)
|
||||
{
|
||||
line=tmp.line;
|
||||
type=tmp.type;
|
||||
num=tmp.num;
|
||||
str.swap(tmp.str);
|
||||
children.swap(tmp.children);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void nasal_ast::clear()
|
||||
{
|
||||
this->line=0;
|
||||
this->type=ast_null;
|
||||
this->str="";
|
||||
this->children.clear();
|
||||
line=0;
|
||||
num=0;
|
||||
str="";
|
||||
type=ast_null;
|
||||
children.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_ast::set_line(int l)
|
||||
void nasal_ast::print_ast(const int depth)
|
||||
{
|
||||
this->line=l;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_ast::set_type(int t)
|
||||
{
|
||||
this->type=t;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_ast::set_str(std::string& s)
|
||||
{
|
||||
this->str=s;
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_ast::add_child(nasal_ast ast)
|
||||
{
|
||||
children.push_back(ast);
|
||||
return;
|
||||
}
|
||||
|
||||
int nasal_ast::get_line()
|
||||
{
|
||||
return this->line;
|
||||
}
|
||||
|
||||
int nasal_ast::get_type()
|
||||
{
|
||||
return this->type;
|
||||
}
|
||||
|
||||
std::string nasal_ast::get_str()
|
||||
{
|
||||
return this->str;
|
||||
}
|
||||
|
||||
std::vector<nasal_ast>& nasal_ast::get_children()
|
||||
{
|
||||
return this->children;
|
||||
}
|
||||
|
||||
void nasal_ast::print_ast(int depth)
|
||||
{
|
||||
std::string indentation="";
|
||||
for(int i=0;i<depth;++i) indentation+="| ";
|
||||
indentation+=ast_str(this->type);
|
||||
std::cout<<indentation;
|
||||
if(this->type==ast_number || this->type==ast_string || this->type==ast_identifier || this->type==ast_dynamic_id || this->type==ast_call_hash)
|
||||
std::cout<<":"<<this->str;
|
||||
std::cout<<std::endl;
|
||||
int child_size=this->children.size();
|
||||
for(int i=0;i<child_size;++i)
|
||||
this->children[i].print_ast(depth+1);
|
||||
for(int i=0;i<depth;++i)
|
||||
std::cout<<"| ";
|
||||
std::cout<<ast_name[type];
|
||||
if(type==ast_str || type==ast_id || type==ast_default_arg || type==ast_dynamic_id || type==ast_callh)
|
||||
{
|
||||
std::cout<<":";
|
||||
raw_string(str);
|
||||
}
|
||||
else if(type==ast_num || type==ast_file)
|
||||
std::cout<<":"<<num;
|
||||
std::cout<<'\n';
|
||||
for(auto& i:children)
|
||||
i.print_ast(depth+1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
1197
nasal_builtin.h
1197
nasal_builtin.h
File diff suppressed because it is too large
Load Diff
1423
nasal_codegen.h
1423
nasal_codegen.h
File diff suppressed because it is too large
Load Diff
190
nasal_enum.h
190
nasal_enum.h
@@ -1,190 +0,0 @@
|
||||
#ifndef __NASAL_ENUM_H__
|
||||
#define __NASAL_ENUM_H__
|
||||
|
||||
/* token_type is used in lexer */
|
||||
enum token_type
|
||||
{
|
||||
tok_null=0,
|
||||
tok_number,tok_string,tok_identifier,
|
||||
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_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_greater_than,tok_less_equal,tok_greater_equal
|
||||
};
|
||||
|
||||
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_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_add,ast_sub,ast_mult,ast_div,ast_link,
|
||||
ast_unary_sub,ast_unary_not,
|
||||
ast_trinocular,
|
||||
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,
|
||||
ast_definition,ast_multi_assign,
|
||||
ast_continue,ast_break,ast_return
|
||||
};
|
||||
|
||||
std::string ast_str(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;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
enum parse_error
|
||||
{
|
||||
unknown,
|
||||
error_token,
|
||||
error_expr,
|
||||
lack_left_curve,
|
||||
lack_right_curve,
|
||||
lack_left_bracket,
|
||||
lack_right_bracket,
|
||||
lack_left_brace,
|
||||
lack_right_brace,
|
||||
exprs_lack_rbrace,
|
||||
lack_semi,
|
||||
lack_comma,
|
||||
lack_colon,
|
||||
lack_equal,
|
||||
lack_scalar,
|
||||
lack_identifier,
|
||||
lack_calculation,
|
||||
lack_exprs,
|
||||
lack_token,
|
||||
lack_args,
|
||||
default_arg_not_end,
|
||||
dynamic_id_not_end,
|
||||
name_repetition,
|
||||
definition_use_call,
|
||||
multi_id_use_call,
|
||||
multi_assign_lack_val,
|
||||
lack_definition,
|
||||
lack_loop_iter,
|
||||
lack_func_content
|
||||
};
|
||||
|
||||
void error_info(int line,int error_type,std::string error_str="")
|
||||
{
|
||||
std::string detail;
|
||||
std::cout<<">> [parse] error_info: [line "<<line<<"] ";
|
||||
switch(error_type)
|
||||
{
|
||||
case unknown: std::cout<<"unknown error.\n"; break;
|
||||
case error_token: std::cout<<"error token \""+error_str+"\".\n"; break;
|
||||
case error_expr: std::cout<<"error expression \""+error_str+"\".\n"; break;
|
||||
case lack_left_curve: std::cout<<"expected \"(\".\n"; break;
|
||||
case lack_right_curve: std::cout<<"expected \")\".\n"; break;
|
||||
case lack_left_bracket: std::cout<<"expected \"[\".\n"; break;
|
||||
case lack_right_bracket: std::cout<<"expected \"]\".\n"; break;
|
||||
case lack_left_brace: std::cout<<"expected \"{\".\n"; break;
|
||||
case lack_right_brace: std::cout<<"expected \"}\".\n"; break;
|
||||
case exprs_lack_rbrace: std::cout<<"expected \"}\" with this line\'s \"{\".\n";break;
|
||||
case lack_semi: std::cout<<"expected \";\".\n"; break;
|
||||
case lack_comma: std::cout<<"expected \",\".\n"; break;
|
||||
case lack_colon: std::cout<<"expected \":\".\n"; break;
|
||||
case lack_equal: std::cout<<"expected \"=\".\n"; break;
|
||||
case lack_scalar: std::cout<<"expected scalar here.\n"; break;
|
||||
case lack_identifier: std::cout<<"expected identifier here.\n"; break;
|
||||
case lack_calculation: std::cout<<"expected arithmetic-expression here.\n"; break;
|
||||
case lack_exprs: std::cout<<"expected expression block here.\n"; break;
|
||||
case lack_token: std::cout<<"expected \""+error_str+"\" here.\n"; break;
|
||||
case lack_args: std::cout<<"expected arguments here.\n"; break;
|
||||
case default_arg_not_end: std::cout<<"default argument missing for parameter of "+error_str+".\n";break;
|
||||
case dynamic_id_not_end: std::cout<<"dynamic id must be the end of "+error_str+".\n";break;
|
||||
case name_repetition: std::cout<<"this identifier name has existed.\n";break;
|
||||
case definition_use_call: std::cout<<"should not use call_scalar in definition progress.\n";break;
|
||||
case multi_id_use_call: std::cout<<"should not use call_scalar in multi_id progress.\n";break;
|
||||
case multi_assign_lack_val:std::cout<<"multi-assignment lacks value list.\n";break;
|
||||
case lack_definition: std::cout<<"expected a definition expression here.\n";break;
|
||||
case lack_loop_iter: std::cout<<"expected an iterator to loop through.\n";break;
|
||||
case lack_func_content: std::cout<<"expected arguments or expression block here.\n";break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
enum runtime_scalar_type
|
||||
{
|
||||
vm_nil=0,
|
||||
vm_number,
|
||||
vm_string,
|
||||
vm_closure,
|
||||
vm_function,
|
||||
vm_vector,
|
||||
vm_hash
|
||||
};
|
||||
|
||||
#endif
|
||||
1946
nasal_gc.h
1946
nasal_gc.h
File diff suppressed because it is too large
Load Diff
150
nasal_import.h
150
nasal_import.h
@@ -4,56 +4,37 @@
|
||||
class nasal_import
|
||||
{
|
||||
private:
|
||||
nasal_resource import_src;
|
||||
nasal_lexer import_lex;
|
||||
nasal_parse import_par;
|
||||
nasal_ast import_ast;
|
||||
int error;
|
||||
nasal_lexer import_lex;
|
||||
nasal_parse import_par;
|
||||
nasal_ast import_ast;
|
||||
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&);
|
||||
void die(const std::string&,const char*);
|
||||
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 load(nasal_ast&);
|
||||
nasal_ast load(nasal_ast&,uint16_t);
|
||||
public:
|
||||
nasal_import();
|
||||
int get_error();
|
||||
void preprocessing(nasal_ast&);
|
||||
nasal_ast& get_root();
|
||||
const int get_error(){return error;}
|
||||
void link(nasal_ast&,const std::string&);
|
||||
const nasal_ast&
|
||||
get_root(){return import_ast;}
|
||||
const std::vector<std::string>&
|
||||
get_file(){return filename_table;}
|
||||
};
|
||||
|
||||
nasal_import::nasal_import()
|
||||
{
|
||||
import_src.clear();
|
||||
import_lex.clear();
|
||||
import_par.clear();
|
||||
import_ast.clear();
|
||||
filename_table.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_import::die(std::string filename,std::string error_stage)
|
||||
void nasal_import::die(const std::string& filename,const char* error_stage)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [import] in <\""<<filename<<"\">: error(s) occurred in "<<error_stage<<"."<<std::endl;
|
||||
std::cout<<"[import] in <\""<<filename<<"\">: error(s) occurred in "<<error_stage<<".\n";
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_import::init()
|
||||
{
|
||||
import_src.clear();
|
||||
import_lex.clear();
|
||||
import_par.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
bool nasal_import::check_import(nasal_ast& node)
|
||||
bool nasal_import::check_import(const nasal_ast& node)
|
||||
{
|
||||
/*
|
||||
only this kind of node can be recognized as 'import':
|
||||
|
||||
only this kind of node can be recognized as 'import':
|
||||
call
|
||||
id:import
|
||||
call_func
|
||||
@@ -61,124 +42,93 @@ bool nasal_import::check_import(nasal_ast& node)
|
||||
*/
|
||||
if(node.get_type()!=ast_call)
|
||||
return false;
|
||||
std::vector<nasal_ast>& ref_vec=node.get_children();
|
||||
const std::vector<nasal_ast>& ref_vec=node.get_children();
|
||||
if(ref_vec.size()!=2)
|
||||
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;
|
||||
}
|
||||
|
||||
bool nasal_import::check_exist(std::string filename)
|
||||
bool nasal_import::check_exist(const std::string& file)
|
||||
{
|
||||
// avoid importing the same file
|
||||
int size=filename_table.size();
|
||||
for(int i=0;i<size;++i)
|
||||
if(filename==filename_table[i])
|
||||
for(auto& fname:filename_table)
|
||||
if(file==fname)
|
||||
return true;
|
||||
filename_table.push_back(filename);
|
||||
filename_table.push_back(file);
|
||||
return false;
|
||||
}
|
||||
|
||||
void nasal_import::linker(nasal_ast& root,nasal_ast& add_root)
|
||||
void nasal_import::linker(nasal_ast& root,nasal_ast&& add_root)
|
||||
{
|
||||
// add children of add_root to the back of root
|
||||
std::vector<nasal_ast>& ref_vec=add_root.get_children();
|
||||
int size=ref_vec.size();
|
||||
for(int i=0;i<size;++i)
|
||||
root.add_child(ref_vec[i]);
|
||||
for(auto& i:add_root.get_children())
|
||||
root.add_child(std::move(i));
|
||||
return;
|
||||
}
|
||||
|
||||
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))
|
||||
return tmp;
|
||||
|
||||
// start importing...
|
||||
if(!import_src.input_file(filename))
|
||||
{
|
||||
this->die(filename,"resource");
|
||||
return tmp;
|
||||
}
|
||||
import_lex.scanner(import_src.get_file());
|
||||
import_lex.openfile(filename);
|
||||
import_lex.scanner();
|
||||
if(import_lex.get_error())
|
||||
{
|
||||
this->die(filename,"lexer");
|
||||
die(filename,"lexer");
|
||||
return tmp;
|
||||
}
|
||||
import_par.set_toklist(import_lex.get_token_list());
|
||||
import_par.main_process();
|
||||
import_par.main_process(import_lex.get_token_list());
|
||||
if(import_par.get_error())
|
||||
{
|
||||
this->die(filename,"parser");
|
||||
die(filename,"parser");
|
||||
return tmp;
|
||||
}
|
||||
tmp=import_par.get_root();
|
||||
|
||||
tmp=std::move(import_par.get_root());
|
||||
// check if tmp has 'import'
|
||||
return load(tmp);
|
||||
return load(tmp,filename_table.size()-1);
|
||||
}
|
||||
|
||||
nasal_ast nasal_import::load(nasal_ast& root)
|
||||
nasal_ast nasal_import::load(nasal_ast& root,uint16_t fileindex)
|
||||
{
|
||||
nasal_ast new_root;
|
||||
new_root.set_line(0);
|
||||
new_root.set_type(ast_root);
|
||||
|
||||
std::vector<nasal_ast>& ref_vec=root.get_children();
|
||||
int size=ref_vec.size();
|
||||
for(int i=0;i<size;++i)
|
||||
{
|
||||
if(check_import(ref_vec[i]))
|
||||
{
|
||||
nasal_ast tmp=file_import(ref_vec[i]);
|
||||
// add tmp to the back of new_root
|
||||
linker(new_root,tmp);
|
||||
}
|
||||
}
|
||||
nasal_ast new_root(0,ast_root);
|
||||
for(auto& i:root.get_children())
|
||||
if(check_import(i))
|
||||
linker(new_root,file_import(i));
|
||||
// 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?
|
||||
nasal_ast file_head(0,ast_file);
|
||||
file_head.set_num(fileindex);
|
||||
new_root.add_child(std::move(file_head));
|
||||
linker(new_root,std::move(root));
|
||||
return new_root;
|
||||
}
|
||||
|
||||
void nasal_import::preprocessing(nasal_ast& root)
|
||||
void nasal_import::link(nasal_ast& root,const std::string& self)
|
||||
{
|
||||
// initializing
|
||||
error=0;
|
||||
filename_table.clear();
|
||||
filename_table.push_back(self);
|
||||
import_ast.clear();
|
||||
// scan root and import files,then generate a new ast and return to import_ast
|
||||
import_ast=load(root);
|
||||
// the main file's index is 0
|
||||
import_ast=load(root,0);
|
||||
return;
|
||||
}
|
||||
|
||||
nasal_ast& nasal_import::get_root()
|
||||
{
|
||||
return import_ast;
|
||||
}
|
||||
|
||||
int nasal_import::get_error()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif
|
||||
626
nasal_lexer.h
626
nasal_lexer.h
@@ -1,317 +1,320 @@
|
||||
#ifndef __NASAL_LEXER_H__
|
||||
#define __NASAL_LEXER_H__
|
||||
|
||||
#define IS_IDENTIFIER_HEAD(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z'))
|
||||
#define IS_IDENTIFIER_BODY(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||('0'<=c&&c<='9'))
|
||||
#define IS_IDENTIFIER(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z'))
|
||||
#define IS_HEX_NUMBER(c) (('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F'))
|
||||
#define IS_OCT_NUMEBR(c) ('0'<=c&&c<='7')
|
||||
#define IS_DIGIT(c) ('0'<=c&&c<='9')
|
||||
#define IS_STRING_HEAD(c) (c=='\''||c=='\"')
|
||||
#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==':'||\
|
||||
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=='~')
|
||||
#define IS_NOTE_HEAD(c) (c=='#')
|
||||
#define IS_NOTE(c) (c=='#')
|
||||
|
||||
#ifndef TOKEN_TABLE_SIZE
|
||||
#define TOKEN_TABLE_SIZE 45
|
||||
struct token_table
|
||||
enum token_type
|
||||
{
|
||||
std::string str;
|
||||
int tok_type;
|
||||
}tok_tbl[TOKEN_TABLE_SIZE]=
|
||||
{
|
||||
{"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_greater_than },
|
||||
{"<=" ,tok_less_equal },
|
||||
{">=" ,tok_greater_equal},
|
||||
tok_null=0,
|
||||
tok_num,tok_str,tok_id,
|
||||
tok_for,tok_forindex,tok_foreach,tok_while,
|
||||
tok_var,tok_func,tok_break,tok_continue,
|
||||
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_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
|
||||
{
|
||||
const char* str;
|
||||
const 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_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 },
|
||||
{nullptr ,-1 }
|
||||
};
|
||||
#endif
|
||||
|
||||
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;}
|
||||
};
|
||||
|
||||
class nasal_lexer
|
||||
{
|
||||
private:
|
||||
int error;
|
||||
int res_size;
|
||||
int line;
|
||||
int ptr;
|
||||
std::string line_code;
|
||||
std::string res;
|
||||
std::vector<token> token_list;
|
||||
std::string identifier_gen(std::vector<char>&,int&,int&);
|
||||
void generate_number_error(int,std::string);
|
||||
std::string number_gen(std::vector<char>&,int&,int&);
|
||||
std::string string_gen(std::vector<char>&,int&,int&);
|
||||
int get_tok_type(const std::string&);
|
||||
void die(const char*);
|
||||
std::string id_gen();
|
||||
std::string num_gen();
|
||||
std::string str_gen();
|
||||
public:
|
||||
void clear();
|
||||
void scanner(std::vector<char>&);
|
||||
void openfile(const std::string&);
|
||||
void scanner();
|
||||
void print_token();
|
||||
int get_error();
|
||||
std::vector<token>& get_token_list();
|
||||
int get_error(){return error;}
|
||||
std::vector<token>& get_token_list(){return token_list;}
|
||||
};
|
||||
|
||||
void nasal_lexer::clear()
|
||||
void nasal_lexer::openfile(const std::string& filename)
|
||||
{
|
||||
token_list.clear();
|
||||
error=0;
|
||||
res.clear();
|
||||
std::ifstream fin(filename,std::ios::binary);
|
||||
if(fin.fail())
|
||||
{
|
||||
++error;
|
||||
std::cout<<"[lexer] cannot open file <"<<filename<<">.\n";
|
||||
return;
|
||||
}
|
||||
while(!fin.eof())
|
||||
{
|
||||
char c=fin.get();
|
||||
if(fin.eof())
|
||||
break;
|
||||
res+=c;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
std::string nasal_lexer::identifier_gen(std::vector<char>& res,int& ptr,int& line)
|
||||
int nasal_lexer::get_tok_type(const std::string& tk_str)
|
||||
{
|
||||
int res_size=res.size();
|
||||
std::string token_str="";
|
||||
while(ptr<res_size && IS_IDENTIFIER_BODY(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
return token_str;
|
||||
// after running this process, ptr will point to the next token's beginning character
|
||||
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::generate_number_error(int line,std::string token_str)
|
||||
void nasal_lexer::die(const char* error_info)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [lexer] line "<<line<<": \""<<token_str<<"\" is not a correct number.\n";
|
||||
return;
|
||||
}
|
||||
std::string nasal_lexer::number_gen(std::vector<char>& res,int& ptr,int& line)
|
||||
{
|
||||
int res_size=res.size();
|
||||
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')
|
||||
{
|
||||
token_str="0x";
|
||||
ptr+=2;
|
||||
while(ptr<res_size && IS_HEX_NUMBER(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
if(token_str=="0x")
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
return token_str;
|
||||
}
|
||||
// generate oct number
|
||||
else if(res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='o')
|
||||
{
|
||||
token_str="0o";
|
||||
ptr+=2;
|
||||
while(ptr<res_size && IS_OCT_NUMEBR(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
if(token_str=="0o")
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
return token_str;
|
||||
}
|
||||
// generate dec number
|
||||
// dec number -> 0|[1~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
|
||||
if(ptr<res_size && res[ptr]=='0')
|
||||
token_str+=res[ptr++];
|
||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
if(ptr<res_size && res[ptr]=='.')
|
||||
{
|
||||
token_str+=res[ptr++];
|
||||
// "xxxx." is not a correct number
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
// "xxxx." is not a correct number
|
||||
if(token_str.back()=='.')
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
if(ptr<res_size && (res[ptr]=='e' || res[ptr]=='E'))
|
||||
{
|
||||
token_str+=res[ptr++];
|
||||
// "xxxe" is not a correct number
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
if(ptr<res_size && (res[ptr]=='-' || res[ptr]=='+'))
|
||||
token_str+=res[ptr++];
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
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()=='+')
|
||||
{
|
||||
generate_number_error(line,token_str);
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
return token_str;
|
||||
++error;
|
||||
std::cout<<"[lexer] line "<<line<<" column "<<line_code.length()<<": \n"<<line_code<<"\n";
|
||||
for(auto i:line_code)
|
||||
std::cout<<(i=='\t'?'\t':' ');
|
||||
std::cout<<"^"<<error_info<<'\n';
|
||||
return;
|
||||
}
|
||||
|
||||
std::string nasal_lexer::string_gen(std::vector<char>& res,int& ptr,int& line)
|
||||
std::string nasal_lexer::id_gen()
|
||||
{
|
||||
int res_size=res.size();
|
||||
std::string token_str="";
|
||||
char str_begin=res[ptr++];
|
||||
if(ptr>=res_size) return token_str;
|
||||
while(ptr<res_size && res[ptr]!=str_begin)
|
||||
{
|
||||
if(res[ptr]=='\n') ++line;
|
||||
if(res[ptr]=='\\' && ptr+1<res.size())
|
||||
{
|
||||
++ptr;
|
||||
switch(res[ptr])
|
||||
{
|
||||
case 'a':token_str.push_back('\a');break;
|
||||
case 'b':token_str.push_back('\b');break;
|
||||
case 'f':token_str.push_back('\f');break;
|
||||
case 'n':token_str.push_back('\n');break;
|
||||
case 'r':token_str.push_back('\r');break;
|
||||
case 't':token_str.push_back('\t');break;
|
||||
case 'v':token_str.push_back('\v');break;
|
||||
case '?':token_str.push_back('\?');break;
|
||||
case '0':token_str.push_back('\0');break;
|
||||
case '\\':token_str.push_back('\\');break;
|
||||
case '\'':token_str.push_back('\'');break;
|
||||
case '\"':token_str.push_back('\"');break;
|
||||
default: token_str.push_back(res[ptr]);break;
|
||||
}
|
||||
}
|
||||
else
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
}
|
||||
// check if this string ends with a " or '
|
||||
if(ptr>=res_size)
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [lexer] line "<<line<<": get EOF when generating string.\n";
|
||||
}
|
||||
++ptr;
|
||||
return token_str;
|
||||
std::string token_str="";
|
||||
while(ptr<res_size && (IS_IDENTIFIER(res[ptr])||IS_DIGIT(res[ptr])))
|
||||
token_str+=res[ptr++];
|
||||
line_code+=token_str;
|
||||
return token_str;
|
||||
// after running this process, ptr will point to the next token's beginning character
|
||||
}
|
||||
|
||||
void nasal_lexer::scanner(std::vector<char>& res)
|
||||
std::string nasal_lexer::num_gen()
|
||||
{
|
||||
// generate hex number
|
||||
if(ptr+1<res_size && res[ptr]=='0' && res[ptr+1]=='x')
|
||||
{
|
||||
std::string token_str="0x";
|
||||
ptr+=2;
|
||||
while(ptr<res_size && IS_HEX_NUMBER(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
line_code+=token_str;
|
||||
if(token_str.length()<3)// "0x"
|
||||
die("incorrect number.");
|
||||
return token_str;
|
||||
}
|
||||
// generate oct number
|
||||
else if(ptr+1<res_size && res[ptr]=='0' && res[ptr+1]=='o')
|
||||
{
|
||||
std::string token_str="0o";
|
||||
ptr+=2;
|
||||
while(ptr<res_size && IS_OCT_NUMEBR(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
line_code+=token_str;
|
||||
if(token_str.length()<3)// "0o"
|
||||
die("incorrect number.");
|
||||
return token_str;
|
||||
}
|
||||
// generate dec number
|
||||
// dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
|
||||
std::string token_str="";
|
||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
if(ptr<res_size && res[ptr]=='.')
|
||||
{
|
||||
token_str+=res[ptr++];
|
||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||
token_str+=res[ptr++];
|
||||
// "xxxx." is not a correct number
|
||||
if(token_str.back()=='.')
|
||||
{
|
||||
line_code+=token_str;
|
||||
die("incorrect number.");
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
if(ptr<res_size && (res[ptr]=='e' || res[ptr]=='E'))
|
||||
{
|
||||
token_str+=res[ptr++];
|
||||
if(ptr<res_size && (res[ptr]=='-' || res[ptr]=='+'))
|
||||
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("incorrect number.");
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
line_code+=token_str;
|
||||
return token_str;
|
||||
}
|
||||
|
||||
std::string nasal_lexer::str_gen()
|
||||
{
|
||||
std::string token_str="";
|
||||
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')
|
||||
{
|
||||
line_code="";
|
||||
++line;
|
||||
}
|
||||
if(res[ptr]=='\\' && ptr+1<res_size)
|
||||
{
|
||||
line_code+=res[++ptr];
|
||||
switch(res[ptr])
|
||||
{
|
||||
case 'a': token_str.push_back('\a');break;
|
||||
case 'b': token_str.push_back('\b');break;
|
||||
case 'f': token_str.push_back('\f');break;
|
||||
case 'n': token_str.push_back('\n');break;
|
||||
case 'r': token_str.push_back('\r');break;
|
||||
case 't': token_str.push_back('\t');break;
|
||||
case 'v': token_str.push_back('\v');break;
|
||||
case '?': token_str.push_back('\?');break;
|
||||
case '0': token_str.push_back('\0');break;
|
||||
case '\\':token_str.push_back('\\');break;
|
||||
case '\'':token_str.push_back('\'');break;
|
||||
case '\"':token_str.push_back('\"');break;
|
||||
default: token_str.push_back(res[ptr]);break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
token_str+=res[ptr];
|
||||
}
|
||||
// check if this string ends with a " or '
|
||||
if(ptr++>=res_size)
|
||||
die("get EOF when generating string.");
|
||||
if(str_begin=='`' && token_str.length()!=1)
|
||||
die("\'`\' is used for string that includes one character.");
|
||||
return token_str;
|
||||
}
|
||||
|
||||
void nasal_lexer::scanner()
|
||||
{
|
||||
error=0;
|
||||
token_list.clear();
|
||||
int line=1,ptr=0,res_size=res.size();
|
||||
std::string token_str;
|
||||
while(ptr<res_size)
|
||||
{
|
||||
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
|
||||
if(res[ptr]=='\n') ++line;
|
||||
++ptr;
|
||||
}
|
||||
if(ptr>=res_size) break;
|
||||
if(IS_IDENTIFIER_HEAD(res[ptr]))
|
||||
{
|
||||
token_str=identifier_gen(res,ptr,line);
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
new_token.type=0;
|
||||
for(int i=0;i<TOKEN_TABLE_SIZE;++i)
|
||||
if(token_str==tok_tbl[i].str)
|
||||
{
|
||||
new_token.type=tok_tbl[i].tok_type;
|
||||
break;
|
||||
}
|
||||
if(!new_token.type)
|
||||
new_token.type=tok_identifier;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_DIGIT(res[ptr]))
|
||||
{
|
||||
token_str=number_gen(res,ptr,line);
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
new_token.type=tok_number;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_STRING_HEAD(res[ptr]))
|
||||
{
|
||||
token_str=string_gen(res,ptr,line);
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.type=tok_string;
|
||||
new_token.str=token_str;
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_SINGLE_OPRATOR(res[ptr]))
|
||||
{
|
||||
token_str="";
|
||||
token_str+=res[ptr];
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
for(int i=0;i<TOKEN_TABLE_SIZE;++i)
|
||||
if(token_str==tok_tbl[i].str)
|
||||
{
|
||||
new_token.type=tok_tbl[i].tok_type;
|
||||
break;
|
||||
}
|
||||
token_list.push_back(new_token);
|
||||
++ptr;
|
||||
}
|
||||
line=1;
|
||||
ptr=0;
|
||||
line_code="";
|
||||
res_size=res.size();
|
||||
|
||||
std::string token_str;
|
||||
while(ptr<res_size)
|
||||
{
|
||||
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
|
||||
line_code+=res[ptr];
|
||||
if(res[ptr++]=='\n')
|
||||
{
|
||||
++line;
|
||||
line_code="";
|
||||
}
|
||||
}
|
||||
if(ptr>=res_size) break;
|
||||
if(IS_IDENTIFIER(res[ptr]))
|
||||
{
|
||||
token_str=id_gen();
|
||||
token_list.push_back({line,get_tok_type(token_str),token_str});
|
||||
if(!token_list.back().type)
|
||||
token_list.back().type=tok_id;
|
||||
}
|
||||
else if(IS_DIGIT(res[ptr]))
|
||||
token_list.push_back({line,tok_num,num_gen()});
|
||||
else if(IS_STRING(res[ptr]))
|
||||
token_list.push_back({line,tok_str,str_gen()});
|
||||
else if(IS_SINGLE_OPERATOR(res[ptr]))
|
||||
{
|
||||
token_str=res[ptr];
|
||||
line_code+=res[ptr];
|
||||
int type=get_tok_type(token_str);
|
||||
if(!type)
|
||||
die("incorrect operator.");
|
||||
token_list.push_back({line,type,token_str});
|
||||
++ptr;
|
||||
}
|
||||
else if(res[ptr]=='.')
|
||||
{
|
||||
if(ptr+2<res_size && res[ptr+1]=='.' && res[ptr+2]=='.')
|
||||
@@ -324,71 +327,36 @@ void nasal_lexer::scanner(std::vector<char>& res)
|
||||
token_str=".";
|
||||
++ptr;
|
||||
}
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
for(int i=0;i<TOKEN_TABLE_SIZE;++i)
|
||||
if(token_str==tok_tbl[i].str)
|
||||
{
|
||||
new_token.type=tok_tbl[i].tok_type;
|
||||
break;
|
||||
}
|
||||
token_list.push_back(new_token);
|
||||
line_code+=token_str;
|
||||
token_list.push_back({line,get_tok_type(token_str),token_str});
|
||||
}
|
||||
else if(IS_CALC_OPERATOR(res[ptr]))
|
||||
{
|
||||
// get calculation operator
|
||||
token_str="";
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
if(ptr<res.size() && res[ptr]=='=')
|
||||
{
|
||||
token_str+=res[ptr];
|
||||
++ptr;
|
||||
}
|
||||
token new_token;
|
||||
new_token.line=line;
|
||||
new_token.str=token_str;
|
||||
for(int i=0;i<TOKEN_TABLE_SIZE;++i)
|
||||
if(token_str==tok_tbl[i].str)
|
||||
{
|
||||
new_token.type=tok_tbl[i].tok_type;
|
||||
break;
|
||||
}
|
||||
token_list.push_back(new_token);
|
||||
}
|
||||
else if(IS_NOTE_HEAD(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
|
||||
{
|
||||
++error;
|
||||
std::cout<<">> [lexer] line "<<line<<": unknown char "<<(int)res[ptr]<<'.'<<std::endl;
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
return;
|
||||
else if(IS_CALC_OPERATOR(res[ptr]))
|
||||
{
|
||||
// get calculation operator
|
||||
token_str=res[ptr++];
|
||||
if(ptr<res_size && res[ptr]=='=')
|
||||
token_str+=res[ptr++];
|
||||
line_code+=token_str;
|
||||
token_list.push_back({line,get_tok_type(token_str),token_str});
|
||||
}
|
||||
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("unknown character.");
|
||||
}
|
||||
}
|
||||
token_list.push_back({line,tok_eof,""});
|
||||
res.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_lexer::print_token()
|
||||
{
|
||||
int size=token_list.size();
|
||||
for(int i=0;i<size;++i)
|
||||
std::cout<<"("<<token_list[i].line<<" | "<<token_list[i].str<<")\n";
|
||||
for(auto& tok:token_list)
|
||||
std::cout<<"("<<tok.line<<" | "<<tok.str<<")\n";
|
||||
return;
|
||||
}
|
||||
|
||||
int nasal_lexer::get_error()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
std::vector<token>& nasal_lexer::get_token_list()
|
||||
{
|
||||
return token_list;
|
||||
}
|
||||
#endif
|
||||
258
nasal_misc.h
258
nasal_misc.h
@@ -1,258 +0,0 @@
|
||||
#ifndef __NASAL_MISC_H__
|
||||
#define __NASAL_MISC_H__
|
||||
|
||||
/*
|
||||
check_numerable_string:
|
||||
check if a string can be converted to a number
|
||||
|
||||
strings like these below is correct:
|
||||
'0.00012'
|
||||
'12314.234'
|
||||
'1234'
|
||||
'0xdeadbeef'
|
||||
'0xDEADBEEF'
|
||||
'0o71230'
|
||||
'1e23'
|
||||
'1E-123'
|
||||
'1.34E10'
|
||||
*/
|
||||
inline bool check_hex_string(std::string str,int len)
|
||||
{
|
||||
for(int i=2;i<len;++i)
|
||||
if(!(('0'<=str[i] && str[i]<='9') || ('a'<=str[i] && str[i]<='f') || ('A'<=str[i] && str[i]<='F')))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
inline bool check_oct_string(std::string str,int len)
|
||||
{
|
||||
for(int i=2;i<len;++i)
|
||||
if(str[i]<'0' || str[i]>'7')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
inline bool check_dec_string(std::string str,int len)
|
||||
{
|
||||
int i=0;
|
||||
// check integer part
|
||||
while('0'<=str[i] && str[i]<='9' && i<len) ++i;
|
||||
if(i==len) return true;
|
||||
if(str[i]!='e' && str[i]!='E' && str[i]!='.') return false;
|
||||
// check decimal part
|
||||
if(str[i]=='.')
|
||||
{
|
||||
++i;
|
||||
if(i==len) return false;
|
||||
while('0'<=str[i] && str[i]<='9' && i<len) ++i;
|
||||
}
|
||||
if(i==len) return true;
|
||||
if(str[i]!='e' && str[i]!='E') return false;
|
||||
// check scientific notation
|
||||
if(str[i]=='e' || str[i]=='E')
|
||||
{
|
||||
++i;
|
||||
if(i==len) return false;
|
||||
if(str[i]=='-' || str[i]=='+')
|
||||
{
|
||||
++i;
|
||||
if(i==len) return false;
|
||||
}
|
||||
for(;i<len;++i)
|
||||
if(str[i]<'0' || str[i]>'9')
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_numerable_string(std::string str)
|
||||
{
|
||||
int len=str.length();
|
||||
if(!len) return false;
|
||||
if(str[0]=='-' || str[0]=='+')
|
||||
{
|
||||
if(len==1) return false;
|
||||
std::string tmp="";
|
||||
for(int i=1;i<len;++i)
|
||||
tmp+=str[i];
|
||||
str=tmp;
|
||||
--len;
|
||||
}
|
||||
if(len>2 && str[0]=='0' && str[1]=='x')
|
||||
return check_hex_string(str,len);
|
||||
else if(len>2 && str[0]=='0' && str[1]=='o')
|
||||
return check_oct_string(str,len);
|
||||
else if('0'<=str[0] && str[0]<='9')
|
||||
return check_dec_string(str,len);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
trans_string_to_number:
|
||||
convert string to number
|
||||
*/
|
||||
inline double hex_to_double(std::string str,int len)
|
||||
{
|
||||
double ret=0,num_pow=1;
|
||||
for(int i=len-1;i>1;--i)
|
||||
{
|
||||
if('0'<=str[i] && str[i]<='9')
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
else if('a'<=str[i] && str[i]<='f')
|
||||
ret+=num_pow*(str[i]-'a'+10);
|
||||
else if('A'<=str[i] && str[i]<='F')
|
||||
ret+=num_pow*(str[i]-'A'+10);
|
||||
num_pow*=16;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
inline double oct_to_double(std::string str,int len)
|
||||
{
|
||||
double ret=0,num_pow=1;
|
||||
for(int i=len-1;i>1;--i)
|
||||
{
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
num_pow*=8;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
inline double dec_to_double(std::string str,int len)
|
||||
{
|
||||
double ret=0;
|
||||
int i=0;
|
||||
while('0'<=str[i] && str[i]<='9' && i<len)
|
||||
{
|
||||
ret=ret*10+(str[i]-'0');
|
||||
++i;
|
||||
}
|
||||
if(i==len) return ret;
|
||||
if(str[i]=='.')
|
||||
{
|
||||
++i;
|
||||
double num_pow=0.1;
|
||||
while('0'<=str[i] && str[i]<='9' && i<len)
|
||||
{
|
||||
ret+=num_pow*(str[i]-'0');
|
||||
num_pow*=0.1;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if(i==len) return ret;
|
||||
if(str[i]=='e' || str[i]=='E')
|
||||
{
|
||||
++i;
|
||||
bool is_negative=(str[i]=='-');
|
||||
if(str[i]=='-' || str[i]=='+') ++i;
|
||||
double num_pow=0;
|
||||
for(;i<len;++i) num_pow=num_pow*10+(str[i]-'0');
|
||||
num_pow=std::pow(10,is_negative?-num_pow:num_pow);
|
||||
ret*=num_pow;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
double trans_string_to_number(std::string str)
|
||||
{
|
||||
bool is_negative=false;
|
||||
int len=str.length();
|
||||
double ret_num=0;
|
||||
if(!len) return 0;
|
||||
if(str[0]=='-' || str[0]=='+')
|
||||
{
|
||||
is_negative=(str[0]=='-');
|
||||
std::string tmp="";
|
||||
for(int i=1;i<len;++i)
|
||||
tmp.push_back(str[i]);
|
||||
str=tmp;
|
||||
--len;
|
||||
}
|
||||
if(len>2 && str[0]=='0' && str[1]=='x')
|
||||
ret_num=hex_to_double(str,len);
|
||||
else if(len>2 && str[0]=='0' && str[1]=='o')
|
||||
ret_num=oct_to_double(str,len);
|
||||
else if('0'<=str[0] && str[0]<='9')
|
||||
ret_num=dec_to_double(str,len);
|
||||
return is_negative?-ret_num:ret_num;
|
||||
}
|
||||
|
||||
/*
|
||||
trans_number_to_string:
|
||||
convert number to string
|
||||
*/
|
||||
std::string trans_number_to_string(double number)
|
||||
{
|
||||
std::string trans_num_string="";
|
||||
if(number<0)
|
||||
{
|
||||
trans_num_string+='-';
|
||||
number=-number;
|
||||
}
|
||||
if(number==0)
|
||||
return "0";
|
||||
double integer_bit=1;
|
||||
while(number>=integer_bit)
|
||||
integer_bit*=10;
|
||||
integer_bit/=10;
|
||||
if(integer_bit==0.1)
|
||||
trans_num_string+='0';
|
||||
while(integer_bit!=0.1)
|
||||
{
|
||||
trans_num_string+=(char)('0'+(int(number/integer_bit)));
|
||||
number-=(double)(int(number/integer_bit))*integer_bit;
|
||||
integer_bit/=10;
|
||||
}
|
||||
if(number!=0)
|
||||
trans_num_string+='.';
|
||||
while(number!=0)
|
||||
{
|
||||
trans_num_string+=(char)('0'+int(number*10));
|
||||
number*=10;
|
||||
number-=(double)(int(number));
|
||||
}
|
||||
return trans_num_string;
|
||||
}
|
||||
|
||||
/*
|
||||
prt_hex:
|
||||
transform int to hex format and print it out (std::cout)
|
||||
*/
|
||||
void prt_hex(const int ptr)
|
||||
{
|
||||
char hex[9];
|
||||
hex[8]=0;
|
||||
int tmp_plc=ptr;
|
||||
if(tmp_plc<0)
|
||||
{
|
||||
tmp_plc=-tmp_plc;
|
||||
std::cout<<"-0x";
|
||||
}
|
||||
else
|
||||
std::cout<<"0x";
|
||||
/*
|
||||
int: 00000000 00000000 00000000 00000000
|
||||
int: 0x00 00 00 00
|
||||
example:
|
||||
a=0x13 57 9b df
|
||||
a=00010011 01010111 10011011 11011111
|
||||
a & 0x00 00 00 0f:
|
||||
00010011 01010111 10011011 11011111
|
||||
and 00000000 00000000 00000000 00001111
|
||||
---------------------------------------
|
||||
00000000 00000000 00000000 00001111
|
||||
a>>=4:
|
||||
00000001 00110101 01111001 10111101
|
||||
a & 0x00 00 00 0f
|
||||
00000001 00110101 01111001 10111101
|
||||
and 00000000 00000000 00000000 00001111
|
||||
---------------------------------------
|
||||
00000000 00000000 00000000 00001101
|
||||
then convert 0~15 to 0~9 a~f
|
||||
*/
|
||||
for(int j=7;j>=0;--j)
|
||||
{
|
||||
int tmp=(tmp_plc & 0x0000000f);
|
||||
hex[j]=tmp<10? (char)('0'+tmp):(char)('a'+tmp-10);
|
||||
tmp_plc>>=4;
|
||||
}
|
||||
std::cout<<hex;
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
1611
nasal_parse.h
1611
nasal_parse.h
File diff suppressed because it is too large
Load Diff
@@ -1,75 +0,0 @@
|
||||
#ifndef __NASAL_RESOURCE_H__
|
||||
#define __NASAL_RESOURCE_H__
|
||||
|
||||
class nasal_resource
|
||||
{
|
||||
private:
|
||||
std::vector<char> res;
|
||||
public:
|
||||
bool input_file(std::string);
|
||||
void clear();
|
||||
void print_file();
|
||||
std::vector<char>& get_file();
|
||||
};
|
||||
|
||||
bool nasal_resource::input_file(std::string filename)
|
||||
{
|
||||
res.clear();
|
||||
std::ifstream fin(filename,std::ios::binary);
|
||||
if(fin.fail())
|
||||
{
|
||||
std::cout<<">> [resource] cannot open file \""<<filename<<"\".\n";
|
||||
fin.close();
|
||||
return false;
|
||||
}
|
||||
while(!fin.eof())
|
||||
{
|
||||
char c=fin.get();
|
||||
if(fin.eof())
|
||||
break;
|
||||
res.push_back(c);
|
||||
}
|
||||
fin.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void nasal_resource::clear()
|
||||
{
|
||||
res.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
void nasal_resource::print_file()
|
||||
{
|
||||
int size=res.size(),line=1;
|
||||
std::cout<<line<<"\t";
|
||||
std::string unicode_str="";
|
||||
for(int i=0;i<size;++i)
|
||||
{
|
||||
if(res[i]>=0 && unicode_str.length())
|
||||
{
|
||||
std::cout<<unicode_str;
|
||||
unicode_str="";
|
||||
}
|
||||
if(32<=res[i])
|
||||
std::cout<<res[i];
|
||||
else if(res[i]<0)
|
||||
unicode_str+=res[i];
|
||||
else
|
||||
std::cout<<" ";
|
||||
if(res[i]=='\n')
|
||||
{
|
||||
++line;
|
||||
std::cout<<std::endl<<line<<"\t";
|
||||
}
|
||||
}
|
||||
std::cout<<(unicode_str.length()?unicode_str:"")<<'\n';
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<char>& nasal_resource::get_file()
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
1661
nasal_runtime.h
1661
nasal_runtime.h
File diff suppressed because it is too large
Load Diff
1040
nasal_vm.h
Normal file
1040
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 |
157
props.nas
Normal file
157
props.nas
Normal file
@@ -0,0 +1,157 @@
|
||||
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)=='str')
|
||||
{
|
||||
if(val=='true' or val=='false')
|
||||
tmp.type='BOOL';
|
||||
else
|
||||
tmp.type='STRING';
|
||||
}
|
||||
elsif(typeof(val)=='num')
|
||||
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);
|
||||
if(!size(key))
|
||||
{
|
||||
println("{}");
|
||||
return;
|
||||
}
|
||||
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());
|
||||
162
stl/lib.nas
Normal file
162
stl/lib.nas
Normal file
@@ -0,0 +1,162 @@
|
||||
var import=func(filename)
|
||||
{
|
||||
return __builtin_import(filename);
|
||||
}
|
||||
var print=func(elems...)
|
||||
{
|
||||
return __builtin_print(elems);
|
||||
};
|
||||
var println=func(elems...)
|
||||
{
|
||||
__builtin_print(elems);
|
||||
elems=['\n'];
|
||||
return __builtin_print(elems);
|
||||
}
|
||||
var append=func(vec,elems...)
|
||||
{
|
||||
return __builtin_append(vec,elems);
|
||||
}
|
||||
var setsize=func(vec,size)
|
||||
{
|
||||
return __builtin_setsize(vec,size);
|
||||
}
|
||||
var system=func(str)
|
||||
{
|
||||
return __builtin_system(str);
|
||||
}
|
||||
var input=func()
|
||||
{
|
||||
return __builtin_input();
|
||||
}
|
||||
var sleep=func(duration)
|
||||
{
|
||||
return __builtin_sleep(duration);
|
||||
}
|
||||
var split=func(deli,str)
|
||||
{
|
||||
return __builtin_split(deli,str);
|
||||
}
|
||||
var rand=func(seed=nil)
|
||||
{
|
||||
return __builtin_rand(seed);
|
||||
}
|
||||
var id=func(object)
|
||||
{
|
||||
return __builtin_id(object);
|
||||
}
|
||||
var int=func(val)
|
||||
{
|
||||
return __builtin_int(val);
|
||||
}
|
||||
var num=func(val)
|
||||
{
|
||||
return __builtin_num(val);
|
||||
}
|
||||
var pop=func(vec)
|
||||
{
|
||||
return __builtin_pop(vec);
|
||||
}
|
||||
var str=func(num)
|
||||
{
|
||||
return __builtin_str(num);
|
||||
}
|
||||
var size=func(object)
|
||||
{
|
||||
return __builtin_size(object);
|
||||
}
|
||||
var contains=func(hash,key)
|
||||
{
|
||||
return __builtin_contains(hash,key);
|
||||
}
|
||||
var delete=func(hash,key)
|
||||
{
|
||||
return __builtin_delete(hash,key);
|
||||
}
|
||||
var keys=func(hash)
|
||||
{
|
||||
return __builtin_keys(hash);
|
||||
}
|
||||
var time=func(begin_time)
|
||||
{
|
||||
return __builtin_time(begin_time);
|
||||
}
|
||||
var die=func(str)
|
||||
{
|
||||
return __builtin_die(str);
|
||||
}
|
||||
var typeof=func(object)
|
||||
{
|
||||
return __builtin_type(object);
|
||||
}
|
||||
var substr=func(str,begin,len)
|
||||
{
|
||||
return __builtin_substr(str,begin,len);
|
||||
}
|
||||
var streq=func(a,b)
|
||||
{
|
||||
return __builtin_streq(a,b);
|
||||
}
|
||||
var left=func(str,len)
|
||||
{
|
||||
return __builtin_left(str,len);
|
||||
}
|
||||
var right=func(str,len)
|
||||
{
|
||||
return __builtin_right(str,len);
|
||||
}
|
||||
var cmp=func(a,b)
|
||||
{
|
||||
return __builtin_cmp(a,b);
|
||||
}
|
||||
var chr=func(code)
|
||||
{
|
||||
return __builtin_chr(code);
|
||||
}
|
||||
|
||||
var io=
|
||||
{
|
||||
fin: func(filename){return __builtin_fin(filename);},
|
||||
fout:func(filename,str){return __builtin_fout(filename,str);}
|
||||
};
|
||||
|
||||
var bits=
|
||||
{
|
||||
bitxor: func(a,b){return __builtin_xor(a,b); },
|
||||
bitand: func(a,b){return __builtin_and(a,b); },
|
||||
bitor: func(a,b){return __builtin_or(a,b); },
|
||||
bitnand: func(a,b){return __builtin_nand(a,b);},
|
||||
bitnot: func(a) {return __builtin_not(a); }
|
||||
};
|
||||
|
||||
var math=
|
||||
{
|
||||
e: 2.7182818284590452354,
|
||||
pi: 3.14159265358979323846264338327950288,
|
||||
sin: func(x) {return __builtin_sin(x); },
|
||||
cos: func(x) {return __builtin_cos(x); },
|
||||
tan: func(x) {return __builtin_tan(x); },
|
||||
exp: func(x) {return __builtin_exp(x); },
|
||||
ln: func(x) {return __builtin_ln(x); },
|
||||
sqrt: func(x) {return __builtin_sqrt(x); },
|
||||
atan2: func(x,y){return __builtin_atan2(x,y);},
|
||||
inf: 1/0,
|
||||
nan: 0/0,
|
||||
isnan: func(x) {return __builtin_isnan(x); }
|
||||
};
|
||||
|
||||
var D2R=math.pi/180;
|
||||
var FPS2KT=0.5925;
|
||||
var FT2M=0.3048;
|
||||
var GAL2L=3.7854;
|
||||
var IN2M=0.0254;
|
||||
var KG2LB=2.2046;
|
||||
var KT2FPS=1.6878;
|
||||
var KT2MPS=0.5144;
|
||||
var L2GAL=0.2642;
|
||||
var LB2KG=0.4536;
|
||||
var M2FT=3.2808;
|
||||
var M2IN=39.3701;
|
||||
var M2NM=0.00054;
|
||||
var MPS2KT=1.9438;
|
||||
var NM2M=1852;
|
||||
var R2D=180/math.pi;
|
||||
67
stl/list.nas
Normal file
67
stl/list.nas
Normal file
@@ -0,0 +1,67 @@
|
||||
# lib list.nas
|
||||
# valkmjolnir 2021/3/31
|
||||
var list=func()
|
||||
{
|
||||
var (begin,end)=(nil,nil);
|
||||
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;
|
||||
return;
|
||||
},
|
||||
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;
|
||||
return;
|
||||
},
|
||||
pop_back:func()
|
||||
{
|
||||
if(end!=nil)
|
||||
end=end.prev;
|
||||
if(end==nil)
|
||||
begin=nil;
|
||||
else
|
||||
end.next=nil;
|
||||
return;
|
||||
},
|
||||
pop_front:func()
|
||||
{
|
||||
if(begin!=nil)
|
||||
begin=begin.next;
|
||||
if(begin==nil)
|
||||
end=nil;
|
||||
else
|
||||
begin.prev=nil;
|
||||
return;
|
||||
},
|
||||
front:func()
|
||||
{
|
||||
if(begin!=nil)
|
||||
return begin.elem;
|
||||
return nil;
|
||||
},
|
||||
back:func()
|
||||
{
|
||||
if(end!=nil)
|
||||
return end.elem;
|
||||
return nil;
|
||||
},
|
||||
};
|
||||
}
|
||||
46
stl/queue.nas
Normal file
46
stl/queue.nas
Normal file
@@ -0,0 +1,46 @@
|
||||
# lib queue.nas
|
||||
# valkmjolnir 2021/3/31
|
||||
var queue=func()
|
||||
{
|
||||
var (begin,end)=(nil,nil);
|
||||
return
|
||||
{
|
||||
push:func(elem)
|
||||
{
|
||||
var new_node=
|
||||
{
|
||||
elem:elem,
|
||||
next:nil
|
||||
};
|
||||
if(begin==nil)
|
||||
begin=end=new_node;
|
||||
else
|
||||
{
|
||||
end.next=new_node;
|
||||
end=new_node;
|
||||
}
|
||||
return;
|
||||
},
|
||||
pop:func()
|
||||
{
|
||||
if(begin!=nil)
|
||||
begin=begin.next;
|
||||
if(begin==nil)
|
||||
end=nil;
|
||||
},
|
||||
front:func()
|
||||
{
|
||||
if(begin!=nil)
|
||||
return begin.elem;
|
||||
return nil;
|
||||
},
|
||||
clear:func()
|
||||
{
|
||||
begin=end=nil;
|
||||
},
|
||||
empty:func()
|
||||
{
|
||||
return begin==nil;
|
||||
}
|
||||
};
|
||||
}
|
||||
28
stl/result.nas
Normal file
28
stl/result.nas
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
import("lib.nas");
|
||||
var ResultTrait={
|
||||
Ok:func(val){
|
||||
me.ok=val;
|
||||
me.flag=0;
|
||||
return me;
|
||||
},
|
||||
Err:func(info){
|
||||
me.err=info;
|
||||
me.flag=1;
|
||||
return me;
|
||||
},
|
||||
unwrap:func(){
|
||||
if(me.flag)
|
||||
die("error: "~me.err);
|
||||
return me.ok;
|
||||
}
|
||||
};
|
||||
|
||||
var Result=func(){
|
||||
return{
|
||||
ok:nil,
|
||||
err:"",
|
||||
flag:1,
|
||||
parents:[ResultTrait]
|
||||
};
|
||||
};
|
||||
20
stl/sort.nas
Normal file
20
stl/sort.nas
Normal file
@@ -0,0 +1,20 @@
|
||||
# lib sort.nas
|
||||
# valkmjolnir 2021/4/2
|
||||
var sort=func(vec,left,right,cmp=func(a,b){return a<=b;})
|
||||
{
|
||||
if(left>=right) return nil;
|
||||
var (L,R,tmp)=(left,right,vec[left]);
|
||||
while(left<right)
|
||||
{
|
||||
while(left<right and cmp(tmp,vec[right]))
|
||||
right-=1;
|
||||
while(left<right and cmp(vec[left],tmp))
|
||||
left+=1;
|
||||
if(left!=right)
|
||||
(vec[left],vec[right])=(vec[right],vec[left]);
|
||||
}
|
||||
(vec[L],vec[left])=(vec[left],tmp);
|
||||
sort(vec,L,left-1,cmp);
|
||||
sort(vec,left+1,R,cmp);
|
||||
return nil;
|
||||
}
|
||||
36
stl/stack.nas
Normal file
36
stl/stack.nas
Normal file
@@ -0,0 +1,36 @@
|
||||
# lib stack.nas
|
||||
# valkmjolnir 2021/3/31
|
||||
var stack=func()
|
||||
{
|
||||
var next=nil;
|
||||
return
|
||||
{
|
||||
push:func(elem)
|
||||
{
|
||||
next={elem:elem,next:next};
|
||||
return;
|
||||
},
|
||||
pop:func()
|
||||
{
|
||||
var tmp=next;
|
||||
if(tmp!=nil)
|
||||
next=tmp.next;
|
||||
return;
|
||||
},
|
||||
top:func()
|
||||
{
|
||||
var tmp=next;
|
||||
if(tmp!=nil)
|
||||
return tmp.elem;
|
||||
return nil;
|
||||
},
|
||||
clear:func()
|
||||
{
|
||||
next=nil;
|
||||
},
|
||||
empty:func()
|
||||
{
|
||||
return next==nil;
|
||||
}
|
||||
};
|
||||
}
|
||||
335
test/ai.nas
335
test/ai.nas
@@ -1,335 +0,0 @@
|
||||
import("lib.nas");
|
||||
var activate_function=
|
||||
{
|
||||
sigmoid_func:func(x)
|
||||
{
|
||||
return 1.0/(1.0+math.exp(-x));
|
||||
},
|
||||
diffsigmoid_func:func(x)
|
||||
{
|
||||
var t=func(x){return 1.0/(1.0+math.exp(-x));}(x);
|
||||
return t*(1-t);
|
||||
},
|
||||
tanh_func:func(x)
|
||||
{
|
||||
var t1=math.exp(x);
|
||||
var t2=math.exp(-x);
|
||||
return (t1-t2)/(t1+t2);
|
||||
},
|
||||
difftanh_func:func(x)
|
||||
{
|
||||
var t1=math.exp(x);
|
||||
var t2=math.exp(-x);
|
||||
var t=(t1-t2)/(t1+t2);
|
||||
return 1-t*t;
|
||||
},
|
||||
relu_func:func(x)
|
||||
{
|
||||
return x>0? x:0;
|
||||
},
|
||||
diffrelu_func:func(x)
|
||||
{
|
||||
return x>0;
|
||||
},
|
||||
leaky_relu_func:func(k,x)
|
||||
{
|
||||
return x>0? x:k*x;
|
||||
},
|
||||
diffleaky_relu_func:func(k,x)
|
||||
{
|
||||
return x>0? 1:k;
|
||||
}
|
||||
};
|
||||
|
||||
var matrix=
|
||||
{
|
||||
new:func(col,row)
|
||||
{
|
||||
var new_mat=
|
||||
{
|
||||
col:col,
|
||||
row:row,
|
||||
mat:[]
|
||||
};
|
||||
for(var i=0;i<row;i+=1)
|
||||
{
|
||||
append(new_mat.mat,[]);
|
||||
for(var j=0;j<col;j+=1)
|
||||
append(new_mat.mat[i],nil);
|
||||
}
|
||||
return new_mat;
|
||||
},
|
||||
srand:func(x)
|
||||
{
|
||||
rand(x);
|
||||
return nil;
|
||||
},
|
||||
rand_init:func(mat)
|
||||
{
|
||||
for(var i=0;i<mat.row;i+=1)
|
||||
for(var j=0;j<mat.col;j+=1)
|
||||
{
|
||||
if(rand()>0.5)
|
||||
mat.mat[i][j]=-rand();
|
||||
else
|
||||
mat.mat[i][j]=rand();
|
||||
}
|
||||
return;
|
||||
},
|
||||
prt_mat:func(mat)
|
||||
{
|
||||
var prt_s='[\n';
|
||||
foreach(var i;mat.mat)
|
||||
{
|
||||
var s='[';
|
||||
foreach(var j;i)
|
||||
s~=(j~',');
|
||||
s~='],\n';
|
||||
prt_s~=s;
|
||||
}
|
||||
prt_s~=']';
|
||||
print(prt_s);
|
||||
return nil;
|
||||
},
|
||||
mult_mat:func(mat1,mat2)
|
||||
{
|
||||
if(mat1.col!=mat2.row)
|
||||
{
|
||||
die("[error-mult] mat1\'s col does not match mat2\'s row.");
|
||||
return nil;
|
||||
}
|
||||
var new_mat=me.new(mat2.col,mat1.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
{
|
||||
var sum=0;
|
||||
for(var k=0;k<mat1.col;k+=1)
|
||||
sum+=mat1.mat[i][k]*mat2.mat[k][j];
|
||||
new_mat.mat[i][j]=sum;
|
||||
}
|
||||
return new_mat;
|
||||
},
|
||||
add_mat:func(mat1,mat2)
|
||||
{
|
||||
if(mat1.col!=mat2.col or mat1.row!=mat2.row)
|
||||
{
|
||||
die("[error-add] mat1\'s col or row does not match mat2\'s.");
|
||||
return nil;
|
||||
}
|
||||
var new_mat=me.new(mat1.col,mat1.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=mat1.mat[i][j]+mat2.mat[i][j];
|
||||
return new_mat;
|
||||
},
|
||||
sub_mat:func(mat1,mat2)
|
||||
{
|
||||
if(mat1.col!=mat2.col or mat1.row!=mat2.row)
|
||||
{
|
||||
die("[error-sub] mat1\'s col or row does not match mat2\'s.");
|
||||
return nil;
|
||||
}
|
||||
var new_mat=me.new(mat1.col,mat1.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=mat1.mat[i][j]-mat2.mat[i][j];
|
||||
return new_mat;
|
||||
},
|
||||
hadamard:func(mat1,mat2)
|
||||
{
|
||||
if(mat1.col!=mat2.col or mat1.row!=mat2.row)
|
||||
{
|
||||
die("[error-hadamard] mat1\'s col or row does not match mat2\'s.");
|
||||
return nil;
|
||||
}
|
||||
var new_mat=me.new(mat1.col,mat1.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=mat1.mat[i][j]*mat2.mat[i][j];
|
||||
return new_mat;
|
||||
},
|
||||
transpose:func(mat)
|
||||
{
|
||||
var new_mat=me.new(mat.row,mat.col);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=mat.mat[j][i];
|
||||
return new_mat;
|
||||
},
|
||||
sigmoid:func(mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.sigmoid_func(mat.mat[i][j]);
|
||||
return new_mat;
|
||||
},
|
||||
diffsigmoid:func(mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.diffsigmoid_func(mat.mat[i][j]);
|
||||
return new_mat;
|
||||
},
|
||||
tanh:func(mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.tanh_func(mat.mat[i][j]);
|
||||
return new_mat;
|
||||
},
|
||||
difftanh:func(mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.difftanh_func(mat.mat[i][j]);
|
||||
return new_mat;
|
||||
},
|
||||
relu:func(mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.relu_func(mat.mat[i][j]);
|
||||
return new_mat;
|
||||
},
|
||||
diffrelu:func(mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.diffrelu_func(mat.mat[i][j]);
|
||||
return new_mat;
|
||||
},
|
||||
leaky_relu:func(k,mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.leaky_relu_func(k,mat.mat[i][j]);
|
||||
return new_mat;
|
||||
},
|
||||
diffleaky_relu:func(k,mat)
|
||||
{
|
||||
var new_mat=me.new(mat.col,mat.row);
|
||||
for(var i=0;i<new_mat.row;i+=1)
|
||||
for(var j=0;j<new_mat.col;j+=1)
|
||||
new_mat.mat[i][j]=activate_function.diffleaky_relu_func(k,mat.mat[i][j]);
|
||||
return new_mat;
|
||||
}
|
||||
};
|
||||
|
||||
var bp=
|
||||
{
|
||||
inum:2,
|
||||
hnum:4,
|
||||
onum:1,
|
||||
learning_rate:nil,
|
||||
hidden_layer:nil,
|
||||
hidden_res:nil,
|
||||
output_layer:nil,
|
||||
output_res:nil,
|
||||
result:nil,
|
||||
training_set:[],
|
||||
expect_set:[],
|
||||
init:func()
|
||||
{
|
||||
matrix.srand(time(0));
|
||||
me.hidden_layer=matrix.new(me.hnum,me.inum);
|
||||
matrix.rand_init(me.hidden_layer);
|
||||
me.output_layer=matrix.new(me.onum,me.hnum);
|
||||
matrix.rand_init(me.output_layer);
|
||||
return;
|
||||
},
|
||||
set_learning_rate:func(lr)
|
||||
{
|
||||
me.learning_rate=matrix.new(me.onum,1);
|
||||
for(var i=0;i<me.onum;i+=1)
|
||||
me.learning_rate.mat[i][0]=lr;
|
||||
return;
|
||||
},
|
||||
set_training_set:func()
|
||||
{
|
||||
for(var i=0;i<4;i+=1)
|
||||
append(me.training_set,matrix.new(me.inum,1));
|
||||
me.training_set[0].mat[0][0]=0;
|
||||
me.training_set[0].mat[0][1]=0;
|
||||
me.training_set[1].mat[0][0]=0;
|
||||
me.training_set[1].mat[0][1]=1;
|
||||
me.training_set[2].mat[0][0]=1;
|
||||
me.training_set[2].mat[0][1]=0;
|
||||
me.training_set[3].mat[0][0]=1;
|
||||
me.training_set[3].mat[0][1]=1;
|
||||
return;
|
||||
},
|
||||
set_expect_set:func()
|
||||
{
|
||||
for(var i=0;i<4;i+=1)
|
||||
append(me.expect_set,matrix.new(me.onum,1))
|
||||
me.expect_set[0].mat[0][0]=0;
|
||||
me.expect_set[1].mat[0][0]=1;
|
||||
me.expect_set[2].mat[0][0]=1;
|
||||
me.expect_set[3].mat[0][0]=0;
|
||||
return;
|
||||
},
|
||||
forward:func(i)
|
||||
{
|
||||
var tmp=nil;
|
||||
me.hidden_res=matrix.mult_mat(me.training_set[i],me.hidden_layer);
|
||||
tmp=matrix.sigmoid(me.hidden_res);
|
||||
me.output_res=matrix.mult_mat(tmp,me.output_layer);
|
||||
tmp=matrix.sigmoid(me.output_res);
|
||||
me.result=tmp;
|
||||
return;
|
||||
},
|
||||
backward:func(i)
|
||||
{
|
||||
var output_diff=matrix.sub_mat(me.expect_set[i],me.result);
|
||||
output_diff=matrix.hadamard(output_diff,me.learning_rate);
|
||||
output_diff=matrix.hadamard(output_diff,matrix.diffsigmoid(me.output_res));
|
||||
output_diff=matrix.mult_mat(output_diff,matrix.transpose(me.output_layer));
|
||||
matrix.prt_mat(output_diff);
|
||||
var hidden_diff=matrix.mult_mat();
|
||||
matrix.prt_mat(hidden_diff);
|
||||
|
||||
output_layer=matrix.add_mat(output_layer,output_diff);
|
||||
var error=0;
|
||||
foreach(var i;tmp.mat[0])
|
||||
error+=i;
|
||||
error*=0.5;
|
||||
return error;
|
||||
},
|
||||
training_process:func()
|
||||
{
|
||||
var cnt=0;
|
||||
var error=1e8;
|
||||
while(error>0.01)
|
||||
{
|
||||
error=0;
|
||||
for(var i=0;i<4;i+=1)
|
||||
{
|
||||
me.forward(i);
|
||||
error+=me.backward(i);
|
||||
}
|
||||
print(error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
var main=func()
|
||||
{
|
||||
bp.init();
|
||||
bp.set_learning_rate(0.1);
|
||||
bp.set_training_set();
|
||||
bp.set_expect_set();
|
||||
bp.training_process();
|
||||
return nil;
|
||||
}
|
||||
|
||||
# var (a,b,c)=[1,2,3];
|
||||
# (a,b,c)=(b,c,a);
|
||||
# print(a,b,c);
|
||||
main();
|
||||
@@ -4,7 +4,7 @@ var char_ttf=[
|
||||
[" ████╗"," ██╔██║"," ██╔╝██║"," ███████║","██╔═══██║","╚═╝ ╚═╝"],
|
||||
["██████╗ ","██╔══██╗","██████╔╝","██╔══██╗","██████╔╝","╚═════╝ "],
|
||||
[" ██████╗","██╔════╝","██║ ","██║ ","╚██████╗"," ╚═════╝"],
|
||||
["██████╗ ","██╔══██╗","██║ ██║","██║ ██║","██████╔╝","╚═════╝ "],
|
||||
["██████╗ ","██╔══██╗","██║ ██║","██║ ██║","██████╔╝","╚═════╝ "],
|
||||
["███████╗","██╔════╝","█████╗ ","██╔══╝ ","███████╗","╚══════╝"],
|
||||
["███████╗","██╔════╝","█████╗ ","██╔══╝ ","██║ ","╚═╝ "],
|
||||
[" █████╗ ","██╔═══╝ ","██║ ██╗ ","██║ ╚██╗","╚█████╔╝"," ╚════╝ "],
|
||||
@@ -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()
|
||||
@@ -53,9 +53,9 @@ var curve1=func()
|
||||
var shadow=["░","▒","▓","█","▀","▄","▐","▌"];
|
||||
rand(100);
|
||||
var s="";
|
||||
for(var i=0;i<25;i+=1)
|
||||
for(var i=0;i<10;i+=1)
|
||||
{
|
||||
for(var j=0;j<100;j+=1)
|
||||
for(var j=0;j<40;j+=1)
|
||||
s~=shadow[int(8*rand())];
|
||||
s~='\n';
|
||||
}
|
||||
@@ -66,28 +66,15 @@ var curve2=func()
|
||||
var table=["╚","═","╝","╔","║","╗"];
|
||||
rand(100);
|
||||
var s="";
|
||||
for(var i=0;i<25;i+=1)
|
||||
for(var i=0;i<10;i+=1)
|
||||
{
|
||||
for(var j=0;j<100;j+=1)
|
||||
for(var j=0;j<40;j+=1)
|
||||
s~=table[int(6*rand())];
|
||||
s~='\n';
|
||||
}
|
||||
print(s);
|
||||
}
|
||||
var curve3=func()
|
||||
{
|
||||
var block=["░░","▒▒","▓▓","██","▀▀","▄▄","▄▀","▀▄","▐▐","▌▌"];
|
||||
rand(100);
|
||||
var s="";
|
||||
for(var i=0;i<25;i+=1)
|
||||
{
|
||||
for(var j=0;j<50;j+=1)
|
||||
s~=block[int(10*rand())];
|
||||
s~='\n';
|
||||
}
|
||||
print(s);
|
||||
}
|
||||
var curve4=func()
|
||||
{
|
||||
var s=["","","","","",""];
|
||||
var cnt=0;
|
||||
@@ -100,7 +87,7 @@ var curve4=func()
|
||||
{
|
||||
forindex(var i;s)
|
||||
{
|
||||
print(s[i]);
|
||||
println(s[i]);
|
||||
s[i]='';
|
||||
}
|
||||
cnt=0;
|
||||
@@ -108,12 +95,12 @@ var curve4=func()
|
||||
}
|
||||
return;
|
||||
}
|
||||
var curve5=func()
|
||||
var curve4=func()
|
||||
{
|
||||
for(var loop=0;loop<100;loop+=1)
|
||||
var arr=[0,1,2,3,4,5,6,7,8,0,1,2,3,4,5,6,7,8,0,1,2,3,4,5,6,7,8];
|
||||
for(var loop=0;loop<10;loop+=1)
|
||||
{
|
||||
var arr=[0,1,2,3,4,5,6,7,8,0,1,2,3,4,5,6,7,8];
|
||||
for(var i=17;i>=0;i-=1)
|
||||
for(var i=26;i>=0;i-=1)
|
||||
{
|
||||
var rand_index=int(i*rand());
|
||||
(arr[i],arr[rand_index])=(arr[rand_index],arr[i]);
|
||||
@@ -123,13 +110,13 @@ 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();
|
||||
curve4();
|
||||
curve5();
|
||||
curve4();
|
||||
@@ -1,5 +1,10 @@
|
||||
# Road check and auto pilot(??) by ValKmjolnir
|
||||
|
||||
# Road check and auto pilot by ValKmjolnir
|
||||
import("lib.nas");
|
||||
import("props.nas");
|
||||
var dt=0.01;
|
||||
var intergral=0;
|
||||
var derivative=0;
|
||||
var previous_error=0;
|
||||
var position_change = func(position_val,value){
|
||||
if(position_val+value>180)
|
||||
position_val += value-360;
|
||||
@@ -10,12 +15,11 @@ var position_change = func(position_val,value){
|
||||
return position_val;
|
||||
}
|
||||
var road_check_func = func(){
|
||||
|
||||
|
||||
var lat = props.getNode("/position/latitude-deg",1).getValue();
|
||||
var lon = props.getNode("/position/longitude-deg",1).getValue();
|
||||
var position_info = geodinfo(lat,lon);
|
||||
var position_names = position_info[1].names;
|
||||
# the friction_factor of freeway runway and road is 1
|
||||
|
||||
if((position_names[0]=="Freeway") or (position_names[0]=="Road"))
|
||||
{
|
||||
@@ -24,14 +28,14 @@ var road_check_func = func(){
|
||||
var lon_change = 0;
|
||||
var left_range = 0;
|
||||
var right_range = 0;
|
||||
|
||||
|
||||
for(var i=0;i>-0.00005;i-=0.000001)
|
||||
{
|
||||
car_heading = props.getNode("/orientation/heading-deg",1).getValue();
|
||||
lat_change = math.sin(math.pi*car_heading/180);
|
||||
lon_change = -math.cos(math.pi*car_heading/180);
|
||||
lat = props.getNode("/position/latitude-deg",1).getValue()+0.0001*math.cos(math.pi*car_heading/180);
|
||||
lon = props.getNode("/position/longitude-deg",1).getValue()+0.0001*math.sin(math.pi*car_heading/180);
|
||||
lat_change = math.sin(D2R*car_heading);
|
||||
lon_change = -math.cos(D2R*car_heading);
|
||||
lat = props.getNode("/position/latitude-deg",1).getValue()+0.0001*math.cos(D2R*car_heading);
|
||||
lon = props.getNode("/position/longitude-deg",1).getValue()+0.0001*math.sin(D2R*car_heading);
|
||||
var other_position_info = geodinfo(position_change(lat,i*lat_change),position_change(lon,i*lon_change));
|
||||
var other_names = other_position_info[1].names;
|
||||
if((other_names[0]=="Freeway") or (other_names[0]=="Road"))
|
||||
@@ -42,10 +46,10 @@ var road_check_func = func(){
|
||||
for(var i=0;i<0.00005;i+=0.000001)
|
||||
{
|
||||
car_heading = props.getNode("/orientation/heading-deg",1).getValue();
|
||||
lat_change = math.sin(math.pi*car_heading/180);
|
||||
lon_change = -math.cos(math.pi*car_heading/180);
|
||||
lat = props.getNode("/position/latitude-deg",1).getValue()+0.0001*math.cos(math.pi*car_heading/180);
|
||||
lon = props.getNode("/position/longitude-deg",1).getValue()+0.0001*math.sin(math.pi*car_heading/180);
|
||||
lat_change = math.sin(D2R*car_heading);
|
||||
lon_change = -math.cos(D2R*car_heading);
|
||||
lat = props.getNode("/position/latitude-deg",1).getValue()+0.0001*math.cos(D2R*car_heading);
|
||||
lon = props.getNode("/position/longitude-deg",1).getValue()+0.0001*math.sin(D2R*car_heading);
|
||||
var other_position_info = geodinfo(position_change(lat,i*lat_change),position_change(lon,i*lon_change));
|
||||
var other_names = other_position_info[1].names;
|
||||
if((other_names[0]=="Freeway") or (other_names[0]=="Road"))
|
||||
@@ -53,25 +57,26 @@ var road_check_func = func(){
|
||||
else
|
||||
break;
|
||||
}
|
||||
#if(left_range>right_range)
|
||||
#{
|
||||
# setprop("/controls/flight/rudder",-(right_range-left_range)*(right_range-left_range)/10000);
|
||||
# print("right ",right_range);
|
||||
#}
|
||||
#else if(left_range<right_range)
|
||||
#{
|
||||
# setprop("/controls/flight/rudder",(right_range-left_range)*(right_range-left_range)/10000);
|
||||
# print("left ",left_range);
|
||||
#}
|
||||
#else
|
||||
# setprop("/controls/flight/rudder",0);
|
||||
props.getNode("/controls/flight/rudder",1).setValue((right_range-left_range)/200);
|
||||
var error=right_range-left_range;
|
||||
intergral+=error*dt;
|
||||
derivative=(error-previous_error)/dt;
|
||||
var (Kp,Ki,Kd)=(1/900,0.05,0.005);
|
||||
# print("change p ",Kp*error*error,' i ',Ki*intergral,' d ',Kd*derivative);
|
||||
if(error<0)
|
||||
props.getNode("/", 1).setValue("/controls/flight/rudder",-Kp*error*error+Ki*intergral+Kd*derivative);
|
||||
else if(error>0)
|
||||
props.getNode("/", 1).setValue("/controls/flight/rudder",Kp*error*error+Ki*intergral+Kd*derivative);
|
||||
else
|
||||
props.getNode("/", 1).setValue("/controls/flight/rudder",0);
|
||||
previous_error=error;
|
||||
}
|
||||
};
|
||||
var road_check_timer = maketimer(0.1,road_check_func);
|
||||
|
||||
var road_check_timer = maketimer(0.01,road_check_func);
|
||||
var toggle_auto_pilot = func(){
|
||||
if(!road_check_timer.isRunning)
|
||||
{
|
||||
intergral=0;
|
||||
road_check_timer.start();
|
||||
props.getNode("/sim/messages/copilot",1).setValue("ze dong sheng teaan see tong yee tse yung. Auto Sheng Teaan System Activated!");
|
||||
}
|
||||
@@ -80,4 +85,4 @@ var toggle_auto_pilot = func(){
|
||||
road_check_timer.stop();
|
||||
props.getNode("/sim/messages/copilot",1).setValue("ze dong sheng teaan see tong yee guan bee. Auto Sheng Teaan System is off.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
243
test/bf.nas
Normal file
243
test/bf.nas
Normal file
@@ -0,0 +1,243 @@
|
||||
import("lib.nas");
|
||||
|
||||
var mandelbrot=
|
||||
"[A mandelbrot set fractal viewer in brainf*** written by Erik Bosman]
|
||||
+++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++++++++[[
|
||||
>>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-]>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+
|
||||
<<<<<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+[>>>>>>[>>>>>>>[-]>>]<<<<<<<<<[<<<<<<<<<]>>
|
||||
>>>>>[-]+<<<<<<++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<+++++++[-[->>>
|
||||
>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[[-]>>>>>>[>>>>>
|
||||
>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>
|
||||
[>>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<
|
||||
<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>+++++++++++++++[[
|
||||
>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[
|
||||
>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[
|
||||
-<<+>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<
|
||||
<<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<
|
||||
[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>
|
||||
>>>>[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+
|
||||
<<<<<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>
|
||||
>>>>>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<
|
||||
+>>>>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<
|
||||
<]<+<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>
|
||||
>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<
|
||||
<<<]>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<
|
||||
<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->
|
||||
>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<
|
||||
<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++++++++++++++++
|
||||
+++++++>>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>[<<<<<<<+<[-<+>>>>+<<[-]]>[-<<[->+>>>-
|
||||
<<<<]>>>]>>>>>>>>>>>>>[>>[-]>[-]>[-]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>>>>>>[>>>>>
|
||||
[-<<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>[-<<<<<<<<
|
||||
<+>>>>>>>>>]>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>>]+>[-
|
||||
]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>>>>>>>]<<<
|
||||
<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+>>]<
|
||||
<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[->>>>
|
||||
>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-]<->>>
|
||||
[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-<
|
||||
<<<<+>>>>>]<<<<<[->>>>>+<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+>>>>>>>>
|
||||
]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+
|
||||
>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>
|
||||
[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-
|
||||
]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>>
|
||||
[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++
|
||||
+++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-<<<<<<<+
|
||||
>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[
|
||||
-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>>]>[-<<<<<<[->>>>>+<++<<<<]>>>>>[-<
|
||||
<<<<+>>>>>]<->+>]<[->+<]<<<<<[->>>>>+<<<<<]>>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<<
|
||||
[->>>>->>>>>[>>[-<<->>]+<<[->>->[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]
|
||||
+>>>>>>[>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<<<<<<<<<<[<<<<<
|
||||
<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<
|
||||
[<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<
|
||||
<<<+<[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<
|
||||
<<<<<+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<
|
||||
<<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+<]>>>>>>>>]<<<
|
||||
<<<<<+<[>[->>>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>[->>>>+<<<<]>]<[->>>>-<<<<<<<
|
||||
<<<<<<<+>>>>>>>>>>]<]>>[->>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>>+<<<<
|
||||
]<<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>>>>>>>>>]<<<<<<<<<
|
||||
[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<<<<<<
|
||||
+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<<<<<<
|
||||
<<<<<]]>[-]>>[-]>[-]>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<
|
||||
<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[
|
||||
[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+
|
||||
[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>
|
||||
[-<<+>>]<<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<
|
||||
<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[
|
||||
>[-]<->>>[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[
|
||||
>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>
|
||||
>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>[-]>>>>+++++++++++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<
|
||||
<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<
|
||||
<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-
|
||||
<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>
|
||||
>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>>>
|
||||
[-<<<->>>]<<<[->>>+<<<]>>>>>>>>]<<<<<<<<+<[>[->+>[-<-<<<<<<<<<<+>>>>>>>>>>>>[-<<
|
||||
+>>]<]>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<<<]>>[-<+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<]>
|
||||
[-<<+>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>
|
||||
>>>>>>]<<<<<<<<+<[>[->+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>[-<+>]>]<[-<-<<<<<<<<<<+>>>>
|
||||
>>>>>>>]<<]>>>[-<<+>[-<-<<<<<<<<<<+>>>>>>>>>>>]>]<[-<+>]<<<<<<<<<<<<]>>>>>+<<<<<
|
||||
]>>>>>>>>>[>>>[-]>[-]>[-]>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>>>[-<<<<<
|
||||
<+>>>>>>]<<<<<<[->>>>>>+<<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>
|
||||
>]>>[-<<<<<<<[->>>>>+<++<<<<]>>>>>[-<<<<<+>>>>>]<->+>>]<<[->>+<<]<<<<<[->>>>>+<<
|
||||
<<<]+>>>>[-<<<<->>>>]+<<<<[->>>>->>>>>[>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<
|
||||
<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>[-<<->>]+<<[->>->[-<<<+>>>]<
|
||||
<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<
|
||||
<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+
|
||||
<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>[->>>+<<<]>]<[->>>-
|
||||
<<<<<<<<<<<<<+>>>>>>>>>>]<]>>[->>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>+<<<
|
||||
]<<<<<<<<<<<]>>>>>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]]>>>>[-<<<<+>
|
||||
>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<<[->>>-
|
||||
<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[
|
||||
->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>>
|
||||
>>]<<<<[->>>>+>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>[>>>>>>
|
||||
>>>]<<<<<<<<<[>[->>>>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<
|
||||
<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<
|
||||
<<<<]]>>>>>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>[-<<<<+
|
||||
>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<+>>>>>
|
||||
]<<<<<[->>>>>+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>
|
||||
>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>
|
||||
>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[-<<+
|
||||
>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>
|
||||
[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-
|
||||
]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>>
|
||||
[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<
|
||||
<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>
|
||||
>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<+>>>
|
||||
>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+
|
||||
<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>
|
||||
>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<<<<]
|
||||
>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<
|
||||
]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->>>+<
|
||||
<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>
|
||||
>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>->>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>]<<+>>>>[-<<<<
|
||||
->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[-<<<<<<<.>>>>>>>]<<<[-]>[-]>[-]>[-]>[-]>[-]>>>[
|
||||
>[-]>[-]>[-]>[-]>[-]>[-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]>>>>]<<<<<<<<<
|
||||
[<<<<<<<<<]>+++++++++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+>>>>>>>>>+<<<<<<<<
|
||||
<<<<<<[<<<<<<<<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+[-]>>[>>>>>>>>>]<<<<<
|
||||
<<<<[>>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<[<<<<<<<<<]>>>>>>>[-]+>>>]<<<<
|
||||
<<<<<<]]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+>>[>+>>>>[-<<<<->>>>]<<<<[->>>
|
||||
>+<<<<]>>>>>>>>]<<+<<<<<<<[>>>>>[->>+<<]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<
|
||||
<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<<<<<[->>>>>>+<<<<<<]<
|
||||
+<<<<<<<<<]>>>>>>>-<<<<[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>->>[>>
|
||||
>>>[->>+<<]>>>>]<<<<<<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<
|
||||
<<<<[->>>>>>+<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+<<<
|
||||
<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>->>[-<<<<<<<+>>>>>>>]<<<<
|
||||
<<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>[-<
|
||||
<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<<
|
||||
<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<
|
||||
<<[<<<<<<<<<]>>>>[-]<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>-<<<<<[<<<<<<<
|
||||
<<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++[-[->>>>>>>>
|
||||
>+<<<<<<<<<]>>>>>>>>>]>>>>>+>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<<
|
||||
<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+[-]>[>>>>>>>>>]<<<<<<<<<[>>>>>>>>[-<<<<<<<+>>>>>>
|
||||
>]<<<<<<<[->>>>>>>+<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+>>]<<<<<<<<<<]]>>>>>>>>[-<<<<<
|
||||
<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+>[>+>>>>>[-<<<<<->>>>>]<<<<<[->>>>>+<<<<<]>>>>>>
|
||||
>>]<+<<<<<<<<[>>>>>>[->>+<<]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<-
|
||||
>>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<]<+<<<<<<
|
||||
<<<]>>>>>>>>-<<<<<[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>->[>>>
|
||||
>>>[->>+<<]>>>]<<<<<<<<<[>[-]<->>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<
|
||||
<<<<<[->>>>>>>+<<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>
|
||||
+>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<->>>>>>]+<
|
||||
<<<<<[->>>>>>->>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<
|
||||
<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>
|
||||
-<<[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>
|
||||
>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<++++
|
||||
+[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>->>>>>>>>>>>>>>>>>>>>>>>>>>>-<<<<<<[<<<<
|
||||
<<<<<]]>>>]";
|
||||
|
||||
var paper=[];
|
||||
var (ptr,pc)=(0,0);
|
||||
var (code,inum,stack)=(nil,nil,nil);
|
||||
var (add,mov,jt,jf,in,out)=(0,1,2,3,4,5);
|
||||
var func_table=[
|
||||
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);
|
||||
(ptr,code,inum,stack)=(0,[],[],[]);
|
||||
var len=size(program);
|
||||
|
||||
for(var i=0;i<len;i+=1)
|
||||
{
|
||||
var c=chr(program[i]);
|
||||
if(c=='+' or c=='-')
|
||||
{
|
||||
append(code,func_table[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,func_table[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,func_table[in]);
|
||||
append(inum,0);
|
||||
}
|
||||
elsif(c=='.')
|
||||
{
|
||||
append(code,func_table[out]);
|
||||
append(inum,0);
|
||||
}
|
||||
elsif(c=='[')
|
||||
{
|
||||
append(code,func_table[jf]);
|
||||
append(inum,0);
|
||||
append(stack,size(code)-1);
|
||||
}
|
||||
elsif(c==']')
|
||||
{
|
||||
if(!size(stack))
|
||||
die("lack [");
|
||||
var label=pop(stack);
|
||||
append(code,func_table[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)
|
||||
code[pc]();
|
||||
return;
|
||||
}
|
||||
|
||||
bf(mandelbrot);
|
||||
248
test/bfconvertor.nas
Normal file
248
test/bfconvertor.nas
Normal file
@@ -0,0 +1,248 @@
|
||||
import("lib.nas");
|
||||
|
||||
var mandelbrot=
|
||||
"[A mandelbrot set fractal viewer in brainf*** written by Erik Bosman]
|
||||
+++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++++++++[[
|
||||
>>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-]>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+
|
||||
<<<<<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
>+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+[>>>>>>[>>>>>>>[-]>>]<<<<<<<<<[<<<<<<<<<]>>
|
||||
>>>>>[-]+<<<<<<++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<+++++++[-[->>>
|
||||
>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[[-]>>>>>>[>>>>>
|
||||
>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>
|
||||
[>>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<
|
||||
<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>+++++++++++++++[[
|
||||
>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[
|
||||
>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[
|
||||
-<<+>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<
|
||||
<<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<
|
||||
[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>
|
||||
>>>>[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+
|
||||
<<<<<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>
|
||||
>>>>>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<
|
||||
+>>>>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<
|
||||
<]<+<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>
|
||||
>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<
|
||||
<<<]>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<
|
||||
<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->
|
||||
>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<
|
||||
<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++++++++++++++++
|
||||
+++++++>>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>[<<<<<<<+<[-<+>>>>+<<[-]]>[-<<[->+>>>-
|
||||
<<<<]>>>]>>>>>>>>>>>>>[>>[-]>[-]>[-]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>>>>>>[>>>>>
|
||||
[-<<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>[-<<<<<<<<
|
||||
<+>>>>>>>>>]>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>>]+>[-
|
||||
]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>>>>>>>]<<<
|
||||
<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+>>]<
|
||||
<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[->>>>
|
||||
>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-]<->>>
|
||||
[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-<
|
||||
<<<<+>>>>>]<<<<<[->>>>>+<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+>>>>>>>>
|
||||
]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+
|
||||
>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>
|
||||
[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-
|
||||
]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>>
|
||||
[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++
|
||||
+++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-<<<<<<<+
|
||||
>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[
|
||||
-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>>]>[-<<<<<<[->>>>>+<++<<<<]>>>>>[-<
|
||||
<<<<+>>>>>]<->+>]<[->+<]<<<<<[->>>>>+<<<<<]>>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<<
|
||||
[->>>>->>>>>[>>[-<<->>]+<<[->>->[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]
|
||||
+>>>>>>[>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<<<<<<<<<<[<<<<<
|
||||
<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<
|
||||
[<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<
|
||||
<<<+<[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<
|
||||
<<<<<+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<
|
||||
<<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+<]>>>>>>>>]<<<
|
||||
<<<<<+<[>[->>>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>[->>>>+<<<<]>]<[->>>>-<<<<<<<
|
||||
<<<<<<<+>>>>>>>>>>]<]>>[->>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>>+<<<<
|
||||
]<<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>>>>>>>>>]<<<<<<<<<
|
||||
[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<<<<<<
|
||||
+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<<<<<<
|
||||
<<<<<]]>[-]>>[-]>[-]>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<
|
||||
<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[
|
||||
[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+
|
||||
[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>
|
||||
[-<<+>>]<<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<
|
||||
<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[
|
||||
>[-]<->>>[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[
|
||||
>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>
|
||||
>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>[-]>>>>+++++++++++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<
|
||||
<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<
|
||||
<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-
|
||||
<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>
|
||||
>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>>>
|
||||
[-<<<->>>]<<<[->>>+<<<]>>>>>>>>]<<<<<<<<+<[>[->+>[-<-<<<<<<<<<<+>>>>>>>>>>>>[-<<
|
||||
+>>]<]>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<<<]>>[-<+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<]>
|
||||
[-<<+>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>
|
||||
>>>>>>]<<<<<<<<+<[>[->+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>[-<+>]>]<[-<-<<<<<<<<<<+>>>>
|
||||
>>>>>>>]<<]>>>[-<<+>[-<-<<<<<<<<<<+>>>>>>>>>>>]>]<[-<+>]<<<<<<<<<<<<]>>>>>+<<<<<
|
||||
]>>>>>>>>>[>>>[-]>[-]>[-]>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>>>[-<<<<<
|
||||
<+>>>>>>]<<<<<<[->>>>>>+<<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>
|
||||
>]>>[-<<<<<<<[->>>>>+<++<<<<]>>>>>[-<<<<<+>>>>>]<->+>>]<<[->>+<<]<<<<<[->>>>>+<<
|
||||
<<<]+>>>>[-<<<<->>>>]+<<<<[->>>>->>>>>[>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<
|
||||
<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>[-<<->>]+<<[->>->[-<<<+>>>]<
|
||||
<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<
|
||||
<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+
|
||||
<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>[->>>+<<<]>]<[->>>-
|
||||
<<<<<<<<<<<<<+>>>>>>>>>>]<]>>[->>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>+<<<
|
||||
]<<<<<<<<<<<]>>>>>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]]>>>>[-<<<<+>
|
||||
>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<<[->>>-
|
||||
<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[
|
||||
->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>>
|
||||
>>]<<<<[->>>>+>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>[>>>>>>
|
||||
>>>]<<<<<<<<<[>[->>>>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<
|
||||
<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<
|
||||
<<<<]]>>>>>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>[-<<<<+
|
||||
>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<+>>>>>
|
||||
]<<<<<[->>>>>+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>
|
||||
>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>
|
||||
>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[-<<+
|
||||
>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>
|
||||
[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-
|
||||
]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>>
|
||||
[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<
|
||||
<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>
|
||||
>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<+>>>
|
||||
>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+
|
||||
<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>
|
||||
>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>
|
||||
>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<<<<]
|
||||
>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<<
|
||||
]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->>>+<
|
||||
<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>
|
||||
>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>->>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>]<<+>>>>[-<<<<
|
||||
->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[-<<<<<<<.>>>>>>>]<<<[-]>[-]>[-]>[-]>[-]>[-]>>>[
|
||||
>[-]>[-]>[-]>[-]>[-]>[-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]>>>>]<<<<<<<<<
|
||||
[<<<<<<<<<]>+++++++++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+>>>>>>>>>+<<<<<<<<
|
||||
<<<<<<[<<<<<<<<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+[-]>>[>>>>>>>>>]<<<<<
|
||||
<<<<[>>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<[<<<<<<<<<]>>>>>>>[-]+>>>]<<<<
|
||||
<<<<<<]]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+>>[>+>>>>[-<<<<->>>>]<<<<[->>>
|
||||
>+<<<<]>>>>>>>>]<<+<<<<<<<[>>>>>[->>+<<]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<
|
||||
<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<<<<<[->>>>>>+<<<<<<]<
|
||||
+<<<<<<<<<]>>>>>>>-<<<<[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>->>[>>
|
||||
>>>[->>+<<]>>>>]<<<<<<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<
|
||||
<<<<[->>>>>>+<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+<<<
|
||||
<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>->>[-<<<<<<<+>>>>>>>]<<<<
|
||||
<<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>[-<
|
||||
<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<<
|
||||
<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<
|
||||
<<[<<<<<<<<<]>>>>[-]<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>-<<<<<[<<<<<<<
|
||||
<<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++[-[->>>>>>>>
|
||||
>+<<<<<<<<<]>>>>>>>>>]>>>>>+>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<<
|
||||
<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+[-]>[>>>>>>>>>]<<<<<<<<<[>>>>>>>>[-<<<<<<<+>>>>>>
|
||||
>]<<<<<<<[->>>>>>>+<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+>>]<<<<<<<<<<]]>>>>>>>>[-<<<<<
|
||||
<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+>[>+>>>>>[-<<<<<->>>>>]<<<<<[->>>>>+<<<<<]>>>>>>
|
||||
>>]<+<<<<<<<<[>>>>>>[->>+<<]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<-
|
||||
>>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<]<+<<<<<<
|
||||
<<<]>>>>>>>>-<<<<<[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>->[>>>
|
||||
>>>[->>+<<]>>>]<<<<<<<<<[>[-]<->>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<
|
||||
<<<<<[->>>>>>>+<<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>
|
||||
+>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<->>>>>>]+<
|
||||
<<<<<[->>>>>>->>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<<
|
||||
<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>
|
||||
-<<[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>
|
||||
>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<++++
|
||||
+[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>->>>>>>>>>>>>>>>>>>>>>>>>>>>-<<<<<<[<<<<
|
||||
<<<<<]]>>>]";
|
||||
|
||||
var bf=func(program)
|
||||
{
|
||||
var stack=[];
|
||||
var len=size(program);
|
||||
var f="import('lib.nas');\nvar ptr=0;\nvar paper=[];\nsetsize(paper,131072);\n";
|
||||
for(var i=0;i<len;i+=1)
|
||||
{
|
||||
var c=chr(program[i]);
|
||||
if(c=='+' or c=='-')
|
||||
{
|
||||
var cnt=0;
|
||||
for(;i<len;i+=1)
|
||||
{
|
||||
if(chr(program[i])=='+')
|
||||
cnt+=1;
|
||||
elsif(chr(program[i])=='-')
|
||||
cnt-=1;
|
||||
elsif(chr(program[i])!='\n')
|
||||
{
|
||||
i-=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(cnt!=0)
|
||||
for(var j=0;j<size(stack);j+=1)
|
||||
f~='\t';
|
||||
if(cnt>0)
|
||||
f~="paper[ptr]+="~cnt~";\n";
|
||||
elsif(cnt<0)
|
||||
f~="paper[ptr]-="~(-cnt)~";\n";
|
||||
}
|
||||
elsif(c=='<' or c=='>')
|
||||
{
|
||||
var cnt=0;
|
||||
for(;i<len;i+=1)
|
||||
{
|
||||
if(chr(program[i])=='>')
|
||||
cnt+=1;
|
||||
elsif(chr(program[i])=='<')
|
||||
cnt-=1;
|
||||
elsif(chr(program[i])!='\n')
|
||||
{
|
||||
i-=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(cnt!=0)
|
||||
for(var j=0;j<size(stack);j+=1)
|
||||
f~='\t';
|
||||
if(cnt>0)
|
||||
f~="ptr+="~cnt~";\n";
|
||||
elsif(cnt<0)
|
||||
f~="ptr-="~(-cnt)~";\n";
|
||||
}
|
||||
elsif(c==',')
|
||||
{
|
||||
for(var j=0;j<size(stack);j+=1)
|
||||
f~='\t';
|
||||
f~="paper[ptr]=input();\n";
|
||||
}
|
||||
elsif(c=='.')
|
||||
{
|
||||
for(var j=0;j<size(stack);j+=1)
|
||||
f~='\t';
|
||||
f~="print(chr(paper[ptr]));\n";
|
||||
}
|
||||
elsif(c=='[')
|
||||
{
|
||||
for(var j=0;j<size(stack);j+=1)
|
||||
f~='\t';
|
||||
f~="while(paper[ptr])\n";
|
||||
for(var j=0;j<size(stack);j+=1)
|
||||
f~='\t';
|
||||
f~="{\n";
|
||||
append(stack,0);
|
||||
}
|
||||
elsif(c==']')
|
||||
{
|
||||
if(!size(stack))
|
||||
{
|
||||
println("lack [");
|
||||
return;
|
||||
}
|
||||
pop(stack);
|
||||
for(var j=0;j<size(stack);j+=1)
|
||||
f~='\t';
|
||||
f~="}\n";
|
||||
}
|
||||
}
|
||||
if(size(stack))
|
||||
{
|
||||
println("lack ]");
|
||||
return;
|
||||
}
|
||||
io.fout("mandel.nas",f);
|
||||
return;
|
||||
}
|
||||
|
||||
bf(mandelbrot);
|
||||
60
test/bfs.nas
Normal file
60
test/bfs.nas
Normal file
@@ -0,0 +1,60 @@
|
||||
import("stl/lib.nas");
|
||||
import("stl/queue.nas");
|
||||
|
||||
rand(time(0));
|
||||
|
||||
var pixel=[' ','#','.','*'];
|
||||
var map=[];
|
||||
for(var i=0;i<10;i+=1)
|
||||
{
|
||||
append(map,[]);
|
||||
for(var j=0;j<10;j+=1)
|
||||
append(map[i],(rand()>0.7));
|
||||
}
|
||||
|
||||
var prt=func()
|
||||
{
|
||||
var s="";
|
||||
for(var i=0;i<10;i+=1)
|
||||
{
|
||||
for(var j=0;j<10;j+=1)
|
||||
s~=pixel[map[i][j]];
|
||||
s~='\n';
|
||||
}
|
||||
s~='----------\n';
|
||||
print(s);
|
||||
}
|
||||
|
||||
var bfs=func(begin,end)
|
||||
{
|
||||
var move=[[1,0],[0,1],[-1,0],[0,-1]];
|
||||
var que=queue();
|
||||
que.push(begin);
|
||||
map[begin[0]][begin[1]]=2;
|
||||
while(!que.empty())
|
||||
{
|
||||
var vertex=que.front();
|
||||
que.pop();
|
||||
foreach(var i;move)
|
||||
{
|
||||
var x=vertex[0]+i[0];
|
||||
var y=vertex[1]+i[1];
|
||||
if(x==end[0] and y==end[1])
|
||||
{
|
||||
map[x][y]=3;
|
||||
prt();
|
||||
return;
|
||||
}
|
||||
if(0<=x and x<10 and 0<=y and y<10 and map[x][y]==0)
|
||||
{
|
||||
que.push([x,y]);
|
||||
map[x][y]=2;
|
||||
}
|
||||
}
|
||||
prt();
|
||||
}
|
||||
print("cannot reach.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bfs([0,0],[9,9]);
|
||||
1
test/bigloop.nas
Normal file
1
test/bigloop.nas
Normal file
@@ -0,0 +1 @@
|
||||
for(var i=0;i<4e6;i+=1);
|
||||
42
test/bp.nas
42
test/bp.nas
@@ -4,14 +4,13 @@ rand(time(0));
|
||||
|
||||
var new_neuron=func()
|
||||
{
|
||||
var neuron={
|
||||
return {
|
||||
in:0,
|
||||
out:0,
|
||||
w:[],
|
||||
bia:0,
|
||||
diff:0
|
||||
};
|
||||
return neuron;
|
||||
}
|
||||
|
||||
var sigmoid=func(x)
|
||||
@@ -24,12 +23,9 @@ var diffsigmoid=func(x)
|
||||
return x*(1-x);
|
||||
}
|
||||
|
||||
var inum=2;
|
||||
var hnum=4;
|
||||
var onum=1;
|
||||
var lr=0.1;
|
||||
var (inum,hnum,onum,lr)=(2,4,1,0.1);
|
||||
var training_set=[[0,0],[0,1],[1,0],[1,1]];
|
||||
var expect=[[0],[1],[1],[0]];
|
||||
var expect=[0,1,1,0];
|
||||
|
||||
var hidden=[];
|
||||
for(var i=0;i<hnum;i+=1)
|
||||
@@ -89,19 +85,12 @@ var run=func(vec)
|
||||
}
|
||||
var get_error=func(x)
|
||||
{
|
||||
var error=0;
|
||||
var expect_set=expect[x];
|
||||
for(var i=0;i<onum;i+=1)
|
||||
error+=(expect_set[i]-output[i].out)*(expect_set[i]-output[i].out);
|
||||
error*=0.5;
|
||||
return error;
|
||||
return 0.5*(expect[x]-output[0].out)*(expect[x]-output[0].out);
|
||||
}
|
||||
var backward=func(x)
|
||||
{
|
||||
var input=training_set[x];
|
||||
var expect_set=expect[x];
|
||||
for(var i=0;i<onum;i+=1)
|
||||
output[i].diff=(expect_set[i]-output[i].out)*diffsigmoid(output[i].in);
|
||||
output[0].diff=(expect[x]-output[0].out)*diffsigmoid(output[0].in);
|
||||
for(var i=0;i<hnum;i+=1)
|
||||
{
|
||||
hidden[i].diff=0;
|
||||
@@ -124,9 +113,8 @@ var backward=func(x)
|
||||
return;
|
||||
}
|
||||
|
||||
var cnt=0;
|
||||
var error=1e8;
|
||||
while(error>0.01)
|
||||
var (cnt,error)=(0,100);
|
||||
while(error>0.0005)
|
||||
{
|
||||
error=0;
|
||||
for(var i=0;i<4;i+=1)
|
||||
@@ -136,18 +124,10 @@ while(error>0.01)
|
||||
backward(i);
|
||||
}
|
||||
cnt+=1;
|
||||
print('epoch ',cnt,':',error);
|
||||
}
|
||||
print('\afinished.');
|
||||
while(1)
|
||||
print('finished after ',cnt,' epoch.\n');
|
||||
foreach(var v;training_set)
|
||||
{
|
||||
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');
|
||||
}
|
||||
32
test/calc.nas
Normal file
32
test/calc.nas
Normal file
@@ -0,0 +1,32 @@
|
||||
import("lib.nas");
|
||||
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 space=[" "," ","",""," "," "," "," "," "," "];
|
||||
var enter_cnt=func(s)
|
||||
{
|
||||
var (cnt,len,enter)=(0,size(s),'\n'[0]);
|
||||
for(var i=0;i<len;i+=1)
|
||||
cnt+=(s[i]==enter);
|
||||
return cnt;
|
||||
}
|
||||
var semic_cnt=func(s)
|
||||
{
|
||||
var (cnt,len,semi)=(0,size(s),';'[0]);
|
||||
for(var i=0;i<len;i+=1)
|
||||
cnt+=(s[i]==semi);
|
||||
return cnt;
|
||||
}
|
||||
func(){
|
||||
var (bytes,line,semi)=(0,0,0);
|
||||
forindex(var i;filename)
|
||||
{
|
||||
var s=io.fin(filename[i]);
|
||||
bytes+=size(s);
|
||||
var line_cnt=enter_cnt(s);
|
||||
var semi_cnt=semic_cnt(s);
|
||||
println(filename[i],space[i],'| ',line_cnt,' \tline | ',semi_cnt,' \tsemi');
|
||||
line+=line_cnt;
|
||||
semi+=semi_cnt;
|
||||
}
|
||||
println('total: | ',line,' \tline | ',semi,' \tsemi');
|
||||
println('bytes: | ',bytes,' bytes| ',int(bytes/1024),' \tkb');
|
||||
}();
|
||||
@@ -1,30 +0,0 @@
|
||||
id[0] and id[1];
|
||||
1 or 2;
|
||||
"str" ==1;
|
||||
1*1/1+1;
|
||||
2*3*4/1-2+3;
|
||||
1-1+20-2*10;
|
||||
1+s1*(s2+s3[0])-1;
|
||||
var e=1+s1*(s2+s3[0])-1;
|
||||
id;
|
||||
"str";
|
||||
id(id);
|
||||
id("str",1,1);
|
||||
var e=1;
|
||||
var x=10*2-20;
|
||||
var id;
|
||||
var id=[1,2,3,4];
|
||||
var id={id:"str"};
|
||||
id();
|
||||
id.id();
|
||||
id.id.id();
|
||||
id[0].id.id(id,"str",1,2,3,4).id[10];
|
||||
id(0)[1].id;
|
||||
var hash={
|
||||
h:"hello",
|
||||
parent:[id],
|
||||
};
|
||||
function_test([1,2,3,4,55],1,2,3,{str:"str"});
|
||||
var (i,j,k,l,m,n) =[1,2,3,4,5,6];
|
||||
(var i,j,k)=[1,2,3];
|
||||
e=e[1:][0];
|
||||
29
test/choice.nas
Normal file
29
test/choice.nas
Normal file
@@ -0,0 +1,29 @@
|
||||
import("lib.nas");
|
||||
var condition_true=1;
|
||||
var condition_false=0;
|
||||
if(condition_true)
|
||||
{
|
||||
var a=1;
|
||||
}
|
||||
else if(!condition_false)
|
||||
{
|
||||
var b=1;
|
||||
}
|
||||
elsif(!condition_true and condition_false)
|
||||
{
|
||||
print("impossible");
|
||||
}
|
||||
else
|
||||
{
|
||||
var c=1;
|
||||
var d=1;
|
||||
}
|
||||
|
||||
if(condition_true)
|
||||
var a=1;
|
||||
else if(!condition_false)
|
||||
var b=1;
|
||||
elsif(!condition_true and condition_false)
|
||||
print("impossible");
|
||||
else
|
||||
var c=1;
|
||||
@@ -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);
|
||||
}
|
||||
68
test/class.nas
Normal file
68
test/class.nas
Normal file
@@ -0,0 +1,68 @@
|
||||
import("lib.nas");
|
||||
|
||||
var student=func(name,age)
|
||||
{
|
||||
var (n,a)=(name,age);
|
||||
return {
|
||||
print_info:func println(n,' ',a),
|
||||
set_age: func(age) a=age,
|
||||
get_age: func return a,
|
||||
set_name: func(name) n=name,
|
||||
get_name: func return n
|
||||
};
|
||||
}
|
||||
var s=student('valk',24);
|
||||
s.print_info();
|
||||
println(s.get_age(),' ',s.get_name());
|
||||
s.set_age(20);
|
||||
s.set_name('aluo');
|
||||
s.print_info();
|
||||
println(s.get_age(),' ',s.get_name());
|
||||
s.set_age(20);
|
||||
s.set_name('Sidi Liang');
|
||||
s.print_info();
|
||||
println(s.get_age(),' ',s.get_name());
|
||||
# flightgear nasal-console cannot use this kind of object initializing
|
||||
var m=func(){
|
||||
var (_1,_2)=(0,1);
|
||||
return {
|
||||
a:func(){
|
||||
print(_1,' ',_2,'\n');
|
||||
},
|
||||
b:func(x){
|
||||
_1=x;
|
||||
},
|
||||
c:func(x){
|
||||
_2=x;
|
||||
},
|
||||
d:func(x){
|
||||
return func{
|
||||
print(_1,' ',_2,' ',x,'\n');
|
||||
};
|
||||
},
|
||||
g:func(x){
|
||||
var y=x;
|
||||
return func{
|
||||
print(_1,' ',_2,' ',x,' ',y,'\n');
|
||||
}
|
||||
},
|
||||
h:func(){
|
||||
return func(x){
|
||||
_1=x;
|
||||
}
|
||||
}
|
||||
};
|
||||
}();
|
||||
|
||||
m.a(); # 0 1
|
||||
m.b(2048);
|
||||
m.c(1024);
|
||||
var a=m.d(-1);
|
||||
var b=m.g(1);
|
||||
a(); # 2048 1024 -1
|
||||
b(); # 2048 1024 1 1
|
||||
|
||||
m.h()(2147483647);
|
||||
m.a();
|
||||
# flightgear-nasal-console: 2147483647 1024
|
||||
# nasal-interpreter 2048 1024
|
||||
39
test/exception.nas
Normal file
39
test/exception.nas
Normal file
@@ -0,0 +1,39 @@
|
||||
import("lib.nas");
|
||||
|
||||
var ResultTrait={
|
||||
Ok:func(val){
|
||||
me.ok=val;
|
||||
me.flag=0;
|
||||
return me;
|
||||
},
|
||||
Err:func(info){
|
||||
me.err=info;
|
||||
me.flag=1;
|
||||
return me;
|
||||
},
|
||||
unwrap:func(){
|
||||
if(me.flag)
|
||||
die("error: "~me.err);
|
||||
return me.ok;
|
||||
}
|
||||
};
|
||||
|
||||
var Result=func(){
|
||||
return{
|
||||
ok:nil,
|
||||
err:"",
|
||||
flag:1,
|
||||
parents:[ResultTrait]
|
||||
};
|
||||
};
|
||||
|
||||
var a=func(){
|
||||
return Result().Ok("hello world");
|
||||
}
|
||||
|
||||
var b=func(){
|
||||
return Result().Err("unknown");
|
||||
}
|
||||
|
||||
println(a().unwrap());
|
||||
b().unwrap();
|
||||
9
test/fib.nas
Normal file
9
test/fib.nas
Normal file
@@ -0,0 +1,9 @@
|
||||
import("lib.nas");
|
||||
var fib=func(x)
|
||||
{
|
||||
if(x<2) return x;
|
||||
return fib(x-1)+fib(x-2);
|
||||
}
|
||||
for(var i=0;i<31;i+=1)
|
||||
print(fib(i),'\n');
|
||||
|
||||
@@ -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);
|
||||
@@ -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"});
|
||||
91
test/hexdump.nas
Normal file
91
test/hexdump.nas
Normal file
@@ -0,0 +1,91 @@
|
||||
# hexdump.nas by ValKmjolnir
|
||||
# 2021/8/13
|
||||
|
||||
import("lib.nas");
|
||||
|
||||
# init
|
||||
var hex_num=[
|
||||
'0','1','2','3',
|
||||
'4','5','6','7',
|
||||
'8','9','a','b',
|
||||
'c','d','e','f'
|
||||
];
|
||||
var hex=[];
|
||||
foreach(var i;hex_num)
|
||||
foreach(var j;hex_num)
|
||||
append(hex,i~j);
|
||||
|
||||
# read file
|
||||
var s=func()
|
||||
{
|
||||
var filename=[
|
||||
"nasal.h",
|
||||
"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",
|
||||
];
|
||||
var ret="";
|
||||
foreach(var elem;filename)
|
||||
ret~=io.fin(elem);
|
||||
return ret;
|
||||
}();
|
||||
|
||||
# used to change line and control the spaces
|
||||
var cnt=0;
|
||||
|
||||
# used to print hex index
|
||||
var hex_index=[0,0,0,0];
|
||||
|
||||
# print binary in text format
|
||||
var textprint=func(index)
|
||||
{
|
||||
print(' |');
|
||||
for(var i=index-cnt;i<index;i+=1)
|
||||
print((0<=s[i] and s[i]<32)?'.':chr(s[i]));
|
||||
for(var i=cnt;i<16;i+=1)
|
||||
print('.');
|
||||
print('|\n');
|
||||
}
|
||||
|
||||
# print index
|
||||
var indexprint=func(index)
|
||||
{
|
||||
forindex(var i;hex_index)
|
||||
{
|
||||
hex_index[i]=index-int(index/256)*256;
|
||||
index=int(index/256);
|
||||
}
|
||||
for(var i=3;i>=0;i-=1)
|
||||
print(hex[hex_index[i]]);
|
||||
print(' ');
|
||||
return;
|
||||
}
|
||||
|
||||
# main
|
||||
func()
|
||||
{
|
||||
indexprint(0);
|
||||
for(var i=0;i<size(s);i+=1)
|
||||
{
|
||||
if(cnt==16){
|
||||
textprint(i);
|
||||
cnt=0;
|
||||
indexprint(i);
|
||||
}elsif(cnt==8){
|
||||
print(' ');
|
||||
}
|
||||
cnt+=1;
|
||||
print(hex[s[i]],' ');
|
||||
}
|
||||
for(var l=cnt;l<16;l+=1)
|
||||
print(' ');
|
||||
if(cnt<=8)
|
||||
print(' ');
|
||||
textprint(i);
|
||||
}();
|
||||
196
test/json.nas
Normal file
196
test/json.nas
Normal file
@@ -0,0 +1,196 @@
|
||||
#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:[],
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if(me.ptr>=me.size)
|
||||
{
|
||||
me.token.content="";
|
||||
me.token.type="eof";
|
||||
return;
|
||||
}
|
||||
|
||||
if(me.text[me.ptr]=='{')
|
||||
{
|
||||
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]!='\"')
|
||||
{
|
||||
s~=me.text[me.ptr];
|
||||
me.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]=='.'))
|
||||
{
|
||||
s~=me.text[me.ptr];
|
||||
me.ptr+=1;
|
||||
}
|
||||
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")
|
||||
{
|
||||
append(vec,me.token.content);
|
||||
me.next();
|
||||
}
|
||||
}
|
||||
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")
|
||||
{
|
||||
hash[name]=me.token.content;
|
||||
me.next();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
json.parse=func()
|
||||
{
|
||||
me.content={};
|
||||
me.next();
|
||||
me.match("left brace");
|
||||
me.member(me.content);
|
||||
while(me.token.type=="comma")
|
||||
{
|
||||
me.match("comma");
|
||||
me.member(me.content);
|
||||
}
|
||||
me.match("right brace");
|
||||
return;
|
||||
}
|
||||
32
test/leetcode1319.nas
Normal file
32
test/leetcode1319.nas
Normal file
@@ -0,0 +1,32 @@
|
||||
import("lib.nas");
|
||||
# union set
|
||||
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);
|
||||
foreach(var i;connections)
|
||||
if(union_root(i[0],i[1],parent))
|
||||
cnt-=1;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
println(makeConnect(n,input));
|
||||
193
test/lexer.nas
Normal file
193
test/lexer.nas
Normal file
@@ -0,0 +1,193 @@
|
||||
import("lib.nas");
|
||||
|
||||
var lexer=func(file)
|
||||
{
|
||||
var (ptr,token)=(0,[]);
|
||||
var s=io.fin(file);
|
||||
var len=size(s);
|
||||
return
|
||||
{
|
||||
jmp_note:func()
|
||||
{
|
||||
while(ptr<len and chr(s[ptr])!='\n')
|
||||
ptr+=1;
|
||||
ptr+=1;
|
||||
},
|
||||
id_gen:func()
|
||||
{
|
||||
var tmp="";
|
||||
while(ptr<len)
|
||||
{
|
||||
var c=s[ptr];
|
||||
if(('a'[0]<=c and c<='z'[0])
|
||||
or ('A'[0]<=c and c<='Z'[0])
|
||||
or ('0'[0]<=c and c<='9'[0])
|
||||
or c=='_'[0])
|
||||
tmp~=chr(c);
|
||||
else
|
||||
break;
|
||||
ptr+=1;
|
||||
}
|
||||
append(token,tmp);
|
||||
},
|
||||
str_gen:func()
|
||||
{
|
||||
var str="";
|
||||
var mark=chr(s[ptr]);
|
||||
ptr+=1;
|
||||
while(ptr<len and chr(s[ptr])!=mark)
|
||||
{
|
||||
if(chr(s[ptr])=='\\')
|
||||
{
|
||||
ptr+=1;
|
||||
var c=chr(s[ptr]);
|
||||
if (c=='a' ) str~='\a';
|
||||
elsif(c=='b' ) str~='\b';
|
||||
elsif(c=='f' ) str~='\f';
|
||||
elsif(c=='n' ) str~='\n';
|
||||
elsif(c=='r' ) str~='\r';
|
||||
elsif(c=='t' ) str~='\t';
|
||||
elsif(c=='v' ) str~='\v';
|
||||
elsif(c=='?' ) str~='\?';
|
||||
elsif(c=='0' ) str~='\0';
|
||||
elsif(c=='\\') str~='\\';
|
||||
elsif(c=='\'') str~='\'';
|
||||
elsif(c=='\"') str~='\"';
|
||||
else str~=c;
|
||||
}
|
||||
else
|
||||
str~=chr(s[ptr]);
|
||||
ptr+=1;
|
||||
}
|
||||
if(ptr>=len)
|
||||
print("read eof when generating string.\n");
|
||||
ptr+=1;
|
||||
append(token,str);
|
||||
},
|
||||
num_gen:func()
|
||||
{
|
||||
var number=chr(s[ptr]);
|
||||
ptr+=1;
|
||||
if(ptr<len and chr(s[ptr])=='x')
|
||||
{
|
||||
ptr+=1;
|
||||
while(ptr<len and
|
||||
('a'[0]<=s[ptr] and s[ptr]<='f'[0]
|
||||
or '0'[0]<=s[ptr] and s[ptr]<='9'[0]))
|
||||
{
|
||||
number~=chr(s[ptr]);
|
||||
ptr+=1;
|
||||
}
|
||||
append(token,num(number));
|
||||
return;
|
||||
}
|
||||
elsif(ptr<len and chr(s[ptr])=='o')
|
||||
{
|
||||
ptr+=1;
|
||||
while(ptr<len and ('0'[0]<=s[ptr] and s[ptr]<='7'[0]))
|
||||
{
|
||||
number~=chr(s[ptr]);
|
||||
ptr+=1;
|
||||
}
|
||||
append(token,num(number));
|
||||
return;
|
||||
}
|
||||
while(ptr<len and ('0'[0]<=s[ptr] and s[ptr]<='9'[0]))
|
||||
{
|
||||
number~=chr(s[ptr]);
|
||||
ptr+=1;
|
||||
}
|
||||
if(ptr<len and chr(s[ptr])=='.')
|
||||
{
|
||||
number~=chr(s[ptr]);
|
||||
ptr+=1;
|
||||
while(ptr<len and ('0'[0]<=s[ptr] and s[ptr]<='9'[0]))
|
||||
{
|
||||
number~=chr(s[ptr]);
|
||||
ptr+=1;
|
||||
}
|
||||
}
|
||||
if(chr(s[ptr])=='e' or chr(s[ptr])=='E')
|
||||
{
|
||||
number~=chr(s[ptr]);
|
||||
ptr+=1;
|
||||
if(chr(s[ptr])=='-' or chr(s[ptr])=='+')
|
||||
{
|
||||
number~=chr(s[ptr]);
|
||||
ptr+=1;
|
||||
}
|
||||
while(ptr<len and ('0'[0]<=s[ptr] and s[ptr]<='9'[0]))
|
||||
{
|
||||
number~=chr(s[ptr]);
|
||||
ptr+=1;
|
||||
}
|
||||
}
|
||||
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));
|
||||
},
|
||||
opr_gen:func()
|
||||
{
|
||||
var c=chr(s[ptr]);
|
||||
if(c=='+' or c=='-' or c=='~' or c=='/' or c=='*' or c=='>' or c=='<' or c=='!' or c=='=')
|
||||
{
|
||||
var tmp=c;
|
||||
ptr+=1;
|
||||
if(ptr<len and chr(s[ptr])=='=')
|
||||
{
|
||||
tmp~=chr(s[ptr]);
|
||||
ptr+=1;
|
||||
}
|
||||
append(token,tmp);
|
||||
return;
|
||||
}
|
||||
elsif(c=='.')
|
||||
{
|
||||
if(ptr+2<len and chr(s[ptr+1])=='.' and chr(s[ptr+2])=='.')
|
||||
{
|
||||
append(token,"...");
|
||||
ptr+=3;
|
||||
}
|
||||
else
|
||||
{
|
||||
append(token,".");
|
||||
ptr+=1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
elsif(c!=' ' and c!='\t' and c!='\n' and c!='\r' and s[ptr]>0)
|
||||
append(token,c);
|
||||
ptr+=1;
|
||||
return;
|
||||
},
|
||||
main:func()
|
||||
{
|
||||
while(ptr<len)
|
||||
{
|
||||
var c=s[ptr];
|
||||
if(c=='#'[0])
|
||||
me.jmp_note();
|
||||
elsif('a'[0]<=c and c<='z'[0]
|
||||
or 'A'[0]<=c and c<='Z'[0]
|
||||
or c=='_'[0])
|
||||
me.id_gen();
|
||||
elsif(c=='\''[0] or c=='\"'[0])
|
||||
me.str_gen();
|
||||
elsif('0'[0]<=c and c<='9'[0])
|
||||
me.num_gen();
|
||||
else
|
||||
me.opr_gen();
|
||||
}
|
||||
return;
|
||||
},
|
||||
get_token:func(){return token;}
|
||||
};
|
||||
}
|
||||
|
||||
var nasal_lexer=lexer("test/lexer.nas");
|
||||
nasal_lexer.main();
|
||||
var info="";
|
||||
foreach(var tok;nasal_lexer.get_token())
|
||||
info~=tok~' ';
|
||||
println(info);
|
||||
62
test/life.nas
Normal file
62
test/life.nas
Normal file
@@ -0,0 +1,62 @@
|
||||
import("lib.nas");
|
||||
|
||||
var map=nil;
|
||||
|
||||
var check=func(x,y)
|
||||
{
|
||||
if(x>14) x=0;
|
||||
if(y>19) y=0;
|
||||
return map[x][y];
|
||||
}
|
||||
|
||||
var new_map=func()
|
||||
{
|
||||
var tmp=[];
|
||||
setsize(tmp,15);
|
||||
forindex(var i;tmp)
|
||||
{
|
||||
tmp[i]=[];
|
||||
setsize(tmp[i],20);
|
||||
}
|
||||
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<100;r+=1)
|
||||
{
|
||||
prt(map);
|
||||
var tmp=new_map();
|
||||
for(var i=0;i<15;i+=1)
|
||||
for(var j=0;j<20;j+=1)
|
||||
{
|
||||
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;
|
||||
}();
|
||||
@@ -1,38 +1,31 @@
|
||||
while(n==1 )
|
||||
import("lib.nas");
|
||||
for(;;)break;
|
||||
for(;;)
|
||||
{
|
||||
i=i+1;
|
||||
f(i);
|
||||
print("str");
|
||||
var a=1;
|
||||
break;
|
||||
}
|
||||
for(var i=1;;)break;
|
||||
for(var i=1;;i+=1)break;
|
||||
for(var i=1;i<10;i+=1)print(i);
|
||||
|
||||
while(1)break;
|
||||
var j=0;
|
||||
while(j<10)
|
||||
{
|
||||
print(j);
|
||||
j+=1;
|
||||
}
|
||||
|
||||
while(n==1 and "str"==str)
|
||||
forindex(var j;[0,1,2,3])print(j);
|
||||
forindex(var j;[0,1,2,3])
|
||||
{
|
||||
print("str");
|
||||
var a=j;
|
||||
print(a*a);
|
||||
}
|
||||
|
||||
i+=i1;
|
||||
i+=i.i[0];
|
||||
i=i.i[0].i(0);
|
||||
var hash={
|
||||
f:func {var e=1;return 0;},
|
||||
};
|
||||
for(var i=0;i<1024;i+=1)
|
||||
foreach(var j;[0,1,2,3])print([0,1,2,3][j]);
|
||||
foreach(var j;[0,1,2,3])
|
||||
{
|
||||
print(i);
|
||||
var a=[0,1,2,3][j];
|
||||
print(a*a-1);
|
||||
}
|
||||
for(var i=0;(2*512)>=i;i+=1)
|
||||
{
|
||||
print(i);
|
||||
}
|
||||
foreach(var i;[1+(1+1),2,3,4])
|
||||
{
|
||||
print(i);
|
||||
}
|
||||
forindex(var i=list;[1,2,3,4])
|
||||
{
|
||||
print(i[0]);
|
||||
}
|
||||
while(!id)
|
||||
{
|
||||
print("yes");
|
||||
}
|
||||
27
test/mandelbrot.nas
Normal file
27
test/mandelbrot.nas
Normal file
@@ -0,0 +1,27 @@
|
||||
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)
|
||||
{
|
||||
var y=(yPixel/24)*yDel+yMin;
|
||||
for(var xPixel=0;xPixel<80;xPixel+=1)
|
||||
{
|
||||
var x=(xPixel/80)*xDel+xMin;
|
||||
var pixel=" ";
|
||||
var (x0,y0)=(x,y);
|
||||
for(var iter=0;iter<80;iter+=1)
|
||||
{
|
||||
var x1=(x0*x0)-(y0*y0)+x;
|
||||
var y1=2*x0*y0+y;
|
||||
(x0,y0)=(x1,y1);
|
||||
if((x0*x0)+(y0*y0)>4)
|
||||
{
|
||||
pixel=chr(" .:;+=xX$&"[iter/8]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
line~=pixel;
|
||||
}
|
||||
line~='\n';
|
||||
}
|
||||
print(line);
|
||||
@@ -1,10 +1,10 @@
|
||||
#//This is written for Nasal Intepreter
|
||||
#//Sidi Liang
|
||||
|
||||
# This is written for Nasal Intepreter
|
||||
# Sidi Liang
|
||||
import("lib.nas");
|
||||
var w = 1;
|
||||
var x = "hello";
|
||||
var f = func(){
|
||||
print("f is called");
|
||||
println("f is called");
|
||||
}
|
||||
var f2 = func(){
|
||||
return 2;
|
||||
@@ -28,71 +28,27 @@ var z1 = {
|
||||
hashh:z
|
||||
};
|
||||
var y2 = [w, x, y, z1];
|
||||
|
||||
var z2 = {
|
||||
hashh: z1,
|
||||
listt2: y2,
|
||||
};
|
||||
|
||||
print(w);#//1
|
||||
print("\n");
|
||||
print(x);#//hello
|
||||
print("\n");
|
||||
print(y);#//Empty
|
||||
print("\n");
|
||||
print(z);#//Empty
|
||||
print("\n");
|
||||
print(z1);#//Empty
|
||||
print("\n");
|
||||
print(y2);#//Empty
|
||||
print("\n");
|
||||
print(y[0]);#//1
|
||||
print("\n");
|
||||
print(y1[2][1]);#//hello
|
||||
print("\n");
|
||||
print(z.numb);#//1
|
||||
print("\n");
|
||||
print(z.listt[2][1]);#//hello
|
||||
print("\n");
|
||||
print(z1.hashh.listt[2][1]);#//hello
|
||||
print("\n");
|
||||
print(y2[3].hashh.listt[2][1]);#//hello
|
||||
print("\n");
|
||||
print(f);#//Empty
|
||||
print("\n");
|
||||
println(w);#//1
|
||||
println(x);#//hello
|
||||
println(y);#//[1,hello]
|
||||
println(z);#//{...}
|
||||
println(z1);#//{...}
|
||||
println(y2);#//[...]
|
||||
println(y[0]);#//1
|
||||
println(y1[2][1]);#//hello
|
||||
println(z.numb);#//1
|
||||
println(z.listt[2][1]);#//hello
|
||||
println(z1.hashh.listt[2][1]);#//hello
|
||||
println(y2[3].hashh.listt[2][1]);#//hello
|
||||
println(f);#//func(...){...}
|
||||
f();#//f is called
|
||||
print("\n");
|
||||
print(z.funcc);#//Empty
|
||||
print("\n");
|
||||
println(z.funcc);#//func(...){...}
|
||||
z.funcc();#//f is called
|
||||
print("\n");
|
||||
print(z.funcccall);#//Empty
|
||||
print("\n");
|
||||
z.funcccall();#//f is called
|
||||
print("\n");
|
||||
println(z.funcccall);#//func(...){...}
|
||||
z2.listt2[3].hashh.funcc();#//f is called
|
||||
print("\n");
|
||||
print(y1[f2()][w]);#//hello
|
||||
print("\n");
|
||||
#//print(z.f3()); Error
|
||||
call(f);#//f is called
|
||||
print("\n");
|
||||
call(z.funcc);#//f is called
|
||||
print("\n");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
println(y1[f2()][w]);#//hello
|
||||
9
test/pi.nas
Normal file
9
test/pi.nas
Normal file
@@ -0,0 +1,9 @@
|
||||
import("lib.nas");
|
||||
|
||||
var (t,res)=(1,0);
|
||||
for(var m=1;m<4e6;m+=2)
|
||||
{
|
||||
res+=t*1/m;
|
||||
t=-t;
|
||||
}
|
||||
println(res*4);
|
||||
40
test/prime.nas
Normal file
40
test/prime.nas
Normal file
@@ -0,0 +1,40 @@
|
||||
import("lib.nas");
|
||||
|
||||
var is_prime=func(x){
|
||||
for(var i=2;i<x;i+=1)
|
||||
if(x/i==int(x/i))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
var is_prime_sqrt=func(x){
|
||||
for(var i=2;i<=math.sqrt(x);i+=1)
|
||||
if(x/i==int(x/i))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
var primes=[];
|
||||
var filter=func(x){
|
||||
foreach(var i;primes){
|
||||
if(x/i==int(x/i))
|
||||
return 0;
|
||||
if(x>=i){
|
||||
for(var j=i+1;j<=math.sqrt(x);j+=1)
|
||||
if(x/j==int(x/j))
|
||||
return 0;
|
||||
append(primes,x);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
append(primes,x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
func(){
|
||||
var cnt=0;
|
||||
for(var i=2;i<50000;i+=1)
|
||||
if(filter(i))
|
||||
cnt+=1;
|
||||
println(cnt);
|
||||
}();
|
||||
577
test/props.nas
Normal file
577
test/props.nas
Normal file
@@ -0,0 +1,577 @@
|
||||
##
|
||||
# Node class definition. The class methods simply wrap the
|
||||
# low level extension functions which work on a "ghost" handle to a
|
||||
# SGPropertyNode object stored in the _g field.
|
||||
#
|
||||
# Not all of the features of SGPropertyNode are supported. There is
|
||||
# no support for ties, obviously, as that wouldn't make much sense
|
||||
# from a Nasal context. The various get/set methods work only on the
|
||||
# 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)),
|
||||
getChild : func wrap(_getChild(me._g, arg)),
|
||||
getChildren : func wrap(_getChildren(me._g, arg)),
|
||||
setChildren : func wrap(_setChildren(me._g, arg)),
|
||||
addChild : func wrap(_addChild(me._g, arg)),
|
||||
addChildren : func wrap(_addChildren(me._g, arg)),
|
||||
removeChild : func wrap(_removeChild(me._g, arg)),
|
||||
removeChildren : func wrap(_removeChildren(me._g, arg)),
|
||||
removeAllChildren: func wrap(_removeAllChildren(me._g, arg)),
|
||||
getAliasTarget : func wrap(_getAliasTarget(me._g, arg)),
|
||||
|
||||
getName : func _getName(me._g, arg),
|
||||
getIndex : func _getIndex(me._g, arg),
|
||||
getType : func _getType(me._g, arg),
|
||||
getAttribute : func _getAttribute(me._g, arg),
|
||||
setAttribute : func _setAttribute(me._g, arg),
|
||||
getValue : func _getValue(me._g, arg),
|
||||
setValue : func _setValue(me._g, arg),
|
||||
setValues : func _setValues(me._g, arg),
|
||||
setIntValue : func _setIntValue(me._g, arg),
|
||||
setBoolValue : func _setBoolValue(me._g, arg),
|
||||
setDoubleValue : func _setDoubleValue(me._g, arg),
|
||||
unalias : func _unalias(me._g, arg),
|
||||
alias : func(n) _alias(me._g, [isa(n, Node) ? n._g : n]),
|
||||
equals : func(n) _equals(me._g, [isa(n, Node) ? n._g : n]),
|
||||
clearValue : func _alias(me._g, [_globals()]) and me.unalias(),
|
||||
|
||||
getPath : func {
|
||||
var (name, index, parent) = (me.getName(), me.getIndex(), me.getParent());
|
||||
if(index != 0) { name ~= "[" ~ index ~ "]"; }
|
||||
if(parent != nil) { name = parent.getPath() ~ "/" ~ name; }
|
||||
return name;
|
||||
},
|
||||
|
||||
getBoolValue : func {
|
||||
var val = me.getValue();
|
||||
var mytype = me.getType();
|
||||
if((mytype == "STRING" or mytype == "UNSPECIFIED") and val == "false") return 0;
|
||||
return !!val;
|
||||
},
|
||||
|
||||
remove : func {
|
||||
if((var p = me.getParent()) == nil) return nil;
|
||||
p.removeChild(me.getName(), me.getIndex());
|
||||
},
|
||||
};
|
||||
|
||||
##
|
||||
# Static constructor for a Node object. Accepts a Nasal hash
|
||||
# expression to initialize the object a-la setValues().
|
||||
#
|
||||
Node.new = func(values = nil) {
|
||||
var result = wrapNode(_new());
|
||||
if(typeof(values) == "hash")
|
||||
result.setValues(values);
|
||||
return result;
|
||||
}
|
||||
|
||||
##
|
||||
# Counter piece of setValues(). Returns a hash with all values
|
||||
# in the subtree. Nodes with same name are returned as vector,
|
||||
# where the original node indices are lost. The function should
|
||||
# only be used if all or almost all values are needed, and never
|
||||
# in performance-critical code paths. If it's called on a node
|
||||
# without children, then the result is equivalent to getValue().
|
||||
#
|
||||
Node.getValues = func {
|
||||
var children = me.getChildren();
|
||||
if(!size(children)) return me.getValue();
|
||||
var val = {};
|
||||
var numchld = {};
|
||||
foreach(var c; children) {
|
||||
var name = c.getName();
|
||||
if(contains(numchld, name)) { var nc = numchld[name]; }
|
||||
else {
|
||||
var nc = size(me.getChildren(name));
|
||||
numchld[name] = nc;
|
||||
if(nc > 1 and !contains(val, name)) val[name] = [];
|
||||
}
|
||||
if(nc > 1) append(val[name], c.getValues());
|
||||
else val[name] = c.getValues();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
##
|
||||
# Initializes property if it's still undefined. First argument
|
||||
# is a property name/path. It can also be nil or an empty string,
|
||||
# in which case the node itself gets initialized, rather than one
|
||||
# of its children. Second argument is the default value. The third,
|
||||
# optional argument is a property type (one of "STRING", "DOUBLE",
|
||||
# "INT", or "BOOL"). If it is omitted, then "DOUBLE" is used for
|
||||
# numbers, and STRING for everything else. Returns the property
|
||||
# as props.Node. The fourth optional argument enforces a type if
|
||||
# non-zero.
|
||||
#
|
||||
Node.initNode = func(path = nil, value = 0, type = nil, force = 0) {
|
||||
var prop = me.getNode(path or "", 1);
|
||||
if(prop.getType() != "NONE") value = prop.getValue();
|
||||
if(force) prop.clearValue();
|
||||
if(type == nil) prop.setValue(value);
|
||||
elsif(type == "DOUBLE") prop.setDoubleValue(value);
|
||||
elsif(type == "INT") prop.setIntValue(value);
|
||||
elsif(type == "BOOL") prop.setBoolValue(value);
|
||||
elsif(type == "STRING") prop.setValue("" ~ value);
|
||||
else die("initNode(): unsupported type '" ~ type ~ "'");
|
||||
return prop;
|
||||
}
|
||||
|
||||
##
|
||||
# Useful debugging utility. Recursively dumps the full state of a
|
||||
# Node object to the console. Try binding "props.dump(props.globals)"
|
||||
# to a key for a fun hack.
|
||||
#
|
||||
var dump = func {
|
||||
if(size(arg) == 1) { prefix = ""; node = arg[0]; }
|
||||
else { prefix = arg[0]; node = arg[1]; }
|
||||
|
||||
index = node.getIndex();
|
||||
type = node.getType();
|
||||
name = node.getName();
|
||||
val = node.getValue();
|
||||
|
||||
if(val == nil) { val = "nil"; }
|
||||
name = prefix ~ name;
|
||||
if(index > 0) { name = name ~ "[" ~ index ~ "]"; }
|
||||
print(name, " {", type, "} = ", val);
|
||||
|
||||
# Don't recurse into aliases, lest we get stuck in a loop
|
||||
if(type != "ALIAS") {
|
||||
children = node.getChildren();
|
||||
foreach(c; children) { dump(name ~ "/", c); }
|
||||
}
|
||||
}
|
||||
|
||||
##
|
||||
# Recursively copy property branch from source Node to
|
||||
# destination Node. Doesn't copy aliases. Copies attributes
|
||||
# if optional third argument is set and non-zero.
|
||||
#
|
||||
var copy = func(src, dest, attr = 0) {
|
||||
foreach(var c; src.getChildren()) {
|
||||
var name = c.getName() ~ "[" ~ c.getIndex() ~ "]";
|
||||
copy(src.getNode(name), dest.getNode(name, 1), attr);
|
||||
}
|
||||
var type = src.getType();
|
||||
var val = src.getValue();
|
||||
if(type == "ALIAS" or type == "NONE") return;
|
||||
elsif(type == "BOOL") dest.setBoolValue(val);
|
||||
elsif(type == "INT" or type == "LONG") dest.setIntValue(val);
|
||||
elsif(type == "FLOAT" or type == "DOUBLE") dest.setDoubleValue(val);
|
||||
else dest.setValue(val);
|
||||
if(attr) dest.setAttribute(src.getAttribute());
|
||||
}
|
||||
|
||||
##
|
||||
# Utility. Returns a new object with its superclass/parent set to the
|
||||
# Node object and its _g (ghost) field set to the specified object.
|
||||
# Nasal's literal syntax can be pleasingly terse. I like that. :)
|
||||
#
|
||||
var wrapNode = func(node) { { parents : [Node], _g : node } }
|
||||
|
||||
##
|
||||
# Global property tree. Set once at initialization. Is that OK?
|
||||
# Does anything ever call globals.set_props() from C++? May need to
|
||||
# turn this into a function if so.
|
||||
#
|
||||
var globals = wrapNode(_globals());
|
||||
|
||||
##
|
||||
# Shortcut for props.globals.getNode().
|
||||
#
|
||||
var getNode = func return call(props.globals.getNode, arg, props.globals);
|
||||
|
||||
##
|
||||
# Sets all indexed property children to a single value. arg[0]
|
||||
# specifies a property name (e.g. /controls/engines/engine), arg[1] a
|
||||
# path under each node of that name to set (e.g. "throttle"), arg[2]
|
||||
# is the value.
|
||||
#
|
||||
var setAll = func(base, child, value) {
|
||||
var node = props.globals.getNode(base);
|
||||
if(node == nil) return;
|
||||
var name = node.getName();
|
||||
node = node.getParent();
|
||||
if(node == nil) return;
|
||||
var children = node.getChildren();
|
||||
foreach(var c; children)
|
||||
if(c.getName() == name)
|
||||
c.getNode(child, 1).setValue(value);
|
||||
}
|
||||
|
||||
##
|
||||
# Turns about anything into a list of props.Nodes, including ghosts,
|
||||
# path strings, vectors or hashes containing, as well as functions
|
||||
# returning any of the former and in arbitrary nesting. This is meant
|
||||
# to be used in functions whose main purpose is to handle collections
|
||||
# of properties.
|
||||
#
|
||||
var nodeList = func {
|
||||
var list = [];
|
||||
foreach(var a; arg) {
|
||||
var t = typeof(a);
|
||||
if(isa(a, Node))
|
||||
append(list, a);
|
||||
elsif(t == "scalar")
|
||||
append(list, props.globals.getNode(a, 1));
|
||||
elsif(t == "vector")
|
||||
foreach(var i; a)
|
||||
list ~= nodeList(i);
|
||||
elsif(t == "hash")
|
||||
foreach(var i; keys(a))
|
||||
list ~= nodeList(a[i]);
|
||||
elsif(t == "func")
|
||||
list ~= nodeList(a());
|
||||
elsif(t == "ghost" and ghosttype(a) == "prop")
|
||||
append(list, wrapNode(a));
|
||||
else
|
||||
die("nodeList: invalid nil property");
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
##
|
||||
# Compiles a <condition> property branch according to the rules
|
||||
# set out in $FG_ROOT/Docs/README.conditions into a Condition object.
|
||||
# The 'test' method of the returend object can be used to evaluate
|
||||
# the condition.
|
||||
# The function returns nil on error.
|
||||
#
|
||||
var compileCondition = func(p) {
|
||||
if(p == nil) return nil;
|
||||
if(!isa(p, Node)) p = props.globals.getNode(p);
|
||||
return _createCondition(p._g);
|
||||
}
|
||||
|
||||
##
|
||||
# Evaluates a <condition> property branch according to the rules
|
||||
# set out in $FG_ROOT/Docs/README.conditions. Undefined conditions
|
||||
# and a nil argument are "true". The function dumps the condition
|
||||
# branch and returns nil on error.
|
||||
#
|
||||
var condition = func(p) {
|
||||
if(p == nil) return 1;
|
||||
if(!isa(p, Node)) p = props.globals.getNode(p);
|
||||
return _cond_and(p)
|
||||
}
|
||||
|
||||
var _cond_and = func(p) {
|
||||
foreach(var c; p.getChildren())
|
||||
if(!_cond(c)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
var _cond_or = func(p) {
|
||||
foreach(var c; p.getChildren())
|
||||
if(_cond(c)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
var _cond = func(p) {
|
||||
var n = p.getName();
|
||||
if(n == "or") return _cond_or(p);
|
||||
if(n == "and") return _cond_and(p);
|
||||
if(n == "not") return !_cond_and(p);
|
||||
if(n == "equals") return _cond_cmp(p, 0);
|
||||
if(n == "not-equals") return !_cond_cmp(p, 0);
|
||||
if(n == "less-than") return _cond_cmp(p, -1);
|
||||
if(n == "greater-than") return _cond_cmp(p, 1);
|
||||
if(n == "less-than-equals") return !_cond_cmp(p, 1);
|
||||
if(n == "greater-than-equals") return !_cond_cmp(p, -1);
|
||||
if(n == "property") return !!getprop(p.getValue());
|
||||
printlog("alert", "condition: invalid operator ", n);
|
||||
dump(p);
|
||||
return nil;
|
||||
}
|
||||
|
||||
var _cond_cmp = func(p, op) {
|
||||
var left = p.getChild("property", 0, 0);
|
||||
if(left != nil) { left = getprop(left.getValue()); }
|
||||
else {
|
||||
printlog("alert", "condition: no left value");
|
||||
dump(p);
|
||||
return nil;
|
||||
}
|
||||
var right = p.getChild("property", 1, 0);
|
||||
if(right != nil) { right = getprop(right.getValue()); }
|
||||
else {
|
||||
right = p.getChild("value", 0, 0);
|
||||
if(right != nil) { right = right.getValue(); }
|
||||
else {
|
||||
printlog("alert", "condition: no right value");
|
||||
dump(p);
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
if(left == nil or right == nil) {
|
||||
printlog("alert", "condition: comparing with nil");
|
||||
dump(p);
|
||||
return nil;
|
||||
}
|
||||
if(op < 0) return left < right;
|
||||
if(op > 0) return left > right;
|
||||
return left == right;
|
||||
}
|
||||
|
||||
##
|
||||
# Runs <binding> as described in $FG_ROOT/Docs/README.commands using
|
||||
# a given module by default, and returns 1 if fgcommand() succeeded,
|
||||
# or 0 otherwise. The module name won't override a <module> defined
|
||||
# in the binding.
|
||||
#
|
||||
var runBinding = func(node, module = nil) {
|
||||
if(module != nil and node.getNode("module") == nil)
|
||||
node.getNode("module", 1).setValue(module);
|
||||
var cmd = node.getNode("command", 1).getValue() or "null";
|
||||
condition(node.getNode("condition")) ? fgcommand(cmd, node) : 0;
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Property / object update manager
|
||||
#
|
||||
# - Manage updates when a value has changed more than a predetermined amount.
|
||||
# This class is designed to make updating displays (e.g. canvas), or
|
||||
# performing actions based on a property (or value in a hash) changing
|
||||
# by more than the preset amount.
|
||||
# This can make a significant improvement to performance compared to simply
|
||||
# redrawing a canvas in an update loop.
|
||||
# - Author : Richard Harrison (rjh@zaretto.com)
|
||||
#---------------------------------------------------------------------------*/
|
||||
|
||||
#example usage:
|
||||
# this is using the hashlist (which works well with an Emesary notification)
|
||||
# basically when the method is called it will call each section (in the lambda)
|
||||
# when the value changes by more than the amount specified as the second parameter.
|
||||
# It is possible to reference multiple elements from the hashlist in each FromHashList; if either
|
||||
# one changes then it will result in the lambda being called.
|
||||
#
|
||||
# obj.update_items = [
|
||||
# UpdateManager.FromHashList(["VV_x","VV_y"], 0.01, func(val)
|
||||
# {
|
||||
# obj.VV.setTranslation (val.VV_x, val.VV_y + pitch_offset);
|
||||
# }),
|
||||
# UpdateManager.FromHashList(["pitch","roll"], 0.025, func(hdp)
|
||||
# {
|
||||
# obj.ladder.setTranslation (0.0, hdp.pitch * pitch_factor+pitch_offset);
|
||||
# obj.ladder.setCenter (118,830 - hdp.pitch * pitch_factor-pitch_offset);
|
||||
# obj.ladder.setRotation (-hdp.roll_rad);
|
||||
# obj.roll_pointer.setRotation (hdp.roll_rad);
|
||||
# }),
|
||||
# props.UpdateManager.FromProperty("velocities/airspeed-kt", 0.01, func(val)
|
||||
# {
|
||||
# obj.ias_range.setTranslation(0, val * ias_range_factor);
|
||||
# }),
|
||||
# props.UpdateManager.FromPropertyHashList(["orientation/alpha-indicated-deg", "orientation/side-slip-deg"], 0.1, func(val)
|
||||
# {
|
||||
# obj.VV_x = val.property["orientation/side-slip-deg"].getValue()*10; # adjust for view
|
||||
# obj.VV_y = val.property["orientation/alpha-indicated-deg"].getValue()*10; # adjust for view
|
||||
# obj.VV.setTranslation (obj.VV_x, obj.VV_y);
|
||||
# }),
|
||||
# ]
|
||||
#
|
||||
#==== the update loop then becomes ======
|
||||
#
|
||||
# foreach(var update_item; me.update_items)
|
||||
# {
|
||||
# # hdp is a data provider that can be used as the hashlist for the property
|
||||
# # update from hash methods.
|
||||
# update_item.update(hdp);
|
||||
# }
|
||||
#
|
||||
var UpdateManager =
|
||||
{
|
||||
_updateProperty : func(_property)
|
||||
{
|
||||
},
|
||||
FromProperty : func(_propname, _delta, _changed_method)
|
||||
{
|
||||
var obj = {parents : [UpdateManager] };
|
||||
obj.propname = _propname;
|
||||
obj.property = props.globals.getNode(_propname);
|
||||
obj.delta = _delta;
|
||||
obj.curval = obj.property.getValue();
|
||||
obj.lastval = obj.curval;
|
||||
obj.changed = _changed_method;
|
||||
obj.update = func(obj)
|
||||
{
|
||||
me.curval = me.property.getValue();
|
||||
if (me.curval != nil)
|
||||
{
|
||||
me.localType = me.property.getType();
|
||||
if (me.localType == "INT" or me.localType == "LONG" or me.localType == "FLOAT" or me.localType == "DOUBLE")
|
||||
{
|
||||
if(me.lastval == nil or math.abs(me.lastval - me.curval) >= me.delta)
|
||||
{
|
||||
me.lastval = me.curval;
|
||||
me.changed(me.curval);
|
||||
}
|
||||
}
|
||||
else if(me.lastval == nil or me.lastval != me.curval)
|
||||
{
|
||||
me.lastval = me.curval;
|
||||
me.changed(me.curval);
|
||||
}
|
||||
}
|
||||
};
|
||||
obj.update(obj);
|
||||
return obj;
|
||||
},
|
||||
|
||||
IsNumeric : func(hashkey)
|
||||
{
|
||||
me.localType = me.property[hashkey].getType();
|
||||
if (me.localType == "UNSPECIFIED") {
|
||||
print("UpdateManager: warning ",hashkey," is ",ty, " excluding from update");
|
||||
me.property[hashkey] = nil;
|
||||
}
|
||||
if (me.localType == "INT" or me.localType == "LONG" or me.localType == "FLOAT" or me.localType == "DOUBLE")
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
},
|
||||
|
||||
FromPropertyHashList : func(_keylist, _delta, _changed_method)
|
||||
{
|
||||
var obj = {parents : [UpdateManager] };
|
||||
obj.hashkeylist = _keylist;
|
||||
obj.delta = _delta;
|
||||
obj.lastval = {};
|
||||
obj.hashkey = nil;
|
||||
obj.changed = _changed_method;
|
||||
obj.needs_update = 0;
|
||||
obj.property = {};
|
||||
obj.is_numeric = {};
|
||||
foreach (hashkey; obj.hashkeylist) {
|
||||
obj.property[hashkey] = props.globals.getNode(hashkey);
|
||||
obj.lastval[hashkey] = nil;
|
||||
# var ty = obj.property[hashkey].getType();
|
||||
# if (ty == "INT" or ty == "LONG" or ty == "FLOAT" or ty == "DOUBLE") {
|
||||
# obj.is_numeric[hashkey] = 1;
|
||||
# } else
|
||||
# obj.is_numeric[hashkey] = 0;
|
||||
#print("create: ", hashkey," ", ty, " isnum=",obj.is_numeric[hashkey]);
|
||||
# if (ty == "UNSPECIFIED")
|
||||
# print("UpdateManager: warning ",hashkey," is ",ty);
|
||||
}
|
||||
obj.update = func(obj)
|
||||
{
|
||||
if (me.lastval == nil)
|
||||
me.needs_update = 1;
|
||||
else {
|
||||
me.needs_update = 0;
|
||||
|
||||
foreach (hashkey; me.hashkeylist) {
|
||||
if (me.property[hashkey] != nil) {
|
||||
me.valIsNumeric = me.IsNumeric(hashkey);
|
||||
|
||||
if (me.lastval[hashkey] == nil
|
||||
or (me.valIsNumeric and (math.abs(me.lastval[hashkey] - me.property[hashkey].getValue()) >= me.delta))
|
||||
or (!me.valIsNumeric and (me.lastval[hashkey] != me.property[hashkey].getValue()))) {
|
||||
me.needs_update = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (me.needs_update) {
|
||||
me.changed(me);
|
||||
foreach (hashkey; me.hashkeylist) {
|
||||
me.lastval[hashkey] = me.property[hashkey].getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
;
|
||||
return obj;
|
||||
},
|
||||
FromHashValue : func(_key, _delta, _changed_method)
|
||||
{
|
||||
var obj = {parents : [UpdateManager] };
|
||||
obj.hashkey = _key;
|
||||
obj.delta = _delta;
|
||||
obj.isnum = _delta != nil;
|
||||
obj.curval = nil;
|
||||
obj.lastval = nil;
|
||||
obj.changed = _changed_method;
|
||||
obj.update = func(obj)
|
||||
{
|
||||
me.curval = obj[me.hashkey];
|
||||
if (me.curval != nil) {
|
||||
if (me.isnum) {
|
||||
me.curval = num(me.curval);
|
||||
if (me.lastval == nil or math.abs(me.lastval - me.curval) >= me.delta) {
|
||||
me.lastval = me.curval;
|
||||
me.changed(me.curval);
|
||||
}
|
||||
} else {
|
||||
if (me.lastval == nil or me.lastval != me.curval) {
|
||||
me.lastval = me.curval;
|
||||
me.changed(me.curval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
;
|
||||
return obj;
|
||||
},
|
||||
FromHashList : func(_keylist, _delta, _changed_method)
|
||||
{
|
||||
var obj = {parents : [UpdateManager] };
|
||||
obj.hashkeylist = _keylist;
|
||||
obj.delta = _delta;
|
||||
obj.lastval = {};
|
||||
obj.hashkey = nil;
|
||||
obj.changed = _changed_method;
|
||||
obj.needs_update = 0;
|
||||
obj.isnum = _delta != nil;
|
||||
obj.update = func(obj)
|
||||
{
|
||||
if (me.lastval == nil)
|
||||
me.needs_update = 1;
|
||||
else
|
||||
me.needs_update = 0;
|
||||
|
||||
if (obj != nil or me.lastval == nil) {
|
||||
foreach (hashkey; me.hashkeylist) {
|
||||
if (me.isnum) {
|
||||
if (me.lastval[hashkey] == nil or math.abs(me.lastval[hashkey] - obj[hashkey]) >= me.delta) {
|
||||
me.needs_update = 1;
|
||||
break;
|
||||
}
|
||||
} elsif (me.lastval[hashkey] == nil or me.lastval[hashkey] != obj[hashkey]) {
|
||||
me.needs_update = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (me.needs_update) {
|
||||
me.changed(obj);
|
||||
foreach (hashkey; me.hashkeylist) {
|
||||
me.lastval[hashkey] = obj[hashkey];
|
||||
}
|
||||
}
|
||||
};
|
||||
return obj;
|
||||
},
|
||||
};
|
||||
25
test/quick_sort.nas
Normal file
25
test/quick_sort.nas
Normal file
@@ -0,0 +1,25 @@
|
||||
import("lib.nas");
|
||||
var sort=func(vec,left,right)
|
||||
{
|
||||
if(left>=right) return;
|
||||
var (L,R,tmp)=(left,right,vec[left]);
|
||||
while(left<right)
|
||||
{
|
||||
while(left<right and tmp<=vec[right])
|
||||
right-=1;
|
||||
while(left<right and tmp>=vec[left])
|
||||
left+=1;
|
||||
if(left!=right)
|
||||
(vec[left],vec[right])=(vec[right],vec[left]);
|
||||
}
|
||||
(vec[L],vec[left])=(vec[left],tmp);
|
||||
sort(vec,L,left-1);
|
||||
sort(vec,left+1,R);
|
||||
return;
|
||||
}
|
||||
var vec=[];
|
||||
rand(time(0));
|
||||
for(var i=0;i<200;i+=1)
|
||||
append(vec,int(rand()*1000));
|
||||
sort(vec,0,size(vec)-1);
|
||||
println(vec);
|
||||
152
test/scalar.nas
Normal file
152
test/scalar.nas
Normal file
@@ -0,0 +1,152 @@
|
||||
# basic type
|
||||
import("lib.nas");
|
||||
nil;
|
||||
2147483647;
|
||||
0x7fffffff;
|
||||
0xdeadbeef;
|
||||
0o70120327;
|
||||
"hello world!";
|
||||
'hello world!';
|
||||
-12;
|
||||
!0;
|
||||
-((30));
|
||||
[];
|
||||
{};
|
||||
[0,1,2,3,4,5][2]; # 2
|
||||
[0,1,2,3,4,5,6,7,8,9,10][0,2,4:7,9];
|
||||
[0,1,2,3,4,5,6,7,8,9,10,][0,2,4:7,9];
|
||||
([0,1,2,3,4])[2]; # 2
|
||||
(([0,1,2,3]))[2]; # 2
|
||||
[0,1,2,3,4,5][5,4,3,2+1][0:2][0]; # 5
|
||||
{str:"hello"}.str; # "hello"
|
||||
{str:"hello"}["str"]; # "hello"
|
||||
{"str":"hello\"\"\n"}["str"]; # "hello"
|
||||
20? 1:0;
|
||||
|
||||
# normal scalar
|
||||
var number_1=1;
|
||||
var number_2=0xdeadbeef;
|
||||
var number_3=0x13702;
|
||||
var number_4=0.12341490239423;
|
||||
var string_1="hello";
|
||||
var string_2='hello';
|
||||
var string_3=number_1? 'yes':'no'; # yes
|
||||
|
||||
# vector
|
||||
var vector_1=[];
|
||||
var vector_2=[0,1,2,"str",number_1,vector_1];
|
||||
var vector_3=vector_2[-3,-1];
|
||||
var vector_4=vector_2[0:3];
|
||||
var vector_5=vector_2[3:];
|
||||
|
||||
# hash
|
||||
var hash_1={};
|
||||
var hash_2={str1:'str1', str2:'str2', num1:0x7fffffff};
|
||||
var hash_3={
|
||||
"member_1":1,
|
||||
"member_2":2,
|
||||
"member_3":3,
|
||||
};
|
||||
var hash_4={
|
||||
mem_1:hash_1,
|
||||
mem_2:hash_2.num1, # also this can be written as hash_2["num1"]
|
||||
mem_3:hash_3["member_1"]
|
||||
};
|
||||
|
||||
# function
|
||||
var func_1=func(){return 1;}
|
||||
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);}
|
||||
|
||||
func_with_lack_para(a:1, b:2, c:3, d:4);
|
||||
func_with_lack_para(b:1, c:3, a:4, d:1);
|
||||
func_with_func_para(f:func prt,a:1);
|
||||
func_with_func_para(func func_1(),func(x){return x;});
|
||||
func_with_func_para(func_1(),func_1);
|
||||
prt(func func_1());
|
||||
var test_func_ret_number_1=func func_1(); # 1
|
||||
var test_func_ret_number_2=func_1(); # 1
|
||||
|
||||
var source={
|
||||
member_1: func func_1(), # this will get a number
|
||||
member_2: func {return 2.71828;} # this will get a function
|
||||
};
|
||||
println(source['member_2']());
|
||||
println(source.member_2());
|
||||
|
||||
var test_func=func{return 1;}
|
||||
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{println("hello world");})();
|
||||
(((func(x){return 1.0/math.exp(x);})))(0);
|
||||
|
||||
# flexible definition & assignment
|
||||
var (r,g,b)=[0x00,0x10,0xff];
|
||||
(var r,g,b)=[0x00,0x10,0xff];
|
||||
var color=[0x00,0x10,0xff];
|
||||
var (r,g,b)=color;
|
||||
(var r,g,b)=color;
|
||||
(r,g,b)=(b,g,r);
|
||||
(number_1,number_2)=(number_2,number_1);
|
||||
var (swap_a,swap_b)=(0x1,0x80);
|
||||
(swap_a,swap_b)=(swap_b,swap_a);
|
||||
# ((swap_a),(swap_b))=(swap_b,swap_a) is wrong
|
||||
# anything that use multi_assignment must not have curve around them
|
||||
var multi_assign_1=[0,1,2,3,4];
|
||||
var multi_assign_2=[10,9,8,7];
|
||||
(multi_assign_1[1],multi_assign_2[0])=(multi_assign_1[2],multi_assign_2[1]);
|
||||
|
||||
# calculation
|
||||
1+1;
|
||||
1+1-2+3-4+5-6;
|
||||
1+1*8-9/3;
|
||||
1*-1;
|
||||
1*(1+2*(3+4*(5+6*(7+8*(9+10/(1+1))))));
|
||||
((-1*2+9))/7-1;
|
||||
((({num:2})))["num"]*2*2*2;
|
||||
((((([0,1,2])[0:2]))[0:2]))[1]-1;
|
||||
println((((((((((((((((((((1+1+2+3+5)+8))+13)))+21))))+34)))))+55))))*89); # 12727
|
||||
number_1*(number_2+number_3)/90-number_4;
|
||||
(func test_func)()-1;
|
||||
hash_3.member_3+(func {return {what:"i don't tell you.",case_small:80,case_large:100}})()["case_large"]/10;
|
||||
-1*10+5 or 10-10;
|
||||
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;
|
||||
|
||||
var hash={str:'hello',f:func{return me.str;}};
|
||||
var tmp_f=hash.f;
|
||||
hash=1;
|
||||
println(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;
|
||||
println(h2.f());
|
||||
# print 'world'
|
||||
# this means that 'me' in hash's functions
|
||||
# only points to the hash this function belongs to
|
||||
|
||||
var f1=func(){println(1);return 1;}
|
||||
var f2=func(){println(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
|
||||
39
test/trait.nas
Normal file
39
test/trait.nas
Normal file
@@ -0,0 +1,39 @@
|
||||
import("lib.nas");
|
||||
|
||||
var trait={
|
||||
get:func{return me.val;},
|
||||
set:func(x){me.val=x;}
|
||||
};
|
||||
|
||||
var class={
|
||||
new:func(){
|
||||
return {
|
||||
val:nil,
|
||||
parents:[trait]
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
var class2={
|
||||
new:func(){
|
||||
return {
|
||||
val:nil,
|
||||
parents:[trait],
|
||||
set:func(x){me.val=typeof(x);}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
var class_obj=[];
|
||||
for(var i=0;i<10;i+=1){
|
||||
append(class_obj,class.new());
|
||||
class_obj[i].set(i);
|
||||
}
|
||||
for(var i=0;i<10;i+=1){
|
||||
append(class_obj,class2.new());
|
||||
class_obj[10+i].set(i);
|
||||
}
|
||||
|
||||
foreach(var object;class_obj){
|
||||
println(object.get(),' ',keys(object));
|
||||
}
|
||||
17
test/ycombinator.nas
Normal file
17
test/ycombinator.nas
Normal file
@@ -0,0 +1,17 @@
|
||||
# Y combinator by ValKmjolnir
|
||||
|
||||
import("lib.nas");
|
||||
|
||||
var fib=func(f){
|
||||
return f(f);
|
||||
}(
|
||||
func(f){
|
||||
return func(x){
|
||||
if(x<2) return x;
|
||||
return f(f)(x-1)+f(f)(x-2);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
for(var i=1;i<31;i+=1)
|
||||
println(fib(i));
|
||||
Reference in New Issue
Block a user