118 Commits
v4.0 ... v7.0

Author SHA1 Message Date
ValKmjolnir
d71b4f09e2 prepare for version 8.0 2021-10-08 15:32:18 +08:00
ValKmjolnir
13d40e886e update 2021-09-25 23:25:31 +08:00
Li Haokun
618ce59233 bad access bug fixed 2021-09-13 19:55:03 +08:00
Li Haokun
071d8bd1ce update 2021-09-10 19:13:42 +08:00
Li Haokun
c498d5c8c4 add fg constants & change int(), num() 2021-09-02 19:10:49 +08:00
Li Haokun
11971267dc add math.nan math.inf 2021-09-01 19:15:32 +08:00
Li Haokun
418531a44a add result.nas 2021-09-01 19:14:03 +08:00
Li Haokun
59dc0d1423 add isnan 2021-08-27 17:43:01 +08:00
Li Haokun
385f0af17e nothing changed 2021-08-24 19:34:52 +08:00
Li Haokun
ef9b781961 security holes fixed 2021-08-19 17:54:36 +08:00
ValKmjolnir
80cc8e9db7 closure bugs fixed 2021-08-17 01:18:35 +08:00
Li Haokun
b2be386be8 update hexdump.nas 2021-08-13 15:10:20 +08:00
Li Haokun
e4c598cae6 add hexdump.nas 2021-08-12 20:01:51 +08:00
Li Haokun
5fe6681b0d update lexer 2021-08-12 19:00:17 +08:00
Li Haokun
35fc848672 fully functional closure 2021-08-11 14:54:17 +08:00
Li Haokun
e3f3bd7387 update readme 2021-08-10 17:55:49 +08:00
ValKmjolnir
638ec1c3a3 use same indentation 2021-08-09 21:30:18 +08:00
Li Haokun
90ac468aa9 update 2021-08-09 19:13:39 +08:00
ValKmjolnir
65dfef0a33 update 2021-08-09 01:02:27 +08:00
Li Haokun
76a2548e95 update 2021-08-06 18:57:06 +08:00
Li Haokun
40b690b67b update 2021-08-05 19:02:41 +08:00
Li Haokun
2b17f3d702 update debug info 2021-08-04 14:32:56 +08:00
ValKmjolnir
5b6c78783e update README 2021-08-04 00:03:49 +08:00
Li Haokun
fa618eb97f variables can be used before definition
change program to command line
change trace back info
change print function of nasal_vec and nasal_hash
2021-08-03 18:55:11 +08:00
ValKmjolnir
d0616ef028 update 2021-08-01 22:37:42 +08:00
ValKmjolnir
91771297d3 add test file 2021-08-01 22:34:02 +08:00
ValKmjolnir
4e1a3c5f2d syntax bug fixed
syntax like:
var f=func(){}
(var a,b,c)=(1,2,3);
will be incorrectly recognized like:
var f=func(){}(var a,b,c)

this bug is fixed now.
2021-08-01 02:11:27 +08:00
ValKmjolnir
df634cb1b2 update readme:difference between this and andy's interpreter 2021-08-01 01:54:14 +08:00
Li Haokun
aa797142d1 update parser
one bug found, waiting to be fixed
2021-07-28 18:22:40 +08:00
Li Haokun
816be43a98 update 2021-07-24 19:59:56 +08:00
Li Haokun
9ebabfe737 fixed bug in nasal_parse 2021-07-21 17:38:11 +08:00
ValKmjolnir
884b56ac09 bug fixed & raw string print 2021-07-21 00:20:25 +08:00
Li Haokun
61677101e4 show vm stack top's info when error occurs 2021-07-20 19:21:05 +08:00
Li Haokun
7a93f5b89b update 2021-07-19 17:04:45 +08:00
Li Haokun
9fe7a86a3b add trace back info 2021-07-16 17:18:13 +08:00
ValKmjolnir
9da029b8fe prepare for debugger 2021-07-16 02:17:53 +08:00
ValKmjolnir
8b8e72c879 update 2021-07-14 01:24:15 +08:00
ValKmjolnir
590c595522 delete slice_stack 2021-07-07 14:46:46 +08:00
ValKmjolnir
57d6bcdc52 add const compare instructions 2021-07-03 15:22:23 +08:00
ValKmjolnir
0b2fe61e6e add instruction & changes in codegen
add some instructions that execute const values.
the first symbol called in assignment will use op_load instead of op_meq,op_pop to assign.
2021-06-29 17:18:05 +08:00
ValKmjolnir
706659ba3d change instruction dispatch to computed-goto
bug fixed
prepare for version 7.0
2021-06-26 14:53:10 +08:00
ValKmjolnir
3c9a10d710 avoid unnecessary deep copy by using rvalue ref
and test file update.
bug fixed in test/lexer.nas
2021-06-24 22:10:08 +08:00
ValKmjolnir
fd57e9a47c performance optimization of vm/lex/parse/test 2021-06-24 00:26:26 +08:00
ValKmjolnir
ab99d2d1ed change mcall to call->mcall&allow differen lvalue in assignment 2021-06-21 16:46:47 +08:00
Valk Richard Li
ae0dae5956 update 2021-06-21 01:02:09 +08:00
Valk Richard Li
00c6e3b4fd nothing changed 2021-06-20 01:27:01 +08:00
Valk Richard Li
cdf7b92a8e add statistical information 2021-06-19 00:32:10 +08:00
Valk Richard Li
0e979a6e7b bug fixed & delete operand vapp 2021-06-15 00:49:32 +08:00
Valk Richard Li
dd144305da update test file 2021-06-14 00:27:00 +08:00
Valk Richard Li
4f3ddf803a add tips 2021-06-13 01:01:32 +08:00
Valk Richard Li
de305d26ad fixed an error in README 2021-06-12 01:23:06 +08:00
Valk Richard Li
9f30f45774 Update README.md 2021-06-11 15:28:25 +08:00
Valk Richard Li
1ae47807eb Add command line parameters & chr supports extended ASCII 2021-06-11 15:16:06 +08:00
Valk Richard Li
3deea632f8 front end optimization&stack overflow prompt
change parameter type to avoid unnecessary copies of string.
change stack depth from 65536<<4 to 16+(65536<<2).
now you could know stack overflow when it happens
2021-06-07 23:53:43 +08:00
Valk Richard Li
9f2c31149a bug fixed
fixed SIGSEGV when failed to load file in nasal_lexer::openfile
2021-06-06 19:17:02 +08:00
Valk Richard Li
b25a1bc3f4 more efficient str2num 2021-06-05 20:42:58 +08:00
Valk Richard Li
fd7677f94f update README.md(some history of this project)
AND a question of admins' brains of gitee
2021-06-05 17:15:07 +08:00
Valk Richard Li
2e31a70406 Update README.md 2021-06-03 21:59:15 +08:00
Valk Richard Li
8e29a3ec5b bug fixed & more efficient callfv
I changed callfv's way of calling a function with arguments in vm_vec.
now callfv fetches arguments from val_stack directly,so it runs test/fib.nas from 2.4s to 1.9s.

delete operand callf,add operands callfv & callfh.

also,i check val_stack's top to make sure there is not a stack overflow.
2021-06-03 21:49:31 +08:00
Valk Richard Li
a68bf85f04 bug fixed
a gc bug which causes  fatal error.
add member value collect to make sure that nasal_val is not collected repeatedly.
use builtin_alloc in builtin function to avoid incorrect collection of value in use(gc_alloc).
change free_list to free_list[vm_type_size] to avoid too many calls of new/delete(but seems useless?)
but the most important thing is fixing this bug.
2021-05-31 19:10:59 +08:00
Valk Richard Li
aae9395d66 bug fixed
add operand op_offset to make sure arguments are loaded at correct places,before this commit,arguments are not loaded from a correct offset,which will cause SIGSEGV when calling a function that has complex closure
2021-05-17 21:15:57 +08:00
Valk Richard Li
a463af53b7 add license & other changes
parser recognizes syntax errors more accurately.
change some for loop to standard c++11 for(auto iter:obj)
add MIT license
change info in README.md
2021-05-04 17:39:24 +08:00
Valk Richard Li
6adb991c04 parser reports syntax error accurately
still need improvement
2021-05-04 01:13:53 +08:00
Valk Richard Li
c5f4736984 change scope from unordered_map to vector 2021-04-19 19:12:41 +08:00
Valk Richard Li
1a233fbe15 update 2021-04-12 13:21:13 +08:00
Valk Richard Li
a7d6518bff add test file & update README 2021-04-04 23:35:13 +08:00
Valk Richard Li
0700ce14f7 change function of vapp & README update 2021-04-03 23:47:14 +08:00
Valk Richard Li
c88620920b add stl & more efficient scope 2021-04-02 22:19:29 +08:00
Valk Richard Li
125fc8a9fe bug fixed & test file changes
compare operators now run more efficiently.
2021-03-31 20:59:13 +08:00
Valk Richard Li
b06e1bb5dd add static symbol check & test file update 2021-03-30 15:55:38 +08:00
Valk Richard Li
c7316e9780 change id name & add test file 2021-03-30 00:12:48 +08:00
Valk Richard Li
be1bcdfe2c bug fixed 2021-03-28 17:39:24 +08:00
Valk Richard Li
144e6f45da gc changed to mark-sweep 2021-03-27 01:08:05 +08:00
Valk Richard Li
569d5c6c6a update 2021-03-11 23:18:04 +08:00
Valk Richard Li
7087c67d79 add constant table in vm 2021-03-08 19:45:33 +08:00
Valk Richard Li
c4e6a89959 update test files and prepare the release of v5.0 2021-03-07 16:33:43 +08:00
Valk Richard Li
f60f674845 delete op_entry 2021-03-04 15:53:34 +08:00
Valk Richard Li
c21d40c466 change test files 2021-03-03 09:20:42 +08:00
Valk Richard Li
19b590f3bb add test files 2021-03-03 01:09:57 +08:00
Valk Richard Li
a421470715 change map to unordered_map 2021-03-01 15:54:58 +08:00
Valk Richard Li
79dc13f419 update 2021-02-27 22:45:51 +08:00
Valk Richard Li
2e8208a752 add getParent & getPath 2021-02-25 22:30:28 +08:00
Valk Richard Li
1c40cca673 add tutorial of how to add built-in function 2021-02-23 23:33:01 +08:00
Valk Richard Li
b1a5a5f6c0 clear memory footprint when codegen complete 2021-02-23 22:53:28 +08:00
Valk Richard Li
64961877de Add props lib & bug fixed(op_ret in foreach/index got SIGSEGV) 2021-02-18 23:49:29 +08:00
Valk Richard Li
9c9bb52818 codegen will not generate 'jmp' if 'if' and 'elsif' is the last condition 2021-02-18 11:45:47 +08:00
Valk Richard Li
02148f4766 bug fixed & more efficient function call
fixed a bug when different hash calling the same function,'me' will be set to the latest called hash's address.
changed the way of pushing the scope to the stack by copying a new scope from the function's scope address.
use map as the nasal_scop instead of list<map>,it'll be more efficient.
2021-02-17 19:31:44 +08:00
Valk Richard Li
767711c93a change identifier name to avoid misunderstanding 2021-02-15 15:29:55 +08:00
Valk Richard Li
78ba0641a6 change the way of calling built-in functions
change std::map to struct array,use index to call built-in functions.this may be more efficient.
2021-02-14 17:36:42 +08:00
Valk Richard Li
80683c381f bug fixed 2021-02-13 23:57:53 +08:00
Li Haokun
6aac46adaf Merge pull request #5 from sidi762/master
Added left, right, streq, cmp, chr to library functions
2021-02-13 07:24:17 -08:00
Sidi Liang
388ef66308 Library: added comment for chr 2021-02-13 21:43:07 +08:00
Sidi Liang
8faa4ef2db Library: Added core library function chr according to FlightGear Nasal 2021-02-13 21:40:10 +08:00
Sidi Liang
441c02d0fb Library: Added core library function streq and cmp according to FlightGear Nasal 2021-02-13 21:09:13 +08:00
Sidi Liang
953ad80482 Library: Added core library function left and right according to FlightGear Nasal 2021-02-13 20:19:49 +08:00
Valk Richard Li
e2ee9cff4c update 2021-02-13 14:37:21 +08:00
Valk Richard Li
996ac59c79 update parser to LL(1) 2021-02-13 13:28:20 +08:00
Valk Richard Li
944f713ee9 update 2021-02-13 11:09:31 +08:00
Valk Richard Li
7329c70492 identifiers' name changed 2021-02-12 23:48:51 +08:00
Valk Richard Li
b5514fd269 update 2021-02-12 22:27:41 +08:00
Valk Richard Li
3be50116fa update 2021-02-10 00:12:22 +08:00
Valk Richard Li
125d6d3a7d update 2021-01-23 19:21:37 +08:00
Valk Richard Li
bb746dfbfb update 2021-01-23 17:57:05 +08:00
Valk Richard Li
8069a1b659 update 2021-01-06 22:12:19 +08:00
Valk Richard Li
f0cb8b6ef3 update 2021-01-06 21:07:34 +08:00
Valk Richard Li
9474ac9ef0 update & bug fixed 2021-01-05 23:17:32 +08:00
Valk Richard Li
b862aa91eb update 2021-01-05 01:55:17 +08:00
Valk Richard Li
bc64d530be update 2021-01-02 23:57:21 +08:00
Valk Richard Li
ea5116e963 update 2020-12-29 19:09:20 +08:00
Valk Richard Li
cc4e697246 bug fixed 2020-12-26 19:05:04 +08:00
Valk Richard Li
515bef3f5d bug fixed 2020-12-25 22:06:42 +08:00
Valk Richard Li
05800fe518 bug fixed 2020-12-25 13:22:57 +08:00
Valk Richard Li
33d37771ce update 2020-12-24 23:53:31 +08:00
Valk Richard Li
89540475cf update 2020-12-20 20:18:02 +08:00
Valk Richard Li
e03da2f737 update 2020-12-20 13:39:24 +08:00
Valk Richard Li
4617eb8f17 update 2020-12-19 23:47:04 +08:00
Valk Richard Li
fed1e20085 update 2020-12-19 21:02:02 +08:00
Valk Richard Li
9f30440286 preparation for v5.0 2020-12-19 01:26:15 +08:00
70 changed files with 6892 additions and 20229 deletions

21
LICENSE Normal file
View 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.

895
README.md
View File

@@ -1,60 +1,129 @@
# Nasal Interpreter
# Nasal Script Language
[![nasal_new_logo](pic/nasal.png?raw=true)](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.
They found it much easier to check syntax and runtime errors before copying nasal-codes in nasal-console in Flightgear to test.
# How to Compile
Also, you could use this language to write some interesting programs and run them without the lib of Flightgear.
> g++ -std=c++11 main.cpp -o main.exe
# Lexical Analysis
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).
The flow chart of lexer is here:
## How to Compile
[![nasal_lexer.png](pic/nasal_lexer.png?raw=true)](https://github.com/ValKmjolnir/Nasal-Interpreter/blob/master/pic/nasal_lexer.png)
Better choose the latest update of the interpreter.
This picture seems ugly. I will re-draw it later(maybe 1000 years later).
MUST USE -O2/-O3 if want to optimize the interpreter!
# Parser
Also remember to use g++ or clang++.
## Version 3.0
> [cpp compiler] -std=c++11 -O2 main.cpp -o nasal.exe
I refactored parser and make it easier to maintain.
Or use this in linux/macOS/Unix
The EBNF is also refactored.
> [cpp compiler] -std=c++11 -O2 main.cpp -o nasal
# Abstract Syntax Tree
## How to Use?
## Version 1.2
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.
```javascript
(var a,b,c)=[{b:nil},[1,2],func return 0;];
(a.b,b[0],c)=(1,2,3);
```
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
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
### Version 2.0(last update 2020/8/31)
A completed ast-interpreter with unfinished lib functions.
## Version 3.0
### Version 3.0(last update 2020/10/23)
The ast is refactored and is now easier to read and maintain.
@@ -64,9 +133,15 @@ 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...
# Byte Code Interpreter
### Version 5.0(last update 2021/3/7)
## Version 4.0
I change my mind.AST interpreter leaves me too much things to do.
If i continue saving this interpreter,it will be harder for me to make the bytecode vm become more efficient.
## Byte Code Interpreter
### Version 4.0 (last update 2020/12/17)
I have just finished the first version of byte-code-interpreter.
@@ -77,21 +152,759 @@ Now i am trying to search hidden bugs in this interpreter.Hope you could help me
There's an example of byte code below:
```javascript
var (a,b,c)=(1,2,3);
for(var i=0;i<4000000;i+=1);
```
```asm
.number 0
.number 4e+006
.number 1
.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
.number 3
.symbol a
.symbol b
.symbol c
0x00000000: pone 0x00000000
0x00000001: load 0x00000000 (a)
0x00000002: pnum 0x00000001 (2)
0x00000003: load 0x00000001 (b)
0x00000004: pnum 0x00000002 (3)
0x00000005: load 0x00000002 (c)
0x00000006: nop 0x00000000
.symbol _
.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);
```
### conditional expression
```javascript
if(1){
;
}elsif(2){
;
}else if(3){
;
}else{
;
}
```
### loop
```javascript
while(condition)
continue;
for(var i=0;i<10;i+=1)
break;
forindex(var i;elem)
print(elem[i]);
foreach(var i;elem)
print(i);
```
### subvec
Use index to search one element in the string will get the ascii number of this character.If you want to get the character,use built-in function chr().
```javascript
a[-1,1,0:2,0:,:3,:,nil:8,3:nil,nil:nil];
"hello world"[0];
```
### special function call
This is of great use but is not very efficient(because hashmap use string as the key to compare).
```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)
```

193
lib.nas
View File

@@ -1,167 +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 typeof=func(object)
{
return nasal_call_builtin_type(object);
return __builtin_type(object);
}
var substr=func(str,begin,length)
var substr=func(str,begin,len)
{
return nasal_call_builtin_substr(str,begin,length);
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.14159265358979323846264338327950288,
sin:func(x)
{
return nasal_call_builtin_sin(x);
},
cos:func(x)
{
return nasal_call_builtin_cos(x);
},
tan:func(x)
{
return nasal_call_builtin_tan(x);
},
exp:func(x)
{
return nasal_call_builtin_exp(x);
},
ln:func(x)
{
return nasal_call_builtin_cpp_math_ln(x);
},
sqrt:func(x)
{
return nasal_call_builtin_cpp_math_sqrt(x);
},
atan2:func(x,y)
{
return nasal_call_builtin_cpp_atan2(x,y);
},
e: 2.7182818284590452354,
pi: 3.14159265358979323846264338327950288,
sin: func(x) {return __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;

329
main.cpp
View File

@@ -1,221 +1,144 @@
#include "nasal.h"
nasal_lexer lexer;
nasal_parse parse;
nasal_import import;
std::string inputfile="null";
nasal_runtime runtime;
nasal_codegen code_generator;
nasal_bytecode_vm bytevm;
void help()
void help_cmd()
{
std::cout<<">> [\"file\"] input a file name.\n";
std::cout<<">> [help ] show help.\n";
std::cout<<">> [clear ] clear the screen.\n";
std::cout<<">> [del ] clear the input filename.\n";
std::cout<<">> [lex ] use lexer to turn code into tokens.\n";
std::cout<<">> [ast ] do parsing and check the abstract syntax tree.\n";
std::cout<<">> [run ] run abstract syntax tree.\n";
std::cout<<">> [code ] show byte code.\n";
std::cout<<">> [exec ] execute program on bytecode vm.\n";
std::cout<<">> [logo ] print logo of nasal .\n";
std::cout<<">> [exit ] quit nasal interpreter.\n";
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)
{
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[])
{
lexer.openfile(inputfile);
lexer.scanner();
if(lexer.get_error())
{
die("lexer",inputfile);
return;
}
lexer.print_token();
return;
}
void ast_print()
{
lexer.openfile(inputfile);
lexer.scanner();
if(lexer.get_error())
{
die("lexer",inputfile);
return;
}
parse.set_toklist(lexer.get_token_list());
parse.main_process();
if(parse.get_error())
{
die("parse",inputfile);
return;
}
parse.get_root().print_ast(0);
return;
}
void runtime_start()
{
lexer.openfile(inputfile);
lexer.scanner();
if(lexer.get_error())
{
die("lexer",inputfile);
return;
}
parse.set_toklist(lexer.get_token_list());
parse.main_process();
if(parse.get_error())
{
die("parse",inputfile);
return;
}
import.link(parse.get_root());
if(import.get_error())
{
die("import",inputfile);
return;
}
runtime.set_root(import.get_root());
runtime.run();
return;
}
void show_bytecode()
{
lexer.openfile(inputfile);
lexer.scanner();
if(lexer.get_error())
{
die("lexer",inputfile);
return;
}
parse.set_toklist(lexer.get_token_list());
parse.main_process();
if(parse.get_error())
{
die("parse",inputfile);
return;
}
import.link(parse.get_root());
if(import.get_error())
{
die("import",inputfile);
return;
}
code_generator.main_progress(import.get_root());
code_generator.print_byte_code();
return;
}
void execute()
{
lexer.openfile(inputfile);
lexer.scanner();
if(lexer.get_error())
{
die("lexer",inputfile);
return;
}
parse.set_toklist(lexer.get_token_list());
parse.main_process();
if(parse.get_error())
{
die("parse",inputfile);
return;
}
import.link(parse.get_root());
if(import.get_error())
{
die("import",inputfile);
return;
}
code_generator.main_progress(import.get_root());
bytevm.run(
code_generator.get_string_table(),
code_generator.get_number_table(),
code_generator.get_exec_code()
);
return;
}
int main()
{
std::string command;
#ifdef _WIN32
// use chcp 65001 to use unicode io
system("chcp 65001");
system("cls");
#endif
logo();
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=="lex")
lex_func();
else if(command=="ast")
ast_print();
else if(command=="run")
runtime_start();
else if(command=="code")
show_bytecode();
else if(command=="exec")
execute();
else if(command=="logo")
logo();
else if(command=="exit")
break;
else
inputfile=command;
}
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;
}

View File

@@ -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::=
@@ -63,11 +63,11 @@ unary::=
;
scalar::=
function {call_scalar}
|[func] 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

187
nasal.h
View File

@@ -3,6 +3,7 @@
#pragma GCC optimize(2)
#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
@@ -14,118 +15,115 @@
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <thread>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <unordered_map>
/*
check if a string can be converted to a number
if this string cannot be converted to a number,it will return nan
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(std::string str)
inline double hex_to_double(const char* str)
{
double ret=0;
for(int i=2;str[i];++i)
{
ret*=16;
if('0'<=str[i] && str[i]<='9')
ret+=(str[i]-'0');
else if('a'<=str[i] && str[i]<='f')
ret+=(str[i]-'a'+10);
else if('A'<=str[i] && str[i]<='F')
ret+=(str[i]-'A'+10);
else
return std::nan("");
}
return ret;
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(std::string str)
inline double oct_to_double(const char* str)
{
double ret=0;
for(int i=2;str[i];++i)
{
ret*=8;
if('0'<=str[i] && str[i]<='8')
ret+=(str[i]-'0');
else
return std::nan("");
}
return ret;
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(std::string str,int len)
inline double dec_to_double(const char* str)
{
double ret=0;
int i=0;
while('0'<=str[i] && str[i]<='9' && i<len)
ret=ret*10+(str[i++]-'0');
if(i==len) return ret;
if(str[i]!='.' && str[i]!='e' && str[i]!='E')
return std::nan("");
if(str[i]=='.')
{
++i;
if(i==len) return std::nan("");
double num_pow=0.1;
while('0'<=str[i] && str[i]<='9' && i<len)
{
ret+=num_pow*(str[i++]-'0');
num_pow*=0.1;
}
}
if(i==len) return ret;
if(str[i]!='e' && str[i]!='E')
return std::nan("");
++i;
if(i==len) return std::nan("");
double negative=(str[i]=='-'? -1:1);
if(str[i]=='-' || str[i]=='+')
++i;
if(i==len) return std::nan("");
double num_pow=0;
for(;i<len;++i)
{
if('0'<=str[i] && str[i]<='9')
num_pow=num_pow*10+(str[i]-'0');
else
return std::nan("");
}
return ret*std::pow(10,negative*num_pow);
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 trans_string_to_number(std::string str)
double str2num(const char* str)
{
double is_negative=1;
int len=str.length();
double ret_num=0;
if(!len) return std::nan("");
if(str[0]=='-' || str[0]=='+')
{
if(len==1) return std::nan("");
is_negative=(str[0]=='-'?-1:1);
str=str.substr(1,len--);
}
if(len>1 && str[0]=='0' && str[1]=='x')
ret_num=hex_to_double(str);
else if(len>1 && str[0]=='0' && str[1]=='o')
ret_num=oct_to_double(str);
else
ret_num=dec_to_double(str,len);
return is_negative*ret_num;
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;
}
/*
trans_number_to_string:
convert number to string
show raw string
*/
std::string trans_number_to_string(double number)
void raw_string(const std::string& str)
{
std::string res;
std::stringstream ss;
ss<<number;
ss>>res;
return res;
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"
@@ -133,8 +131,7 @@ std::string trans_number_to_string(double number)
#include "nasal_import.h"
#include "nasal_gc.h"
#include "nasal_builtin.h"
#include "nasal_runtime.h"
#include "nasal_codegen.h"
#include "nasal_bytecode_vm.h"
#include "nasal_vm.h"
#endif

View File

@@ -3,230 +3,151 @@
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_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_add_equal,ast_sub_equal,ast_mult_equal,ast_div_equal,ast_link_equal,
ast_cmp_equal,ast_cmp_not_equal,
ast_less_than,ast_less_equal,
ast_greater_than,ast_greater_equal,
ast_equal,ast_addeq,ast_subeq,ast_multeq,ast_diveq,ast_lnkeq,
ast_cmpeq,ast_neq,
ast_less,ast_leq,
ast_grt,ast_geq,
ast_add,ast_sub,ast_mult,ast_div,ast_link,
ast_unary_sub,ast_unary_not,
ast_trinocular,
ast_neg,ast_not,
ast_trino,
ast_for,ast_forindex,ast_foreach,ast_while,ast_new_iter,
ast_conditional,ast_if,ast_elsif,ast_else,
ast_multi_id,ast_multi_scalar,
ast_definition,ast_multi_assign,
ast_continue,ast_break,ast_return
ast_def,ast_multi_assign,
ast_continue,ast_break,ast_ret
};
std::string ast_str(int type)
const char* ast_name[]=
{
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;
}
"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;
double num;
std::vector<nasal_ast> children;
public:
nasal_ast(int,int);
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 set_num(double);
void add_child(nasal_ast);
int get_line();
int get_type();
std::string get_str();
double get_num();
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(int init_line=0,int init_type=ast_null)
{
this->line=init_line;
this->type=init_type;
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->num=tmp.num;
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->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->num=tmp.num;
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->str="";
this->num=0;
this->type=ast_null;
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::set_num(double n)
{
this->num=n;
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;
}
double nasal_ast::get_num()
{
return this->num;
}
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_string || this->type==ast_identifier || this->type==ast_dynamic_id || this->type==ast_call_hash)
std::cout<<":"<<this->str;
else if(this->type==ast_number)
std::cout<<":"<<this->num;
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;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1026
nasal_gc.h

File diff suppressed because it is too large Load Diff

View File

@@ -4,53 +4,37 @@
class nasal_import
{
private:
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 link(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_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_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
@@ -58,51 +42,44 @@ 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))
@@ -113,65 +90,45 @@ nasal_ast nasal_import::file_import(nasal_ast& node)
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::link(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

View File

@@ -7,8 +7,8 @@
#define IS_DIGIT(c) ('0'<=c&&c<='9')
#define IS_STRING(c) (c=='\''||c=='\"'||c=='`')
// single operators have only one character
#define IS_SINGLE_OPRATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\
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(c) (c=='#')
@@ -16,72 +16,73 @@
enum token_type
{
tok_null=0,
tok_number,tok_string,tok_identifier,
tok_num,tok_str,tok_id,
tok_for,tok_forindex,tok_foreach,tok_while,
tok_var,tok_func,tok_break,tok_continue,
tok_return,tok_if,tok_elsif,tok_else,tok_nil,
tok_left_curve,tok_right_curve,
tok_left_bracket,tok_right_bracket,
tok_left_brace,tok_right_brace,
tok_ret,tok_if,tok_elsif,tok_else,tok_nil,
tok_lcurve,tok_rcurve,
tok_lbracket,tok_rbracket,
tok_lbrace,tok_rbrace,
tok_semi,tok_and,tok_or,tok_comma,tok_dot,tok_ellipsis,tok_quesmark,
tok_colon,tok_add,tok_sub,tok_mult,tok_div,tok_link,tok_not,
tok_equal,
tok_add_equal,tok_sub_equal,tok_mult_equal,tok_div_equal,tok_link_equal,
tok_cmp_equal,tok_cmp_not_equal,tok_less_than,tok_less_equal,tok_greater_than,tok_greater_equal
tok_eq,
tok_addeq,tok_subeq,tok_multeq,tok_diveq,tok_lnkeq,
tok_cmpeq,tok_neq,tok_less,tok_leq,tok_grt,tok_geq,
tok_eof
};
struct
{
const char* str;
int tok_type;
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_return },
{"if" ,tok_if },
{"elsif" ,tok_elsif },
{"else" ,tok_else },
{"nil" ,tok_nil },
{"(" ,tok_left_curve },
{")" ,tok_right_curve },
{"[" ,tok_left_bracket },
{"]" ,tok_right_bracket},
{"{" ,tok_left_brace },
{"}" ,tok_right_brace },
{";" ,tok_semi },
{"and" ,tok_and },
{"or" ,tok_or },
{"," ,tok_comma },
{"." ,tok_dot },
{"..." ,tok_ellipsis },
{"?" ,tok_quesmark },
{":" ,tok_colon },
{"+" ,tok_add },
{"-" ,tok_sub },
{"*" ,tok_mult },
{"/" ,tok_div },
{"~" ,tok_link },
{"!" ,tok_not },
{"=" ,tok_equal },
{"+=" ,tok_add_equal },
{"-=" ,tok_sub_equal },
{"*=" ,tok_mult_equal },
{"/=" ,tok_div_equal },
{"~=" ,tok_link_equal },
{"==" ,tok_cmp_equal },
{"!=" ,tok_cmp_not_equal},
{"<" ,tok_less_than },
{"<=" ,tok_less_equal },
{">" ,tok_greater_than },
{">=" ,tok_greater_equal},
{NULL ,-1 }
{"for" ,tok_for },
{"forindex",tok_forindex },
{"foreach" ,tok_foreach },
{"while" ,tok_while },
{"var" ,tok_var },
{"func" ,tok_func },
{"break" ,tok_break },
{"continue",tok_continue },
{"return" ,tok_ret },
{"if" ,tok_if },
{"elsif" ,tok_elsif },
{"else" ,tok_else },
{"nil" ,tok_nil },
{"(" ,tok_lcurve },
{")" ,tok_rcurve },
{"[" ,tok_lbracket },
{"]" ,tok_rbracket },
{"{" ,tok_lbrace },
{"}" ,tok_rbrace },
{";" ,tok_semi },
{"and" ,tok_and },
{"or" ,tok_or },
{"," ,tok_comma },
{"." ,tok_dot },
{"..." ,tok_ellipsis },
{"?" ,tok_quesmark },
{":" ,tok_colon },
{"+" ,tok_add },
{"-" ,tok_sub },
{"*" ,tok_mult },
{"/" ,tok_div },
{"~" ,tok_link },
{"!" ,tok_not },
{"=" ,tok_eq },
{"+=" ,tok_addeq },
{"-=" ,tok_subeq },
{"*=" ,tok_multeq },
{"/=" ,tok_diveq },
{"~=" ,tok_lnkeq },
{"==" ,tok_cmpeq },
{"!=" ,tok_neq },
{"<" ,tok_less },
{"<=" ,tok_leq },
{">" ,tok_grt },
{">=" ,tok_geq },
{nullptr ,-1 }
};
struct token
@@ -89,53 +90,41 @@ 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::vector<char> res;
int res_size;
int line;
int ptr;
std::string line_code;
std::string res;
std::vector<token> token_list;
std::string identifier_gen();
std::string number_gen();
std::string string_gen();
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 openfile(std::string);
void die(std::string,int,int);
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)
{
error=0;
res_size=0;
line=0;
ptr=0;
line_code="";
res.clear();
token_list.clear();
return;
}
void nasal_lexer::openfile(std::string filename)
{
error=0;
res.clear();
error=0;
res.clear();
std::ifstream fin(filename,std::ios::binary);
if(fin.fail())
{
++error;
std::cout<<">> [lexer] cannot open file \""<<filename<<"\".\n";
fin.close();
++error;
std::cout<<"[lexer] cannot open file <"<<filename<<">.\n";
return;
}
while(!fin.eof())
@@ -143,244 +132,189 @@ void nasal_lexer::openfile(std::string filename)
char c=fin.get();
if(fin.eof())
break;
res.push_back(c);
res+=c;
}
fin.close();
res_size=res.size();
return;
}
void nasal_lexer::die(std::string error_info,int line=-1,int column=-1)
int nasal_lexer::get_tok_type(const std::string& tk_str)
{
++error;
std::cout<<">> [lexer] line "<<line<<" column "<<column<<": "<<error_info<<"\n";
return;
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;
}
std::string nasal_lexer::identifier_gen()
void nasal_lexer::die(const char* error_info)
{
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
++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::number_gen()
std::string nasal_lexer::id_gen()
{
bool scientific_notation=false;// numbers like 1e8 are scientific_notation
std::string token_str="";
// generate hex number
if(res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='x')
{
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=="0x")
{
die("["+line_code+"_] incorrect number.",line,line_code.length());
return "0";
}
return token_str;
}
// generate oct number
else if(res[ptr]=='0' && ptr+1<res_size && res[ptr+1]=='o')
{
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=="0o")
{
die("["+line_code+"_] incorrect number.",line,line_code.length());
return "0";
}
return token_str;
}
// generate dec number
// dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
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)
{
line_code+=token_str;
die("["+line_code+"_] incorrect number.",line,line_code.length());
return "0";
}
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("["+line_code+"_] incorrect number.",line,line_code.length());
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)
{
line_code+=token_str;
die("["+line_code+"_] incorrect number.",line,line_code.length());
return "0";
}
if(ptr<res_size && (res[ptr]=='-' || res[ptr]=='+'))
token_str+=res[ptr++];
if(ptr>=res_size)
{
line_code+=token_str;
die("["+line_code+"_] incorrect number.",line,line_code.length());
return "0";
}
if(ptr<res_size && res[ptr]=='0')
token_str+=res[ptr++];
while(ptr<res_size && IS_DIGIT(res[ptr]))
token_str+=res[ptr++];
// "xxxe(-|+)" is not a correct number
if(token_str.back()=='e' || token_str.back()=='E' || token_str.back()=='-' || token_str.back()=='+')
{
line_code+=token_str;
die("["+line_code+"_] incorrect number.",line,line_code.length());
return "0";
}
}
line_code+=token_str;
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
}
std::string nasal_lexer::string_gen()
std::string nasal_lexer::num_gen()
{
std::string token_str="";
line_code+=res[ptr];
char str_begin=res[ptr++];
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)
{
++ptr;
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;
}
}
else
token_str+=res[ptr];
++ptr;
}
// check if this string ends with a " or '
if(ptr>=res_size)
die("["+line_code+"_] get EOF when generating string.",line,line_code.length());
++ptr;
return token_str;
// 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()
{
token_list.clear();
line=1;
ptr=0;
line_code="";
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="";
}
++ptr;
}
if(ptr>=res_size) break;
if(IS_IDENTIFIER(res[ptr]))
{
token_str=identifier_gen();
token new_token;
new_token.line=line;
new_token.str=token_str;
new_token.type=0;
for(int i=0;token_table[i].str;++i)
if(token_str==token_table[i].str)
{
new_token.type=token_table[i].tok_type;
break;
}
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();
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(res[ptr]))
{
token_str=string_gen();
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];
line_code+=res[ptr];
token new_token;
new_token.line=line;
new_token.str=token_str;
new_token.type=-1;
for(int i=0;token_table[i].str;++i)
if(token_str==token_table[i].str)
{
new_token.type=token_table[i].tok_type;
break;
}
if(new_token.type<0)
die("["+line_code+"_] incorrect operator.",line,line_code.length());
token_list.push_back(new_token);
++ptr;
}
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]=='.')
@@ -393,72 +327,36 @@ void nasal_lexer::scanner()
token_str=".";
++ptr;
}
line_code+=token_str;
token new_token;
new_token.line=line;
new_token.str=token_str;
for(int i=0;token_table[i].str;++i)
if(token_str==token_table[i].str)
{
new_token.type=token_table[i].tok_type;
break;
}
token_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=res[ptr];
++ptr;
if(ptr<res.size() && res[ptr]=='=')
{
token_str+=res[ptr];
++ptr;
}
line_code+=token_str;
token new_token;
new_token.line=line;
new_token.str=token_str;
for(int i=0;token_table[i].str;++i)
if(token_str==token_table[i].str)
{
new_token.type=token_table[i].tok_type;
break;
}
token_list.push_back(new_token);
}
else if(IS_NOTE(res[ptr]))
{
// avoid note
while(ptr<res_size && res[ptr]!='\n') ++ptr;
// after this process ptr will point to a '\n'
// don't ++ptr then the counter for line can work correctly
}
else
{
line_code+=res[ptr];
die("["+line_code+"_] unknown character.",line,line_code.length());
++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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}
};
}

View File

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

View File

@@ -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();

View File

@@ -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();

View File

@@ -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
View 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
View 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);

View File

@@ -1,8 +1,9 @@
import("lib.nas");
import("queue.nas");
import("stl/lib.nas");
import("stl/queue.nas");
rand(time(0));
var pixel=[' ','#','.','*'];
var map=[];
for(var i=0;i<10;i+=1)
{
@@ -17,49 +18,43 @@ var prt=func()
for(var i=0;i<10;i+=1)
{
for(var j=0;j<10;j+=1)
s~=map[i][j];
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 queue=new_queue();
queue_push(queue,begin);
map[begin[0]][begin[1]]=3;
while(!queue_empty(queue))
var que=queue();
que.push(begin);
map[begin[0]][begin[1]]=2;
while(!que.empty())
{
var vertex=queue_front(queue);
queue_pop(queue);
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]='*';
map[x][y]=3;
prt();
return;
}
if(0<=x and x<10 and 0<=y and y<10 and map[x][y]==0)
{
queue_push(queue,[x,y]);
map[x][y]=3;
que.push([x,y]);
map[x][y]=2;
}
}
prt();
}
print("cannot reach.");
print("cannot reach.\n");
return;
}
prt();
var x=num(input());
var y=num(input());
var begin=[x,y];
x=num(input());
y=num(input());
var end=[x,y];
bfs(begin,end);
prt();
bfs([0,0],[9,9]);

1
test/bigloop.nas Normal file
View File

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

View File

@@ -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
View 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');
}();

View File

@@ -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];

View File

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

View File

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

68
test/class.nas Normal file
View 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

File diff suppressed because it is too large Load Diff

39
test/exception.nas Normal file
View 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
View 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');

View File

@@ -1,210 +0,0 @@
var smartScreen = canvas.new({
"name": "smartScreen", # The name is optional but allow for easier identification
"size": [2048, 2048], # Size of the underlying texture (should be a power of 2, required) [Resolution]
"view": [768, 768], # Virtual resolution (Defines the coordinate system of the canvas [Dimensions]
# which will be stretched the size of the texture, required)
"mipmapping": 1 # Enable mipmapping (optional)
});
smartScreen.addPlacement({"node": "screen", "texture": "screen.jpeg"});
var group = smartScreen.createGroup();
# Create a text element and set some values
var text = group.createChild("text", "optional-id-for element")
.setTranslation(10, 20) # The origin is in the top left corner
.setAlignment("left-center") # All values from osgText are supported (see $FG_ROOT/Docs/README.osgtext)
.setFont("LiberationFonts/LiberationSans-Regular.ttf") # Fonts are loaded either from $AIRCRAFT_DIR/Fonts or $FG_ROOT/Fonts
.setFontSize(14, 1.2) # Set fontsize and optionally character aspect ratio
.setColor(1,0,0) # Text color
.setText("This is a text element");
text.hide();
text.setText("SELF TEST NORMAL").show();
var ui_root = smartScreen.createGroup();
var vbox = canvas.VBoxLayout.new();
smartScreen.setLayout(vbox);
var button_onl = canvas.gui.widgets.Button.new(ui_root, canvas.style, {}).setText("Online OSM").listen("clicked", func showOnlineMap());
var button_offl = canvas.gui.widgets.Button.new(ui_root, canvas.style, {}).setText("Offline OSM").listen("clicked", func showOfflineMap());
button_onl.setSizeHint([32, 128]);
button_offl.setSizeHint([32, 128]);
var label = canvas.gui.widgets.Label.new(ui_root, canvas.style, {});
var button_box = canvas.HBoxLayout.new();
button_box.addItem(button_onl);
button_box.addItem(button_offl);
button_box.addItem(label);
button_box.addStretch(1);
vbox.addItem(button_box);
vbox.addStretch(1);
var showOnlineMap = func(){
TestMap.show();
g.hide();
label.setText("Online Mode");
}
var showOfflineMap = func(){
TestMap.hide();
g.show();
label.setText("Offline Mode");
}
# Online Map using MapStructure
var TestMap = smartScreen.createGroup().createChild("map");
TestMap.setTranslation(smartScreen.get("view[0]")/2,smartScreen.get("view[1]")/2);
var ctrl_ns = canvas.Map.Controller.get("Aircraft position");
var source = ctrl_ns.SOURCES["map-dialog"];
if (source == nil) {
# TODO: amend
var source = ctrl_ns.SOURCES["map-dialog"] = {
getPosition: func subvec(geo.aircraft_position().latlon(), 0, 2),# ? ? ?
getAltitude: func getprop('/position/altitude-ft'),
getHeading: func {
if (me.aircraft_heading)
getprop('/orientation/heading-deg');
else
0;
},
aircraft_heading: 1,
};
}
setlistener("/sim/gui/dialogs/map-canvas/aircraft-heading-up", func(n){source.aircraft_heading = n.getBoolValue();}, 1);
TestMap.setController("Aircraft position", "map-dialog");
TestMap.setRange(1);
var r = func(name,vis=1,zindex=nil){return caller(0)[0];};
# TODO: we'll need some z-indexing here, right now it's just random
foreach(var type; [r('APS')] ){
TestMap.addLayer(factory: canvas.SymbolLayer, type_arg: type.name, visible: type.vis, priority: 2);
}
foreach(var type; [ r('OSM')]) {
TestMap.addLayer(factory: canvas.OverlayLayer,
type_arg: type.name,
visible: type.vis,
priority: 1);
}
TestMap.hide();
# Offline map
var g = smartScreen.createGroup();
var zoom = 15;
var type = "intl";
var tile_size = 256;
var changeZoom = func(d)
{
zoom = math.max(2, math.min(19, zoom + d));
updateTiles();
}
# http://polymaps.org/docs/
# https://github.com/simplegeo/polymaps
# https://github.com/Leaflet/Leaflet
var maps_base = getprop("/sim/fg-home") ~ '/cache/maps';
var makePath =
string.compileTemplate(maps_base ~ '/osm-{type}/{z}/{x}/{y}.jpg');
var num_tiles = [4, 4];
var center_tile_offset = [(num_tiles[0]-1)/2, (num_tiles[1]-1)/ 2];
# simple aircraft icon at current position/center of the map
g.createChild("path")
.moveTo( tile_size*center_tile_offset[0]-10, tile_size*center_tile_offset[1])
.horiz(20)
.move(-10,-10)
.vert(20)
.set("stroke", "red")
.set("stroke-width", 2)
.set("z-index", 1);
# initialize the map by setting up
# a grid of raster images
var tiles = setsize([], num_tiles[0]);
for(var x=0; x<num_tiles[0]; x+=1)
{
tiles[x] = setsize([], num_tiles[1]);
for(var y=0; y<num_tiles[1]; y+=1)
tiles[x][y] = g.createChild("image", "map-tile");
}
var last_tile = [-1,-1];
var last_type = type;
# this is the callback that will be regularly called by the timer
# to update the map
var updateTiles = func()
{
# get current position
var lat = getprop('/position/latitude-deg');
var lon = getprop('/position/longitude-deg');
var n = math.pow(2, zoom);
var offset = [n*((lon+180)/360)-center_tile_offset[0], (1-math.ln(math.tan(lat*math.pi/180)+1/math.cos(lat*math.pi/180))/math.pi)/2*n-center_tile_offset[1]];
var tile_index = [int(offset[0]), int(offset[1])];
var ox = tile_index[0] - offset[0];
var oy = tile_index[1] - offset[1];
for(var x = 0; x < num_tiles[0]; x += 1)
for(var y = 0; y < num_tiles[1]; y += 1)
tiles[x][y].setTranslation(int((ox + x) * tile_size + 0.5), int((oy + y) * tile_size + 0.5));
if( tile_index[0] != last_tile[0]
or tile_index[1] != last_tile[1]
or type != last_type )
{
for(var x = 0; x < num_tiles[0]; x += 1)
for(var y = 0; y < num_tiles[1]; y += 1)
{
var pos = {
z: zoom,
x: int(offset[0] + x),
y: int(offset[1] + y),
type: type
};
(func {
var img_path = makePath(pos);
var tile = tiles[x][y];
print('loading ' ~ img_path);
tile.set("src", img_path);
})();
# lambda
}
last_tile = tile_index;
last_type = type;
}
};
# set up a timer that will invoke updateTiles at 2-second intervals
var update_timer = maketimer(2, updateTiles);
# actually start the timer
update_timer.start();
# set up default zoom level
changeZoom(0);
#g.hide();

View File

@@ -1,643 +0,0 @@
###############################################################################
##
## Nasal module for dual control over the multiplayer network.
##
## Copyright (C) 2007 - 2010 Anders Gidenstam (anders(at)gidenstam.org)
## This file is licensed under the GPL license version 2 or later.
##
###############################################################################
## MP properties
var lat_mpp = "position/latitude-deg";
var lon_mpp = "position/longitude-deg";
var alt_mpp = "position/altitude-ft";
var heading_mpp = "orientation/true-heading-deg";
var pitch_mpp = "orientation/pitch-deg";
var roll_mpp = "orientation/roll-deg";
# Import components from the mp_broadcast module.
var Binary = mp_broadcast.Binary;
var MessageChannel = mp_broadcast.MessageChannel;
###############################################################################
# Utility classes
############################################################
# Translate a property into another.
# Factor and offsets are only used for numeric values.
# src - source : property node
# dest - destination : property node
# factor - : double
# offset - : double
var Translator = {};
Translator.new = func (src = nil, dest = nil, factor = 1, offset = 0) {
var obj = { parents : [Translator],
src : src,
dest : dest,
factor : factor,
offset : offset };
if (obj.src == nil or obj.dest == nil) {
print("Translator[");
print(" ", debug.string(obj.src));
print(" ", debug.string(obj.dest));
print("]");
fail();
}
return obj;
}
Translator.update = func () {
var v = me.src.getValue();
if (is_num(v)) {
me.dest.setValue(me.factor * v + me.offset);
} else {
if (typeof(v) == "scalar")
me.dest.setValue(v);
}
}
############################################################
# Detects flanks on two insignals encoded in a property.
# - positive signal up/down flank
# - negative signal up/down flank
# n - source : property node
# on_positive_flank - action : func (v)
# on_negative_flank - action : func (v)
var EdgeTrigger = {};
EdgeTrigger.new = func (n, on_positive_flank, on_negative_flank) {
var obj = { parents : [EdgeTrigger],
old : 0,
node : n,
pos_flank : on_positive_flank,
neg_flank : on_negative_flank };
if (obj.node == nil) {
print("EdgeTrigger[");
print(" ", debug.string(obj.node));
print("]");
fail();
}
return obj;
}
EdgeTrigger.update = func {
# NOTE: float MP properties get interpolated.
# This detector relies on that steady state is reached between
# flanks.
var val = me.node.getValue();
if (!is_num(val)) return;
if (me.old == 1) {
if (val < me.old) {
me.pos_flank(0);
}
} elsif (me.old == 0) {
if (val > me.old) {
me.pos_flank(1);
} elsif (val < me.old) {
me.neg_flank(1);
}
} elsif (me.old == -1) {
if (val > me.old) {
me.neg_flank(0);
}
}
me.old = val;
}
############################################################
# StableTrigger: Triggers an action when a MPP property
# becomes stable (i.e. doesn't change for
# MIN_STABLE seconds).
# src - MP prop : property node
# action - action to take when the value becomes stable : [func(v)]
# An action is triggered when value has stabilized.
var StableTrigger = {};
StableTrigger.new = func (src, action) {
var obj = { parents : [StableTrigger],
src : src,
action : action,
old : 0,
stable_since : 0,
wait : 0,
MIN_STABLE : 0.01 };
# Error checking.
var bad = (obj.src == nil) or (action = nil);
if (bad) {
print("StableTrigger[");
print(" ", debug.string(obj.src));
print(" ", debug.string(obj.action));
print("]");
fail();
}
return obj;
}
StableTrigger.update = func () {
var v = me.src.getValue();
if (!is_num(v)) return;
var t = getprop("/sim/time/elapsed-sec"); # NOTE: simulated time.
if ((me.old == v) and
((t - me.stable_since) > me.MIN_STABLE) and (me.wait == 1)) {
# Trigger action.
me.action(v);
me.wait = 0;
} elsif (me.old == v) {
# Wait. This is either before the signal is stable or after the action.
} else {
me.stable_since = t;
me.wait = 1;
me.old = me.src.getValue();
}
}
############################################################
# Selects the most recent value of two properties.
# src1 - : property node
# src2 - : property node
# dest - : property node
# threshold - : double
var MostRecentSelector = {};
MostRecentSelector.new = func (src1, src2, dest, threshold) {
var obj = { parents : [MostRecentSelector],
old1 : 0,
old2 : 0,
src1 : src1,
src2 : src2,
dest : dest,
thres : threshold };
if (obj.src1 == nil or obj.src2 == nil or obj.dest == nil) {
print("MostRecentSelector[");
print(" ", debug.string(obj.src1));
print(" ", debug.string(obj.src2));
print(" ", debug.string(obj.dest));
print("]");
}
return obj;
}
MostRecentSelector.update = func {
var v1 = me.src1.getValue();
var v2 = me.src2.getValue();
if (!is_num(v1) and !is_num(v2)) return;
elsif (!is_num(v1)) me.dest.setValue(v2);
elsif (!is_num(v2)) me.dest.setValue(v1);
else {
if (abs (v2 - me.old2) > me.thres) {
me.old2 = v2;
me.dest.setValue(me.old2);
}
if (abs (v1 - me.old1) > me.thres) {
me.old1 = v1;
me.dest.setValue(me.old1);
}
}
}
############################################################
# Adds two input properties.
# src1 - : property node
# src2 - : property node
# dest - : property node
var Adder = {};
Adder.new = func (src1, src2, dest) {
var obj = { parents : [DeltaAccumulator],
src1 : src1,
src2 : src2,
dest : dest };
if (obj.src1 == nil or obj.src2 == nil or obj.dest == nil) {
print("Adder[");
print(" ", debug.string(obj.src1));
print(" ", debug.string(obj.src2));
print(" ", debug.string(obj.dest));
print("]");
fail();
}
return obj;
}
Adder.update = func () {
var v1 = me.src1.getValue();
var v2 = me.src2.getValue();
if (!is_num(v1) or !is_num(v2)) return;
me.dest.setValue(v1 + v2);
}
############################################################
# Adds the delta of src to dest.
# src - : property node
# dest - : property node
var DeltaAdder = {};
DeltaAdder.new = func (src, dest) {
var obj = { parents : [DeltaAdder],
old : 0,
src : src,
dest : dest };
if (obj.src == nil or obj.dest == nil) {
print("DeltaAdder[", debug.string(obj.src), ", ",
debug.string(obj.dest), "]");
fail();
}
return obj;
}
DeltaAdder.update = func () {
var v = me.src.getValue();
if (!is_num(v)) return;
me.dest.setValue((v - me.old) + me.dest.getValue());
me.old = v;
}
############################################################
# Switch encoder: Encodes upto 32 boolean properties in one
# int property.
# inputs - list of property nodes
# dest - where the bitmask is stored : property node
var SwitchEncoder = {};
SwitchEncoder.new = func (inputs, dest) {
var obj = { parents : [SwitchEncoder],
inputs : inputs,
dest : dest };
# Error checking.
var bad = (obj.dest == nil);
foreach (var i; inputs) {
if (i == nil) { bad = 1; }
}
if (bad) {
print("SwitchEncoder[");
foreach (var i; inputs) {
print(" ", debug.string(i));
}
print(" ", debug.string(obj.dest));
print("]");
fail();
}
return obj;
}
SwitchEncoder.update = func () {
var v = 0;
var b = 1;
forindex (var i; me.inputs) {
if (me.inputs[i].getBoolValue()) {
v = v + b;
}
b *= 2;
}
me.dest.setIntValue(v);
}
############################################################
# Switch decoder: Decodes a bitmask in an int property.
# src - : property node
# actions - list of actions : [func(b)]
# Actions are triggered when their input bit change.
# Due to interpolation the decoder needs to wait for a
# stable input value.
var SwitchDecoder = {};
SwitchDecoder.new = func (src, actions) {
var obj = { parents : [SwitchDecoder],
wait : 0,
old : 0,
old_stable : 0,
stable_since : 0,
reset : 1,
src : src,
actions : actions,
MIN_STABLE : 0.1 };
# Error checking.
var bad = (obj.src == nil);
foreach (var a; obj.actions) {
if (a == nil) { bad = 1; }
}
if (bad) {
print("SwitchDecoder[");
print(" ", debug.string(obj.src));
foreach (var a; obj.actions) {
print(" ", debug.string(a));
}
print("]");
fail();
}
return obj;
}
SwitchDecoder.update = func () {
var t = getprop("/sim/time/elapsed-sec"); # NOTE: simulated time.
var v = me.src.getValue();
if (!is_num(v)) return;
if ((me.old == v) and ((t - me.stable_since) > me.MIN_STABLE) and
(me.wait == 1)) {
var ov = me.old_stable;
# Use this to improve.
#<cptf> here's the boring version: var bittest = func(u, b) { while (b) { u = int(u / 2); b -= 1; } u != int(u / 2) * 2; }
forindex (var i; me.actions) {
var m = math.mod(v, 2);
var om = math.mod(ov, 2);
if ((m != om or me.reset)) { me.actions[i](m?1:0); }
v = (v - m)/2;
ov = (ov - om)/2;
}
me.old_stable = me.src.getValue();
me.wait = 0;
me.reset = 0;
} elsif (me.old == v) {
# Wait. This is either before the bitmask is stable or after
# it has been processed.
} else {
me.stable_since = t;
me.wait = 1;
me.old = me.src.getValue();
}
}
############################################################
# Time division multiplexing encoder: Transmits a list of
# properties over a MP enabled string property.
# inputs - input properties : [property node]
# dest - MP string prop : property node
# Note: TDM can have high latency so it is best used for
# non-time critical properties.
var TDMEncoder = {};
TDMEncoder.new = func (inputs, dest) {
var obj = { parents : [TDMEncoder],
inputs : inputs,
channel : MessageChannel.new(dest,
func (msg) {
print("This should not happen!");
}),
MIN_INT : 0.25,
last_time : 0,
next_item : 0,
old : [] };
# Error checking.
var bad = (dest == nil) or (obj.channel == nil);
foreach (var i; inputs) {
if (i == nil) { bad = 1; }
}
if (bad) {
print("TDMEncoder[");
foreach (var i; inputs) {
print(" ", debug.string(i));
}
print(" ", debug.string(dest));
print("]");
}
setsize(obj.old, size(obj.inputs));
return obj;
}
TDMEncoder.update = func () {
var t = getprop("/sim/time/elapsed-sec"); # NOTE: simulated time.
if (t > me.last_time + me.MIN_INT) {
var n = size(me.inputs);
while (1) {
var v = me.inputs[me.next_item].getValue();
if ((n <= 0) or (me.old[me.next_item] != v)) {
# Set the MP properties to send the next item.
me.channel.send(Binary.encodeByte(me.next_item) ~
Binary.encodeDouble(v));
me.old[me.next_item] = v;
me.last_time = t;
me.next_item += 1;
if (me.next_item >= size(me.inputs)) { me.next_item = 0; }
return;
} else {
# Search for changed property.
n -= 1;
me.next_item += 1;
if (me.next_item >= size(me.inputs)) { me.next_item = 0; }
}
}
}
}
############################################################
# Time division multiplexing decoder: Receives a list of
# properties over a MP enabled string property.
# src - MP string prop : property node
# actions - list of actions : [func(v)]
# An action is triggered when its value is received.
# Note: TDM can have high latency so it is best used for
# non-time critical properties.
var TDMDecoder = {};
TDMDecoder.new = func (src, actions) {
var obj = { parents : [TDMDecoder],
actions : actions };
obj.channel = MessageChannel.new(src,
func (msg) {
obj.process(msg);
});
# Error checking.
var bad = (src == nil) or (obj.channel == nil);
foreach (var a; actions) {
if (a == nil) { bad = 1; }
}
if (bad) {
print("TDMDecoder[");
print(" ", debug.string(src));
foreach (var a; actions) {
print(" ", debug.string(a));
}
print("]");
fail();
}
return obj;
}
TDMDecoder.process = func (msg) {
var v1 = Binary.decodeByte(msg);
var v2 = Binary.decodeDouble(substr(msg, 1));
# Trigger action.
me.actions[v1](v2);
}
TDMDecoder.update = func {
me.channel.update();
}
###############################################################################
# Internal utility functions
var is_num = func (v) {
return num(v) != nil;
}
# fail causes a Nasal runtime error so we get a backtrace.
var fail = func {
error_detected_in_calling_context();
}
###############################################################################
###############################################################################
# Copilot selection dialog.
#
# Usage: dual_control_tools.copilot_dialog.show(<copilot type string>);
#
var COPILOT_DLG = 0;
var copilot_dialog = {};
############################################################
copilot_dialog.init = func (copilot_type, x = nil, y = nil) {
me.x = x;
me.y = y;
me.bg = [0, 0, 0, 0.3]; # background color
me.fg = [[1.0, 1.0, 1.0, 1.0]];
#
# "private"
if (contains(aircraft_dual_control, "copilot_view")) {
me.title = "Pilot selection";
} else {
me.title = "Copilot selection";
}
me.basenode = props.globals.getNode("sim/remote", 1);
me.dialog = nil;
me.namenode = props.Node.new({"dialog-name" : me.title });
me.listeners = [];
me.copilot_type = copilot_type;
}
############################################################
copilot_dialog.create = func {
if (me.dialog != nil)
me.close();
me.dialog = gui.Widget.new();
me.dialog.set("name", me.title);
if (me.x != nil)
me.dialog.set("x", me.x);
if (me.y != nil)
me.dialog.set("y", me.y);
me.dialog.set("layout", "vbox");
me.dialog.set("default-padding", 0);
var titlebar = me.dialog.addChild("group");
titlebar.set("layout", "hbox");
titlebar.addChild("empty").set("stretch", 1);
if (contains(aircraft_dual_control, "copilot_view")) {
titlebar.addChild("text").set("label", "Book your flight");
} else {
titlebar.addChild("text").set("label", "Passengers online");
}
var w = titlebar.addChild("button");
w.set("pref-width", 16);
w.set("pref-height", 16);
w.set("legend", "");
w.set("default", 0);
w.set("key", "esc");
w.setBinding("nasal", "dual_control_tools.copilot_dialog.destroy(); ");
w.setBinding("dialog-close");
me.dialog.addChild("hrule");
var content = me.dialog.addChild("group");
content.set("layout", "vbox");
content.set("halign", "center");
content.set("default-padding", 5);
# Generate the dialog contents.
me.players = me.find_copilot_players();
var i = 0;
var tmpbase = me.basenode.getNode("dialog", 1);
var selected = me.basenode.getNode("pilot-callsign").getValue();
foreach (var p; me.players) {
var tmp = tmpbase.getNode("b[" ~ i ~ "]", 1);
tmp.setBoolValue(streq(selected, p));
var w = content.addChild("checkbox");
w.node.setValues({"label" : p,
"halign" : "left",
"property" : tmp.getPath()});
w.setBinding
("nasal",
"dual_control_tools.copilot_dialog.select_action(" ~ i ~ ");");
i = i + 1;
}
me.dialog.addChild("hrule");
# Display the dialog.
fgcommand("dialog-new", me.dialog.prop());
fgcommand("dialog-show", me.namenode);
}
############################################################
copilot_dialog.close = func {
fgcommand("dialog-close", me.namenode);
}
############################################################
copilot_dialog.destroy = func {
COPILOT_DLG = 0;
me.close();
foreach(var l; me.listeners)
removelistener(l);
delete(gui.dialog, "\"" ~ me.title ~ "\"");
}
############################################################
copilot_dialog.show = func (copilot_type) {
# print("Showing MPCopilots dialog!");
if (!COPILOT_DLG) {
COPILOT_DLG = int(getprop("/sim/time/elapsed-sec"));
me.init(copilot_type);
me.create();
me._update_(COPILOT_DLG);
}
}
############################################################
copilot_dialog._redraw_ = func {
if (me.dialog != nil) {
me.close();
me.create();
}
}
############################################################
copilot_dialog._update_ = func (id) {
if (COPILOT_DLG != id) return;
me._redraw_();
settimer(func { me._update_(id); }, 4.1);
}
############################################################
copilot_dialog.select_action = func (n) {
var selected = me.basenode.getNode("pilot-callsign").getValue();
var bs = me.basenode.getNode("dialog").getChildren();
# Assumption: There are two true b:s or none. The one not matching selected
# is the new selection.
var i = 0;
me.basenode.getNode("pilot-callsign").setValue("");
foreach (var b; bs) {
if (!b.getValue() and (i == n)) {
b.setValue(1);
me.basenode.getNode("pilot-callsign").setValue(me.players[i]);
} else {
b.setValue(0);
}
i = i + 1;
}
dual_control.main.reset();
me._redraw_();
}
############################################################
# Return a list containing all nearby copilot players of the right type.
copilot_dialog.find_copilot_players = func {
var mpplayers =
props.globals.getNode("ai/models").getChildren("multiplayer");
var res = [];
foreach (var pilot; mpplayers) {
if ((pilot.getNode("valid") != nil) and
(pilot.getNode("valid").getValue()) and
(pilot.getNode("sim/model/path") != nil)) {
var type = pilot.getNode("sim/model/path").getValue();
if (type == me.copilot_type) {
append(res, pilot.getNode("callsign").getValue());
}
}
}
# debug.dump(res);
return res;
}
###############################################################################

View File

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

File diff suppressed because it is too large Load Diff

View File

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

91
test/hexdump.nas Normal file
View 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);
}();

View File

@@ -1,4 +1,5 @@
#lib json.nas
import("lib.nas");
var json={
text:'',
line:1,

32
test/leetcode1319.nas Normal file
View 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));

View File

@@ -1,183 +1,193 @@
import("lib.nas");
var s=io.fin("a.nas");
s=split('',s);
var len=size(s);
var ptr=0;
var jump_note=func()
var lexer=func(file)
{
while(ptr<len and s[ptr]!='\n')
ptr+=1;
ptr+=1;
return;
}
var generate_id=func()
{
var tmp="";
while(ptr<len)
var (ptr,token)=(0,[]);
var s=io.fin(file);
var len=size(s);
return
{
if('a'<=s[ptr] and s[ptr]<='z'
or 'A'<=s[ptr] and s[ptr]<='Z'
or s[ptr]=='_'
or '0'<=s[ptr] and s[ptr]<='9')
tmp~=s[ptr];
else
break;
ptr+=1;
}
return tmp;
}
var generate_str=func()
{
var tok_str="";
var mark=s[ptr];
ptr+=1;
while(ptr<len and s[ptr]!=mark)
{
if(s[ptr]=='\\')
jmp_note:func()
{
while(ptr<len and chr(s[ptr])!='\n')
ptr+=1;
ptr+=1;
if(s[ptr]=='a') tok_str~='\a';
elsif(s[ptr]=='b') tok_str~='\b';
elsif(s[ptr]=='f') tok_str~='\f';
elsif(s[ptr]=='n') tok_str~='\n';
elsif(s[ptr]=='r') tok_str~='\r';
elsif(s[ptr]=='t') tok_str~='\t';
elsif(s[ptr]=='v') tok_str~='\v';
elsif(s[ptr]=='?') tok_str~='?';
elsif(s[ptr]=='0') tok_str~='\0';
elsif(s[ptr]=='\\') tok_str~='\\';
elsif(s[ptr]=='\'') tok_str~='\'';
elsif(s[ptr]=='\"') tok_str~='\"';
else tok_str~=s[ptr];
}
else
tok_str~=s[ptr];
ptr+=1;
}
if(ptr>=len)
print("read eof when generating string.");
ptr+=1;
return tok_str;
}
var generate_number=func()
{
var number=s[ptr];
ptr+=1;
if(s[ptr]=='x')
{
ptr+=1;
while(ptr<len and ('a'<=s[ptr] and s[ptr]<='f' or '0'<=s[ptr] and s[ptr]<='9'))
},
id_gen:func()
{
number~=s[ptr];
ptr+=1;
}
return num(number);
}
elsif(s[ptr]=='o')
{
ptr+=1;
while(ptr<len and ('0'<=s[ptr] and s[ptr]<='7'))
{
number~=s[ptr];
ptr+=1;
}
return num(number);
}
while(ptr<len and ('0'<=s[ptr] and s[ptr]<='9'))
{
number~=s[ptr];
ptr+=1;
}
if(s[ptr]=='.')
number~=s[ptr];
else
return num(number);
ptr+=1;
while(ptr<len and ('0'<=s[ptr] and s[ptr]<='9'))
{
number~=s[ptr];
ptr+=1;
}
if(s[ptr]=='e' or s[ptr]=='E')
number~=s[ptr];
else
return num(number);
ptr+=1;
if(s[ptr]=='-' or s[ptr]=='+')
{
number~=s[ptr];
ptr+=1;
}
while(ptr<len and ('0'<=s[ptr] and s[ptr]<='9'))
{
number~=s[ptr];
ptr+=1;
}
return num(number);
}
var generate_operator=func()
{
var tmp="";
if(s[ptr]=='+' or s[ptr]=='-' or s[ptr]=='~' or s[ptr]=='/' or s[ptr]=='*' or s[ptr]=='>' or s[ptr]=='<' or s[ptr]=='!' or s[ptr]=='=')
{
tmp=s[ptr];
ptr+=1;
if(ptr<len and s[ptr]=='=')
{
tmp~=s[ptr];
ptr+=1;
}
return tmp;
}
elsif(s[ptr]=='.')
{
if(ptr+2<len and s[ptr+1]=='.' and s[ptr+2]=='.')
{
tmp='...';
ptr+=3;
}
else
{
tmp='.';
ptr+=1;
}
return tmp;
}
elsif(s[ptr]!=' ' and s[ptr]!='\t' and s[ptr]!='\n' and s[ptr]!='\r' and s[ptr][0]>0)
tmp=s[ptr];
ptr+=1;
return tmp;
}
var cnt=0;
var token=[];
while(ptr<len)
{
if(s[ptr]=='#')
jump_note();
elsif('a'<=s[ptr] and s[ptr]<='z' or 'A'<=s[ptr] and s[ptr]<='Z' or s[ptr]=='_')
append(token,generate_id());
elsif(s[ptr]=='\'' or s[ptr]=='\"')
append(token,generate_str());
elsif('0'<=s[ptr] and s[ptr]<='9')
append(token,generate_number());
else
{
var tmp=generate_operator();
if(size(tmp))
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);
}
if(ptr>=len)
break;
},
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;}
};
}
foreach(var i;token)
{
print("(",cnt," | ",i,")");
cnt+=1;
}
var nasal_lexer=lexer("test/lexer.nas");
nasal_lexer.main();
var info="";
foreach(var tok;nasal_lexer.get_token())
info~=tok~' ';
println(info);

View File

@@ -1,167 +0,0 @@
var import=func(filename)
{
nasal_call_import(filename);
return nil;
}
var print=func(elements...)
{
nasal_call_builtin_std_cout(elements);
return nil;
};
var append=func(vector,elements...)
{
nasal_call_builtin_push_back(vector,elements);
return nil;
}
var setsize=func(vector,size)
{
nasal_call_builtin_set_size(vector,size);
return nil;
}
var system=func(str)
{
nasal_call_builtin_system(str);
return;
}
var input=func()
{
return nasal_call_builtin_input();
}
var sleep=func(duration)
{
nasal_call_builtin_sleep(duration);
return;
}
var split=func(delimeter,string)
{
return nasal_call_builtin_split(delimeter,string);
}
var rand=func(seed=nil)
{
return nasal_call_builtin_rand(seed);
}
var id=func(thing)
{
return nasal_call_builtin_get_id(thing);
}
var int=func(value)
{
return nasal_call_builtin_trans_int(value);
}
var num=func(value)
{
return nasal_call_builtin_trans_num(value);
}
var pop=func(vector)
{
return nasal_call_builtin_pop_back(vector);
}
var str=func(number)
{
return nasal_call_builtin_trans_str(number);
}
var size=func(object)
{
return nasal_call_builtin_size(object);
}
var contains=func(hash,key)
{
return nasal_call_builtin_contains(hash,key);
}
var delete=func(hash,key)
{
nasal_call_builtin_delete(hash,key);
return;
}
var keys=func(hash)
{
return nasal_call_builtin_get_keys(hash);
}
var time=func(begin_time)
{
return nasal_call_builtin_time(begin_time);
}
var die=func(str)
{
nasal_call_builtin_die(str);
return nil;
}
var typeof=func(object)
{
return nasal_call_builtin_type(object);
}
var substr=func(str,begin,length)
{
return nasal_call_builtin_substr(str,begin,length);
}
var io=
{
fin:func(filename)
{
return nasal_call_builtin_finput(filename);
},
fout:func(filename,str)
{
nasal_call_builtin_foutput(filename,str);
return;
}
};
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);
}
};
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);
},
};

62
test/life.nas Normal file
View 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;
}();

View File

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

View File

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

27
test/mandelbrot.nas Normal file
View 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);

View File

@@ -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

View File

@@ -1,156 +0,0 @@
import("lib.nas");
rand(time(0));
var chartable=split('','abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
var node=func(type)
{
var s="";
for(var i=0;i<10;i+=1)
s~=chartable[rand()*62];
return {name:s,type:type,next:[]};
}
var film_node=[];
for(var i=0;i<1000;i+=1)
append(film_node,node("film"));
var director_node=[];
for(var i=0;i<400;i+=1)
append(director_node,node("direct"));
var actor_node=[];
for(var i=0;i<2000;i+=1)
append(actor_node,node("actor"));
var writer_node=[];
for(var i=0;i<300;i+=1)
append(writer_node,node("writer"));
var type_node=[];
for(var i=0;i<20;i+=1)
append(type_node,node("type"));
var lang_node=[];
for(var i=0;i<120;i+=1)
append(lang_node,node("lang"));
var country_node=[];
for(var i=0;i<120;i+=1)
append(country_node,node("country"));
func()
{
var director_size=size(director_node);
var actor_size=size(actor_node);
var writer_size=size(writer_node);
var type_size=size(type_node);
var lang_size=size(lang_node);
var country_size=size(country_node);
var director_link=int(1+rand()*2);
var actor_link=int(1+rand()*10);
var writer_link=int(1+rand());
var type_link=int(1+rand()*3);
var lang_link=int(1+rand()*4);
var country_link=int(1+rand()*2);
foreach(var film;film_node)
{
for(var i=0;i<director_link;i+=1)
{
var director=director_node[rand()*director_size];
append(film.next,director);
append(director.next,film);
}
for(var i=0;i<actor_link;i+=1)
{
var actor=actor_node[rand()*actor_size];
append(film.next,actor);
append(actor.next,film);
}
for(var i=0;i<writer_link;i+=1)
{
var writer=writer_node[rand()*writer_size];
append(film.next,writer);
append(writer.next,film);
}
for(var i=0;i<type_link;i+=1)
{
var _type=type_node[rand()*type_size];
append(film.next,_type);
append(_type.next,film);
}
for(var i=0;i<lang_link;i+=1)
{
var lang=lang_node[rand()*lang_size];
append(film.next,lang);
append(lang.next,film);
}
for(var i=0;i<country_link;i+=1)
{
var country=country_node[rand()*country_size];
append(film.next,country);
append(country.next,film);
}
}
return;
}();
var film_list=[];
var count_list=[];
for(var i=0;i<10;i+=1)
{
append(film_list,film_node[i]);
append(count_list,1);
}
var sort_list=func(begin,end)
{
for(var i=begin;i<end;i+=1)
{
var index=i;
for(var j=i+1;j<end;j+=1)
if(count_list[index]<count_list[j])
index=j;
if(index!=i)
{
var tmp=film_list[i];
film_list[i]=film_list[index];
film_list[index]=tmp;
tmp=count_list[i];
count_list[i]=count_list[index];
count_list[index]=tmp;
}
}
return;
}
while(1)
{
var list_size=size(film_list);
list_size=list_size>10?10:list_size;
for(var i=0;i<list_size;i+=1)
print(i,'\t:',film_list[i].name,'\t',count_list[i]);
var choose=input();
if(choose=="exit")
break;
if(num(choose)>=list_size)
die("choose a correct index");
var label_list=film_node[num(choose)].next;
film_list=[];
count_list=[];
foreach(var label;label_list)
foreach(var film;label.next)
{
var has=0;
for(var i=0;i<size(film_list);i+=1)
if(film_list[i].name==film.name)
{
has=1;
count_list[i]+=rand();
break;
}
if(has==0)
{
append(film_list,film);
append(count_list,1);
}
}
sort_list(0,size(film_list));
}
foreach(var film;film_node)
setsize(film.next,0);

9
test/pi.nas Normal file
View 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
View 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);
}();

View File

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

View File

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

View File

@@ -1,35 +0,0 @@
# lib queue.nas
var block_alloc=func()
{
return {elem:nil,next:nil};
}
var new_queue=func()
{
return {next:nil};
}
var queue_push=func(queue,elem)
{
var tmp=queue;
while(tmp.next!=nil)
tmp=tmp.next;
tmp.next=block_alloc();
tmp.next.elem=elem;
}
var queue_pop=func(queue)
{
var tmp=queue.next;
if(tmp!=nil)
queue.next=tmp.next;
return;
}
var queue_front=func(queue)
{
var tmp=queue.next;
if(tmp!=nil)
return tmp.elem;
return nil;
}
var queue_empty=func(queue)
{
return queue.next==nil;
}

25
test/quick_sort.nas Normal file
View 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);

View File

@@ -1,4 +1,5 @@
# basic type
import("lib.nas");
nil;
2147483647;
0x7fffffff;
@@ -54,7 +55,7 @@ var hash_4={
# function
var func_1=func(){return 1;}
var prt=func(x){print(x);return nil;}
var prt=func(x){println(x);return nil;}
var func_with_dynamic_id=func(a,b,c,d...){return [a,b,c,d];}
var func_with_lack_para=func(a,b,c=1,d=2){return a+b+c+d;}
var func_with_func_para=func(a,f){return f(a);}
@@ -72,21 +73,21 @@ var source={
member_1: func func_1(), # this will get a number
member_2: func {return 2.71828;} # this will get a function
};
print(source['member_2']());
print(source.member_2());
println(source['member_2']());
println(source.member_2());
var test_func=func{return 1;}
print(func test_func()); # 1
print(test_func()); # 1
print(func test_func); # nothing
print(test_func); # nothing
print(([0,1,2,3])[1]); # 1
print(({str:"what?"})["str"]); # what?
print(({str:"what?"}).str); # what?
println(func test_func()); # 1
println(test_func()); # 1
println(func test_func); # nothing
println(test_func); # nothing
println(([0,1,2,3])[1]); # 1
println(({str:"what?"})["str"]); # what?
println(({str:"what?"}).str); # what?
# lambda
(func(x){return x>0? x:0;})(12);
(func{print("hello world");})();
(func{println("hello world");})();
(((func(x){return 1.0/math.exp(x);})))(0);
# flexible definition & assignment
@@ -114,7 +115,7 @@ var multi_assign_2=[10,9,8,7];
((-1*2+9))/7-1;
((({num:2})))["num"]*2*2*2;
((((([0,1,2])[0:2]))[0:2]))[1]-1;
(((((((((((((((((((1+1+2+3+5)+8))+13)))+21))))+34)))))+55))))*89;
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;
@@ -123,4 +124,29 @@ nil and 1+7*8;
(number_1 or number_2) and (number_3 or number_4-number_4*1);
[0,1,4,3,2][4]*2-4+1*2*2*2*2*2/8;
{num:0}.num or {what_is_the_secret_of_universe:42}["what_is_the_secret_of_universe"];
"123"~"456"-123456*2/2;
"123"~"456"-123456*2/2;
var hash={str:'hello',f:func{return me.str;}};
var tmp_f=hash.f;
hash=1;
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

View File

@@ -1,62 +0,0 @@
var global_value=0;
var global_hash=
{
var1:1,
var2:2,
var3:func(){return me.var2;}
};
print(global_value);
print(global_hash.var3());
var func1=func()
{
global_value=1;
print(global_value);
var closure_value=1;
var temp_value=1;
print(temp_value);
return func{return closure_value;};
}
var func2=func()
{
for(var temp_value=0;temp_value<100;temp_value+=1)
{
if(temp_value<10)
print(temp_value,"< 10");
elsif(10<=temp_value and temp_value<50)
print(temp_value,"< 50");
temp_value=10;
}
return;
}
var func3=func()
{
var fake_closure_value=1;
return func()
{
var fake_closure_value=2;
return fake_closure_value;
};
}
func1()();
func2();
func3()();
if(!global_value)
{
var temp_value=1;
if(temp_value)
{
var temp_value=2;
if(temp_value>=1)
{
var temp_value=3;
print(temp_value);
}
print(temp_value);
}
print(temp_value);
}

View File

@@ -1,24 +0,0 @@
var hash={str:'hello',f:func{return me.str;}};
var tmp_f=hash.f;
hash=1;
print(tmp_f());
# undefined symbol 'me'
# this means that
# when generating local_scope for function f,
# nasal_gc will not count 'me' as one reference of this hash
var h1={str:'hello',f:func{return me.str;}};
var h2={str:'world',f:func{return nil;}};
h2.f=h1.f;
print(h2.f());
# print 'world'
# this means that 'me' in hash's functions
# only points to the hash this function belongs to
var f1=func(){print(1);return 1;}
var f2=func(){print(2);return 0;}
f1() or f2();
# print '1'
# this means that when using 'or' or 'and',
# if the result is clear when calculating,
# objects behind will not be calculated

View File

@@ -1,34 +0,0 @@
# lib stack.nas
var block_alloc=func()
{
return {elem:nil,next:nil};
}
var new_stack=func()
{
return {next:nil};
}
var stack_push=func(stack,elem)
{
var tmp=stack.next;
stack.next=block_alloc();
stack.next.elem=elem;
stack.next.next=tmp;
}
var stack_pop=func(stack)
{
var tmp=stack.next;
if(tmp!=nil)
stack.next=tmp.next;
return;
}
var stack_top=func(stack)
{
var tmp=stack.next;
if(tmp!=nil)
return tmp.elem;
return nil;
}
var stack_empty=func(stack)
{
return stack.next==nil;
}

View File

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

39
test/trait.nas Normal file
View 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
View 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));