Merge pull request #43 from ValKmjolnir/develop
🎨 rename & file structure change & improve ast/gc dump format
This commit is contained in:
commit
0cf8e3bd23
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
project(nasal VERSION 10.1)
|
project(nasal VERSION 11.2)
|
||||||
|
|
||||||
message("CMAKE_HOST_SYSTEM_NAME: ${CMAKE_HOST_SYSTEM_NAME}")
|
message("CMAKE_HOST_SYSTEM_NAME: ${CMAKE_HOST_SYSTEM_NAME}")
|
||||||
|
|
||||||
|
@ -16,10 +16,8 @@ set(CMAKE_BUILD_TYPE "Release")
|
||||||
|
|
||||||
# build nasal used object
|
# build nasal used object
|
||||||
set(NASAL_OBJECT_SOURCE_FILE
|
set(NASAL_OBJECT_SOURCE_FILE
|
||||||
${CMAKE_SOURCE_DIR}/src/ast_dumper.cpp
|
${CMAKE_SOURCE_DIR}/src/cli/cli.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/ast_visitor.cpp
|
${CMAKE_SOURCE_DIR}/src/natives/builtin.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_ast.cpp
|
|
||||||
${CMAKE_SOURCE_DIR}/src/natives/nasal_builtin.cpp
|
|
||||||
${CMAKE_SOURCE_DIR}/src/natives/coroutine.cpp
|
${CMAKE_SOURCE_DIR}/src/natives/coroutine.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/natives/fg_props.cpp
|
${CMAKE_SOURCE_DIR}/src/natives/fg_props.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/natives/bits_lib.cpp
|
${CMAKE_SOURCE_DIR}/src/natives/bits_lib.cpp
|
||||||
|
@ -29,31 +27,37 @@ set(NASAL_OBJECT_SOURCE_FILE
|
||||||
${CMAKE_SOURCE_DIR}/src/natives/dylib_lib.cpp
|
${CMAKE_SOURCE_DIR}/src/natives/dylib_lib.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/natives/regex_lib.cpp
|
${CMAKE_SOURCE_DIR}/src/natives/regex_lib.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/natives/unix_lib.cpp
|
${CMAKE_SOURCE_DIR}/src/natives/unix_lib.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/repl/repl.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/util/fs.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/util/util.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/ast_dumper.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/ast_visitor.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/nasal_ast.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_codegen.cpp
|
${CMAKE_SOURCE_DIR}/src/nasal_codegen.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_dbg.cpp
|
${CMAKE_SOURCE_DIR}/src/nasal_dbg.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_err.cpp
|
${CMAKE_SOURCE_DIR}/src/nasal_err.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_gc.cpp
|
${CMAKE_SOURCE_DIR}/src/nasal_gc.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_import.cpp
|
${CMAKE_SOURCE_DIR}/src/nasal_import.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_lexer.cpp
|
${CMAKE_SOURCE_DIR}/src/nasal_lexer.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_misc.cpp
|
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_opcode.cpp
|
${CMAKE_SOURCE_DIR}/src/nasal_opcode.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_parse.cpp
|
${CMAKE_SOURCE_DIR}/src/nasal_parse.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_type.cpp
|
${CMAKE_SOURCE_DIR}/src/nasal_type.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_vm.cpp
|
${CMAKE_SOURCE_DIR}/src/nasal_vm.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/optimizer.cpp
|
${CMAKE_SOURCE_DIR}/src/optimizer.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/symbol_finder.cpp
|
${CMAKE_SOURCE_DIR}/src/symbol_finder.cpp)
|
||||||
${CMAKE_SOURCE_DIR}/src/repl.cpp)
|
|
||||||
add_library(nasal-object STATIC ${NASAL_OBJECT_SOURCE_FILE})
|
add_library(nasal-object STATIC ${NASAL_OBJECT_SOURCE_FILE})
|
||||||
target_include_directories(nasal-object PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
target_include_directories(nasal-object PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||||
|
|
||||||
# build nasal
|
# build nasal
|
||||||
add_executable(nasal ${CMAKE_SOURCE_DIR}/src/main.cpp)
|
add_executable(nasal ${CMAKE_SOURCE_DIR}/src/main.cpp)
|
||||||
target_link_libraries(nasal nasal-object)
|
target_link_libraries(nasal nasal-object)
|
||||||
|
# link ldl and lpthread
|
||||||
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
||||||
target_link_libraries(nasal dl)
|
target_link_libraries(nasal dl)
|
||||||
target_link_libraries(nasal pthread)
|
target_link_libraries(nasal pthread)
|
||||||
endif()
|
endif()
|
||||||
target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||||
|
# copy nasal from build dir to the outside dir
|
||||||
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET nasal POST_BUILD
|
TARGET nasal POST_BUILD
|
||||||
|
@ -67,10 +71,12 @@ endif()
|
||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/module)
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/module)
|
||||||
|
|
||||||
set(MODULE_USED_OBJECT_SOURCE_FILE
|
set(MODULE_USED_OBJECT_SOURCE_FILE
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_misc.cpp
|
${CMAKE_SOURCE_DIR}/src/util/util.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/util/fs.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_type.cpp
|
${CMAKE_SOURCE_DIR}/src/nasal_type.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_gc.cpp)
|
${CMAKE_SOURCE_DIR}/src/nasal_gc.cpp)
|
||||||
add_library(module-used-object STATIC ${MODULE_USED_OBJECT_SOURCE_FILE})
|
add_library(module-used-object STATIC ${MODULE_USED_OBJECT_SOURCE_FILE})
|
||||||
|
target_include_directories(module-used-object PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||||
|
|
||||||
add_library(fib SHARED ${CMAKE_SOURCE_DIR}/module/fib.cpp)
|
add_library(fib SHARED ${CMAKE_SOURCE_DIR}/module/fib.cpp)
|
||||||
target_include_directories(fib PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
target_include_directories(fib PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||||
|
|
64
README.md
64
README.md
|
@ -26,11 +26,9 @@
|
||||||
|
|
||||||
__Contact us if having great ideas to share!__
|
__Contact us if having great ideas to share!__
|
||||||
|
|
||||||
* __E-mail__:
|
* __lhk101lhk101@qq.com__ (ValKmjolnir)
|
||||||
|
|
||||||
* __lhk101lhk101@qq.com__ (ValKmjolnir)
|
* __sidi.liang@gmail.com__ (Sidi)
|
||||||
|
|
||||||
* __sidi.liang@gmail.com__ (Sidi)
|
|
||||||
|
|
||||||
## __Introduction__
|
## __Introduction__
|
||||||
|
|
||||||
|
@ -117,6 +115,14 @@ if (os.platform()=="windows") {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Or use `std.runtime.windows.set_utf8_output()`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
use std.runtime;
|
||||||
|
|
||||||
|
runtime.windows.set_utf8_output();
|
||||||
|
```
|
||||||
|
|
||||||
## __Difference Between Andy's and This Interpreter__
|
## __Difference Between Andy's and This Interpreter__
|
||||||
|
|
||||||

|

|
||||||
|
@ -337,9 +343,8 @@ and the debugger will print this:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
source code:
|
source code:
|
||||||
--> var fib=func(x)
|
--> var fib = func(x) {
|
||||||
{
|
if (x<2) return x;
|
||||||
if(x<2) return x;
|
|
||||||
return fib(x-1)+fib(x-2);
|
return fib(x-1)+fib(x-2);
|
||||||
}
|
}
|
||||||
for(var i=0;i<31;i+=1)
|
for(var i=0;i<31;i+=1)
|
||||||
|
@ -347,16 +352,16 @@ source code:
|
||||||
|
|
||||||
|
|
||||||
next bytecode:
|
next bytecode:
|
||||||
0x000848 4a 00 00 01 callfv 0x1(std/lib.nas:427)
|
0x0003a8 07:00 00 00 00 00 00 00 00 pnil 0x0 (std/lib.nas:413)
|
||||||
0x000849 3d 00 00 00 pop 0x0(std/lib.nas:427)
|
0x0003a9 56:00 00 00 00 00 00 00 00 ret 0x0 (std/lib.nas:413)
|
||||||
0x00084a 07 00 00 00 pnil 0x0(std/lib.nas:423)
|
0x0003aa 03:00 00 00 00 00 00 00 56 loadg 0x56 (std/lib.nas:413)
|
||||||
0x00084b 56 00 00 00 ret 0x0(std/lib.nas:423)
|
--> 0x0003ab 0b:00 00 00 00 00 00 03 af newf 0x3af (test/fib.nas:1)
|
||||||
0x00084c 03 00 00 5e loadg 0x5e(std/lib.nas:423)
|
0x0003ac 02:00 00 00 00 00 00 00 03 intl 0x3 (test/fib.nas:1)
|
||||||
--> 0x00084d 0b 00 08 51 newf 0x851(test/fib.nas:1)
|
0x0003ad 0d:00 00 00 00 00 00 00 22 para 0x22 (x) (test/fib.nas:1)
|
||||||
0x00084e 02 00 00 03 intl 0x3(test/fib.nas:1)
|
0x0003ae 3e:00 00 00 00 00 00 03 be jmp 0x3be (test/fib.nas:1)
|
||||||
0x00084f 0d 00 00 08 para 0x8 (x)(test/fib.nas:1)
|
0x0003af 45:00 00 00 00 00 00 00 01 calll 0x1 (test/fib.nas:2)
|
||||||
|
|
||||||
stack (0x55ccd0a1b9d0, limit 10, total 0)
|
vm stack (0x7fca7e9f1010, limit 16, total 0)
|
||||||
>>
|
>>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -371,9 +376,8 @@ This will help you debugging or learning how the vm works:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
source code:
|
source code:
|
||||||
var fib=func(x)
|
var fib = func(x) {
|
||||||
{
|
--> if (x<2) return x;
|
||||||
--> if(x<2) return x;
|
|
||||||
return fib(x-1)+fib(x-2);
|
return fib(x-1)+fib(x-2);
|
||||||
}
|
}
|
||||||
for(var i=0;i<31;i+=1)
|
for(var i=0;i<31;i+=1)
|
||||||
|
@ -381,24 +385,24 @@ source code:
|
||||||
|
|
||||||
|
|
||||||
next bytecode:
|
next bytecode:
|
||||||
0x000850 3e 00 08 60 jmp 0x860(test/fib.nas:1)
|
0x0003a8 07:00 00 00 00 00 00 00 00 pnil 0x0 (std/lib.nas:413)
|
||||||
--> 0x000851 45 00 00 01 calll 0x1(test/fib.nas:3)
|
0x0003a9 56:00 00 00 00 00 00 00 00 ret 0x0 (std/lib.nas:413)
|
||||||
0x000852 39 00 00 07 lessc 0x7 (2)(test/fib.nas:3)
|
0x0003aa 03:00 00 00 00 00 00 00 56 loadg 0x56 (std/lib.nas:413)
|
||||||
0x000853 40 00 08 56 jf 0x856(test/fib.nas:3)
|
0x0003ab 0b:00 00 00 00 00 00 03 af newf 0x3af (test/fib.nas:1)
|
||||||
0x000854 45 00 00 01 calll 0x1(test/fib.nas:3)
|
0x0003ac 02:00 00 00 00 00 00 00 03 intl 0x3 (test/fib.nas:1)
|
||||||
0x000855 56 00 00 00 ret 0x0(test/fib.nas:3)
|
0x0003ad 0d:00 00 00 00 00 00 00 22 para 0x22 (x) (test/fib.nas:1)
|
||||||
0x000856 44 00 00 5f callg 0x5f(test/fib.nas:4)
|
0x0003ae 3e:00 00 00 00 00 00 03 be jmp 0x3be (test/fib.nas:1)
|
||||||
0x000857 45 00 00 01 calll 0x1(test/fib.nas:4)
|
--> 0x0003af 45:00 00 00 00 00 00 00 01 calll 0x1 (test/fib.nas:2)
|
||||||
|
|
||||||
stack (0x55ccd0a1b9d0, limit 10, total 8)
|
vm stack (0x7fca7e9f1010, limit 16, total 8)
|
||||||
0x000007 | pc | 0x869
|
0x000007 | pc | 0x3c7
|
||||||
0x000006 | addr | 0x0
|
0x000006 | addr | 0x0
|
||||||
0x000005 | nil |
|
0x000005 | nil |
|
||||||
0x000004 | nil |
|
0x000004 | nil |
|
||||||
0x000003 | num | 0
|
0x000003 | num | 0
|
||||||
0x000002 | nil |
|
0x000002 | nil |
|
||||||
0x000001 | nil |
|
0x000001 | nil |
|
||||||
0x000000 | func | <0x55ccd0a58fa0> entry:0x487
|
0x000000 | func | <0x5573f66ef5f0> func(elems...) {..}
|
||||||
>>
|
>>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,9 @@
|
||||||
|
|
||||||
__如果有好的意见或建议,欢迎联系我们!__
|
__如果有好的意见或建议,欢迎联系我们!__
|
||||||
|
|
||||||
* __E-mail__:
|
* __lhk101lhk101@qq.com__ (ValKmjolnir)
|
||||||
|
|
||||||
* __lhk101lhk101@qq.com__ (ValKmjolnir)
|
* __sidi.liang@gmail.com__ (Sidi)
|
||||||
|
|
||||||
* __1467329765@qq.com__(Sidi762)
|
|
||||||
|
|
||||||
## __简介__
|
## __简介__
|
||||||
|
|
||||||
|
@ -103,7 +101,7 @@ Windows 平台的预览版解释器现在还没配置相关流水线,
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
如果你是 `Windows` 用户且想正常输出unicode,在nasal代码里写这个来开启unicode代码页:
|
如果你是 `Windows` 用户且想正常输出 unicode,可以这样开启 unicode 代码页:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
if (os.platform()=="windows") {
|
if (os.platform()=="windows") {
|
||||||
|
@ -111,6 +109,14 @@ if (os.platform()=="windows") {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
或者使用 `std.runtime.windows.set_utf8_output()`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
use std.runtime;
|
||||||
|
|
||||||
|
runtime.windows.set_utf8_output();
|
||||||
|
```
|
||||||
|
|
||||||
## __与andy解释器的不同之处__
|
## __与andy解释器的不同之处__
|
||||||
|
|
||||||

|

|
||||||
|
@ -322,9 +328,8 @@ local (0x55dcb5b43190 <+7>)
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
source code:
|
source code:
|
||||||
--> var fib=func(x)
|
--> var fib = func(x) {
|
||||||
{
|
if (x<2) return x;
|
||||||
if(x<2) return x;
|
|
||||||
return fib(x-1)+fib(x-2);
|
return fib(x-1)+fib(x-2);
|
||||||
}
|
}
|
||||||
for(var i=0;i<31;i+=1)
|
for(var i=0;i<31;i+=1)
|
||||||
|
@ -332,16 +337,16 @@ source code:
|
||||||
|
|
||||||
|
|
||||||
next bytecode:
|
next bytecode:
|
||||||
0x000848 4a 00 00 01 callfv 0x1(std/lib.nas:427)
|
0x0003a8 07:00 00 00 00 00 00 00 00 pnil 0x0 (std/lib.nas:413)
|
||||||
0x000849 3d 00 00 00 pop 0x0(std/lib.nas:427)
|
0x0003a9 56:00 00 00 00 00 00 00 00 ret 0x0 (std/lib.nas:413)
|
||||||
0x00084a 07 00 00 00 pnil 0x0(std/lib.nas:423)
|
0x0003aa 03:00 00 00 00 00 00 00 56 loadg 0x56 (std/lib.nas:413)
|
||||||
0x00084b 56 00 00 00 ret 0x0(std/lib.nas:423)
|
--> 0x0003ab 0b:00 00 00 00 00 00 03 af newf 0x3af (test/fib.nas:1)
|
||||||
0x00084c 03 00 00 5e loadg 0x5e(std/lib.nas:423)
|
0x0003ac 02:00 00 00 00 00 00 00 03 intl 0x3 (test/fib.nas:1)
|
||||||
--> 0x00084d 0b 00 08 51 newf 0x851(test/fib.nas:1)
|
0x0003ad 0d:00 00 00 00 00 00 00 22 para 0x22 (x) (test/fib.nas:1)
|
||||||
0x00084e 02 00 00 03 intl 0x3(test/fib.nas:1)
|
0x0003ae 3e:00 00 00 00 00 00 03 be jmp 0x3be (test/fib.nas:1)
|
||||||
0x00084f 0d 00 00 08 para 0x8 (x)(test/fib.nas:1)
|
0x0003af 45:00 00 00 00 00 00 00 01 calll 0x1 (test/fib.nas:2)
|
||||||
|
|
||||||
stack (0x55ccd0a1b9d0, limit 10, total 0)
|
vm stack (0x7fca7e9f1010, limit 16, total 0)
|
||||||
>>
|
>>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -356,9 +361,8 @@ stack (0x55ccd0a1b9d0, limit 10, total 0)
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
source code:
|
source code:
|
||||||
var fib=func(x)
|
var fib = func(x) {
|
||||||
{
|
--> if (x<2) return x;
|
||||||
--> if(x<2) return x;
|
|
||||||
return fib(x-1)+fib(x-2);
|
return fib(x-1)+fib(x-2);
|
||||||
}
|
}
|
||||||
for(var i=0;i<31;i+=1)
|
for(var i=0;i<31;i+=1)
|
||||||
|
@ -366,24 +370,24 @@ source code:
|
||||||
|
|
||||||
|
|
||||||
next bytecode:
|
next bytecode:
|
||||||
0x000850 3e 00 08 60 jmp 0x860(test/fib.nas:1)
|
0x0003a8 07:00 00 00 00 00 00 00 00 pnil 0x0 (std/lib.nas:413)
|
||||||
--> 0x000851 45 00 00 01 calll 0x1(test/fib.nas:3)
|
0x0003a9 56:00 00 00 00 00 00 00 00 ret 0x0 (std/lib.nas:413)
|
||||||
0x000852 39 00 00 07 lessc 0x7 (2)(test/fib.nas:3)
|
0x0003aa 03:00 00 00 00 00 00 00 56 loadg 0x56 (std/lib.nas:413)
|
||||||
0x000853 40 00 08 56 jf 0x856(test/fib.nas:3)
|
0x0003ab 0b:00 00 00 00 00 00 03 af newf 0x3af (test/fib.nas:1)
|
||||||
0x000854 45 00 00 01 calll 0x1(test/fib.nas:3)
|
0x0003ac 02:00 00 00 00 00 00 00 03 intl 0x3 (test/fib.nas:1)
|
||||||
0x000855 56 00 00 00 ret 0x0(test/fib.nas:3)
|
0x0003ad 0d:00 00 00 00 00 00 00 22 para 0x22 (x) (test/fib.nas:1)
|
||||||
0x000856 44 00 00 5f callg 0x5f(test/fib.nas:4)
|
0x0003ae 3e:00 00 00 00 00 00 03 be jmp 0x3be (test/fib.nas:1)
|
||||||
0x000857 45 00 00 01 calll 0x1(test/fib.nas:4)
|
--> 0x0003af 45:00 00 00 00 00 00 00 01 calll 0x1 (test/fib.nas:2)
|
||||||
|
|
||||||
stack (0x55ccd0a1b9d0, limit 10, total 8)
|
vm stack (0x7fca7e9f1010, limit 16, total 8)
|
||||||
0x000007 | pc | 0x869
|
0x000007 | pc | 0x3c7
|
||||||
0x000006 | addr | 0x0
|
0x000006 | addr | 0x0
|
||||||
0x000005 | nil |
|
0x000005 | nil |
|
||||||
0x000004 | nil |
|
0x000004 | nil |
|
||||||
0x000003 | num | 0
|
0x000003 | num | 0
|
||||||
0x000002 | nil |
|
0x000002 | nil |
|
||||||
0x000001 | nil |
|
0x000001 | nil |
|
||||||
0x000000 | func | <0x55ccd0a58fa0> entry:0x487
|
0x000000 | func | <0x5573f66ef5f0> func(elems...) {..}
|
||||||
>>
|
>>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
61
makefile
61
makefile
|
@ -13,7 +13,7 @@ NASAL_HEADER = \
|
||||||
src/ast_dumper.h\
|
src/ast_dumper.h\
|
||||||
src/ast_visitor.h\
|
src/ast_visitor.h\
|
||||||
src/nasal_ast.h\
|
src/nasal_ast.h\
|
||||||
src/natives/nasal_builtin.h\
|
src/natives/builtin.h\
|
||||||
src/nasal_codegen.h\
|
src/nasal_codegen.h\
|
||||||
src/nasal_dbg.h\
|
src/nasal_dbg.h\
|
||||||
src/nasal_err.h\
|
src/nasal_err.h\
|
||||||
|
@ -27,6 +27,7 @@ NASAL_HEADER = \
|
||||||
src/nasal.h\
|
src/nasal.h\
|
||||||
src/optimizer.h\
|
src/optimizer.h\
|
||||||
src/symbol_finder.h\
|
src/symbol_finder.h\
|
||||||
|
src/cli/cli.h\
|
||||||
src/natives/fg_props.h\
|
src/natives/fg_props.h\
|
||||||
src/natives/bits_lib.h\
|
src/natives/bits_lib.h\
|
||||||
src/natives/io_lib.h\
|
src/natives/io_lib.h\
|
||||||
|
@ -35,8 +36,10 @@ NASAL_HEADER = \
|
||||||
src/natives/json_lib.h\
|
src/natives/json_lib.h\
|
||||||
src/natives/unix_lib.h\
|
src/natives/unix_lib.h\
|
||||||
src/natives/coroutine.h\
|
src/natives/coroutine.h\
|
||||||
src/repl.h\
|
src/natives/regex_lib.h\
|
||||||
src/natives/regex_lib.h
|
src/repl/repl.h\
|
||||||
|
src/util/fs.h\
|
||||||
|
src/util/util.h
|
||||||
|
|
||||||
NASAL_OBJECT = \
|
NASAL_OBJECT = \
|
||||||
build/nasal_err.o\
|
build/nasal_err.o\
|
||||||
|
@ -51,9 +54,8 @@ NASAL_OBJECT = \
|
||||||
build/nasal_opcode.o\
|
build/nasal_opcode.o\
|
||||||
build/symbol_finder.o\
|
build/symbol_finder.o\
|
||||||
build/nasal_codegen.o\
|
build/nasal_codegen.o\
|
||||||
build/nasal_misc.o\
|
|
||||||
build/nasal_gc.o\
|
build/nasal_gc.o\
|
||||||
build/nasal_builtin.o\
|
build/builtin.o\
|
||||||
build/fg_props.o\
|
build/fg_props.o\
|
||||||
build/io_lib.o\
|
build/io_lib.o\
|
||||||
build/math_lib.o\
|
build/math_lib.o\
|
||||||
|
@ -64,8 +66,11 @@ NASAL_OBJECT = \
|
||||||
build/nasal_type.o\
|
build/nasal_type.o\
|
||||||
build/nasal_vm.o\
|
build/nasal_vm.o\
|
||||||
build/nasal_dbg.o\
|
build/nasal_dbg.o\
|
||||||
build/repl.o\
|
|
||||||
build/regex_lib.o\
|
build/regex_lib.o\
|
||||||
|
build/repl.o\
|
||||||
|
build/cli.o\
|
||||||
|
build/fs.o\
|
||||||
|
build/util.o\
|
||||||
build/main.o
|
build/main.o
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,16 +91,25 @@ build:
|
||||||
build/main.o: $(NASAL_HEADER) src/main.cpp | build
|
build/main.o: $(NASAL_HEADER) src/main.cpp | build
|
||||||
$(CXX) $(CXXFLAGS) src/main.cpp -o build/main.o
|
$(CXX) $(CXXFLAGS) src/main.cpp -o build/main.o
|
||||||
|
|
||||||
build/nasal_misc.o: src/nasal.h src/nasal_misc.cpp | build
|
build/cli.o: src/cli/cli.h src/cli/cli.cpp | build
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_misc.cpp -o build/nasal_misc.o
|
$(CXX) $(CXXFLAGS) src/cli/cli.cpp -o build/cli.o
|
||||||
|
|
||||||
build/repl.o: $(NASAL_HEADER) src/repl.h src/repl.cpp | build
|
build/util.o: src/util/util.h src/util/util.cpp | build
|
||||||
$(CXX) $(CXXFLAGS) src/repl.cpp -o build/repl.o
|
$(CXX) $(CXXFLAGS) src/util/util.cpp -o build/util.o
|
||||||
|
|
||||||
build/nasal_err.o: src/nasal.h src/repl.h src/nasal_err.h src/nasal_err.cpp | build
|
build/fs.o: src/nasal.h src/util/util.h src/util/fs.h src/util/fs.cpp | build
|
||||||
|
$(CXX) $(CXXFLAGS) src/util/fs.cpp -o build/fs.o
|
||||||
|
|
||||||
|
build/repl.o: $(NASAL_HEADER) src/repl/repl.h src/repl/repl.cpp | build
|
||||||
|
$(CXX) $(CXXFLAGS) src/repl/repl.cpp -o build/repl.o
|
||||||
|
|
||||||
|
build/nasal_err.o: src/nasal.h src/repl/repl.h src/nasal_err.h src/nasal_err.cpp | build
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_err.cpp -o build/nasal_err.o
|
$(CXX) $(CXXFLAGS) src/nasal_err.cpp -o build/nasal_err.o
|
||||||
|
|
||||||
build/nasal_type.o: src/nasal.h src/nasal_type.h src/nasal_type.cpp | build
|
build/nasal_type.o:\
|
||||||
|
src/nasal.h\
|
||||||
|
src/util/util.h\
|
||||||
|
src/nasal_type.h src/nasal_type.cpp | build
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_type.cpp -o build/nasal_type.o
|
$(CXX) $(CXXFLAGS) src/nasal_type.cpp -o build/nasal_type.o
|
||||||
|
|
||||||
build/nasal_gc.o: src/nasal.h src/nasal_type.h src/nasal_gc.h src/nasal_gc.cpp | build
|
build/nasal_gc.o: src/nasal.h src/nasal_type.h src/nasal_gc.h src/nasal_gc.cpp | build
|
||||||
|
@ -106,12 +120,16 @@ build/nasal_import.o: \
|
||||||
src/nasal_ast.h\
|
src/nasal_ast.h\
|
||||||
src/nasal_lexer.h\
|
src/nasal_lexer.h\
|
||||||
src/nasal_parse.h\
|
src/nasal_parse.h\
|
||||||
|
src/util/util.h\
|
||||||
|
src/util/fs.h\
|
||||||
src/nasal_import.h src/nasal_import.cpp | build
|
src/nasal_import.h src/nasal_import.cpp | build
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_import.cpp -o build/nasal_import.o
|
$(CXX) $(CXXFLAGS) src/nasal_import.cpp -o build/nasal_import.o
|
||||||
|
|
||||||
build/nasal_lexer.o: \
|
build/nasal_lexer.o: \
|
||||||
src/nasal.h\
|
src/nasal.h\
|
||||||
src/repl.h\
|
src/repl/repl.h\
|
||||||
|
src/util/util.h\
|
||||||
|
src/util/fs.h\
|
||||||
src/nasal_err.h\
|
src/nasal_err.h\
|
||||||
src/nasal_lexer.h src/nasal_lexer.cpp | build
|
src/nasal_lexer.h src/nasal_lexer.cpp | build
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_lexer.cpp -o build/nasal_lexer.o
|
$(CXX) $(CXXFLAGS) src/nasal_lexer.cpp -o build/nasal_lexer.o
|
||||||
|
@ -122,12 +140,14 @@ build/nasal_ast.o: \
|
||||||
src/nasal_ast.h src/nasal_ast.cpp | build
|
src/nasal_ast.h src/nasal_ast.cpp | build
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_ast.cpp -o build/nasal_ast.o
|
$(CXX) $(CXXFLAGS) src/nasal_ast.cpp -o build/nasal_ast.o
|
||||||
|
|
||||||
build/nasal_builtin.o: \
|
build/builtin.o: \
|
||||||
src/nasal.h\
|
src/nasal.h\
|
||||||
src/nasal_type.h\
|
src/nasal_type.h\
|
||||||
src/nasal_gc.h\
|
src/nasal_gc.h\
|
||||||
src/natives/nasal_builtin.h src/natives/nasal_builtin.cpp | build
|
src/util/util.h\
|
||||||
$(CXX) $(CXXFLAGS) src/natives/nasal_builtin.cpp -o build/nasal_builtin.o
|
src/natives/builtin.h\
|
||||||
|
src/natives/builtin.cpp | build
|
||||||
|
$(CXX) $(CXXFLAGS) src/natives/builtin.cpp -o build/builtin.o
|
||||||
|
|
||||||
build/coroutine.o: \
|
build/coroutine.o: \
|
||||||
src/nasal.h\
|
src/nasal.h\
|
||||||
|
@ -143,7 +163,6 @@ build/bits_lib.o: \
|
||||||
src/natives/bits_lib.h src/natives/bits_lib.cpp | build
|
src/natives/bits_lib.h src/natives/bits_lib.cpp | build
|
||||||
$(CXX) $(CXXFLAGS) src/natives/bits_lib.cpp -o build/bits_lib.o
|
$(CXX) $(CXXFLAGS) src/natives/bits_lib.cpp -o build/bits_lib.o
|
||||||
|
|
||||||
|
|
||||||
build/math_lib.o: \
|
build/math_lib.o: \
|
||||||
src/nasal.h\
|
src/nasal.h\
|
||||||
src/nasal_type.h\
|
src/nasal_type.h\
|
||||||
|
@ -155,6 +174,7 @@ build/io_lib.o: \
|
||||||
src/nasal.h\
|
src/nasal.h\
|
||||||
src/nasal_type.h\
|
src/nasal_type.h\
|
||||||
src/nasal_gc.h\
|
src/nasal_gc.h\
|
||||||
|
src/util/fs.h\
|
||||||
src/natives/io_lib.h src/natives/io_lib.cpp | build
|
src/natives/io_lib.h src/natives/io_lib.cpp | build
|
||||||
$(CXX) $(CXXFLAGS) src/natives/io_lib.cpp -o build/io_lib.o
|
$(CXX) $(CXXFLAGS) src/natives/io_lib.cpp -o build/io_lib.o
|
||||||
|
|
||||||
|
@ -169,6 +189,7 @@ build/json_lib.o: \
|
||||||
src/nasal.h\
|
src/nasal.h\
|
||||||
src/nasal_type.h\
|
src/nasal_type.h\
|
||||||
src/nasal_gc.h\
|
src/nasal_gc.h\
|
||||||
|
src/util/util.h\
|
||||||
src/natives/json_lib.h src/natives/json_lib.cpp | build
|
src/natives/json_lib.h src/natives/json_lib.cpp | build
|
||||||
$(CXX) $(CXXFLAGS) src/natives/json_lib.cpp -o build/json_lib.o
|
$(CXX) $(CXXFLAGS) src/natives/json_lib.cpp -o build/json_lib.o
|
||||||
|
|
||||||
|
@ -198,7 +219,8 @@ build/nasal_codegen.o: $(NASAL_HEADER) src/nasal_codegen.h src/nasal_codegen.cpp
|
||||||
|
|
||||||
build/nasal_opcode.o: \
|
build/nasal_opcode.o: \
|
||||||
src/nasal.h\
|
src/nasal.h\
|
||||||
src/natives/nasal_builtin.h\
|
src/natives/builtin.h\
|
||||||
|
src/util/util.h\
|
||||||
src/nasal_opcode.h src/nasal_opcode.cpp | build
|
src/nasal_opcode.h src/nasal_opcode.cpp | build
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_opcode.cpp -o build/nasal_opcode.o
|
$(CXX) $(CXXFLAGS) src/nasal_opcode.cpp -o build/nasal_opcode.o
|
||||||
|
|
||||||
|
@ -207,6 +229,7 @@ build/nasal_parse.o: \
|
||||||
src/nasal_ast.h\
|
src/nasal_ast.h\
|
||||||
src/nasal_lexer.h\
|
src/nasal_lexer.h\
|
||||||
src/nasal_err.h\
|
src/nasal_err.h\
|
||||||
|
src/util/util.h\
|
||||||
src/nasal_parse.h src/nasal_parse.cpp src/nasal_ast.h | build
|
src/nasal_parse.h src/nasal_parse.cpp src/nasal_ast.h | build
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_parse.cpp -o build/nasal_parse.o
|
$(CXX) $(CXXFLAGS) src/nasal_parse.cpp -o build/nasal_parse.o
|
||||||
|
|
||||||
|
@ -238,6 +261,7 @@ build/ast_dumper.o: \
|
||||||
src/nasal_err.h\
|
src/nasal_err.h\
|
||||||
src/nasal_ast.h\
|
src/nasal_ast.h\
|
||||||
src/ast_visitor.h\
|
src/ast_visitor.h\
|
||||||
|
src/util/util.h\
|
||||||
src/ast_dumper.h src/ast_dumper.cpp | build
|
src/ast_dumper.h src/ast_dumper.cpp | build
|
||||||
$(CXX) $(CXXFLAGS) src/ast_dumper.cpp -o build/ast_dumper.o
|
$(CXX) $(CXXFLAGS) src/ast_dumper.cpp -o build/ast_dumper.o
|
||||||
|
|
||||||
|
@ -294,5 +318,6 @@ test:nasal
|
||||||
@ ./nasal -e test/trait.nas
|
@ ./nasal -e test/trait.nas
|
||||||
@ ./nasal -t -d test/turingmachine.nas
|
@ ./nasal -t -d test/turingmachine.nas
|
||||||
@ ./nasal -d test/wavecollapse.nas
|
@ ./nasal -d test/wavecollapse.nas
|
||||||
|
@ ./nasal -d test/wavecity.nas
|
||||||
@ ./nasal test/word_collector.nas test/md5compare.nas
|
@ ./nasal test/word_collector.nas test/md5compare.nas
|
||||||
@ ./nasal -t -d test/ycombinator.nas
|
@ ./nasal -t -d test/ycombinator.nas
|
||||||
|
|
|
@ -34,7 +34,8 @@ public:
|
||||||
tcgetattr(0, &init_termios);
|
tcgetattr(0, &init_termios);
|
||||||
new_termios = init_termios;
|
new_termios = init_termios;
|
||||||
new_termios.c_lflag &= ~(ICANON|ECHO|ECHONL|ECHOE);
|
new_termios.c_lflag &= ~(ICANON|ECHO|ECHONL|ECHOE);
|
||||||
// vmin=0 is nonblock input, but in wsl there is a bug that will block input
|
// vmin = 0 is nonblock input,
|
||||||
|
// but in wsl1 there is a bug that will block input
|
||||||
// so we use fcntl to write the nonblock input
|
// so we use fcntl to write the nonblock input
|
||||||
new_termios.c_cc[VMIN] = 1;
|
new_termios.c_cc[VMIN] = 1;
|
||||||
new_termios.c_cc[VTIME] = 0;
|
new_termios.c_cc[VTIME] = 0;
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
dynamic_libs_so = libfib.so libkey.so libnasock.so libmat.so
|
dynamic_libs_so = libfib.so libkey.so libnasock.so libmat.so
|
||||||
dynamic_libs_dll = libfib.dll libkey.dll libnasock.dll libmat.dll
|
dynamic_libs_dll = libfib.dll libkey.dll libnasock.dll libmat.dll
|
||||||
|
|
||||||
used_header = ../src/nasal.h ../src/nasal_type.h ../src/nasal_gc.h
|
used_header = ../src/nasal.h ../src/util/util.h ../src/nasal_type.h ../src/nasal_gc.h
|
||||||
used_object = ../build/nasal_misc.o ../build/nasal_type.o ../build/nasal_gc.o
|
used_object = ../build/util.o ../build/nasal_type.o ../build/nasal_gc.o
|
||||||
|
|
||||||
STD = c++17
|
STD = c++17
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "ast_dumper.h"
|
#include "ast_dumper.h"
|
||||||
|
#include "util/util.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -6,7 +7,7 @@ namespace nasal {
|
||||||
|
|
||||||
bool ast_dumper::visit_use_stmt(use_stmt* node) {
|
bool ast_dumper::visit_use_stmt(use_stmt* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "use" << format_location(node->get_location());
|
std::cout << "use" << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
for(auto i : node->get_path()) {
|
for(auto i : node->get_path()) {
|
||||||
if (i==node->get_path().back()) {
|
if (i==node->get_path().back()) {
|
||||||
|
@ -20,48 +21,48 @@ bool ast_dumper::visit_use_stmt(use_stmt* node) {
|
||||||
|
|
||||||
bool ast_dumper::visit_null_expr(null_expr* node) {
|
bool ast_dumper::visit_null_expr(null_expr* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "null" << format_location(node->get_location());
|
std::cout << "null" << format_location(node);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ast_dumper::visit_nil_expr(nil_expr* node) {
|
bool ast_dumper::visit_nil_expr(nil_expr* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "nil" << format_location(node->get_location());
|
std::cout << "nil" << format_location(node);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ast_dumper::visit_number_literal(number_literal* node) {
|
bool ast_dumper::visit_number_literal(number_literal* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "number " << node->get_number();
|
std::cout << "number " << node->get_number();
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ast_dumper::visit_string_literal(string_literal* node) {
|
bool ast_dumper::visit_string_literal(string_literal* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "string \"" << rawstr(node->get_content()) << "\"";
|
std::cout << "string \"" << util::rawstr(node->get_content()) << "\"";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ast_dumper::visit_identifier(identifier* node) {
|
bool ast_dumper::visit_identifier(identifier* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "identifier " << node->get_name();
|
std::cout << "identifier " << node->get_name();
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ast_dumper::visit_bool_literal(bool_literal* node) {
|
bool ast_dumper::visit_bool_literal(bool_literal* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "bool " << node->get_flag();
|
std::cout << "bool " << node->get_flag();
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ast_dumper::visit_vector_expr(vector_expr* node) {
|
bool ast_dumper::visit_vector_expr(vector_expr* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "vector";
|
std::cout << "vector";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
for(auto i : node->get_elements()) {
|
for(auto i : node->get_elements()) {
|
||||||
if (i==node->get_elements().back()) {
|
if (i==node->get_elements().back()) {
|
||||||
|
@ -76,7 +77,7 @@ bool ast_dumper::visit_vector_expr(vector_expr* node) {
|
||||||
bool ast_dumper::visit_hash_expr(hash_expr* node) {
|
bool ast_dumper::visit_hash_expr(hash_expr* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "hash";
|
std::cout << "hash";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
for(auto i : node->get_members()) {
|
for(auto i : node->get_members()) {
|
||||||
if (i==node->get_members().back()) {
|
if (i==node->get_members().back()) {
|
||||||
|
@ -91,7 +92,7 @@ bool ast_dumper::visit_hash_expr(hash_expr* node) {
|
||||||
bool ast_dumper::visit_hash_pair(hash_pair* node) {
|
bool ast_dumper::visit_hash_pair(hash_pair* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "pair " << node->get_name();
|
std::cout << "pair " << node->get_name();
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
if (node->get_value()) {
|
if (node->get_value()) {
|
||||||
push_indent();
|
push_indent();
|
||||||
set_last();
|
set_last();
|
||||||
|
@ -104,7 +105,7 @@ bool ast_dumper::visit_hash_pair(hash_pair* node) {
|
||||||
bool ast_dumper::visit_function(function* node) {
|
bool ast_dumper::visit_function(function* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "function";
|
std::cout << "function";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
for(auto i : node->get_parameter_list()) {
|
for(auto i : node->get_parameter_list()) {
|
||||||
i->accept(this);
|
i->accept(this);
|
||||||
|
@ -118,7 +119,7 @@ bool ast_dumper::visit_function(function* node) {
|
||||||
bool ast_dumper::visit_code_block(code_block* node) {
|
bool ast_dumper::visit_code_block(code_block* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "block";
|
std::cout << "block";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
for(auto i : node->get_expressions()) {
|
for(auto i : node->get_expressions()) {
|
||||||
if (i==node->get_expressions().back()) {
|
if (i==node->get_expressions().back()) {
|
||||||
|
@ -133,7 +134,7 @@ bool ast_dumper::visit_code_block(code_block* node) {
|
||||||
bool ast_dumper::visit_parameter(parameter* node) {
|
bool ast_dumper::visit_parameter(parameter* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "parameter " << node->get_parameter_name();
|
std::cout << "parameter " << node->get_parameter_name();
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
if (node->get_default_value()) {
|
if (node->get_default_value()) {
|
||||||
push_indent();
|
push_indent();
|
||||||
set_last();
|
set_last();
|
||||||
|
@ -146,7 +147,7 @@ bool ast_dumper::visit_parameter(parameter* node) {
|
||||||
bool ast_dumper::visit_ternary_operator(ternary_operator* node) {
|
bool ast_dumper::visit_ternary_operator(ternary_operator* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "ternary_operator";
|
std::cout << "ternary_operator";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
node->get_condition()->accept(this);
|
node->get_condition()->accept(this);
|
||||||
node->get_left()->accept(this);
|
node->get_left()->accept(this);
|
||||||
|
@ -166,7 +167,7 @@ bool ast_dumper::visit_binary_operator(binary_operator* node) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "binary_operator ";
|
std::cout << "binary_operator \"";
|
||||||
switch(node->get_operator_type()) {
|
switch(node->get_operator_type()) {
|
||||||
case binary_operator::binary_type::add: std::cout << "+"; break;
|
case binary_operator::binary_type::add: std::cout << "+"; break;
|
||||||
case binary_operator::binary_type::sub: std::cout << "-"; break;
|
case binary_operator::binary_type::sub: std::cout << "-"; break;
|
||||||
|
@ -185,7 +186,7 @@ bool ast_dumper::visit_binary_operator(binary_operator* node) {
|
||||||
case binary_operator::binary_type::condition_and: std::cout << "and"; break;
|
case binary_operator::binary_type::condition_and: std::cout << "and"; break;
|
||||||
case binary_operator::binary_type::condition_or: std::cout << "or"; break;
|
case binary_operator::binary_type::condition_or: std::cout << "or"; break;
|
||||||
}
|
}
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << "\"" << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
node->get_left()->accept(this);
|
node->get_left()->accept(this);
|
||||||
set_last();
|
set_last();
|
||||||
|
@ -200,13 +201,13 @@ bool ast_dumper::visit_unary_operator(unary_operator* node) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "unary_operator ";
|
std::cout << "unary_operator \"";
|
||||||
switch(node->get_operator_type()) {
|
switch(node->get_operator_type()) {
|
||||||
case unary_operator::unary_type::negative: std::cout << "-"; break;
|
case unary_operator::unary_type::negative: std::cout << "-"; break;
|
||||||
case unary_operator::unary_type::logical_not: std::cout << "!"; break;
|
case unary_operator::unary_type::logical_not: std::cout << "!"; break;
|
||||||
case unary_operator::unary_type::bitwise_not: std::cout << "~"; break;
|
case unary_operator::unary_type::bitwise_not: std::cout << "~"; break;
|
||||||
}
|
}
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << "\"" << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
set_last();
|
set_last();
|
||||||
node->get_value()->accept(this);
|
node->get_value()->accept(this);
|
||||||
|
@ -217,7 +218,7 @@ bool ast_dumper::visit_unary_operator(unary_operator* node) {
|
||||||
bool ast_dumper::visit_call_expr(call_expr* node) {
|
bool ast_dumper::visit_call_expr(call_expr* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "call_expr";
|
std::cout << "call_expr";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
if (!node->get_calls().size()) {
|
if (!node->get_calls().size()) {
|
||||||
set_last();
|
set_last();
|
||||||
|
@ -236,14 +237,14 @@ bool ast_dumper::visit_call_expr(call_expr* node) {
|
||||||
bool ast_dumper::visit_call_hash(call_hash* node) {
|
bool ast_dumper::visit_call_hash(call_hash* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "call_hash " << node->get_field();
|
std::cout << "call_hash " << node->get_field();
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ast_dumper::visit_call_vector(call_vector* node) {
|
bool ast_dumper::visit_call_vector(call_vector* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "call_vector";
|
std::cout << "call_vector";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
for(auto i : node->get_slices()) {
|
for(auto i : node->get_slices()) {
|
||||||
if (i==node->get_slices().back()) {
|
if (i==node->get_slices().back()) {
|
||||||
|
@ -258,7 +259,7 @@ bool ast_dumper::visit_call_vector(call_vector* node) {
|
||||||
bool ast_dumper::visit_call_function(call_function* node) {
|
bool ast_dumper::visit_call_function(call_function* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "call_function";
|
std::cout << "call_function";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
for(auto i : node->get_argument()) {
|
for(auto i : node->get_argument()) {
|
||||||
if (i==node->get_argument().back()) {
|
if (i==node->get_argument().back()) {
|
||||||
|
@ -273,7 +274,7 @@ bool ast_dumper::visit_call_function(call_function* node) {
|
||||||
bool ast_dumper::visit_slice_vector(slice_vector* node) {
|
bool ast_dumper::visit_slice_vector(slice_vector* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "slice";
|
std::cout << "slice";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
if (!node->get_end()) {
|
if (!node->get_end()) {
|
||||||
set_last();
|
set_last();
|
||||||
|
@ -290,7 +291,7 @@ bool ast_dumper::visit_slice_vector(slice_vector* node) {
|
||||||
bool ast_dumper::visit_definition_expr(definition_expr* node) {
|
bool ast_dumper::visit_definition_expr(definition_expr* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "definition";
|
std::cout << "definition";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
if (node->get_variable_name()) {
|
if (node->get_variable_name()) {
|
||||||
node->get_variable_name()->accept(this);
|
node->get_variable_name()->accept(this);
|
||||||
|
@ -321,7 +322,7 @@ bool ast_dumper::visit_assignment_expr(assignment_expr* node) {
|
||||||
case assignment_expr::assign_type::bitwise_or_equal: std::cout << "|="; break;
|
case assignment_expr::assign_type::bitwise_or_equal: std::cout << "|="; break;
|
||||||
case assignment_expr::assign_type::bitwise_xor_equal: std::cout << "^="; break;
|
case assignment_expr::assign_type::bitwise_xor_equal: std::cout << "^="; break;
|
||||||
}
|
}
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
node->get_left()->accept(this);
|
node->get_left()->accept(this);
|
||||||
set_last();
|
set_last();
|
||||||
|
@ -333,7 +334,7 @@ bool ast_dumper::visit_assignment_expr(assignment_expr* node) {
|
||||||
bool ast_dumper::visit_multi_identifier(multi_identifier* node) {
|
bool ast_dumper::visit_multi_identifier(multi_identifier* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "multiple_identifier";
|
std::cout << "multiple_identifier";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
for(auto i : node->get_variables()) {
|
for(auto i : node->get_variables()) {
|
||||||
if (i==node->get_variables().back()) {
|
if (i==node->get_variables().back()) {
|
||||||
|
@ -348,7 +349,7 @@ bool ast_dumper::visit_multi_identifier(multi_identifier* node) {
|
||||||
bool ast_dumper::visit_tuple_expr(tuple_expr* node) {
|
bool ast_dumper::visit_tuple_expr(tuple_expr* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "tuple";
|
std::cout << "tuple";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
for(auto i : node->get_elements()) {
|
for(auto i : node->get_elements()) {
|
||||||
if (i==node->get_elements().back()) {
|
if (i==node->get_elements().back()) {
|
||||||
|
@ -363,7 +364,7 @@ bool ast_dumper::visit_tuple_expr(tuple_expr* node) {
|
||||||
bool ast_dumper::visit_multi_assign(multi_assign* node) {
|
bool ast_dumper::visit_multi_assign(multi_assign* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "multiple_assignment";
|
std::cout << "multiple_assignment";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
node->get_tuple()->accept(this);
|
node->get_tuple()->accept(this);
|
||||||
set_last();
|
set_last();
|
||||||
|
@ -375,7 +376,7 @@ bool ast_dumper::visit_multi_assign(multi_assign* node) {
|
||||||
bool ast_dumper::visit_while_expr(while_expr* node) {
|
bool ast_dumper::visit_while_expr(while_expr* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "while";
|
std::cout << "while";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
node->get_condition()->accept(this);
|
node->get_condition()->accept(this);
|
||||||
set_last();
|
set_last();
|
||||||
|
@ -387,7 +388,7 @@ bool ast_dumper::visit_while_expr(while_expr* node) {
|
||||||
bool ast_dumper::visit_for_expr(for_expr* node) {
|
bool ast_dumper::visit_for_expr(for_expr* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "for";
|
std::cout << "for";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
node->get_initial()->accept(this);
|
node->get_initial()->accept(this);
|
||||||
node->get_condition()->accept(this);
|
node->get_condition()->accept(this);
|
||||||
|
@ -405,7 +406,7 @@ bool ast_dumper::visit_iter_expr(iter_expr* node) {
|
||||||
} else {
|
} else {
|
||||||
std::cout << "iterator";
|
std::cout << "iterator";
|
||||||
}
|
}
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
set_last();
|
set_last();
|
||||||
if (node->get_name()) {
|
if (node->get_name()) {
|
||||||
|
@ -424,7 +425,7 @@ bool ast_dumper::visit_forei_expr(forei_expr* node) {
|
||||||
} else {
|
} else {
|
||||||
std::cout << "forindex";
|
std::cout << "forindex";
|
||||||
}
|
}
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
node->get_iterator()->accept(this);
|
node->get_iterator()->accept(this);
|
||||||
node->get_value()->accept(this);
|
node->get_value()->accept(this);
|
||||||
|
@ -437,7 +438,7 @@ bool ast_dumper::visit_forei_expr(forei_expr* node) {
|
||||||
bool ast_dumper::visit_condition_expr(condition_expr* node) {
|
bool ast_dumper::visit_condition_expr(condition_expr* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "condition";
|
std::cout << "condition";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
if (!node->get_elsif_stataments().size() &&
|
if (!node->get_elsif_stataments().size() &&
|
||||||
!node->get_else_statement()) {
|
!node->get_else_statement()) {
|
||||||
|
@ -462,7 +463,7 @@ bool ast_dumper::visit_condition_expr(condition_expr* node) {
|
||||||
bool ast_dumper::visit_if_expr(if_expr* node) {
|
bool ast_dumper::visit_if_expr(if_expr* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "if";
|
std::cout << "if";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
push_indent();
|
push_indent();
|
||||||
if (node->get_condition()) {
|
if (node->get_condition()) {
|
||||||
node->get_condition()->accept(this);
|
node->get_condition()->accept(this);
|
||||||
|
@ -476,21 +477,21 @@ bool ast_dumper::visit_if_expr(if_expr* node) {
|
||||||
bool ast_dumper::visit_continue_expr(continue_expr* node) {
|
bool ast_dumper::visit_continue_expr(continue_expr* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "continue";
|
std::cout << "continue";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ast_dumper::visit_break_expr(break_expr* node) {
|
bool ast_dumper::visit_break_expr(break_expr* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "break";
|
std::cout << "break";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ast_dumper::visit_return_expr(return_expr* node) {
|
bool ast_dumper::visit_return_expr(return_expr* node) {
|
||||||
dump_indent();
|
dump_indent();
|
||||||
std::cout << "return";
|
std::cout << "return";
|
||||||
std::cout << format_location(node->get_location());
|
std::cout << format_location(node);
|
||||||
if (node->get_value()) {
|
if (node->get_value()) {
|
||||||
push_indent();
|
push_indent();
|
||||||
set_last();
|
set_last();
|
||||||
|
|
188
src/ast_dumper.h
188
src/ast_dumper.h
|
@ -1,88 +1,100 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ast_visitor.h"
|
#include "ast_visitor.h"
|
||||||
|
#include "util/util.h"
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
namespace nasal {
|
|
||||||
|
namespace nasal {
|
||||||
class ast_dumper: public ast_visitor {
|
|
||||||
private:
|
class ast_dumper: public ast_visitor {
|
||||||
std::vector<std::string> indent;
|
private:
|
||||||
|
std::vector<std::string> indent;
|
||||||
private:
|
|
||||||
void push_indent() {
|
private:
|
||||||
if (indent.size()) {
|
void push_indent() {
|
||||||
if (indent.back()=="|--") {
|
if (indent.size()) {
|
||||||
indent.back() = "| ";
|
if (indent.back()=="├──") {
|
||||||
} else if (indent.back()=="+--") {
|
indent.back() = "│ ";
|
||||||
indent.back() = " ";
|
} else if (indent.back()=="╰──") {
|
||||||
}
|
indent.back() = " ";
|
||||||
}
|
}
|
||||||
indent.push_back("|--");
|
}
|
||||||
}
|
indent.push_back("├──");
|
||||||
void pop_indent() {indent.pop_back();}
|
}
|
||||||
void set_last() {indent.back() = "+--";}
|
|
||||||
void dump_indent() {
|
void pop_indent() {
|
||||||
if (indent.size() && indent.back()=="| ") {
|
indent.pop_back();
|
||||||
indent.back() = "|--";
|
}
|
||||||
}
|
|
||||||
for(const auto& i : indent) {
|
void set_last() {
|
||||||
std::cout << i;
|
indent.back() = "╰──";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
std::string format_location(const span& location) {
|
void dump_indent() {
|
||||||
std::stringstream ss;
|
if (indent.size() && indent.back()=="│ ") {
|
||||||
ss << " -> ";
|
indent.back() = "├──";
|
||||||
location.dump_begin(ss);
|
}
|
||||||
ss << "\n";
|
for(const auto& i : indent) {
|
||||||
return ss.str();
|
std::cout << i;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public:
|
|
||||||
bool visit_use_stmt(use_stmt*) override;
|
std::string format_location(expr* node) {
|
||||||
bool visit_null_expr(null_expr*) override;
|
std::stringstream ss;
|
||||||
bool visit_nil_expr(nil_expr*) override;
|
ss << " → [";
|
||||||
bool visit_number_literal(number_literal*) override;
|
node->get_location().dump_begin(ss);
|
||||||
bool visit_string_literal(string_literal*) override;
|
ss << "]\n";
|
||||||
bool visit_identifier(identifier*) override;
|
return ss.str();
|
||||||
bool visit_bool_literal(bool_literal*) override;
|
}
|
||||||
bool visit_vector_expr(vector_expr*) override;
|
|
||||||
bool visit_hash_expr(hash_expr*) override;
|
public:
|
||||||
bool visit_hash_pair(hash_pair*) override;
|
bool visit_use_stmt(use_stmt*) override;
|
||||||
bool visit_function(function*) override;
|
bool visit_null_expr(null_expr*) override;
|
||||||
bool visit_code_block(code_block*) override;
|
bool visit_nil_expr(nil_expr*) override;
|
||||||
bool visit_parameter(parameter*) override;
|
bool visit_number_literal(number_literal*) override;
|
||||||
bool visit_ternary_operator(ternary_operator*) override;
|
bool visit_string_literal(string_literal*) override;
|
||||||
bool visit_binary_operator(binary_operator*) override;
|
bool visit_identifier(identifier*) override;
|
||||||
bool visit_unary_operator(unary_operator*) override;
|
bool visit_bool_literal(bool_literal*) override;
|
||||||
bool visit_call_expr(call_expr*) override;
|
bool visit_vector_expr(vector_expr*) override;
|
||||||
bool visit_call_hash(call_hash*) override;
|
bool visit_hash_expr(hash_expr*) override;
|
||||||
bool visit_call_vector(call_vector*) override;
|
bool visit_hash_pair(hash_pair*) override;
|
||||||
bool visit_call_function(call_function*) override;
|
bool visit_function(function*) override;
|
||||||
bool visit_slice_vector(slice_vector*) override;
|
bool visit_code_block(code_block*) override;
|
||||||
bool visit_definition_expr(definition_expr*) override;
|
bool visit_parameter(parameter*) override;
|
||||||
bool visit_assignment_expr(assignment_expr*) override;
|
bool visit_ternary_operator(ternary_operator*) override;
|
||||||
bool visit_multi_identifier(multi_identifier*) override;
|
bool visit_binary_operator(binary_operator*) override;
|
||||||
bool visit_tuple_expr(tuple_expr*) override;
|
bool visit_unary_operator(unary_operator*) override;
|
||||||
bool visit_multi_assign(multi_assign*) override;
|
bool visit_call_expr(call_expr*) override;
|
||||||
bool visit_while_expr(while_expr*) override;
|
bool visit_call_hash(call_hash*) override;
|
||||||
bool visit_for_expr(for_expr*) override;
|
bool visit_call_vector(call_vector*) override;
|
||||||
bool visit_iter_expr(iter_expr*) override;
|
bool visit_call_function(call_function*) override;
|
||||||
bool visit_forei_expr(forei_expr*) override;
|
bool visit_slice_vector(slice_vector*) override;
|
||||||
bool visit_condition_expr(condition_expr*) override;
|
bool visit_definition_expr(definition_expr*) override;
|
||||||
bool visit_if_expr(if_expr*) override;
|
bool visit_assignment_expr(assignment_expr*) override;
|
||||||
bool visit_continue_expr(continue_expr*) override;
|
bool visit_multi_identifier(multi_identifier*) override;
|
||||||
bool visit_break_expr(break_expr*) override;
|
bool visit_tuple_expr(tuple_expr*) override;
|
||||||
bool visit_return_expr(return_expr*) override;
|
bool visit_multi_assign(multi_assign*) override;
|
||||||
|
bool visit_while_expr(while_expr*) override;
|
||||||
public:
|
bool visit_for_expr(for_expr*) override;
|
||||||
void dump(code_block* root) {
|
bool visit_iter_expr(iter_expr*) override;
|
||||||
root->accept(this);
|
bool visit_forei_expr(forei_expr*) override;
|
||||||
}
|
bool visit_condition_expr(condition_expr*) override;
|
||||||
};
|
bool visit_if_expr(if_expr*) override;
|
||||||
|
bool visit_continue_expr(continue_expr*) override;
|
||||||
}
|
bool visit_break_expr(break_expr*) override;
|
||||||
|
bool visit_return_expr(return_expr*) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void dump(code_block* root) {
|
||||||
|
util::windows_code_page_manager wcpm;
|
||||||
|
wcpm.set_utf8_output();
|
||||||
|
root->accept(this);
|
||||||
|
wcpm.restore_code_page();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include "cli/cli.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace nasal::cli {
|
||||||
|
|
||||||
|
cli_config parse(const std::vector<std::string>& args) {
|
||||||
|
cli_config result;
|
||||||
|
|
||||||
|
for(const auto& arg : args) {
|
||||||
|
if (cli_options.count(arg)) {
|
||||||
|
result.options.insert(cli_options.at(arg));
|
||||||
|
} else if (!result.input_file_path.length()) {
|
||||||
|
result.input_file_path = arg;
|
||||||
|
} else {
|
||||||
|
result.nasal_vm_args.push_back(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.input_file_path.length() && result.options.empty()) {
|
||||||
|
result.options.insert(option::cli_execute);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <sstream>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace nasal::cli {
|
||||||
|
|
||||||
|
enum class option {
|
||||||
|
cli_help,
|
||||||
|
cli_version,
|
||||||
|
cli_repl_mode,
|
||||||
|
cli_view_ast,
|
||||||
|
cli_view_raw_ast,
|
||||||
|
cli_view_code,
|
||||||
|
cli_show_symbol,
|
||||||
|
cli_execute,
|
||||||
|
cli_show_execute_time,
|
||||||
|
cli_detail_info,
|
||||||
|
cli_show_referenced_file,
|
||||||
|
cli_debug_mode,
|
||||||
|
cli_profile,
|
||||||
|
cli_profile_all,
|
||||||
|
cli_limit_mode
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cli_config {
|
||||||
|
std::string input_file_path = "";
|
||||||
|
std::unordered_set<option> options = {};
|
||||||
|
std::vector<std::string> nasal_vm_args = {};
|
||||||
|
|
||||||
|
bool has(option opt) const {
|
||||||
|
return options.count(opt);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::unordered_map<std::string, option> cli_options = {
|
||||||
|
{"-h", option::cli_help},
|
||||||
|
{"--help", option::cli_help},
|
||||||
|
{"-v", option::cli_version},
|
||||||
|
{"--version", option::cli_version},
|
||||||
|
{"-r", option::cli_repl_mode},
|
||||||
|
{"--repl", option::cli_repl_mode},
|
||||||
|
{"-a", option::cli_view_ast},
|
||||||
|
{"--ast", option::cli_view_ast},
|
||||||
|
{"--raw-ast", option::cli_view_raw_ast},
|
||||||
|
{"-c", option::cli_view_code},
|
||||||
|
{"--code", option::cli_view_code},
|
||||||
|
{"-s", option::cli_show_symbol},
|
||||||
|
{"--symbol", option::cli_show_symbol},
|
||||||
|
{"-e", option::cli_execute},
|
||||||
|
{"--exec", option::cli_execute},
|
||||||
|
{"-t", option::cli_show_execute_time},
|
||||||
|
{"--time", option::cli_show_execute_time},
|
||||||
|
{"-d", option::cli_detail_info},
|
||||||
|
{"--detail", option::cli_detail_info},
|
||||||
|
{"-f", option::cli_show_referenced_file},
|
||||||
|
{"--ref-file", option::cli_show_referenced_file},
|
||||||
|
{"-dbg", option::cli_debug_mode},
|
||||||
|
{"--debug", option::cli_debug_mode},
|
||||||
|
{"--prof", option::cli_profile},
|
||||||
|
{"--prof-all", option::cli_profile_all},
|
||||||
|
{"--limit", option::cli_limit_mode}
|
||||||
|
};
|
||||||
|
|
||||||
|
cli_config parse(const std::vector<std::string>&);
|
||||||
|
|
||||||
|
}
|
140
src/main.cpp
140
src/main.cpp
|
@ -13,39 +13,26 @@
|
||||||
#include "nasal_codegen.h"
|
#include "nasal_codegen.h"
|
||||||
#include "nasal_vm.h"
|
#include "nasal_vm.h"
|
||||||
#include "nasal_dbg.h"
|
#include "nasal_dbg.h"
|
||||||
#include "repl.h"
|
|
||||||
|
#include "util/util.h"
|
||||||
|
#include "repl/repl.h"
|
||||||
|
#include "cli/cli.h"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
const u32 VM_RAW_AST = 1;
|
|
||||||
const u32 VM_AST = 1<<1;
|
|
||||||
const u32 VM_CODE = 1<<2;
|
|
||||||
const u32 VM_TIME = 1<<3;
|
|
||||||
const u32 VM_EXEC = 1<<4;
|
|
||||||
const u32 VM_DETAIL = 1<<5;
|
|
||||||
const u32 VM_DEBUG = 1<<6;
|
|
||||||
const u32 VM_SYMINFO = 1<<7;
|
|
||||||
const u32 VM_PROFILE = 1<<8;
|
|
||||||
const u32 VM_PROF_ALL = 1<<9;
|
|
||||||
const u32 VM_REF_FILE = 1<<10;
|
|
||||||
const u32 VM_LIMIT = 1<<11;
|
|
||||||
|
|
||||||
std::ostream& help(std::ostream& out) {
|
std::ostream& help(std::ostream& out) {
|
||||||
out
|
out
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< " ,--#-,\n"
|
<< " ,--#-,\n"
|
||||||
<< "<3 / \\____\\ <3\n"
|
<< "<3 / \\____\\ <3\n"
|
||||||
<< " |_|__A_|\n"
|
<< " |_|__A_|\n"
|
||||||
#ifdef _WIN32
|
|
||||||
<< "use command <chcp 65001> to use unicode.\n"
|
|
||||||
#endif
|
|
||||||
<< "\nnasal <option>\n"
|
<< "\nnasal <option>\n"
|
||||||
<< "option:\n"
|
<< "option:\n"
|
||||||
<< " -h, --help | get help.\n"
|
<< " -h, --help | get help.\n"
|
||||||
<< " -v, --version | get version.\n"
|
<< " -v, --version | get version.\n"
|
||||||
<< " -r, --repl | use repl interpreter(experimental).\n"
|
<< " -r, --repl | use repl interpreter.\n"
|
||||||
<< "\nnasal [option] <file> [argv]\n"
|
<< "\nnasal [option] <file> [argv]\n"
|
||||||
<< "option:\n"
|
<< "option:\n"
|
||||||
<< " -a, --ast | view ast after link/optimize process.\n"
|
<< " -a, --ast | view ast after link/optimize process.\n"
|
||||||
|
@ -80,7 +67,7 @@ std::ostream& logo(std::ostream& out) {
|
||||||
<< " \\_\\ \\/ \\__,_|___/\\__,_|_|\n"
|
<< " \\_\\ \\/ \\__,_|___/\\__,_|_|\n"
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< "ver : " << __nasver__
|
<< "ver : " << __nasver__
|
||||||
<< " " << nasal::get_platform() << " " << nasal::get_arch()
|
<< " " << nasal::util::get_platform() << " " << nasal::util::get_arch()
|
||||||
<< " (" << __DATE__ << " " << __TIME__ << ")\n"
|
<< " (" << __DATE__ << " " << __TIME__ << ")\n"
|
||||||
<< "std : c++ " << __cplusplus << "\n"
|
<< "std : c++ " << __cplusplus << "\n"
|
||||||
<< "core : " << std::thread::hardware_concurrency() << " core(s)\n"
|
<< "core : " << std::thread::hardware_concurrency() << " core(s)\n"
|
||||||
|
@ -88,7 +75,9 @@ std::ostream& logo(std::ostream& out) {
|
||||||
<< "repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
|
<< "repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
|
||||||
<< "wiki : https://wiki.flightgear.org/Nasal_scripting_language\n"
|
<< "wiki : https://wiki.flightgear.org/Nasal_scripting_language\n"
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< "presented by fgprc members - http://fgprc.org.cn\n"
|
<< "presented by fgprc members\n"
|
||||||
|
<< " - http://fgprc.org\n"
|
||||||
|
<< " - http://fgprc.org.cn\n"
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< "input <nasal -h> to get help .\n\n";
|
<< "input <nasal -h> to get help .\n\n";
|
||||||
return out;
|
return out;
|
||||||
|
@ -101,28 +90,25 @@ std::ostream& version(std::ostream& out) {
|
||||||
for(u32 i = 0; i<5; ++i) {
|
for(u32 i = 0; i<5; ++i) {
|
||||||
num = (num+rand())*(1.0/(RAND_MAX+1.0));
|
num = (num+rand())*(1.0/(RAND_MAX+1.0));
|
||||||
}
|
}
|
||||||
if (num<0.01) {
|
// give you 5% to see this easter egg
|
||||||
|
if (num<0.05) {
|
||||||
nasal::parse::easter_egg();
|
nasal::parse::easter_egg();
|
||||||
}
|
}
|
||||||
|
|
||||||
out << "nasal interpreter version " << __nasver__;
|
out << "nasal version " << __nasver__;
|
||||||
out << " " << nasal::get_platform() << " " << nasal::get_arch();
|
out << " " << nasal::util::get_platform() << " " << nasal::util::get_arch();
|
||||||
out << " (" << __DATE__ << " " << __TIME__ << ")\n";
|
out << " (" << __DATE__ << " " << __TIME__ << ")\n";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]]
|
[[noreturn]]
|
||||||
void err() {
|
void err() {
|
||||||
std::cerr
|
std::cerr << "invalid argument(s), use <nasal -h> to get help.\n";
|
||||||
<< "invalid argument(s).\n"
|
|
||||||
<< "use <nasal -h> to get help.\n";
|
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(const std::string& file,
|
void execute(const nasal::cli::cli_config& config) {
|
||||||
const std::vector<std::string>& argv,
|
using option = nasal::cli::option;
|
||||||
const u32 cmd) {
|
|
||||||
|
|
||||||
using clk = std::chrono::high_resolution_clock;
|
using clk = std::chrono::high_resolution_clock;
|
||||||
const auto den = clk::duration::period::den;
|
const auto den = clk::duration::period::den;
|
||||||
|
|
||||||
|
@ -132,17 +118,17 @@ void execute(const std::string& file,
|
||||||
nasal::codegen gen;
|
nasal::codegen gen;
|
||||||
|
|
||||||
// lexer scans file to get tokens
|
// lexer scans file to get tokens
|
||||||
lex.scan(file).chkerr();
|
lex.scan(config.input_file_path).chkerr();
|
||||||
|
|
||||||
// parser gets lexer's token list to compile
|
// parser gets lexer's token list to compile
|
||||||
parse.compile(lex).chkerr();
|
parse.compile(lex).chkerr();
|
||||||
if (cmd&VM_RAW_AST) {
|
if (config.has(option::cli_view_raw_ast)) {
|
||||||
nasal::ast_dumper().dump(parse.tree());
|
nasal::ast_dumper().dump(parse.tree());
|
||||||
}
|
}
|
||||||
|
|
||||||
// linker gets parser's ast and load import files to this ast
|
// linker gets parser's ast and load import files to this ast
|
||||||
ld.link(parse, cmd&VM_DETAIL).chkerr();
|
ld.link(parse, config.has(option::cli_detail_info)).chkerr();
|
||||||
if (cmd&VM_REF_FILE) {
|
if (config.has(option::cli_show_referenced_file)) {
|
||||||
if (ld.get_file_list().size()) {
|
if (ld.get_file_list().size()) {
|
||||||
std::cout << "referenced file(s):\n";
|
std::cout << "referenced file(s):\n";
|
||||||
}
|
}
|
||||||
|
@ -154,34 +140,43 @@ void execute(const std::string& file,
|
||||||
// optimizer does simple optimization on ast
|
// optimizer does simple optimization on ast
|
||||||
auto opt = std::make_unique<nasal::optimizer>();
|
auto opt = std::make_unique<nasal::optimizer>();
|
||||||
opt->do_optimization(parse.tree());
|
opt->do_optimization(parse.tree());
|
||||||
if (cmd&VM_AST) {
|
if (config.has(option::cli_view_ast)) {
|
||||||
nasal::ast_dumper().dump(parse.tree());
|
nasal::ast_dumper().dump(parse.tree());
|
||||||
}
|
}
|
||||||
|
|
||||||
// code generator gets parser's ast and import file list to generate code
|
// code generator gets parser's ast and import file list to generate code
|
||||||
gen.compile(parse, ld, false, cmd&VM_LIMIT).chkerr();
|
gen.compile(parse, ld, false, config.has(option::cli_limit_mode)).chkerr();
|
||||||
if (cmd&VM_CODE) {
|
if (config.has(option::cli_view_code)) {
|
||||||
gen.print(std::cout);
|
gen.print(std::cout);
|
||||||
}
|
}
|
||||||
if (cmd&VM_SYMINFO) {
|
if (config.has(option::cli_show_symbol)) {
|
||||||
gen.symbol_dump(std::cout);
|
gen.symbol_dump(std::cout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// run
|
// run
|
||||||
const auto start = clk::now();
|
const auto start = clk::now();
|
||||||
if (cmd&VM_DEBUG) {
|
if (config.has(option::cli_debug_mode)) {
|
||||||
auto debugger = std::make_unique<nasal::dbg>();
|
auto debugger = std::make_unique<nasal::dbg>();
|
||||||
debugger->run(gen, ld, argv, cmd&VM_PROFILE, cmd&VM_PROF_ALL);
|
debugger->run(
|
||||||
} else if (cmd&VM_TIME || cmd&VM_EXEC) {
|
gen,
|
||||||
|
ld,
|
||||||
|
config.nasal_vm_args,
|
||||||
|
config.has(option::cli_profile),
|
||||||
|
config.has(option::cli_profile_all)
|
||||||
|
);
|
||||||
|
} else if (config.has(option::cli_show_execute_time) ||
|
||||||
|
config.has(option::cli_detail_info) ||
|
||||||
|
config.has(option::cli_limit_mode) ||
|
||||||
|
config.has(option::cli_execute)) {
|
||||||
auto runtime = std::make_unique<nasal::vm>();
|
auto runtime = std::make_unique<nasal::vm>();
|
||||||
runtime->set_detail_report_info(cmd&VM_DETAIL);
|
runtime->set_detail_report_info(config.has(option::cli_detail_info));
|
||||||
runtime->set_limit_mode_flag(cmd&VM_LIMIT);
|
runtime->set_limit_mode_flag(config.has(option::cli_limit_mode));
|
||||||
runtime->run(gen, ld, argv);
|
runtime->run(gen, ld, config.nasal_vm_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get running time
|
// get running time
|
||||||
const auto end = clk::now();
|
const auto end = clk::now();
|
||||||
if (cmd&VM_TIME) {
|
if (config.has(option::cli_show_execute_time)) {
|
||||||
std::clog << "process exited after ";
|
std::clog << "process exited after ";
|
||||||
std::clog << static_cast<f64>((end-start).count())/den << "s.\n\n";
|
std::clog << static_cast<f64>((end-start).count())/den << "s.\n\n";
|
||||||
}
|
}
|
||||||
|
@ -194,18 +189,20 @@ i32 main(i32 argc, const char* argv[]) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the first argument is the executable itself, ignore it
|
||||||
|
const auto config = nasal::cli::parse({argv+1, argv+argc});
|
||||||
|
|
||||||
// run directly or show help
|
// run directly or show help
|
||||||
if (argc==2) {
|
if (argc==2) {
|
||||||
std::string s(argv[1]);
|
if (config.has(nasal::cli::option::cli_help)) {
|
||||||
if (s=="-h" || s=="--help") {
|
|
||||||
std::clog << help;
|
std::clog << help;
|
||||||
} else if (s=="-v" || s=="--version") {
|
} else if (config.has(nasal::cli::option::cli_version)) {
|
||||||
std::clog << version;
|
std::clog << version;
|
||||||
} else if (s=="-r" || s=="--repl") {
|
} else if (config.has(nasal::cli::option::cli_repl_mode)) {
|
||||||
auto repl = std::make_unique<nasal::repl::repl>();
|
auto repl = std::make_unique<nasal::repl::repl>();
|
||||||
repl->execute();
|
repl->execute();
|
||||||
} else if (s[0]!='-') {
|
} else if (config.input_file_path.size()) {
|
||||||
execute(s, {}, VM_EXEC);
|
execute(config);
|
||||||
} else {
|
} else {
|
||||||
err();
|
err();
|
||||||
}
|
}
|
||||||
|
@ -213,45 +210,6 @@ i32 main(i32 argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute with arguments
|
// execute with arguments
|
||||||
const std::unordered_map<std::string, u32> command_list = {
|
execute(config);
|
||||||
{"--raw-ast", VM_RAW_AST},
|
|
||||||
{"--ast", VM_AST},
|
|
||||||
{"-a", VM_AST},
|
|
||||||
{"--code", VM_CODE},
|
|
||||||
{"-c", VM_CODE},
|
|
||||||
{"--symbol", VM_SYMINFO},
|
|
||||||
{"-s", VM_SYMINFO},
|
|
||||||
{"--exec", VM_EXEC},
|
|
||||||
{"-e", VM_EXEC},
|
|
||||||
{"--time", VM_TIME|VM_EXEC},
|
|
||||||
{"-t", VM_TIME|VM_EXEC},
|
|
||||||
{"--detail", VM_DETAIL|VM_EXEC},
|
|
||||||
{"-d", VM_DETAIL|VM_EXEC},
|
|
||||||
{"--debug", VM_DEBUG},
|
|
||||||
{"-dbg", VM_DEBUG},
|
|
||||||
{"--prof", VM_PROFILE},
|
|
||||||
{"--prof-all", VM_PROF_ALL},
|
|
||||||
{"-f", VM_REF_FILE},
|
|
||||||
{"--ref-file", VM_REF_FILE},
|
|
||||||
{"--limit", VM_LIMIT|VM_EXEC}
|
|
||||||
};
|
|
||||||
|
|
||||||
u32 commands = 0;
|
|
||||||
std::string filename = "";
|
|
||||||
std::vector<std::string> vm_argv;
|
|
||||||
for(i32 i = 1; i<argc; ++i) {
|
|
||||||
if (command_list.count(argv[i])) {
|
|
||||||
commands |= command_list.at(argv[i]);
|
|
||||||
} else if (!filename.length()) {
|
|
||||||
filename = argv[i];
|
|
||||||
} else {
|
|
||||||
vm_argv.push_back(argv[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!filename.length()) {
|
|
||||||
err();
|
|
||||||
}
|
|
||||||
|
|
||||||
execute(filename, vm_argv, commands? commands:VM_EXEC);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
62
src/nasal.h
62
src/nasal.h
|
@ -4,12 +4,8 @@
|
||||||
#define __nasver__ "11.2"
|
#define __nasver__ "11.2"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <sstream>
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
// abbreviation of some useful basic type
|
// abbreviation of some useful basic type
|
||||||
using i32 = std::int32_t;
|
using i32 = std::int32_t;
|
||||||
|
@ -21,61 +17,5 @@ using u64 = std::uint64_t;
|
||||||
using usize = std::size_t;
|
using usize = std::size_t;
|
||||||
using f64 = double;
|
using f64 = double;
|
||||||
|
|
||||||
namespace nasal {
|
|
||||||
|
|
||||||
bool is_windows();
|
|
||||||
bool is_linux();
|
|
||||||
bool is_macos();
|
|
||||||
bool is_x86();
|
|
||||||
bool is_amd64();
|
|
||||||
bool is_x86_64();
|
|
||||||
bool is_arm();
|
|
||||||
bool is_aarch64();
|
|
||||||
bool is_ia64();
|
|
||||||
bool is_powerpc();
|
|
||||||
bool is_superh();
|
|
||||||
const char* get_platform();
|
|
||||||
const char* get_arch();
|
|
||||||
|
|
||||||
// virtual machine stack depth, both global depth and value stack depth
|
// virtual machine stack depth, both global depth and value stack depth
|
||||||
const u32 VM_STACK_DEPTH = UINT16_MAX;
|
const u32 VM_STACK_DEPTH = UINT16_MAX;
|
||||||
|
|
||||||
f64 hex_to_f64(const char*);
|
|
||||||
f64 oct_to_f64(const char*);
|
|
||||||
// we have the same reason not using atof here
|
|
||||||
// just as andy's interpreter does.
|
|
||||||
// it is not platform independent, and may have strange output.
|
|
||||||
// so we write a new function here to convert str to number manually.
|
|
||||||
// but this also makes 0.1+0.2==0.3,
|
|
||||||
// not another result that you may get in other languages.
|
|
||||||
f64 dec_to_f64(const char*);
|
|
||||||
|
|
||||||
f64 str_to_num(const char*);
|
|
||||||
i32 utf8_hdchk(const char);
|
|
||||||
std::string char_to_hex(const char);
|
|
||||||
std::string rawstr(const std::string&, const usize maxlen = 0);
|
|
||||||
|
|
||||||
namespace fs {
|
|
||||||
|
|
||||||
class path {
|
|
||||||
private:
|
|
||||||
std::string file_system_path;
|
|
||||||
|
|
||||||
public:
|
|
||||||
path(const path&) = default;
|
|
||||||
path(const std::string& file_path): file_system_path(file_path) {}
|
|
||||||
path& operator/(const path&);
|
|
||||||
const char* c_str() const {
|
|
||||||
return file_system_path.c_str();
|
|
||||||
}
|
|
||||||
const std::string& str() const {
|
|
||||||
return file_system_path;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool exists(const path&);
|
|
||||||
bool is_regular(const path&);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "nasal_codegen.h"
|
#include "nasal_codegen.h"
|
||||||
|
#include "util/util.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
|
@ -239,9 +240,9 @@ void codegen::func_gen(function* node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usize newf=code.size();
|
const auto newf = code.size();
|
||||||
emit(op_newf, 0, node->get_location());
|
emit(op_newf, 0, node->get_location());
|
||||||
usize lsize=code.size();
|
const auto lsize = code.size();
|
||||||
emit(op_intl, 0, node->get_location());
|
emit(op_intl, 0, node->get_location());
|
||||||
|
|
||||||
// add special keyword 'me' into symbol table
|
// add special keyword 'me' into symbol table
|
||||||
|
@ -1390,7 +1391,7 @@ void codegen::print(std::ostream& out) {
|
||||||
|
|
||||||
// print const strings
|
// print const strings
|
||||||
for(const auto& str : const_string_table) {
|
for(const auto& str : const_string_table) {
|
||||||
out << " .symbol \"" << rawstr(str) << "\"\n";
|
out << " .symbol \"" << util::rawstr(str) << "\"\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// print blank line
|
// print blank line
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include "nasal_parse.h"
|
#include "nasal_parse.h"
|
||||||
#include "nasal_import.h"
|
#include "nasal_import.h"
|
||||||
|
|
||||||
#include "natives/nasal_builtin.h"
|
#include "natives/builtin.h"
|
||||||
#include "natives/coroutine.h"
|
#include "natives/coroutine.h"
|
||||||
#include "natives/bits_lib.h"
|
#include "natives/bits_lib.h"
|
||||||
#include "natives/math_lib.h"
|
#include "natives/math_lib.h"
|
||||||
|
|
|
@ -13,7 +13,7 @@ void operand_line_counter::load_file_line_counter(
|
||||||
file_name_list = file_list;
|
file_name_list = file_list;
|
||||||
file_line_counter = {};
|
file_line_counter = {};
|
||||||
file_contents = {};
|
file_contents = {};
|
||||||
flstream fs;
|
filestream fs;
|
||||||
for(usize i =0; i<file_list.size(); ++i) {
|
for(usize i =0; i<file_list.size(); ++i) {
|
||||||
fs.load(file_list[i]);
|
fs.load(file_list[i]);
|
||||||
file_contents.push_back(fs.file_content());
|
file_contents.push_back(fs.file_content());
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "nasal_err.h"
|
#include "nasal_err.h"
|
||||||
#include "repl.h"
|
#include "repl/repl.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ std::ostream& reset(std::ostream& s) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void flstream::load(const std::string& f) {
|
void filestream::load(const std::string& f) {
|
||||||
if (file==f) { // don't need to load a loaded file
|
if (file==f) { // don't need to load a loaded file
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,13 +29,13 @@ std::ostream& orange(std::ostream&);
|
||||||
std::ostream& white(std::ostream&);
|
std::ostream& white(std::ostream&);
|
||||||
std::ostream& reset(std::ostream&);
|
std::ostream& reset(std::ostream&);
|
||||||
|
|
||||||
class flstream {
|
class filestream {
|
||||||
protected:
|
protected:
|
||||||
std::string file;
|
std::string file;
|
||||||
std::vector<std::string> res;
|
std::vector<std::string> res;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
flstream(): file("") {}
|
filestream(): file("") {}
|
||||||
void load(const std::string&);
|
void load(const std::string&);
|
||||||
const std::string& operator[](usize n) const {return res[n];}
|
const std::string& operator[](usize n) const {return res[n];}
|
||||||
const auto& name() const {return file;}
|
const auto& name() const {return file;}
|
||||||
|
@ -43,7 +43,7 @@ public:
|
||||||
usize size() const {return res.size();}
|
usize size() const {return res.size();}
|
||||||
};
|
};
|
||||||
|
|
||||||
class error: public flstream {
|
class error: public filestream {
|
||||||
private:
|
private:
|
||||||
u32 cnt; // counter for errors
|
u32 cnt; // counter for errors
|
||||||
|
|
||||||
|
|
|
@ -301,17 +301,17 @@ void gc::info() const {
|
||||||
for(usize i = 0; i<indent; ++i) {
|
for(usize i = 0; i<indent; ++i) {
|
||||||
indent_string += "-";
|
indent_string += "-";
|
||||||
}
|
}
|
||||||
auto last_line = indent_string + "+" +
|
const auto last_line = "+" + indent_string + "+" +
|
||||||
indent_string + "-" + indent_string + "-" + indent_string;
|
indent_string + "-" + indent_string + "-" + indent_string + "+";
|
||||||
indent_string = indent_string + "+" +
|
indent_string = indent_string + "+" +
|
||||||
indent_string + "+" + indent_string + "+" + indent_string;
|
indent_string + "+" + indent_string + "+" + indent_string;
|
||||||
|
|
||||||
std::clog << "\n" << indent_string << "\n";
|
std::clog << "\n+" << indent_string << "+\n";
|
||||||
std::clog << " " << left << setw(indent) << setfill(' ') << "object type";
|
std::clog << "| " << left << setw(indent) << setfill(' ') << "object type";
|
||||||
std::clog << " | " << left << setw(indent) << setfill(' ') << "gc count";
|
std::clog << " | " << left << setw(indent) << setfill(' ') << "gc count";
|
||||||
std::clog << " | " << left << setw(indent) << setfill(' ') << "alloc count";
|
std::clog << " | " << left << setw(indent) << setfill(' ') << "alloc count";
|
||||||
std::clog << " | " << left << setw(indent) << setfill(' ') << "memory size";
|
std::clog << " | " << left << setw(indent) << setfill(' ') << "memory size";
|
||||||
std::clog << "\n" << indent_string << "\n";
|
std::clog << " |\n+" << indent_string << "+\n";
|
||||||
|
|
||||||
double total = 0;
|
double total = 0;
|
||||||
for(u8 i = 0; i<gc_type_size; ++i) {
|
for(u8 i = 0; i<gc_type_size; ++i) {
|
||||||
|
@ -319,33 +319,45 @@ void gc::info() const {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
total += static_cast<f64>(gcnt[i]);
|
total += static_cast<f64>(gcnt[i]);
|
||||||
std::clog << " " << left << setw(indent) << setfill(' ') << name[i];
|
std::clog << "| " << left << setw(indent) << setfill(' ') << name[i];
|
||||||
std::clog << " | " << left << setw(indent) << setfill(' ') << gcnt[i];
|
std::clog << " | " << left << setw(indent) << setfill(' ') << gcnt[i];
|
||||||
std::clog << " | " << left << setw(indent) << setfill(' ') << acnt[i];
|
std::clog << " | " << left << setw(indent) << setfill(' ') << acnt[i];
|
||||||
std::clog << " | " << left << setw(indent) << setfill(' ') << size[i];
|
std::clog << " | " << left << setw(indent) << setfill(' ') << size[i];
|
||||||
std::clog << "\n";
|
std::clog << " |\n";
|
||||||
}
|
}
|
||||||
std::clog << indent_string << "\n";
|
std::clog << "+" << indent_string << "+\n";
|
||||||
|
|
||||||
auto den = std::chrono::high_resolution_clock::duration::period::den;
|
auto den = std::chrono::high_resolution_clock::duration::period::den;
|
||||||
std::clog << " " << left << setw(indent) << setfill(' ') << "detail";
|
std::clog << "| " << left << setw(indent) << setfill(' ') << "detail";
|
||||||
std::clog << " | " << left << setw(indent) << setfill(' ') << "time spend";
|
std::clog << " | " << left << setw(indent) << setfill(' ') << "time spend";
|
||||||
std::clog << " | " << left << setw(indent) << setfill('x') << "x";
|
std::clog << " | " << left << setw(indent) << setfill('x') << "x";
|
||||||
std::clog << " | " << left << setw(indent) << setfill('x') << "x";
|
std::clog << " | " << left << setw(indent) << setfill('x') << "x";
|
||||||
std::clog << "\n" << indent_string << "\n";
|
std::clog << " |\n+" << indent_string << "+\n";
|
||||||
|
|
||||||
|
std::clog << "| " << left << setw(indent) << setfill(' ') << "gc time";
|
||||||
|
std::clog << " | " << setw(indent-3) << std::setprecision(4) << worktime*1.0/den*1000 << " ms";
|
||||||
|
std::clog << setw(indent*2+7) << " " << "|\n";
|
||||||
|
|
||||||
|
std::clog << "| " << left << setw(indent) << setfill(' ') << "avg time";
|
||||||
|
std::clog << " | " << setw(indent-3) << std::setprecision(4) << worktime*1.0/den*1000/total << " ms";
|
||||||
|
std::clog << setw(indent*2+7) << " " << "|\n";
|
||||||
|
|
||||||
|
std::clog << "| " << left << setw(indent) << setfill(' ') << "max gc";
|
||||||
|
std::clog << " | " << setw(indent-3) << std::setprecision(4) << max_time*1.0/den*1000 << " ms";
|
||||||
|
std::clog << setw(indent*2+7) << " " << "|\n";
|
||||||
|
|
||||||
|
std::clog << "| " << left << setw(indent) << setfill(' ') << "max mark";
|
||||||
|
std::clog << " | " << setw(indent-3) << std::setprecision(4) << max_mark_time*1.0/den*1000 << " ms";
|
||||||
|
std::clog << setw(indent*2+7) << " " << "|\n";
|
||||||
|
|
||||||
|
std::clog << "| " << left << setw(indent) << setfill(' ') << "max sweep";
|
||||||
|
std::clog << " | " << setw(indent-3) << std::setprecision(4) << max_sweep_time*1.0/den*1000 << " ms";
|
||||||
|
std::clog << setw(indent*2+7) << " " << "|\n";
|
||||||
|
|
||||||
|
std::clog << "| " << left << setw(indent) << setfill(' ') << "concurrent";
|
||||||
|
std::clog << " | " << setw(indent) << (flag_concurrent_mark_triggered? "true":"false");
|
||||||
|
std::clog << setw(indent*2+7) << " " << "|\n";
|
||||||
|
|
||||||
std::clog << " " << left << setw(indent) << setfill(' ') << "gc time";
|
|
||||||
std::clog << " | " << worktime*1.0/den*1000 << " ms\n";
|
|
||||||
std::clog << " " << left << setw(indent) << setfill(' ') << "avg time";
|
|
||||||
std::clog << " | " << worktime*1.0/den*1000/total << " ms\n";
|
|
||||||
std::clog << " " << left << setw(indent) << setfill(' ') << "max gc";
|
|
||||||
std::clog << " | " << max_time*1.0/den*1000 << " ms\n";
|
|
||||||
std::clog << " " << left << setw(indent) << setfill(' ') << "max mark";
|
|
||||||
std::clog << " | " << max_mark_time*1.0/den*1000 << " ms\n";
|
|
||||||
std::clog << " " << left << setw(indent) << setfill(' ') << "max sweep";
|
|
||||||
std::clog << " | " << max_sweep_time*1.0/den*1000 << " ms\n";
|
|
||||||
std::clog << " " << left << setw(indent) << setfill(' ') << "concurrent";
|
|
||||||
std::clog << " | " << (flag_concurrent_mark_triggered? "true\n":"false\n");
|
|
||||||
std::clog << last_line << "\n";
|
std::clog << last_line << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,7 +392,7 @@ void gc::context_change(nas_co* co) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void gc::context_reserve() {
|
void gc::context_reserve() {
|
||||||
// pc=0 means this coroutine is finished
|
// pc = 0 means this coroutine is finished
|
||||||
cort->status = running_context->pc?
|
cort->status = running_context->pc?
|
||||||
nas_co::status::suspended:
|
nas_co::status::suspended:
|
||||||
nas_co::status::dead;
|
nas_co::status::dead;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "nasal_type.h"
|
#include "nasal_type.h"
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "nasal_import.h"
|
#include "nasal_import.h"
|
||||||
#include "symbol_finder.h"
|
#include "symbol_finder.h"
|
||||||
|
#include "util/util.h"
|
||||||
|
#include "util/fs.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
@ -7,7 +9,7 @@
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
linker::linker(): show_path_flag(false), this_file("") {
|
linker::linker(): show_path_flag(false), this_file("") {
|
||||||
const auto seperator = is_windows()? ';':':';
|
const auto seperator = util::is_windows()? ';':':';
|
||||||
const auto PATH = std::string(getenv("PATH"));
|
const auto PATH = std::string(getenv("PATH"));
|
||||||
usize last = 0, position = PATH.find(seperator, 0);
|
usize last = 0, position = PATH.find(seperator, 0);
|
||||||
while(position!=std::string::npos) {
|
while(position!=std::string::npos) {
|
||||||
|
@ -30,7 +32,7 @@ std::string linker::get_path(expr* node) {
|
||||||
for(auto i : path) {
|
for(auto i : path) {
|
||||||
file_relative_path += i->get_name();
|
file_relative_path += i->get_name();
|
||||||
if (i!=path.back()) {
|
if (i!=path.back()) {
|
||||||
file_relative_path += (is_windows()? "\\":"/");
|
file_relative_path += (util::is_windows()? "\\":"/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return file_relative_path + ".nas";
|
return file_relative_path + ".nas";
|
||||||
|
@ -60,7 +62,7 @@ std::string linker::find_real_file_path(const std::string& filename,
|
||||||
|
|
||||||
// we will find lib.nas in nasal std directory
|
// we will find lib.nas in nasal std directory
|
||||||
if (filename=="lib.nas") {
|
if (filename=="lib.nas") {
|
||||||
return is_windows()?
|
return util::is_windows()?
|
||||||
find_real_file_path("std\\lib.nas", location):
|
find_real_file_path("std\\lib.nas", location):
|
||||||
find_real_file_path("std/lib.nas", location);
|
find_real_file_path("std/lib.nas", location);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "nasal_lexer.h"
|
#include "nasal_lexer.h"
|
||||||
#include "nasal_parse.h"
|
#include "nasal_parse.h"
|
||||||
#include "symbol_finder.h"
|
#include "symbol_finder.h"
|
||||||
|
#include "util/fs.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "nasal_lexer.h"
|
#include "nasal_lexer.h"
|
||||||
#include "repl.h"
|
#include "repl/repl.h"
|
||||||
|
#include "util/util.h"
|
||||||
|
#include "util/fs.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
|
@ -61,7 +63,7 @@ void lexer::err_char() {
|
||||||
char c = res[ptr++];
|
char c = res[ptr++];
|
||||||
err.err("lexer",
|
err.err("lexer",
|
||||||
{line, column-1, line, column, filename},
|
{line, column-1, line, column, filename},
|
||||||
"invalid character 0x" + char_to_hex(c)
|
"invalid character 0x" + util::char_to_hex(c)
|
||||||
);
|
);
|
||||||
++invalid_char;
|
++invalid_char;
|
||||||
}
|
}
|
||||||
|
@ -75,6 +77,11 @@ void lexer::open(const std::string& file) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (file.empty()) {
|
||||||
|
err.err("lexer", "empty input file");
|
||||||
|
err.chkerr();
|
||||||
|
}
|
||||||
|
|
||||||
// check file exsits and it is a regular file
|
// check file exsits and it is a regular file
|
||||||
if (!fs::is_regular(file)) {
|
if (!fs::is_regular(file)) {
|
||||||
err.err("lexer", "<"+file+"> is not a regular file");
|
err.err("lexer", "<"+file+"> is not a regular file");
|
||||||
|
@ -96,14 +103,14 @@ void lexer::open(const std::string& file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tok lexer::get_type(const std::string& str) {
|
tok lexer::get_type(const std::string& str) {
|
||||||
return token_mapper.count(str)? token_mapper.at(str):tok::null;
|
return token_mapper.count(str)? token_mapper.at(str):tok::tk_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string lexer::utf8_gen() {
|
std::string lexer::utf8_gen() {
|
||||||
std::string str = "";
|
std::string str = "";
|
||||||
while(ptr<res.size() && res[ptr]<0) {
|
while(ptr<res.size() && res[ptr]<0) {
|
||||||
std::string tmp = "";
|
std::string tmp = "";
|
||||||
u32 nbytes = utf8_hdchk(res[ptr]);
|
u32 nbytes = util::utf8_hdchk(res[ptr]);
|
||||||
if (!nbytes) {
|
if (!nbytes) {
|
||||||
++ptr;
|
++ptr;
|
||||||
++column;
|
++column;
|
||||||
|
@ -120,9 +127,9 @@ std::string lexer::utf8_gen() {
|
||||||
// utf8 character's total length is 1+nbytes
|
// utf8 character's total length is 1+nbytes
|
||||||
if (tmp.length()!=1+nbytes) {
|
if (tmp.length()!=1+nbytes) {
|
||||||
++column;
|
++column;
|
||||||
std::string utf_info = "0x" + char_to_hex(tmp[0]);
|
std::string utf_info = "0x" + util::char_to_hex(tmp[0]);
|
||||||
for(u32 i = 1; i<tmp.size(); ++i) {
|
for(u32 i = 1; i<tmp.size(); ++i) {
|
||||||
utf_info += " 0x" + char_to_hex(tmp[i]);
|
utf_info += " 0x" + util::char_to_hex(tmp[i]);
|
||||||
}
|
}
|
||||||
err.err("lexer",
|
err.err("lexer",
|
||||||
{line, column-1, line, column, filename},
|
{line, column-1, line, column, filename},
|
||||||
|
@ -152,7 +159,8 @@ token lexer::id_gen() {
|
||||||
tok type = get_type(str);
|
tok type = get_type(str);
|
||||||
return {
|
return {
|
||||||
{begin_line, begin_column, line, column, filename},
|
{begin_line, begin_column, line, column, filename},
|
||||||
(type!=tok::null)? type:tok::id, str
|
(type!=tok::tk_null)? type:tok::tk_id,
|
||||||
|
str
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +182,11 @@ token lexer::num_gen() {
|
||||||
"invalid number `"+str+"`"
|
"invalid number `"+str+"`"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return {{begin_line, begin_column, line, column, filename}, tok::num, str};
|
return {
|
||||||
|
{begin_line, begin_column, line, column, filename},
|
||||||
|
tok::tk_num,
|
||||||
|
str
|
||||||
|
};
|
||||||
} else if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='o') { // generate oct number
|
} else if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='o') { // generate oct number
|
||||||
std::string str = "0o";
|
std::string str = "0o";
|
||||||
ptr += 2;
|
ptr += 2;
|
||||||
|
@ -193,7 +205,11 @@ token lexer::num_gen() {
|
||||||
"invalid number `"+str+"`"
|
"invalid number `"+str+"`"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return {{begin_line, begin_column, line, column, filename}, tok::num, str};
|
return {
|
||||||
|
{begin_line, begin_column, line, column, filename},
|
||||||
|
tok::tk_num,
|
||||||
|
str
|
||||||
|
};
|
||||||
}
|
}
|
||||||
// generate dec number
|
// generate dec number
|
||||||
// dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
|
// dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
|
||||||
|
@ -213,7 +229,11 @@ token lexer::num_gen() {
|
||||||
{begin_line, begin_column, line, column, filename},
|
{begin_line, begin_column, line, column, filename},
|
||||||
"invalid number `"+str+"`"
|
"invalid number `"+str+"`"
|
||||||
);
|
);
|
||||||
return {{begin_line, begin_column, line, column, filename}, tok::num, "0"};
|
return {
|
||||||
|
{begin_line, begin_column, line, column, filename},
|
||||||
|
tok::tk_num,
|
||||||
|
"0"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ptr<res.size() && (res[ptr]=='e' || res[ptr]=='E')) {
|
if (ptr<res.size() && (res[ptr]=='e' || res[ptr]=='E')) {
|
||||||
|
@ -231,11 +251,19 @@ token lexer::num_gen() {
|
||||||
{begin_line, begin_column, line, column, filename},
|
{begin_line, begin_column, line, column, filename},
|
||||||
"invalid number `"+str+"`"
|
"invalid number `"+str+"`"
|
||||||
);
|
);
|
||||||
return {{begin_line, begin_column, line, column, filename}, tok::num, "0"};
|
return {
|
||||||
|
{begin_line, begin_column, line, column, filename},
|
||||||
|
tok::tk_num,
|
||||||
|
"0"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
column += str.length();
|
column += str.length();
|
||||||
return {{begin_line, begin_column, line, column, filename}, tok::num, str};
|
return {
|
||||||
|
{begin_line, begin_column, line, column, filename},
|
||||||
|
tok::tk_num,
|
||||||
|
str
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
token lexer::str_gen() {
|
token lexer::str_gen() {
|
||||||
|
@ -283,18 +311,26 @@ token lexer::str_gen() {
|
||||||
{begin_line, begin_column, line, column, filename},
|
{begin_line, begin_column, line, column, filename},
|
||||||
"get EOF when generating string"
|
"get EOF when generating string"
|
||||||
);
|
);
|
||||||
return {{begin_line, begin_column, line, column, filename}, tok::str, str};
|
return {
|
||||||
|
{begin_line, begin_column, line, column, filename},
|
||||||
|
tok::tk_str,
|
||||||
|
str
|
||||||
|
};
|
||||||
}
|
}
|
||||||
++column;
|
++column;
|
||||||
|
|
||||||
// if is not utf8, 1+utf8_hdchk should be 1
|
// if is not utf8, 1+utf8_hdchk should be 1
|
||||||
if (begin=='`' && str.length()!=1+utf8_hdchk(str[0])) {
|
if (begin=='`' && str.length()!=1+util::utf8_hdchk(str[0])) {
|
||||||
err.err("lexer",
|
err.err("lexer",
|
||||||
{begin_line, begin_column, line, column, filename},
|
{begin_line, begin_column, line, column, filename},
|
||||||
"\'`\' is used for string including one character"
|
"\'`\' is used for string including one character"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return {{begin_line, begin_column, line, column, filename}, tok::str, str};
|
return {
|
||||||
|
{begin_line, begin_column, line, column, filename},
|
||||||
|
tok::tk_str,
|
||||||
|
str
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
token lexer::single_opr() {
|
token lexer::single_opr() {
|
||||||
|
@ -303,7 +339,7 @@ token lexer::single_opr() {
|
||||||
std::string str(1, res[ptr]);
|
std::string str(1, res[ptr]);
|
||||||
++column;
|
++column;
|
||||||
tok type = get_type(str);
|
tok type = get_type(str);
|
||||||
if (type==tok::null) {
|
if (type==tok::tk_null) {
|
||||||
err.err("lexer",
|
err.err("lexer",
|
||||||
{begin_line, begin_column, line, column, filename},
|
{begin_line, begin_column, line, column, filename},
|
||||||
"invalid operator `"+str+"`"
|
"invalid operator `"+str+"`"
|
||||||
|
@ -380,10 +416,14 @@ const error& lexer::scan(const std::string& file) {
|
||||||
}
|
}
|
||||||
if (toks.size()) {
|
if (toks.size()) {
|
||||||
// eof token's location is the last token's location
|
// eof token's location is the last token's location
|
||||||
toks.push_back({toks.back().loc, tok::eof, "<eof>"});
|
toks.push_back({toks.back().loc, tok::tk_eof, "<eof>"});
|
||||||
} else {
|
} else {
|
||||||
// if token sequence is empty, generate a default location
|
// if token sequence is empty, generate a default location
|
||||||
toks.push_back({{line, column, line, column, filename}, tok::eof, "<eof>"});
|
toks.push_back({
|
||||||
|
{line, column, line, column, filename},
|
||||||
|
tok::tk_eof,
|
||||||
|
"<eof>"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
res = "";
|
res = "";
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -16,66 +16,66 @@
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
enum class tok:u32 {
|
enum class tok {
|
||||||
null=0, // null token (default token type)
|
tk_null = 0, // null token (default token type)
|
||||||
num, // number literal
|
tk_num, // number literal
|
||||||
str, // string literal
|
tk_str, // string literal
|
||||||
id, // identifier
|
tk_id, // identifier
|
||||||
tktrue, // keyword true
|
tk_true, // keyword true
|
||||||
tkfalse, // keyword false
|
tk_false, // keyword false
|
||||||
use, // keyword use
|
tk_use, // keyword use
|
||||||
rfor, // loop keyword for
|
tk_for, // loop keyword for
|
||||||
forindex, // loop keyword forindex
|
tk_forindex, // loop keyword forindex
|
||||||
foreach, // loop keyword foreach
|
tk_foreach, // loop keyword foreach
|
||||||
rwhile, // loop keyword while
|
tk_while, // loop keyword while
|
||||||
var, // keyword for definition
|
tk_var, // keyword for definition
|
||||||
func, // keyword for definition of function
|
tk_func, // keyword for definition of function
|
||||||
brk, // loop keyword break
|
tk_brk, // loop keyword break
|
||||||
cont, // loop keyword continue
|
tk_cont, // loop keyword continue
|
||||||
ret, // function keyword return
|
tk_ret, // function keyword return
|
||||||
rif, // condition expression keyword if
|
tk_if, // condition expression keyword if
|
||||||
elsif, // condition expression keyword elsif
|
tk_elsif, // condition expression keyword elsif
|
||||||
relse, // condition expression keyword else
|
tk_else, // condition expression keyword else
|
||||||
nil, // nil literal
|
tk_nil, // nil literal
|
||||||
lcurve, // (
|
tk_lcurve, // (
|
||||||
rcurve, // )
|
tk_rcurve, // )
|
||||||
lbracket, // [
|
tk_lbracket, // [
|
||||||
rbracket, // ]
|
tk_rbracket, // ]
|
||||||
lbrace, // {
|
tk_lbrace, // {
|
||||||
rbrace, // }
|
tk_rbrace, // }
|
||||||
semi, // ;
|
tk_semi, // ;
|
||||||
opand, // operator and
|
tk_and, // operator and
|
||||||
opor, // operator or
|
tk_or, // operator or
|
||||||
comma, // ,
|
tk_comma, // ,
|
||||||
dot, // .
|
tk_dot, // .
|
||||||
ellipsis, // ...
|
tk_ellipsis, // ...
|
||||||
quesmark, // ?
|
tk_quesmark, // ?
|
||||||
colon, // :
|
tk_colon, // :
|
||||||
add, // operator +
|
tk_add, // operator +
|
||||||
sub, // operator -
|
tk_sub, // operator -
|
||||||
mult, // operator *
|
tk_mult, // operator *
|
||||||
div, // operator /
|
tk_div, // operator /
|
||||||
floater, // operator ~ and binary operator ~
|
tk_floater, // operator ~ and binary operator ~
|
||||||
btand, // bitwise operator &
|
tk_btand, // bitwise operator &
|
||||||
btor, // bitwise operator |
|
tk_btor, // bitwise operator |
|
||||||
btxor, // bitwise operator ^
|
tk_btxor, // bitwise operator ^
|
||||||
opnot, // operator !
|
tk_not, // operator !
|
||||||
eq, // operator =
|
tk_eq, // operator =
|
||||||
addeq, // operator +=
|
tk_addeq, // operator +=
|
||||||
subeq, // operator -=
|
tk_subeq, // operator -=
|
||||||
multeq, // operator *=
|
tk_multeq, // operator *=
|
||||||
diveq, // operator /=
|
tk_diveq, // operator /=
|
||||||
lnkeq, // operator ~=
|
tk_lnkeq, // operator ~=
|
||||||
btandeq, // operator &=
|
tk_btandeq, // operator &=
|
||||||
btoreq, // operator |=
|
tk_btoreq, // operator |=
|
||||||
btxoreq, // operator ^=
|
tk_btxoreq, // operator ^=
|
||||||
cmpeq, // operator ==
|
tk_cmpeq, // operator ==
|
||||||
neq, // operator !=
|
tk_neq, // operator !=
|
||||||
less, // operator <
|
tk_less, // operator <
|
||||||
leq, // operator <=
|
tk_leq, // operator <=
|
||||||
grt, // operator >
|
tk_grt, // operator >
|
||||||
geq, // operator >=
|
tk_geq, // operator >=
|
||||||
eof // <eof> end of token list
|
tk_eof // <eof> end of token list
|
||||||
};
|
};
|
||||||
|
|
||||||
struct token {
|
struct token {
|
||||||
|
@ -99,60 +99,60 @@ private:
|
||||||
std::vector<token> toks;
|
std::vector<token> toks;
|
||||||
|
|
||||||
const std::unordered_map<std::string, tok> token_mapper = {
|
const std::unordered_map<std::string, tok> token_mapper = {
|
||||||
{"use" ,tok::use },
|
{"use" , tok::tk_use },
|
||||||
{"true" ,tok::tktrue },
|
{"true" , tok::tk_true },
|
||||||
{"false" ,tok::tkfalse },
|
{"false" , tok::tk_false },
|
||||||
{"for" ,tok::rfor },
|
{"for" , tok::tk_for },
|
||||||
{"forindex",tok::forindex},
|
{"forindex", tok::tk_forindex},
|
||||||
{"foreach" ,tok::foreach },
|
{"foreach" , tok::tk_foreach },
|
||||||
{"while" ,tok::rwhile },
|
{"while" , tok::tk_while },
|
||||||
{"var" ,tok::var },
|
{"var" , tok::tk_var },
|
||||||
{"func" ,tok::func },
|
{"func" , tok::tk_func },
|
||||||
{"break" ,tok::brk },
|
{"break" , tok::tk_brk },
|
||||||
{"continue",tok::cont },
|
{"continue", tok::tk_cont },
|
||||||
{"return" ,tok::ret },
|
{"return" , tok::tk_ret },
|
||||||
{"if" ,tok::rif },
|
{"if" , tok::tk_if },
|
||||||
{"elsif" ,tok::elsif },
|
{"elsif" , tok::tk_elsif },
|
||||||
{"else" ,tok::relse },
|
{"else" , tok::tk_else },
|
||||||
{"nil" ,tok::nil },
|
{"nil" , tok::tk_nil },
|
||||||
{"(" ,tok::lcurve },
|
{"(" , tok::tk_lcurve },
|
||||||
{")" ,tok::rcurve },
|
{")" , tok::tk_rcurve },
|
||||||
{"[" ,tok::lbracket},
|
{"[" , tok::tk_lbracket},
|
||||||
{"]" ,tok::rbracket},
|
{"]" , tok::tk_rbracket},
|
||||||
{"{" ,tok::lbrace },
|
{"{" , tok::tk_lbrace },
|
||||||
{"}" ,tok::rbrace },
|
{"}" , tok::tk_rbrace },
|
||||||
{";" ,tok::semi },
|
{";" , tok::tk_semi },
|
||||||
{"and" ,tok::opand },
|
{"and" , tok::tk_and },
|
||||||
{"or" ,tok::opor },
|
{"or" , tok::tk_or },
|
||||||
{"," ,tok::comma },
|
{"," , tok::tk_comma },
|
||||||
{"." ,tok::dot },
|
{"." , tok::tk_dot },
|
||||||
{"..." ,tok::ellipsis},
|
{"..." , tok::tk_ellipsis},
|
||||||
{"?" ,tok::quesmark},
|
{"?" , tok::tk_quesmark},
|
||||||
{":" ,tok::colon },
|
{":" , tok::tk_colon },
|
||||||
{"+" ,tok::add },
|
{"+" , tok::tk_add },
|
||||||
{"-" ,tok::sub },
|
{"-" , tok::tk_sub },
|
||||||
{"*" ,tok::mult },
|
{"*" , tok::tk_mult },
|
||||||
{"/" ,tok::div },
|
{"/" , tok::tk_div },
|
||||||
{"~" ,tok::floater },
|
{"~" , tok::tk_floater },
|
||||||
{"&" ,tok::btand },
|
{"&" , tok::tk_btand },
|
||||||
{"|" ,tok::btor },
|
{"|" , tok::tk_btor },
|
||||||
{"^" ,tok::btxor },
|
{"^" , tok::tk_btxor },
|
||||||
{"!" ,tok::opnot },
|
{"!" , tok::tk_not },
|
||||||
{"=" ,tok::eq },
|
{"=" , tok::tk_eq },
|
||||||
{"+=" ,tok::addeq },
|
{"+=" , tok::tk_addeq },
|
||||||
{"-=" ,tok::subeq },
|
{"-=" , tok::tk_subeq },
|
||||||
{"*=" ,tok::multeq },
|
{"*=" , tok::tk_multeq },
|
||||||
{"/=" ,tok::diveq },
|
{"/=" , tok::tk_diveq },
|
||||||
{"~=" ,tok::lnkeq },
|
{"~=" , tok::tk_lnkeq },
|
||||||
{"&=" ,tok::btandeq },
|
{"&=" , tok::tk_btandeq },
|
||||||
{"|=" ,tok::btoreq },
|
{"|=" , tok::tk_btoreq },
|
||||||
{"^=" ,tok::btxoreq },
|
{"^=" , tok::tk_btxoreq },
|
||||||
{"==" ,tok::cmpeq },
|
{"==" , tok::tk_cmpeq },
|
||||||
{"!=" ,tok::neq },
|
{"!=" , tok::tk_neq },
|
||||||
{"<" ,tok::less },
|
{"<" , tok::tk_less },
|
||||||
{"<=" ,tok::leq },
|
{"<=" , tok::tk_leq },
|
||||||
{">" ,tok::grt },
|
{">" , tok::tk_grt },
|
||||||
{">=" ,tok::geq }
|
{">=" , tok::tk_geq }
|
||||||
};
|
};
|
||||||
|
|
||||||
tok get_type(const std::string&);
|
tok get_type(const std::string&);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "nasal_opcode.h"
|
#include "nasal_opcode.h"
|
||||||
|
#include "util/util.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ void codestream::dump(std::ostream& out) const {
|
||||||
|
|
||||||
// dump operand index and bytecode(hex format)
|
// dump operand index and bytecode(hex format)
|
||||||
out << hex << "0x"
|
out << hex << "0x"
|
||||||
<< setw(6) << setfill('0') << index << " "
|
<< setw(8) << setfill('0') << index << " "
|
||||||
<< setw(2) << setfill('0') << static_cast<u32>(op) << ":" << dec;
|
<< setw(2) << setfill('0') << static_cast<u32>(op) << ":" << dec;
|
||||||
|
|
||||||
// dump immediate number(hex format)
|
// dump immediate number(hex format)
|
||||||
|
@ -80,7 +81,7 @@ void codestream::dump(std::ostream& out) const {
|
||||||
break;
|
break;
|
||||||
case op_lnkeqc:
|
case op_lnkeqc:
|
||||||
out << hex << "0x" << num << dec;
|
out << hex << "0x" << num << dec;
|
||||||
out << " (" << rawstr(const_string[num], 16) << ")";
|
out << " (" << util::rawstr(const_string[num], 16) << ")";
|
||||||
break;
|
break;
|
||||||
case op_addecp:
|
case op_addecp:
|
||||||
case op_subecp:
|
case op_subecp:
|
||||||
|
@ -91,7 +92,7 @@ void codestream::dump(std::ostream& out) const {
|
||||||
break;
|
break;
|
||||||
case op_lnkecp:
|
case op_lnkecp:
|
||||||
out << hex << "0x" << num << dec;
|
out << hex << "0x" << num << dec;
|
||||||
out << " (" << rawstr(const_string[num], 16) << ") sp-1";
|
out << " (" << util::rawstr(const_string[num], 16) << ") sp-1";
|
||||||
break;
|
break;
|
||||||
case op_addc:
|
case op_addc:
|
||||||
case op_subc:
|
case op_subc:
|
||||||
|
@ -141,7 +142,7 @@ void codestream::dump(std::ostream& out) const {
|
||||||
case op_deft:
|
case op_deft:
|
||||||
case op_dyn:
|
case op_dyn:
|
||||||
out << hex << "0x" << num << dec;
|
out << hex << "0x" << num << dec;
|
||||||
out << " (" << rawstr(const_string[num], 16) << ")";
|
out << " (" << util::rawstr(const_string[num], 16) << ")";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (files) {
|
if (files) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "natives/nasal_builtin.h"
|
#include "natives/builtin.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -16,66 +16,68 @@ class parse {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u64 ptr;
|
u64 ptr;
|
||||||
u64 in_func; // count function block
|
u64 in_func_depth; // count function block
|
||||||
u64 in_loop; // count loop block
|
u64 in_loop_depth; // count loop block
|
||||||
const token* toks;
|
const token* toks;
|
||||||
code_block* root;
|
code_block* root;
|
||||||
error err;
|
error err;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::unordered_map<tok, std::string> tokname {
|
const std::unordered_map<tok, std::string> tokname = {
|
||||||
{tok::use ,"use" },
|
{tok::tk_true , "true" },
|
||||||
{tok::rfor ,"for" },
|
{tok::tk_false , "false" },
|
||||||
{tok::forindex,"forindex"},
|
{tok::tk_use , "use" },
|
||||||
{tok::foreach ,"foreach" },
|
{tok::tk_for , "for" },
|
||||||
{tok::rwhile ,"while" },
|
{tok::tk_forindex, "forindex"},
|
||||||
{tok::var ,"var" },
|
{tok::tk_foreach , "foreach" },
|
||||||
{tok::func ,"func" },
|
{tok::tk_while , "while" },
|
||||||
{tok::brk ,"break" },
|
{tok::tk_var , "var" },
|
||||||
{tok::cont ,"continue"},
|
{tok::tk_func , "func" },
|
||||||
{tok::ret ,"return" },
|
{tok::tk_brk , "break" },
|
||||||
{tok::rif ,"if" },
|
{tok::tk_cont , "continue"},
|
||||||
{tok::elsif ,"elsif" },
|
{tok::tk_ret , "return" },
|
||||||
{tok::relse ,"else" },
|
{tok::tk_if , "if" },
|
||||||
{tok::nil ,"nil" },
|
{tok::tk_elsif , "elsif" },
|
||||||
{tok::lcurve ,"(" },
|
{tok::tk_else , "else" },
|
||||||
{tok::rcurve ,")" },
|
{tok::tk_nil , "nil" },
|
||||||
{tok::lbracket,"[" },
|
{tok::tk_lcurve , "(" },
|
||||||
{tok::rbracket,"]" },
|
{tok::tk_rcurve , ")" },
|
||||||
{tok::lbrace ,"{" },
|
{tok::tk_lbracket, "[" },
|
||||||
{tok::rbrace ,"}" },
|
{tok::tk_rbracket, "]" },
|
||||||
{tok::semi ,";" },
|
{tok::tk_lbrace , "{" },
|
||||||
{tok::opand ,"and" },
|
{tok::tk_rbrace , "}" },
|
||||||
{tok::opor ,"or" },
|
{tok::tk_semi , ";" },
|
||||||
{tok::comma ,"," },
|
{tok::tk_and , "and" },
|
||||||
{tok::dot ,"." },
|
{tok::tk_or , "or" },
|
||||||
{tok::ellipsis,"..." },
|
{tok::tk_comma , "," },
|
||||||
{tok::quesmark,"?" },
|
{tok::tk_dot , "." },
|
||||||
{tok::colon ,":" },
|
{tok::tk_ellipsis, "..." },
|
||||||
{tok::add ,"+" },
|
{tok::tk_quesmark, "?" },
|
||||||
{tok::sub ,"-" },
|
{tok::tk_colon , ":" },
|
||||||
{tok::mult ,"*" },
|
{tok::tk_add , "+" },
|
||||||
{tok::div ,"/" },
|
{tok::tk_sub , "-" },
|
||||||
{tok::floater ,"~" },
|
{tok::tk_mult , "*" },
|
||||||
{tok::btand ,"&" },
|
{tok::tk_div , "/" },
|
||||||
{tok::btor ,"|" },
|
{tok::tk_floater , "~" },
|
||||||
{tok::btxor ,"^" },
|
{tok::tk_btand , "&" },
|
||||||
{tok::opnot ,"!" },
|
{tok::tk_btor , "|" },
|
||||||
{tok::eq ,"=" },
|
{tok::tk_btxor , "^" },
|
||||||
{tok::addeq ,"+=" },
|
{tok::tk_not , "!" },
|
||||||
{tok::subeq ,"-=" },
|
{tok::tk_eq , "=" },
|
||||||
{tok::multeq ,"*=" },
|
{tok::tk_addeq , "+=" },
|
||||||
{tok::diveq ,"/=" },
|
{tok::tk_subeq , "-=" },
|
||||||
{tok::lnkeq ,"~=" },
|
{tok::tk_multeq , "*=" },
|
||||||
{tok::btandeq ,"&=" },
|
{tok::tk_diveq , "/=" },
|
||||||
{tok::btoreq ,"|=" },
|
{tok::tk_lnkeq , "~=" },
|
||||||
{tok::btxoreq ,"^=" },
|
{tok::tk_btandeq , "&=" },
|
||||||
{tok::cmpeq ,"==" },
|
{tok::tk_btoreq , "|=" },
|
||||||
{tok::neq ,"!=" },
|
{tok::tk_btxoreq , "^=" },
|
||||||
{tok::less ,"<" },
|
{tok::tk_cmpeq , "==" },
|
||||||
{tok::leq ,"<=" },
|
{tok::tk_neq , "!=" },
|
||||||
{tok::grt ,">" },
|
{tok::tk_less , "<" },
|
||||||
{tok::geq ,">=" }
|
{tok::tk_leq , "<=" },
|
||||||
|
{tok::tk_grt , ">" },
|
||||||
|
{tok::tk_geq , ">=" }
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -151,7 +153,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
parse(): ptr(0), in_func(0), in_loop(0), toks(nullptr), root(nullptr) {}
|
parse(): ptr(0), in_func_depth(0), in_loop_depth(0),
|
||||||
|
toks(nullptr), root(nullptr) {}
|
||||||
~parse() {delete root;}
|
~parse() {delete root;}
|
||||||
const error& compile(const lexer&);
|
const error& compile(const lexer&);
|
||||||
static void easter_egg();
|
static void easter_egg();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "nasal_type.h"
|
#include "nasal_type.h"
|
||||||
|
#include "util/util.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -268,7 +269,7 @@ void nas_val::clear() {
|
||||||
}
|
}
|
||||||
|
|
||||||
f64 var::to_num() {
|
f64 var::to_num() {
|
||||||
return type!=vm_type::vm_str? val.num:str_to_num(str().c_str());
|
return type!=vm_type::vm_str? val.num:util::str_to_num(str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string var::to_str() {
|
std::string var::to_str() {
|
||||||
|
@ -384,7 +385,7 @@ nas_map& var::map() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var nas_err(const std::string& error_function_name, const std::string& info) {
|
var nas_err(const std::string& error_function_name, const std::string& info) {
|
||||||
std::cerr << "\n[vm] " << error_function_name << ": " << info << "\n";
|
std::cerr << "[vm] " << error_function_name << ": " << info << "\n";
|
||||||
return var::none();
|
return var::none();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "nasal_vm.h"
|
#include "nasal_vm.h"
|
||||||
|
#include "util/util.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
|
@ -75,8 +76,8 @@ void vm::value_info(var& val) {
|
||||||
case vm_type::vm_nil: std::clog << "| nil |"; break;
|
case vm_type::vm_nil: std::clog << "| nil |"; break;
|
||||||
case vm_type::vm_num: std::clog << "| num | " << val.num(); break;
|
case vm_type::vm_num: std::clog << "| num | " << val.num(); break;
|
||||||
case vm_type::vm_str: std::clog << "| str | <0x" << std::hex << p
|
case vm_type::vm_str: std::clog << "| str | <0x" << std::hex << p
|
||||||
<< "> " << rawstr(val.str(), 16)
|
<< "> \"" << util::rawstr(val.str(), 16)
|
||||||
<< std::dec; break;
|
<< "\"" << std::dec; break;
|
||||||
case vm_type::vm_func: std::clog << "| func | <0x" << std::hex << p
|
case vm_type::vm_func: std::clog << "| func | <0x" << std::hex << p
|
||||||
<< std::dec << "> " << val.func();
|
<< std::dec << "> " << val.func();
|
||||||
break;
|
break;
|
||||||
|
@ -191,7 +192,7 @@ void vm::trace_back() {
|
||||||
}
|
}
|
||||||
if (same) {
|
if (same) {
|
||||||
std::clog << " 0x" << std::hex
|
std::clog << " 0x" << std::hex
|
||||||
<< std::setw(6) << std::setfill('0')
|
<< std::setw(8) << std::setfill('0')
|
||||||
<< prev << std::dec << " "
|
<< prev << std::dec << " "
|
||||||
<< same << " same call(s)\n";
|
<< same << " same call(s)\n";
|
||||||
same = 0;
|
same = 0;
|
||||||
|
@ -212,7 +213,7 @@ void vm::stack_info(const u64 limit = 16) {
|
||||||
|
|
||||||
for(u32 i = 0; i<limit && top>=bottom; ++i, --top) {
|
for(u32 i = 0; i<limit && top>=bottom; ++i, --top) {
|
||||||
std::clog << " 0x" << std::hex
|
std::clog << " 0x" << std::hex
|
||||||
<< std::setw(6) << std::setfill('0')
|
<< std::setw(8) << std::setfill('0')
|
||||||
<< static_cast<u64>(top-bottom) << std::dec
|
<< static_cast<u64>(top-bottom) << std::dec
|
||||||
<< " ";
|
<< " ";
|
||||||
value_info(top[0]);
|
value_info(top[0]);
|
||||||
|
@ -220,22 +221,22 @@ void vm::stack_info(const u64 limit = 16) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm::register_info() {
|
void vm::register_info() {
|
||||||
std::clog << "\nregisters (" << (ngc.cort? "coroutine":"main")
|
std::clog << "\nregisters (" << (ngc.cort? "coroutine":"main") << ")\n";
|
||||||
<< ")\n" << std::hex
|
std::clog << std::hex
|
||||||
<< " [pc ] | pc | 0x" << ctx.pc << "\n"
|
<< " [ pc ] | pc | 0x" << ctx.pc << "\n"
|
||||||
<< " [global] | addr | 0x"
|
<< " [ global ] | addr | 0x"
|
||||||
<< reinterpret_cast<u64>(global) << "\n"
|
<< reinterpret_cast<u64>(global) << "\n"
|
||||||
<< " [local ] | addr | 0x"
|
<< " [ local ] | addr | 0x"
|
||||||
<< reinterpret_cast<u64>(ctx.localr) << "\n"
|
<< reinterpret_cast<u64>(ctx.localr) << "\n"
|
||||||
<< " [memr ] | addr | 0x"
|
<< " [ memr ] | addr | 0x"
|
||||||
<< reinterpret_cast<u64>(ctx.memr) << "\n"
|
<< reinterpret_cast<u64>(ctx.memr) << "\n"
|
||||||
<< " [canary] | addr | 0x"
|
<< " [ canary ] | addr | 0x"
|
||||||
<< reinterpret_cast<u64>(ctx.canary) << "\n"
|
<< reinterpret_cast<u64>(ctx.canary) << "\n"
|
||||||
<< " [top ] | addr | 0x"
|
<< " [ top ] | addr | 0x"
|
||||||
<< reinterpret_cast<u64>(ctx.top) << "\n"
|
<< reinterpret_cast<u64>(ctx.top) << "\n"
|
||||||
<< std::dec;
|
<< std::dec;
|
||||||
std::clog << " [funcr ] "; value_info(ctx.funcr);
|
std::clog << " [ funcr ] "; value_info(ctx.funcr);
|
||||||
std::clog << " [upval ] "; value_info(ctx.upvalr);
|
std::clog << " [ upval ] "; value_info(ctx.upvalr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm::global_state() {
|
void vm::global_state() {
|
||||||
|
@ -245,7 +246,7 @@ void vm::global_state() {
|
||||||
std::clog << "\nglobal (0x" << std::hex
|
std::clog << "\nglobal (0x" << std::hex
|
||||||
<< reinterpret_cast<u64>(global) << ")\n" << std::dec;
|
<< reinterpret_cast<u64>(global) << ")\n" << std::dec;
|
||||||
for(usize i = 0; i<global_size; ++i) {
|
for(usize i = 0; i<global_size; ++i) {
|
||||||
std::clog << " 0x" << std::hex << std::setw(6)
|
std::clog << " 0x" << std::hex << std::setw(8)
|
||||||
<< std::setfill('0') << i << std::dec
|
<< std::setfill('0') << i << std::dec
|
||||||
<< " ";
|
<< " ";
|
||||||
value_info(global[i]);
|
value_info(global[i]);
|
||||||
|
@ -261,7 +262,7 @@ void vm::local_state() {
|
||||||
<< " <+" << static_cast<u64>(ctx.localr-ctx.stack)
|
<< " <+" << static_cast<u64>(ctx.localr-ctx.stack)
|
||||||
<< ">)\n" << std::dec;
|
<< ">)\n" << std::dec;
|
||||||
for(u32 i = 0; i<lsize; ++i) {
|
for(u32 i = 0; i<lsize; ++i) {
|
||||||
std::clog << " 0x" << std::hex << std::setw(6)
|
std::clog << " 0x" << std::hex << std::setw(8)
|
||||||
<< std::setfill('0') << i << std::dec
|
<< std::setfill('0') << i << std::dec
|
||||||
<< " ";
|
<< " ";
|
||||||
value_info(ctx.localr[i]);
|
value_info(ctx.localr[i]);
|
||||||
|
@ -278,7 +279,7 @@ void vm::upvalue_state() {
|
||||||
std::clog << " -> upval[" << i << "]:\n";
|
std::clog << " -> upval[" << i << "]:\n";
|
||||||
auto& uv = upval[i].upval();
|
auto& uv = upval[i].upval();
|
||||||
for(u32 j = 0; j<uv.size; ++j) {
|
for(u32 j = 0; j<uv.size; ++j) {
|
||||||
std::clog << " 0x" << std::hex << std::setw(6)
|
std::clog << " 0x" << std::hex << std::setw(8)
|
||||||
<< std::setfill('0') << j << std::dec
|
<< std::setfill('0') << j << std::dec
|
||||||
<< " ";
|
<< " ";
|
||||||
value_info(uv[j]);
|
value_info(uv[j]);
|
||||||
|
@ -391,7 +392,7 @@ std::string vm::type_name_string(const var& value) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm::die(const std::string& str) {
|
void vm::die(const std::string& str) {
|
||||||
std::cerr << "\n[vm] error: " << str << "\n";
|
std::cerr << "[vm] error: " << str << "\n";
|
||||||
function_call_trace();
|
function_call_trace();
|
||||||
trace_back();
|
trace_back();
|
||||||
stack_info();
|
stack_info();
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "nasal_import.h"
|
#include "nasal_import.h"
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
#include "nasal_codegen.h"
|
#include "nasal_codegen.h"
|
||||||
|
#include "util/util.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning (disable:4244)
|
#pragma warning (disable:4244)
|
||||||
|
@ -50,6 +51,7 @@ protected:
|
||||||
/* limited mode, will not load unsafe system api if switched on */
|
/* limited mode, will not load unsafe system api if switched on */
|
||||||
bool flag_limited_mode = false;
|
bool flag_limited_mode = false;
|
||||||
|
|
||||||
|
protected:
|
||||||
/* vm initializing function */
|
/* vm initializing function */
|
||||||
void vm_init_enrty(const std::vector<std::string>&,
|
void vm_init_enrty(const std::vector<std::string>&,
|
||||||
const std::vector<f64>&,
|
const std::vector<f64>&,
|
||||||
|
@ -60,6 +62,7 @@ protected:
|
||||||
const std::vector<std::string>&);
|
const std::vector<std::string>&);
|
||||||
void context_and_global_init();
|
void context_and_global_init();
|
||||||
|
|
||||||
|
protected:
|
||||||
/* debug functions */
|
/* debug functions */
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
void value_info(var&);
|
void value_info(var&);
|
||||||
|
@ -190,20 +193,31 @@ public:
|
||||||
const std::vector<std::string>&); // get command line arguments
|
const std::vector<std::string>&); // get command line arguments
|
||||||
|
|
||||||
/* set detail report info flag */
|
/* set detail report info flag */
|
||||||
void set_detail_report_info(bool flag) {verbose = flag;}
|
void set_detail_report_info(bool flag) {
|
||||||
|
verbose = flag;
|
||||||
|
}
|
||||||
|
|
||||||
/* set repl mode flag */
|
/* set repl mode flag */
|
||||||
void set_repl_mode_flag(bool flag) {is_repl_mode = flag;}
|
void set_repl_mode_flag(bool flag) {
|
||||||
|
is_repl_mode = flag;
|
||||||
|
}
|
||||||
|
|
||||||
/* set repl output flag */
|
/* set repl output flag */
|
||||||
void set_allow_repl_output_flag(bool flag) {allow_repl_output = flag;}
|
void set_allow_repl_output_flag(bool flag) {
|
||||||
|
allow_repl_output = flag;
|
||||||
|
}
|
||||||
|
|
||||||
/* set limit mode flag */
|
/* set limit mode flag */
|
||||||
void set_limit_mode_flag(bool flag) {flag_limited_mode = flag;}
|
void set_limit_mode_flag(bool flag) {
|
||||||
|
flag_limited_mode = flag;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool vm::cond(var& val) {
|
inline bool vm::cond(var& val) {
|
||||||
if (val.is_num()) {
|
if (val.is_num()) {
|
||||||
return val.num();
|
return val.num();
|
||||||
} else if (val.is_str()) {
|
} else if (val.is_str()) {
|
||||||
const f64 num = str_to_num(val.str().c_str());
|
const f64 num = util::str_to_num(val.str().c_str());
|
||||||
return std::isnan(num)? !val.str().empty():num;
|
return std::isnan(num)? !val.str().empty():num;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -320,7 +334,7 @@ inline void vm::o_lnot() {
|
||||||
case vm_type::vm_nil: ctx.top[0] = one; break;
|
case vm_type::vm_nil: ctx.top[0] = one; break;
|
||||||
case vm_type::vm_num: ctx.top[0] = val.num()? zero:one; break;
|
case vm_type::vm_num: ctx.top[0] = val.num()? zero:one; break;
|
||||||
case vm_type::vm_str: {
|
case vm_type::vm_str: {
|
||||||
const f64 num = str_to_num(val.str().c_str());
|
const f64 num = util::str_to_num(val.str().c_str());
|
||||||
if (std::isnan(num)) {
|
if (std::isnan(num)) {
|
||||||
ctx.top[0] = var::num(static_cast<f64>(val.str().empty()));
|
ctx.top[0] = var::num(static_cast<f64>(val.str().empty()));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
#include "natives/nasal_builtin.h"
|
#include "natives/builtin.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
#include "natives/nasal_builtin.h"
|
#include "natives/builtin.h"
|
||||||
|
#include "util/util.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
var builtin_unsafe(context* ctx, gc* ngc) {
|
var builtin_unsafe(context* ctx, gc* ngc) {
|
||||||
|
@ -41,7 +47,7 @@ var builtin_append(context* ctx, gc* ngc) {
|
||||||
var vec = local[1];
|
var vec = local[1];
|
||||||
var elem = local[2];
|
var elem = local[2];
|
||||||
if (!vec.is_vec()) {
|
if (!vec.is_vec()) {
|
||||||
return nas_err("append", "\"vec\" must be vector");
|
return nas_err("native::append", "\"vec\" must be vector");
|
||||||
}
|
}
|
||||||
auto& v = vec.vec().elems;
|
auto& v = vec.vec().elems;
|
||||||
for(auto& i : elem.vec().elems) {
|
for(auto& i : elem.vec().elems) {
|
||||||
|
@ -55,7 +61,7 @@ var builtin_setsize(context* ctx, gc* ngc) {
|
||||||
var vec = local[1];
|
var vec = local[1];
|
||||||
var size = local[2];
|
var size = local[2];
|
||||||
if (!vec.is_vec()) {
|
if (!vec.is_vec()) {
|
||||||
return nas_err("setsize", "\"vec\" must be vector");
|
return nas_err("native::setsize", "\"vec\" must be vector");
|
||||||
}
|
}
|
||||||
if (!size.is_num() || size.num()<0) {
|
if (!size.is_num() || size.num()<0) {
|
||||||
return nil;
|
return nil;
|
||||||
|
@ -89,10 +95,10 @@ var builtin_split(context* ctx, gc* ngc) {
|
||||||
var delimeter = local[1];
|
var delimeter = local[1];
|
||||||
var str = local[2];
|
var str = local[2];
|
||||||
if (!delimeter.is_str()) {
|
if (!delimeter.is_str()) {
|
||||||
return nas_err("split", "\"separator\" must be string");
|
return nas_err("native::split", "\"separator\" must be string");
|
||||||
}
|
}
|
||||||
if (!str.is_str()) {
|
if (!str.is_str()) {
|
||||||
return nas_err("split", "\"str\" must be string");
|
return nas_err("native::split", "\"str\" must be string");
|
||||||
}
|
}
|
||||||
const auto& deli = delimeter.str();
|
const auto& deli = delimeter.str();
|
||||||
const auto& s = str.str();
|
const auto& s = str.str();
|
||||||
|
@ -127,7 +133,7 @@ var builtin_split(context* ctx, gc* ngc) {
|
||||||
var builtin_rand(context* ctx, gc* ngc) {
|
var builtin_rand(context* ctx, gc* ngc) {
|
||||||
auto val = ctx->localr[1];
|
auto val = ctx->localr[1];
|
||||||
if (!val.is_num() && !val.is_nil()) {
|
if (!val.is_num() && !val.is_nil()) {
|
||||||
return nas_err("rand", "\"seed\" must be nil or number");
|
return nas_err("native::rand", "\"seed\" must be nil or number");
|
||||||
}
|
}
|
||||||
if (val.is_num()) {
|
if (val.is_num()) {
|
||||||
srand(static_cast<u32>(val.num()));
|
srand(static_cast<u32>(val.num()));
|
||||||
|
@ -187,7 +193,7 @@ var builtin_num(context* ctx, gc* ngc) {
|
||||||
var builtin_pop(context* ctx, gc* ngc) {
|
var builtin_pop(context* ctx, gc* ngc) {
|
||||||
auto val = ctx->localr[1];
|
auto val = ctx->localr[1];
|
||||||
if (!val.is_vec()) {
|
if (!val.is_vec()) {
|
||||||
return nas_err("pop", "\"vec\" must be vector");
|
return nas_err("native::pop", "\"vec\" must be vector");
|
||||||
}
|
}
|
||||||
auto& vec = val.vec().elems;
|
auto& vec = val.vec().elems;
|
||||||
if (vec.size()) {
|
if (vec.size()) {
|
||||||
|
@ -220,7 +226,7 @@ var builtin_size(context* ctx, gc* ngc) {
|
||||||
var builtin_time(context* ctx, gc* ngc) {
|
var builtin_time(context* ctx, gc* ngc) {
|
||||||
auto val = ctx->localr[1];
|
auto val = ctx->localr[1];
|
||||||
if (!val.is_num()) {
|
if (!val.is_num()) {
|
||||||
return nas_err("time", "\"begin\" must be number");
|
return nas_err("native::time", "\"begin\" must be number");
|
||||||
}
|
}
|
||||||
auto begin = static_cast<time_t>(val.num());
|
auto begin = static_cast<time_t>(val.num());
|
||||||
return var::num(static_cast<f64>(time(&begin)));
|
return var::num(static_cast<f64>(time(&begin)));
|
||||||
|
@ -241,7 +247,7 @@ var builtin_delete(context* ctx, gc* ngc) {
|
||||||
var hash = local[1];
|
var hash = local[1];
|
||||||
var key = local[2];
|
var key = local[2];
|
||||||
if (!hash.is_hash()) {
|
if (!hash.is_hash()) {
|
||||||
return nas_err("delete", "\"hash\" must be hash");
|
return nas_err("native::delete", "\"hash\" must be hash");
|
||||||
}
|
}
|
||||||
if (!key.is_str()) {
|
if (!key.is_str()) {
|
||||||
return nil;
|
return nil;
|
||||||
|
@ -255,7 +261,7 @@ var builtin_delete(context* ctx, gc* ngc) {
|
||||||
var builtin_keys(context* ctx, gc* ngc) {
|
var builtin_keys(context* ctx, gc* ngc) {
|
||||||
auto hash = ctx->localr[1];
|
auto hash = ctx->localr[1];
|
||||||
if (!hash.is_hash() && !hash.is_map()) {
|
if (!hash.is_hash() && !hash.is_map()) {
|
||||||
return nas_err("keys", "\"hash\" must be hash");
|
return nas_err("native::keys", "\"hash\" must be hash");
|
||||||
}
|
}
|
||||||
// avoid being sweeped
|
// avoid being sweeped
|
||||||
auto res = ngc->temp = ngc->alloc(vm_type::vm_vec);
|
auto res = ngc->temp = ngc->alloc(vm_type::vm_vec);
|
||||||
|
@ -274,7 +280,7 @@ var builtin_keys(context* ctx, gc* ngc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_die(context* ctx, gc* ngc) {
|
var builtin_die(context* ctx, gc* ngc) {
|
||||||
return nas_err("error", ctx->localr[1].to_str());
|
return nas_err("native::error", ctx->localr[1].to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_find(context* ctx, gc* ngc) {
|
var builtin_find(context* ctx, gc* ngc) {
|
||||||
|
@ -311,18 +317,18 @@ var builtin_substr(context* ctx, gc* ngc) {
|
||||||
var beg = local[2];
|
var beg = local[2];
|
||||||
var len = local[3];
|
var len = local[3];
|
||||||
if (!str.is_str()) {
|
if (!str.is_str()) {
|
||||||
return nas_err("substr", "\"str\" must be string");
|
return nas_err("native::substr", "\"str\" must be string");
|
||||||
}
|
}
|
||||||
if (!beg.is_num() || beg.num()<0) {
|
if (!beg.is_num() || beg.num()<0) {
|
||||||
return nas_err("substr", "\"begin\" should be number >= 0");
|
return nas_err("native::substr", "\"begin\" should be number >= 0");
|
||||||
}
|
}
|
||||||
if (!len.is_num() || len.num()<0) {
|
if (!len.is_num() || len.num()<0) {
|
||||||
return nas_err("substr", "\"length\" should be number >= 0");
|
return nas_err("native::substr", "\"length\" should be number >= 0");
|
||||||
}
|
}
|
||||||
auto begin = static_cast<usize>(beg.num());
|
auto begin = static_cast<usize>(beg.num());
|
||||||
auto length = static_cast<usize>(len.num());
|
auto length = static_cast<usize>(len.num());
|
||||||
if (begin>=str.str().length()) {
|
if (begin>=str.str().length()) {
|
||||||
return nas_err("susbtr", "begin index out of range: "+std::to_string(begin));
|
return nas_err("native::susbtr", "begin index out of range: "+std::to_string(begin));
|
||||||
}
|
}
|
||||||
return ngc->newstr(str.str().substr(begin, length));
|
return ngc->newstr(str.str().substr(begin, length));
|
||||||
}
|
}
|
||||||
|
@ -342,10 +348,10 @@ var builtin_left(context* ctx, gc* ngc) {
|
||||||
var len = local[2];
|
var len = local[2];
|
||||||
|
|
||||||
if (!str.is_str()) {
|
if (!str.is_str()) {
|
||||||
return nas_err("left", "\"string\" must be string");
|
return nas_err("native::left", "\"string\" must be string");
|
||||||
}
|
}
|
||||||
if (!len.is_num()) {
|
if (!len.is_num()) {
|
||||||
return nas_err("left", "\"length\" must be number");
|
return nas_err("native::left", "\"length\" must be number");
|
||||||
}
|
}
|
||||||
if (len.num()<0) {
|
if (len.num()<0) {
|
||||||
return ngc->newstr("");
|
return ngc->newstr("");
|
||||||
|
@ -359,10 +365,10 @@ var builtin_right(context* ctx, gc* ngc) {
|
||||||
var len = local[2];
|
var len = local[2];
|
||||||
|
|
||||||
if (!str.is_str()) {
|
if (!str.is_str()) {
|
||||||
return nas_err("right", "\"string\" must be string");
|
return nas_err("native::right", "\"string\" must be string");
|
||||||
}
|
}
|
||||||
if (!len.is_num()) {
|
if (!len.is_num()) {
|
||||||
return nas_err("right", "\"length\" must be number");
|
return nas_err("native::right", "\"length\" must be number");
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 length = static_cast<i32>(len.num());
|
i32 length = static_cast<i32>(len.num());
|
||||||
|
@ -382,7 +388,7 @@ var builtin_cmp(context* ctx, gc* ngc) {
|
||||||
var a = local[1];
|
var a = local[1];
|
||||||
var b = local[2];
|
var b = local[2];
|
||||||
if (!a.is_str() || !b.is_str()) {
|
if (!a.is_str() || !b.is_str()) {
|
||||||
return nas_err("cmp", "\"a\" and \"b\" must be string");
|
return nas_err("native::cmp", "\"a\" and \"b\" must be string");
|
||||||
}
|
}
|
||||||
return var::num(static_cast<f64>(strcmp(
|
return var::num(static_cast<f64>(strcmp(
|
||||||
a.str().c_str(),
|
a.str().c_str(),
|
||||||
|
@ -425,7 +431,7 @@ var builtin_char(context* ctx, gc* ngc) {
|
||||||
var builtin_values(context* ctx, gc* ngc) {
|
var builtin_values(context* ctx, gc* ngc) {
|
||||||
auto hash = ctx->localr[1];
|
auto hash = ctx->localr[1];
|
||||||
if (!hash.is_hash() && !hash.is_map()) {
|
if (!hash.is_hash() && !hash.is_map()) {
|
||||||
return nas_err("values", "\"hash\" must be hash or namespace");
|
return nas_err("native::values", "\"hash\" must be hash or namespace");
|
||||||
}
|
}
|
||||||
auto vec = ngc->alloc(vm_type::vm_vec);
|
auto vec = ngc->alloc(vm_type::vm_vec);
|
||||||
auto& v = vec.vec().elems;
|
auto& v = vec.vec().elems;
|
||||||
|
@ -459,11 +465,11 @@ var builtin_sleep(context* ctx, gc* ngc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_platform(context* ctx, gc* ngc) {
|
var builtin_platform(context* ctx, gc* ngc) {
|
||||||
return ngc->newstr(get_platform());
|
return ngc->newstr(util::get_platform());
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_arch(context* ctx, gc* ngc) {
|
var builtin_arch(context* ctx, gc* ngc) {
|
||||||
return ngc->newstr(get_arch());
|
return ngc->newstr(util::get_arch());
|
||||||
}
|
}
|
||||||
|
|
||||||
// md5 related functions
|
// md5 related functions
|
||||||
|
@ -560,7 +566,7 @@ std::string md5(const std::string& src) {
|
||||||
var builtin_md5(context* ctx, gc* ngc) {
|
var builtin_md5(context* ctx, gc* ngc) {
|
||||||
auto str = ctx->localr[1];
|
auto str = ctx->localr[1];
|
||||||
if (!str.is_str()) {
|
if (!str.is_str()) {
|
||||||
return nas_err("md5", "\"str\" must be string");
|
return nas_err("native::md5", "\"str\" must be string");
|
||||||
}
|
}
|
||||||
return ngc->newstr(md5(str.str()));
|
return ngc->newstr(md5(str.str()));
|
||||||
}
|
}
|
||||||
|
@ -700,7 +706,7 @@ var builtin_logtime(context* ctx, gc* ngc) {
|
||||||
var builtin_ghosttype(context* ctx, gc* ngc) {
|
var builtin_ghosttype(context* ctx, gc* ngc) {
|
||||||
auto arg = ctx->localr[1];
|
auto arg = ctx->localr[1];
|
||||||
if (!arg.is_ghost()) {
|
if (!arg.is_ghost()) {
|
||||||
return nas_err("ghosttype", "this is not a ghost object.");
|
return nas_err("native::ghosttype", "this is not a ghost object.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& name = arg.ghost().get_ghost_name();
|
const auto& name = arg.ghost().get_ghost_name();
|
||||||
|
@ -717,6 +723,15 @@ var builtin_ghosttype(context* ctx, gc* ngc) {
|
||||||
return ngc->newstr(name);
|
return ngc->newstr(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var builtin_set_utf8_output(context* ctx, gc* ngc) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
// allow 65001 code page
|
||||||
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
|
#endif
|
||||||
|
// do nothing on other platforms
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
nasal_builtin_table builtin[] = {
|
nasal_builtin_table builtin[] = {
|
||||||
{"__print", builtin_print},
|
{"__print", builtin_print},
|
||||||
{"__println", builtin_println},
|
{"__println", builtin_println},
|
||||||
|
@ -763,6 +778,7 @@ nasal_builtin_table builtin[] = {
|
||||||
{"__gcinfo", builtin_gcinfo},
|
{"__gcinfo", builtin_gcinfo},
|
||||||
{"__logtime", builtin_logtime},
|
{"__logtime", builtin_logtime},
|
||||||
{"__ghosttype", builtin_ghosttype},
|
{"__ghosttype", builtin_ghosttype},
|
||||||
|
{"__set_utf8_output", builtin_set_utf8_output},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
|
@ -81,6 +81,9 @@ var builtin_gcinfo(context*, gc*);
|
||||||
var builtin_logtime(context*, gc*);
|
var builtin_logtime(context*, gc*);
|
||||||
var builtin_ghosttype(context*, gc*);
|
var builtin_ghosttype(context*, gc*);
|
||||||
|
|
||||||
|
// only useful on windows platform
|
||||||
|
var builtin_set_utf8_output(context*, gc*);
|
||||||
|
|
||||||
// register builtin function's name and it's address here in this table below
|
// register builtin function's name and it's address here in this table below
|
||||||
// this table must end with {nullptr, nullptr}
|
// this table must end with {nullptr, nullptr}
|
||||||
struct nasal_builtin_table {
|
struct nasal_builtin_table {
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
#include "natives/nasal_builtin.h"
|
#include "natives/builtin.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
#include "natives/nasal_builtin.h"
|
#include "natives/builtin.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
#include "natives/nasal_builtin.h"
|
#include "natives/builtin.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "natives/io_lib.h"
|
#include "natives/io_lib.h"
|
||||||
|
#include "util/fs.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
#include "natives/nasal_builtin.h"
|
#include "natives/builtin.h"
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "natives/json_lib.h"
|
#include "natives/json_lib.h"
|
||||||
|
#include "util/util.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -170,7 +171,7 @@ void json::next() {
|
||||||
} else if (text[ptr]!=' ' && text[ptr]!='\t' && text[ptr]!='\r') {
|
} else if (text[ptr]!=' ' && text[ptr]!='\t' && text[ptr]!='\r') {
|
||||||
error_info() += "json::parse: line " + std::to_string(line);
|
error_info() += "json::parse: line " + std::to_string(line);
|
||||||
error_info() += ": invalid character `0x";
|
error_info() += ": invalid character `0x";
|
||||||
error_info() += char_to_hex(text[ptr]);
|
error_info() += util::char_to_hex(text[ptr]);
|
||||||
error_info() += "`\n";
|
error_info() += "`\n";
|
||||||
}
|
}
|
||||||
++ptr;
|
++ptr;
|
||||||
|
@ -253,7 +254,7 @@ void json::vector_member(nas_vec& vec, gc* ngc) {
|
||||||
vec.elems.push_back(ngc->newstr(this_token.content));
|
vec.elems.push_back(ngc->newstr(this_token.content));
|
||||||
next();
|
next();
|
||||||
} else if (this_token.type==json_token_type::tok_num) {
|
} else if (this_token.type==json_token_type::tok_num) {
|
||||||
vec.elems.push_back(var::num(str_to_num(this_token.content.c_str())));
|
vec.elems.push_back(var::num(util::str_to_num(this_token.content.c_str())));
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -292,7 +293,7 @@ void json::hash_member(nas_hash& hash, gc* ngc) {
|
||||||
hash.elems.insert({name, ngc->newstr(this_token.content)});
|
hash.elems.insert({name, ngc->newstr(this_token.content)});
|
||||||
next();
|
next();
|
||||||
} else if (this_token.type==json_token_type::tok_num) {
|
} else if (this_token.type==json_token_type::tok_num) {
|
||||||
hash.elems.insert({name, var::num(str_to_num(this_token.content.c_str()))});
|
hash.elems.insert({name, var::num(util::str_to_num(this_token.content.c_str()))});
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
#include "natives/nasal_builtin.h"
|
#include "natives/builtin.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
#include "natives/nasal_builtin.h"
|
#include "natives/builtin.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
#include "natives/nasal_builtin.h"
|
#include "natives/builtin.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
#include "natives/nasal_builtin.h"
|
#include "natives/builtin.h"
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
|
@ -47,12 +47,12 @@ bool repl::check_need_more_input() {
|
||||||
i64 in_brace = 0;
|
i64 in_brace = 0;
|
||||||
for(const auto& t : nasal_lexer->result()) {
|
for(const auto& t : nasal_lexer->result()) {
|
||||||
switch(t.type) {
|
switch(t.type) {
|
||||||
case tok::lcurve: ++in_curve; break;
|
case tok::tk_lcurve: ++in_curve; break;
|
||||||
case tok::rcurve: --in_curve; break;
|
case tok::tk_rcurve: --in_curve; break;
|
||||||
case tok::lbracket: ++in_bracket; break;
|
case tok::tk_lbracket: ++in_bracket; break;
|
||||||
case tok::rbracket: --in_bracket; break;
|
case tok::tk_rbracket: --in_bracket; break;
|
||||||
case tok::lbrace: ++in_brace; break;
|
case tok::tk_lbrace: ++in_brace; break;
|
||||||
case tok::rbrace: --in_brace; break;
|
case tok::tk_rbrace: --in_brace; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#include <io.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning (disable:4996)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "util/util.h"
|
||||||
|
#include "util/fs.h"
|
||||||
|
#include "nasal.h"
|
||||||
|
|
||||||
|
namespace nasal::fs {
|
||||||
|
|
||||||
|
path& path::operator/(const path& another) {
|
||||||
|
this->file_system_path += util::is_windows()? "\\":"/";
|
||||||
|
this->file_system_path += another.file_system_path;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool exists(const path& file_path) {
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define F_OK 0 // fuck msc
|
||||||
|
#endif
|
||||||
|
return access(file_path.c_str(), F_OK)==0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_regular(const path& file_path) {
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define S_ISREG(m) (((m)&0xF000)==0x8000)
|
||||||
|
#endif
|
||||||
|
struct stat buffer;
|
||||||
|
if (stat(file_path.c_str(), &buffer)!=0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return S_ISREG(buffer.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace nasal::fs {
|
||||||
|
|
||||||
|
class path {
|
||||||
|
private:
|
||||||
|
std::string file_system_path;
|
||||||
|
|
||||||
|
public:
|
||||||
|
path(const path&) = default;
|
||||||
|
path(const std::string& file_path): file_system_path(file_path) {}
|
||||||
|
path& operator/(const path&);
|
||||||
|
const char* c_str() const {
|
||||||
|
return file_system_path.c_str();
|
||||||
|
}
|
||||||
|
const std::string& str() const {
|
||||||
|
return file_system_path;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool exists(const path&);
|
||||||
|
bool is_regular(const path&);
|
||||||
|
|
||||||
|
}
|
|
@ -1,17 +1,8 @@
|
||||||
#include "nasal.h"
|
#include "util/util.h"
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#include <cmath>
|
||||||
#include <unistd.h>
|
|
||||||
#else
|
|
||||||
#include <io.h>
|
|
||||||
#endif
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
namespace nasal::util {
|
||||||
#pragma warning (disable:4996)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace nasal {
|
|
||||||
|
|
||||||
bool is_windows() {
|
bool is_windows() {
|
||||||
#if defined(_WIN32) || defined(_WIN64)
|
#if defined(_WIN32) || defined(_WIN64)
|
||||||
|
@ -105,7 +96,7 @@ const char* get_platform() {
|
||||||
} else if (is_macos()) {
|
} else if (is_macos()) {
|
||||||
return "macOS";
|
return "macOS";
|
||||||
}
|
}
|
||||||
return "unknown platform";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* get_arch() {
|
const char* get_arch() {
|
||||||
|
@ -126,7 +117,57 @@ const char* get_arch() {
|
||||||
} else if (is_superh()) {
|
} else if (is_superh()) {
|
||||||
return "superh";
|
return "superh";
|
||||||
}
|
}
|
||||||
return "unknown arch";
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 utf8_hdchk(const char head) {
|
||||||
|
// RFC-2279 but now we use RFC-3629 so nbytes is less than 4
|
||||||
|
const auto c = static_cast<u8>(head);
|
||||||
|
if ((c>>5)==0x06) { // 110x xxxx (10xx xxxx)^1
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((c>>4)==0x0e) { // 1110 xxxx (10xx xxxx)^2
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if ((c>>3)==0x1e) { // 1111 0xxx (10xx xxxx)^3
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string char_to_hex(const char c) {
|
||||||
|
const char hextbl[] = "0123456789abcdef";
|
||||||
|
return {hextbl[(c&0xf0)>>4], hextbl[c&0x0f]};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rawstr(const std::string& str, const usize maxlen) {
|
||||||
|
std::string ret("");
|
||||||
|
for(auto i : str) {
|
||||||
|
// windows doesn't output unicode normally, so we output the hex
|
||||||
|
if (util::is_windows() && i<=0) {
|
||||||
|
ret += "\\x" + char_to_hex(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch(i) {
|
||||||
|
case '\0': ret += "\\0"; break;
|
||||||
|
case '\a': ret += "\\a"; break;
|
||||||
|
case '\b': ret += "\\b"; break;
|
||||||
|
case '\t': ret += "\\t"; break;
|
||||||
|
case '\n': ret += "\\n"; break;
|
||||||
|
case '\v': ret += "\\v"; break;
|
||||||
|
case '\f': ret += "\\f"; break;
|
||||||
|
case '\r': ret += "\\r"; break;
|
||||||
|
case '\033':ret += "\\e"; break;
|
||||||
|
case '\"': ret += "\\\""; break;
|
||||||
|
case '\'': ret += "\\\'"; break;
|
||||||
|
case '\\': ret += "\\\\"; break;
|
||||||
|
default: ret += i; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (maxlen && ret.length()>maxlen) {
|
||||||
|
ret = ret.substr(0, maxlen)+"...";
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
f64 hex_to_f64(const char* str) {
|
f64 hex_to_f64(const char* str) {
|
||||||
|
@ -227,82 +268,4 @@ f64 str_to_num(const char* str) {
|
||||||
return negative? -res:res;
|
return negative? -res:res;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 utf8_hdchk(const char head) {
|
}
|
||||||
// RFC-2279 but now we use RFC-3629 so nbytes is less than 4
|
|
||||||
const auto c = static_cast<u8>(head);
|
|
||||||
if ((c>>5)==0x06) { // 110x xxxx (10xx xxxx)^1
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if ((c>>4)==0x0e) { // 1110 xxxx (10xx xxxx)^2
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
if ((c>>3)==0x1e) { // 1111 0xxx (10xx xxxx)^3
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string char_to_hex(const char c) {
|
|
||||||
const char hextbl[] = "0123456789abcdef";
|
|
||||||
return {hextbl[(c&0xf0)>>4], hextbl[c&0x0f]};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string rawstr(const std::string& str, const usize maxlen) {
|
|
||||||
std::string ret("");
|
|
||||||
for(auto i : str) {
|
|
||||||
// windows doesn't output unicode normally, so we output the hex
|
|
||||||
if (is_windows() && i<=0) {
|
|
||||||
ret += "\\x" + char_to_hex(i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch(i) {
|
|
||||||
case '\0': ret += "\\0"; break;
|
|
||||||
case '\a': ret += "\\a"; break;
|
|
||||||
case '\b': ret += "\\b"; break;
|
|
||||||
case '\t': ret += "\\t"; break;
|
|
||||||
case '\n': ret += "\\n"; break;
|
|
||||||
case '\v': ret += "\\v"; break;
|
|
||||||
case '\f': ret += "\\f"; break;
|
|
||||||
case '\r': ret += "\\r"; break;
|
|
||||||
case '\033':ret += "\\e"; break;
|
|
||||||
case '\"': ret += "\\\""; break;
|
|
||||||
case '\'': ret += "\\\'"; break;
|
|
||||||
case '\\': ret += "\\\\"; break;
|
|
||||||
default: ret += i; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (maxlen && ret.length()>maxlen) {
|
|
||||||
ret = ret.substr(0, maxlen)+"...";
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace fs {
|
|
||||||
|
|
||||||
path& path::operator/(const path& another) {
|
|
||||||
this->file_system_path += is_windows()? "\\":"/";
|
|
||||||
this->file_system_path += another.file_system_path;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool exists(const path& file_path) {
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define F_OK 0 // fuck msc
|
|
||||||
#endif
|
|
||||||
return access(file_path.c_str(), F_OK)==0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_regular(const path& file_path) {
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define S_ISREG(m) (((m)&0xF000)==0x8000)
|
|
||||||
#endif
|
|
||||||
struct stat buffer;
|
|
||||||
if (stat(file_path.c_str(), &buffer)!=0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return S_ISREG(buffer.st_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "nasal.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace nasal::util {
|
||||||
|
|
||||||
|
bool is_windows();
|
||||||
|
bool is_linux();
|
||||||
|
bool is_macos();
|
||||||
|
bool is_x86();
|
||||||
|
bool is_amd64();
|
||||||
|
bool is_x86_64();
|
||||||
|
bool is_arm();
|
||||||
|
bool is_aarch64();
|
||||||
|
bool is_ia64();
|
||||||
|
bool is_powerpc();
|
||||||
|
bool is_superh();
|
||||||
|
const char* get_platform();
|
||||||
|
const char* get_arch();
|
||||||
|
|
||||||
|
u32 utf8_hdchk(const char);
|
||||||
|
|
||||||
|
std::string char_to_hex(const char);
|
||||||
|
std::string rawstr(const std::string&, const usize maxlen = 0);
|
||||||
|
|
||||||
|
f64 hex_to_f64(const char*);
|
||||||
|
f64 oct_to_f64(const char*);
|
||||||
|
// we have the same reason not using atof here
|
||||||
|
// just as andy's interpreter does.
|
||||||
|
// it is not platform independent, and may have strange output.
|
||||||
|
// so we write a new function here to convert str to number manually.
|
||||||
|
// but this also makes 0.1+0.2==0.3,
|
||||||
|
// not another result that you may get in other languages.
|
||||||
|
f64 dec_to_f64(const char*);
|
||||||
|
|
||||||
|
f64 str_to_num(const char*);
|
||||||
|
|
||||||
|
class windows_code_page_manager {
|
||||||
|
private:
|
||||||
|
u32 code_page;
|
||||||
|
|
||||||
|
public:
|
||||||
|
windows_code_page_manager() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
code_page = GetConsoleOutputCP();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_utf8_output() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
// store previous code page
|
||||||
|
code_page = GetConsoleOutputCP();
|
||||||
|
// allow 65001 code page
|
||||||
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void restore_code_page() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
// restore previous code page
|
||||||
|
SetConsoleOutputCP(code_page);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -1,13 +1,35 @@
|
||||||
# runtime.nas
|
# runtime.nas
|
||||||
# 2023 by ValKmjolnir
|
# 2023 by ValKmjolnir
|
||||||
# runtime gives us some functions that we could manage it manually.
|
# runtime gives us some functions that we could manage it manually.
|
||||||
|
|
||||||
# command line arguments
|
# command line arguments
|
||||||
var argv = func() {
|
var argv = func() {
|
||||||
return globals.arg;
|
return globals.arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
var gc = {
|
var _gc_extend = func(type) {
|
||||||
extend: func(type) {return __gcextd;},
|
return __gcextd;
|
||||||
info: func() {return __gcinfo;}
|
}
|
||||||
};
|
|
||||||
|
var gc = {
|
||||||
|
extend: func(type, times = 1) {
|
||||||
|
if (times<=0) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
if (times>16) {
|
||||||
|
times = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var i = 0; i<times; i+=1) {
|
||||||
|
_gc_extend(type);
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
},
|
||||||
|
info: func() {return __gcinfo;}
|
||||||
|
};
|
||||||
|
|
||||||
|
var windows = {
|
||||||
|
set_utf8_output: func() {
|
||||||
|
return __set_utf8_output;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -1,7 +1,24 @@
|
||||||
use std.padding;
|
use std.padding;
|
||||||
use std.process_bar;
|
use std.process_bar;
|
||||||
use std.os;
|
|
||||||
use std.unix;
|
use std.unix;
|
||||||
|
use std.runtime;
|
||||||
|
|
||||||
|
var table_character_set = [
|
||||||
|
"─", "━", "│", "┃", "╌", "╍", "╎", "╏", "┄", "┅",
|
||||||
|
"┆", "┇", "┈", "┉", "┊", "┋", "┌", "┍", "┎", "┏",
|
||||||
|
"┐", "┑", "┒", "┓", "└", "┕", "┖", "┗", "┘", "┙",
|
||||||
|
"┚", "┛", "├", "┝", "┞", "┟", "┠", "┡", "┢", "┣",
|
||||||
|
"┤", "┥", "┦", "┧", "┨", "┩", "┪", "┫", "┬", "┭",
|
||||||
|
"┮", "┯", "┰", "┱", "┲", "┳", "┴", "┵", "┶", "┷",
|
||||||
|
"┸", "┹", "┺", "┻", "┼", "┽", "┾", "┿", "╀", "╁",
|
||||||
|
"╂", "╃", "╄", "╅", "╆", "╇", "╈", "╉", "╊", "╋",
|
||||||
|
"╪", "╫", "╬", "═", "║", "╒", "╓", "╔", "╕", "╖",
|
||||||
|
"╗", "╘", "╙", "╚", "╛", "╜", "╝", "╞", "╟", "╠",
|
||||||
|
"╡", "╢", "╣", "╤", "╥", "╦", "╧", "╨", "╬", "╩",
|
||||||
|
"┷", "┳", "⊥", "﹃", "﹄", "╮", "╭", "╯", "╰", "╳"
|
||||||
|
];
|
||||||
|
|
||||||
|
var selection_box = ["○", "◉", "☐", "▣"];
|
||||||
|
|
||||||
var char_ttf=[
|
var char_ttf=[
|
||||||
[" "," "," "," "," "," "],
|
[" "," "," "," "," "," "],
|
||||||
|
@ -196,9 +213,7 @@ var ansi_escape_sequence = func() {
|
||||||
}
|
}
|
||||||
|
|
||||||
# enable unicode
|
# enable unicode
|
||||||
if (os.platform()=="windows") {
|
runtime.windows.set_utf8_output();
|
||||||
system("chcp 65001");
|
|
||||||
}
|
|
||||||
|
|
||||||
trans_ttf("just for test");
|
trans_ttf("just for test");
|
||||||
trans_ttf(" ValKmjolnir ");
|
trans_ttf(" ValKmjolnir ");
|
||||||
|
|
|
@ -1,252 +1,250 @@
|
||||||
# ray tracing example
|
# ray tracing example
|
||||||
# modified from Artem Yashin's project Console3D
|
# modified from Artem Yashin's project Console3D
|
||||||
|
|
||||||
# MIT License
|
# MIT License
|
||||||
# Copyright (c) 2021 Artem Yashin
|
# Copyright (c) 2021 Artem Yashin
|
||||||
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
# in the Software without restriction, including without limitation the rights
|
# in the Software without restriction, including without limitation the rights
|
||||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
# copies of the Software, and to permit persons to whom the Software is
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
# furnished to do so, subject to the following conditions:
|
# furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
# The above copyright notice and this permission notice shall be included in all
|
# The above copyright notice and this permission notice shall be included in all
|
||||||
# copies or substantial portions of the Software.
|
# copies or substantial portions of the Software.
|
||||||
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
# 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
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
use module.libmat;
|
use module.libmat;
|
||||||
use std.runtime;
|
use std.runtime;
|
||||||
use std.math;
|
use std.math;
|
||||||
|
|
||||||
func() {
|
func() {
|
||||||
# allocate more spaces
|
# allocate more spaces
|
||||||
for(var i = 0; i<10; i+=1) {
|
runtime.gc.extend("str", 8);
|
||||||
runtime.gc.extend("str");
|
runtime.gc.extend("vec", 8);
|
||||||
runtime.gc.extend("vec");
|
}();
|
||||||
}
|
|
||||||
}();
|
var (max,min,sqrt,sin,cos,abs)=(
|
||||||
|
math.max,
|
||||||
var (max,min,sqrt,sin,cos,abs)=(
|
math.min,
|
||||||
math.max,
|
math.sqrt,
|
||||||
math.min,
|
math.sin,
|
||||||
math.sqrt,
|
math.cos,
|
||||||
math.sin,
|
math.abs
|
||||||
math.cos,
|
);
|
||||||
math.abs
|
|
||||||
);
|
var (vec2,vec3)=(
|
||||||
|
libmat.vec2.new,
|
||||||
var (vec2,vec3)=(
|
libmat.vec3.new
|
||||||
libmat.vec2.new,
|
);
|
||||||
libmat.vec3.new
|
|
||||||
);
|
var (vec2add,vec2sub,vec2mul,vec2div,vec2len)=(
|
||||||
|
libmat.vec2.add,
|
||||||
var (vec2add,vec2sub,vec2mul,vec2div,vec2len)=(
|
libmat.vec2.sub,
|
||||||
libmat.vec2.add,
|
libmat.vec2.mul,
|
||||||
libmat.vec2.sub,
|
libmat.vec2.div,
|
||||||
libmat.vec2.mul,
|
libmat.vec2.len
|
||||||
libmat.vec2.div,
|
);
|
||||||
libmat.vec2.len
|
|
||||||
);
|
var (vec3add,vec3sub,vec3mul,vec3div,vec3neg,vec3norm,vec3len,vec3dot)=(
|
||||||
|
libmat.vec3.add,
|
||||||
var (vec3add,vec3sub,vec3mul,vec3div,vec3neg,vec3norm,vec3len,vec3dot)=(
|
libmat.vec3.sub,
|
||||||
libmat.vec3.add,
|
libmat.vec3.mul,
|
||||||
libmat.vec3.sub,
|
libmat.vec3.div,
|
||||||
libmat.vec3.mul,
|
libmat.vec3.neg,
|
||||||
libmat.vec3.div,
|
libmat.vec3.norm,
|
||||||
libmat.vec3.neg,
|
libmat.vec3.len,
|
||||||
libmat.vec3.norm,
|
libmat.vec3.dot
|
||||||
libmat.vec3.len,
|
);
|
||||||
libmat.vec3.dot
|
|
||||||
);
|
var (rotateX,rotateY,rotateZ)=(
|
||||||
|
libmat.vec3.rx,
|
||||||
var (rotateX,rotateY,rotateZ)=(
|
libmat.vec3.ry,
|
||||||
libmat.vec3.rx,
|
libmat.vec3.rz,
|
||||||
libmat.vec3.ry,
|
);
|
||||||
libmat.vec3.rz,
|
|
||||||
);
|
var use_raw = func() {
|
||||||
|
vec2 = func(x,y) {return [x,y];}
|
||||||
var use_raw = func() {
|
vec2add = func(v1,v2) {return [v1[0]+v2[0],v1[1]+v2[1]];}
|
||||||
vec2 = func(x,y) {return [x,y];}
|
vec2sub = func(v1,v2) {return [v1[0]-v2[0],v1[1]-v2[1]];}
|
||||||
vec2add = func(v1,v2) {return [v1[0]+v2[0],v1[1]+v2[1]];}
|
vec2mul = func(v1,v2) {return [v1[0]*v2[0],v1[1]*v2[1]];}
|
||||||
vec2sub = func(v1,v2) {return [v1[0]-v2[0],v1[1]-v2[1]];}
|
vec2div = func(v1,v2) {return [v1[0]/v2[0],v1[1]/v2[1]];}
|
||||||
vec2mul = func(v1,v2) {return [v1[0]*v2[0],v1[1]*v2[1]];}
|
vec3 = func(x,y,z) {return [x,y,z];}
|
||||||
vec2div = func(v1,v2) {return [v1[0]/v2[0],v1[1]/v2[1]];}
|
vec3add = func(v1,v2) {return [v1[0]+v2[0],v1[1]+v2[1],v1[2]+v2[2]];}
|
||||||
vec3 = func(x,y,z) {return [x,y,z];}
|
vec3sub = func(v1,v2) {return [v1[0]-v2[0],v1[1]-v2[1],v1[2]-v2[2]];}
|
||||||
vec3add = func(v1,v2) {return [v1[0]+v2[0],v1[1]+v2[1],v1[2]+v2[2]];}
|
vec3mul = func(v1,v2) {return [v1[0]*v2[0],v1[1]*v2[1],v1[2]*v2[2]];}
|
||||||
vec3sub = func(v1,v2) {return [v1[0]-v2[0],v1[1]-v2[1],v1[2]-v2[2]];}
|
vec3div = func(v1,v2) {return [v1[0]/v2[0],v1[1]/v2[1],v1[2]/v2[2]];}
|
||||||
vec3mul = func(v1,v2) {return [v1[0]*v2[0],v1[1]*v2[1],v1[2]*v2[2]];}
|
vec3neg = func(v) {return [-v[0],-v[1],-v[2]];}
|
||||||
vec3div = func(v1,v2) {return [v1[0]/v2[0],v1[1]/v2[1],v1[2]/v2[2]];}
|
vec2len = func(v) {var (x,y)=(v[0],v[1]); return sqrt(x*x+y*y);}
|
||||||
vec3neg = func(v) {return [-v[0],-v[1],-v[2]];}
|
vec3len = func(v) {var (x,y,z)=(v[0],v[1],v[2]); return sqrt(x*x+y*y+z*z);}
|
||||||
vec2len = func(v) {var (x,y)=(v[0],v[1]); return sqrt(x*x+y*y);}
|
vec3norm = func(v) {var t=vec3len(v); return vec3div(v,[t,t,t]);}
|
||||||
vec3len = func(v) {var (x,y,z)=(v[0],v[1],v[2]); return sqrt(x*x+y*y+z*z);}
|
vec3dot = func(a,b) {return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];}
|
||||||
vec3norm = func(v) {var t=vec3len(v); return vec3div(v,[t,t,t]);}
|
rotateX = func(a,angle) {return [a[0],a[2]*sin(angle)+a[1]*cos(angle),a[2]*cos(angle)-a[1]*sin(angle)];}
|
||||||
vec3dot = func(a,b) {return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];}
|
rotateY = func(a,angle) {return [a[0]*cos(angle)-a[2]*sin(angle),a[1],a[0]*sin(angle)+a[2]*cos(angle)];}
|
||||||
rotateX = func(a,angle) {return [a[0],a[2]*sin(angle)+a[1]*cos(angle),a[2]*cos(angle)-a[1]*sin(angle)];}
|
rotateZ = func(a,angle) {return [a[0]*cos(angle)-a[1]*sin(angle),a[0]*sin(angle)+a[1]*cos(angle),a[2]];}
|
||||||
rotateY = func(a,angle) {return [a[0]*cos(angle)-a[2]*sin(angle),a[1],a[0]*sin(angle)+a[2]*cos(angle)];}
|
}
|
||||||
rotateZ = func(a,angle) {return [a[0]*cos(angle)-a[1]*sin(angle),a[0]*sin(angle)+a[1]*cos(angle),a[2]];}
|
|
||||||
}
|
var clamp = func(value,_min,_max) {
|
||||||
|
return max(min(value,_max),_min);
|
||||||
var clamp = func(value,_min,_max) {
|
}
|
||||||
return max(min(value,_max),_min);
|
var sign = func(a) {
|
||||||
}
|
return (0<a)-(a<0);
|
||||||
var sign = func(a) {
|
}
|
||||||
return (0<a)-(a<0);
|
var step = func(edge,x) {
|
||||||
}
|
return x>edge;
|
||||||
var step = func(edge,x) {
|
}
|
||||||
return x>edge;
|
|
||||||
}
|
var vec3abs = func(v) {
|
||||||
|
return [abs(v[0]),abs(v[1]),abs(v[2])];
|
||||||
var vec3abs = func(v) {
|
}
|
||||||
return [abs(v[0]),abs(v[1]),abs(v[2])];
|
var vec3sign = func(v) {
|
||||||
}
|
return [sign(v[0]),sign(v[1]),sign(v[2])];
|
||||||
var vec3sign = func(v) {
|
}
|
||||||
return [sign(v[0]),sign(v[1]),sign(v[2])];
|
var vec3step = func(edge,v) {
|
||||||
}
|
return [step(edge[0],v[0]),step(edge[1],v[1]),step(edge[2],v[2])];
|
||||||
var vec3step = func(edge,v) {
|
}
|
||||||
return [step(edge[0],v[0]),step(edge[1],v[1]),step(edge[2],v[2])];
|
var vec3reflect = func(rd,n) {
|
||||||
}
|
var d=vec3dot(n,rd);
|
||||||
var vec3reflect = func(rd,n) {
|
return vec3sub(rd,vec3mul(n,vec3mul([2,2,2],[d,d,d])));
|
||||||
var d=vec3dot(n,rd);
|
}
|
||||||
return vec3sub(rd,vec3mul(n,vec3mul([2,2,2],[d,d,d])));
|
|
||||||
}
|
var sphere = func(ro,rd,r) {
|
||||||
|
var b=vec3dot(ro,rd);
|
||||||
var sphere = func(ro,rd,r) {
|
var c=vec3dot(ro,ro)-r*r;
|
||||||
var b=vec3dot(ro,rd);
|
var h=b*b-c;
|
||||||
var c=vec3dot(ro,ro)-r*r;
|
if (h<0.0) return [-1.0,-1.0];
|
||||||
var h=b*b-c;
|
h=sqrt(h);
|
||||||
if (h<0.0) return [-1.0,-1.0];
|
return [-b-h,-b+h];
|
||||||
h=sqrt(h);
|
}
|
||||||
return [-b-h,-b+h];
|
|
||||||
}
|
var box = func(ro,rd,boxSize,outNormal) {
|
||||||
|
var m=vec3div([1.0,1.0,1.0],rd);
|
||||||
var box = func(ro,rd,boxSize,outNormal) {
|
var n=vec3mul(m,ro);
|
||||||
var m=vec3div([1.0,1.0,1.0],rd);
|
var k=vec3mul(vec3abs(m),boxSize);
|
||||||
var n=vec3mul(m,ro);
|
var t1=vec3sub(vec3neg(n),k);
|
||||||
var k=vec3mul(vec3abs(m),boxSize);
|
var t2=vec3add(vec3neg(n),k);
|
||||||
var t1=vec3sub(vec3neg(n),k);
|
var tN=max(max(t1[0],t1[1]),t1[2]);
|
||||||
var t2=vec3add(vec3neg(n),k);
|
var tF=min(min(t2[0],t2[1]),t2[2]);
|
||||||
var tN=max(max(t1[0],t1[1]),t1[2]);
|
if (tN>tF or tF<0.0) return [-1.0,-1.0];
|
||||||
var tF=min(min(t2[0],t2[1]),t2[2]);
|
var yzx=[t1[1],t1[2],t1[0]];
|
||||||
if (tN>tF or tF<0.0) return [-1.0,-1.0];
|
var zxy=[t1[2],t1[0],t1[1]];
|
||||||
var yzx=[t1[1],t1[2],t1[0]];
|
var tmp=vec3mul(vec3mul(vec3neg(vec3sign(rd)), vec3step(yzx,t1)),vec3step(zxy,t1));
|
||||||
var zxy=[t1[2],t1[0],t1[1]];
|
outNormal[0]=tmp[0];
|
||||||
var tmp=vec3mul(vec3mul(vec3neg(vec3sign(rd)), vec3step(yzx,t1)),vec3step(zxy,t1));
|
outNormal[1]=tmp[1];
|
||||||
outNormal[0]=tmp[0];
|
outNormal[2]=tmp[2];
|
||||||
outNormal[1]=tmp[1];
|
return [tN, tF];
|
||||||
outNormal[2]=tmp[2];
|
}
|
||||||
return [tN, tF];
|
|
||||||
}
|
var plane = func(ro,rd,p,w) {
|
||||||
|
return -(vec3dot(ro,p)+w)/vec3dot(rd,p);
|
||||||
var plane = func(ro,rd,p,w) {
|
}
|
||||||
return -(vec3dot(ro,p)+w)/vec3dot(rd,p);
|
|
||||||
}
|
var main = func(frame) {
|
||||||
|
|
||||||
var main = func(frame) {
|
var height=15*2;
|
||||||
|
var width=int(height*1/0.618)*2;
|
||||||
var height=15*2;
|
|
||||||
var width=int(height*1/0.618)*2;
|
var aspect=width/height;
|
||||||
|
var pixelAspect=11.0/24.0;
|
||||||
var aspect=width/height;
|
|
||||||
var pixelAspect=11.0/24.0;
|
var gradient=split(""," .:!/r(l1Z4H9W8$");
|
||||||
|
var gradientSize=size(gradient)-1;
|
||||||
var gradient=split(""," .:!/r(l1Z4H9W8$");
|
|
||||||
var gradientSize=size(gradient)-1;
|
var screen=[];
|
||||||
|
setsize(screen,width*height);
|
||||||
var screen=[];
|
|
||||||
setsize(screen,width*height);
|
var light=vec3norm([-0.5,0.5,-1.0]);
|
||||||
|
var spherePos=[0,3,0];
|
||||||
var light=vec3norm([-0.5,0.5,-1.0]);
|
var vec2_2_2=[2,2];
|
||||||
var spherePos=[0,3,0];
|
var vec2_1_1=[1,1];
|
||||||
var vec2_2_2=[2,2];
|
var vec3_000=[0,0,0];
|
||||||
var vec2_1_1=[1,1];
|
var vec3_00n1=[0,0,-1];
|
||||||
var vec3_000=[0,0,0];
|
var vec3_111=[1,1,1];
|
||||||
var vec3_00n1=[0,0,-1];
|
|
||||||
var vec3_111=[1,1,1];
|
print("\e[2J");
|
||||||
|
var stamp=maketimestamp();
|
||||||
print("\e[2J");
|
for(var t=0;t<frame;t+=1) {
|
||||||
var stamp=maketimestamp();
|
stamp.stamp();
|
||||||
for(var t=0;t<frame;t+=1) {
|
for(var i=0;i<width;i+=1) {
|
||||||
stamp.stamp();
|
for(var j=0;j<height;j+=1) {
|
||||||
for(var i=0;i<width;i+=1) {
|
var uv=vec2sub(vec2mul(vec2div([i,j],[width,height]),vec2_2_2),vec2_1_1);
|
||||||
for(var j=0;j<height;j+=1) {
|
uv[0]*=aspect*pixelAspect;
|
||||||
var uv=vec2sub(vec2mul(vec2div([i,j],[width,height]),vec2_2_2),vec2_1_1);
|
var ro=[-6,0,0];
|
||||||
uv[0]*=aspect*pixelAspect;
|
var rd=vec3norm([2,uv[0],uv[1]]);
|
||||||
var ro=[-6,0,0];
|
ro=rotateY(ro,0.25);
|
||||||
var rd=vec3norm([2,uv[0],uv[1]]);
|
rd=rotateY(rd,0.25);
|
||||||
ro=rotateY(ro,0.25);
|
ro=rotateZ(ro,t*0.03);
|
||||||
rd=rotateY(rd,0.25);
|
rd=rotateZ(rd,t*0.03);
|
||||||
ro=rotateZ(ro,t*0.03);
|
var diff=1;
|
||||||
rd=rotateZ(rd,t*0.03);
|
for (var k=0;k<5;k+=1) {
|
||||||
var diff=1;
|
var minIt=99999;
|
||||||
for (var k=0;k<5;k+=1) {
|
var intersection=sphere(vec3sub(ro,spherePos),rd,1);
|
||||||
var minIt=99999;
|
var n=vec3_000;
|
||||||
var intersection=sphere(vec3sub(ro,spherePos),rd,1);
|
var albedo=1;
|
||||||
var n=vec3_000;
|
if (intersection[0]>0) {
|
||||||
var albedo=1;
|
var itPoint=vec3add(vec3sub(ro,spherePos),vec3mul(rd,[intersection[0],intersection[0],intersection[0]]));
|
||||||
if (intersection[0]>0) {
|
minIt=intersection[0];
|
||||||
var itPoint=vec3add(vec3sub(ro,spherePos),vec3mul(rd,[intersection[0],intersection[0],intersection[0]]));
|
n=vec3norm(itPoint);
|
||||||
minIt=intersection[0];
|
}
|
||||||
n=vec3norm(itPoint);
|
var boxN=[0,0,0];
|
||||||
}
|
intersection=box(ro,rd,vec3_111,boxN);
|
||||||
var boxN=[0,0,0];
|
if (intersection[0]>0 and intersection[0]<minIt) {
|
||||||
intersection=box(ro,rd,vec3_111,boxN);
|
minIt=intersection[0];
|
||||||
if (intersection[0]>0 and intersection[0]<minIt) {
|
n=boxN;
|
||||||
minIt=intersection[0];
|
}
|
||||||
n=boxN;
|
var tmp=plane(ro,rd,vec3_00n1,1);
|
||||||
}
|
intersection=[tmp,tmp];
|
||||||
var tmp=plane(ro,rd,vec3_00n1,1);
|
if (intersection[0]>0 and intersection[0]<minIt) {
|
||||||
intersection=[tmp,tmp];
|
minIt=intersection[0];
|
||||||
if (intersection[0]>0 and intersection[0]<minIt) {
|
n=vec3_00n1;
|
||||||
minIt=intersection[0];
|
albedo=0.5;
|
||||||
n=vec3_00n1;
|
}
|
||||||
albedo=0.5;
|
if (minIt<99999) {
|
||||||
}
|
diff*=(vec3dot(n,light)*0.5+0.5)*albedo;
|
||||||
if (minIt<99999) {
|
ro=vec3add(ro,vec3mul(rd,[minIt-0.01,minIt-0.01,minIt-0.01]));
|
||||||
diff*=(vec3dot(n,light)*0.5+0.5)*albedo;
|
rd=vec3reflect(rd,n);
|
||||||
ro=vec3add(ro,vec3mul(rd,[minIt-0.01,minIt-0.01,minIt-0.01]));
|
}
|
||||||
rd=vec3reflect(rd,n);
|
else break;
|
||||||
}
|
}
|
||||||
else break;
|
var color=int(diff*20);
|
||||||
}
|
color=clamp(color,0,gradientSize);
|
||||||
var color=int(diff*20);
|
screen[i+j*width]=gradient[color];
|
||||||
color=clamp(color,0,gradientSize);
|
}
|
||||||
screen[i+j*width]=gradient[color];
|
}
|
||||||
}
|
var s="";
|
||||||
}
|
forindex(var index;screen) {
|
||||||
var s="";
|
s~=screen[index];
|
||||||
forindex(var index;screen) {
|
if (index+1-int((index+1)/width)*width==0)
|
||||||
s~=screen[index];
|
s~="\n";
|
||||||
if (index+1-int((index+1)/width)*width==0)
|
}
|
||||||
s~="\n";
|
var elt=stamp.elapsedMSec()/1000;
|
||||||
}
|
print("\e[H",int(1/elt)," fps \n",s);
|
||||||
var elt=stamp.elapsedMSec()/1000;
|
}
|
||||||
print("\e[H",int(1/elt)," fps \n",s);
|
}
|
||||||
}
|
|
||||||
}
|
var st=maketimestamp();
|
||||||
|
var run=[0,0];
|
||||||
var st=maketimestamp();
|
var frame=1e3;
|
||||||
var run=[0,0];
|
if (size(runtime.argv())!=0) {
|
||||||
var frame=1e3;
|
var n=num(runtime.argv()[0]);
|
||||||
if (size(runtime.argv())!=0) {
|
if (!math.isnan(n)) {
|
||||||
var n=num(runtime.argv()[0]);
|
frame=n;
|
||||||
if (!math.isnan(n)) {
|
}
|
||||||
frame=n;
|
}
|
||||||
}
|
st.stamp();
|
||||||
}
|
main(frame);
|
||||||
st.stamp();
|
run[0]=st.elapsedMSec();
|
||||||
main(frame);
|
use_raw();
|
||||||
run[0]=st.elapsedMSec();
|
st.stamp();
|
||||||
use_raw();
|
main(frame);
|
||||||
st.stamp();
|
run[1]=st.elapsedMSec();
|
||||||
main(frame);
|
|
||||||
run[1]=st.elapsedMSec();
|
println("test 0: ",run[0]/1000,"s ",frame*1000/run[0]," fps");
|
||||||
|
|
||||||
println("test 0: ",run[0]/1000,"s ",frame*1000/run[0]," fps");
|
|
||||||
println("test 1: ",run[1]/1000,"s ",frame*1000/run[1]," fps");
|
println("test 1: ",run[1]/1000,"s ",frame*1000/run[1]," fps");
|
|
@ -4,9 +4,10 @@ use std.coroutine;
|
||||||
use std.process_bar;
|
use std.process_bar;
|
||||||
use std.padding;
|
use std.padding;
|
||||||
use std.os;
|
use std.os;
|
||||||
|
use std.runtime;
|
||||||
|
|
||||||
if (os.platform()=="windows") {
|
if (os.platform()=="windows") {
|
||||||
system("chcp 65001");
|
runtime.windows.set_utf8_output();
|
||||||
system("color");
|
system("color");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std.os;
|
use std.runtime;
|
||||||
use std.io;
|
use std.io;
|
||||||
use std.unix;
|
use std.unix;
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ var prt = func(s,path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
# enable unicode
|
# enable unicode
|
||||||
if (os.platform()=="windows")
|
runtime.windows.set_utf8_output();
|
||||||
system("chcp 65001");
|
|
||||||
println("\e[33m[",unix.getcwd(),"]\e[36m>\e[0m");
|
println("\e[33m[",unix.getcwd(),"]\e[36m>\e[0m");
|
||||||
prt([""],".");
|
prt([""],".");
|
|
@ -1,7 +1,7 @@
|
||||||
use test.md5_self;
|
use test.md5_self;
|
||||||
use std.process_bar;
|
use std.process_bar;
|
||||||
use std.file;
|
use std.file;
|
||||||
use std.os;
|
use std.runtime;
|
||||||
use std.io;
|
use std.io;
|
||||||
use std.math;
|
use std.math;
|
||||||
|
|
||||||
|
@ -47,6 +47,12 @@ var compare = func() {
|
||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
var add_all_cpp_files = func(vec, path) {
|
||||||
|
foreach(var p; file.find_all_files_with_extension(path,"cpp","h")) {
|
||||||
|
append(vec, path~"/"~p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var filechecksum = func() {
|
var filechecksum = func() {
|
||||||
var files = [];
|
var files = [];
|
||||||
foreach(var p; file.find_all_files_with_extension("./test","nas")) {
|
foreach(var p; file.find_all_files_with_extension("./test","nas")) {
|
||||||
|
@ -61,9 +67,11 @@ var filechecksum = func() {
|
||||||
foreach(var p; file.find_all_files_with_extension(".","md")) {
|
foreach(var p; file.find_all_files_with_extension(".","md")) {
|
||||||
append(files, "./"~p);
|
append(files, "./"~p);
|
||||||
}
|
}
|
||||||
foreach(var p; file.find_all_files_with_extension("./src","cpp","h")) {
|
add_all_cpp_files(files, "./src");
|
||||||
append(files, "./src/"~p);
|
add_all_cpp_files(files, "./src/cli");
|
||||||
}
|
add_all_cpp_files(files, "./src/natives");
|
||||||
|
add_all_cpp_files(files, "./src/repl");
|
||||||
|
add_all_cpp_files(files, "./src/util");
|
||||||
foreach(var p; file.find_all_files_with_extension("./doc","md")) {
|
foreach(var p; file.find_all_files_with_extension("./doc","md")) {
|
||||||
append(files, "./doc/"~p);
|
append(files, "./doc/"~p);
|
||||||
}
|
}
|
||||||
|
@ -101,8 +109,6 @@ var randomchecksum = func() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (os.platform()=="windows") {
|
runtime.windows.set_utf8_output();
|
||||||
system("chcp 65001");
|
|
||||||
}
|
|
||||||
filechecksum();
|
filechecksum();
|
||||||
randomchecksum();
|
randomchecksum();
|
|
@ -11,7 +11,7 @@ var is_windows_platform=os.platform()=="windows";
|
||||||
var is_macos_platform=os.platform()=="macOS";
|
var is_macos_platform=os.platform()=="macOS";
|
||||||
|
|
||||||
if (is_windows_platform) {
|
if (is_windows_platform) {
|
||||||
system("chcp 65001");
|
runtime.windows.set_utf8_output();
|
||||||
}
|
}
|
||||||
|
|
||||||
var cpu_stat = func() {
|
var cpu_stat = func() {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std.os;
|
use std.runtime;
|
||||||
|
|
||||||
var code=[
|
var code=[
|
||||||
[1,1,1,1,1,1,1,0,1,0,0,1,1,0,1,0,1,0,1,1,0,0,1,1,1,1,1,1,1],
|
[1,1,1,1,1,1,1,0,1,0,0,1,1,0,1,0,1,0,1,1,0,0,1,1,1,1,1,1,1],
|
||||||
[1,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,1,1,0,1,0,0,0,0,0,1],
|
[1,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,1,1,0,1,0,0,0,0,0,1],
|
||||||
|
@ -32,8 +33,7 @@ var code=[
|
||||||
];
|
];
|
||||||
|
|
||||||
# enable unicode
|
# enable unicode
|
||||||
if (os.platform()=="windows")
|
runtime.windows.set_utf8_output();
|
||||||
system("chcp 65001");
|
|
||||||
var texture=[" ","██"];
|
var texture=[" ","██"];
|
||||||
for(var i=0;i<size(code);i+=1) {
|
for(var i=0;i<size(code);i+=1) {
|
||||||
for(var j=0;j<size(code[i]);j+=1)
|
for(var j=0;j<size(code[i]);j+=1)
|
||||||
|
|
|
@ -2,7 +2,6 @@ use module.libkey;
|
||||||
use std.list;
|
use std.list;
|
||||||
use std.runtime;
|
use std.runtime;
|
||||||
use std.coroutine;
|
use std.coroutine;
|
||||||
use std.os;
|
|
||||||
use std.unix;
|
use std.unix;
|
||||||
|
|
||||||
var game = func(x,y) {
|
var game = func(x,y) {
|
||||||
|
@ -130,8 +129,7 @@ var co=coroutine.create(func() {
|
||||||
var main = func(argv) {
|
var main = func(argv) {
|
||||||
var should_skip=(size(argv)!=0 and argv[0]=="--skip");
|
var should_skip=(size(argv)!=0 and argv[0]=="--skip");
|
||||||
# enable unicode
|
# enable unicode
|
||||||
if (os.platform()=="windows")
|
runtime.windows.set_utf8_output();
|
||||||
system("chcp 65001");
|
|
||||||
print("\ec");
|
print("\ec");
|
||||||
|
|
||||||
var g=game(15,10);
|
var g=game(15,10);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use module.libkey;
|
use module.libkey;
|
||||||
use std.runtime;
|
use std.runtime;
|
||||||
use std.os;
|
|
||||||
use std.unix;
|
use std.unix;
|
||||||
|
|
||||||
var color=[
|
var color=[
|
||||||
|
@ -277,9 +276,9 @@ var mapgen = func(mapx,mapy) {
|
||||||
var main = func(argv) {
|
var main = func(argv) {
|
||||||
var should_skip=(size(argv)!=0 and argv[0]=="--skip");
|
var should_skip=(size(argv)!=0 and argv[0]=="--skip");
|
||||||
var init_counter=should_skip?5:30;
|
var init_counter=should_skip?5:30;
|
||||||
# windows use chcp 65001 to output unicode
|
|
||||||
if (os.platform()=="windows")
|
# windows use 65001 to output unicode
|
||||||
system("chcp 65001");
|
runtime.windows.set_utf8_output();
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"\ec\e[1:1H",
|
"\ec\e[1:1H",
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
|
use std.runtime;
|
||||||
|
|
||||||
|
# do nothing if platform is not windows
|
||||||
|
runtime.windows.set_utf8_output();
|
||||||
|
|
||||||
var unicode测试 = func() {
|
var unicode测试 = func() {
|
||||||
var 输出=print;
|
var 输出=print;
|
||||||
var 测试成功=[
|
var 测试成功=[
|
||||||
"unicode: utf-8支持测试成功",
|
"unicode: utf-8 支持测试成功",
|
||||||
"目前仅支持utf-8以及ascii格式文件",
|
"目前仅支持 utf-8 以及 ascii 格式文件",
|
||||||
"注意: windows系统请开启chcp 65001代码页"
|
"注意: windows 系统请开启 chcp 65001 代码页"
|
||||||
];
|
];
|
||||||
foreach(var 内容;测试成功)
|
foreach(var 内容; 测试成功)
|
||||||
输出(内容~"\n");
|
输出(内容~"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,10 +46,10 @@ var emoji测试 = func() {
|
||||||
🍾:🍾,
|
🍾:🍾,
|
||||||
🐘:🐘
|
🐘:🐘
|
||||||
};
|
};
|
||||||
foreach(var 📄;📁)
|
foreach(var 📄; 📁)
|
||||||
💻(📄,🎤);
|
💻(📄, 🎤);
|
||||||
foreach(var 📄;keys(🗄️))
|
foreach(var 📄; keys(🗄️))
|
||||||
💻(📄,🗄️[📄],🎤);
|
💻(📄, 🗄️[📄], 🎤);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dotsgen = func() {
|
var dotsgen = func() {
|
||||||
|
|
|
@ -4,16 +4,16 @@ use std.io;
|
||||||
use std.unix;
|
use std.unix;
|
||||||
|
|
||||||
var os_time = func() {
|
var os_time = func() {
|
||||||
return "[\e[33;1m"~os.time()~"\e[0m] ";
|
return "\e[33;1m["~os.time()~"]\e[0m ";
|
||||||
}
|
}
|
||||||
var err_hd = func() {
|
var err_hd = func() {
|
||||||
return "[\e[91;1merror\e[0m] ";
|
return "\e[91;1m[error]\e[0m ";
|
||||||
}
|
}
|
||||||
var info_hd = func() {
|
var info_hd = func() {
|
||||||
return "[\e[96;1minfo\e[0m] ";
|
return "\e[96;1m[info]\e[0m ";
|
||||||
}
|
}
|
||||||
var modified_hd = func() {
|
var modified_hd = func() {
|
||||||
return "[\e[92;1mmodified\e[0m] ";
|
return "\e[92;1m[modified]\e[0m ";
|
||||||
}
|
}
|
||||||
var usage = func() {
|
var usage = func() {
|
||||||
println(os_time(),info_hd(),"\e[1musage: nasal watchdog.nas <filename> [\"argv\"]\e[0m");
|
println(os_time(),info_hd(),"\e[1musage: nasal watchdog.nas <filename> [\"argv\"]\e[0m");
|
||||||
|
@ -41,7 +41,7 @@ if (size(argv)==2) {
|
||||||
var modified_time = io.fstat(filename).st_mtime;
|
var modified_time = io.fstat(filename).st_mtime;
|
||||||
println(os_time(),info_hd(),"\e[1mwatching ",filename," ..\e[0m");
|
println(os_time(),info_hd(),"\e[1mwatching ",filename," ..\e[0m");
|
||||||
while(1) {
|
while(1) {
|
||||||
unix.sleep(1);
|
unix.sleep(5);
|
||||||
if (!io.exists(filename)) {
|
if (!io.exists(filename)) {
|
||||||
println(os_time(),err_hd(),"\e[1mfile <",filename,"> does not exist\e[0m");
|
println(os_time(),err_hd(),"\e[1mfile <",filename,"> does not exist\e[0m");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
use std.runtime;
|
||||||
|
|
||||||
|
runtime.windows.set_utf8_output();
|
||||||
|
|
||||||
|
var road_enum = {
|
||||||
|
null: 0,
|
||||||
|
narrow: 1,
|
||||||
|
wide: 2
|
||||||
|
};
|
||||||
|
|
||||||
|
var block = {
|
||||||
|
"┌": [road_enum.null, road_enum.narrow, road_enum.narrow, road_enum.null],
|
||||||
|
"└": [road_enum.narrow, road_enum.narrow, road_enum.null, road_enum.null],
|
||||||
|
"┐": [road_enum.null, road_enum.null, road_enum.narrow, road_enum.narrow],
|
||||||
|
"┘": [road_enum.narrow, road_enum.null, road_enum.null, road_enum.narrow],
|
||||||
|
"╪": [road_enum.narrow, road_enum.wide, road_enum.narrow, road_enum.wide],
|
||||||
|
"│": [road_enum.narrow, road_enum.null, road_enum.narrow, road_enum.null],
|
||||||
|
"─": [road_enum.null, road_enum.narrow, road_enum.null, road_enum.narrow],
|
||||||
|
"┼": [road_enum.narrow, road_enum.narrow, road_enum.narrow, road_enum.narrow],
|
||||||
|
"╫": [road_enum.wide, road_enum.narrow, road_enum.wide, road_enum.narrow],
|
||||||
|
"╬": [road_enum.wide, road_enum.wide, road_enum.wide, road_enum.wide],
|
||||||
|
"═": [road_enum.null, road_enum.wide, road_enum.null, road_enum.wide],
|
||||||
|
"║": [road_enum.wide, road_enum.null, road_enum.wide, road_enum.null],
|
||||||
|
# "╒": [road_enum.null, road_enum.wide, road_enum.narrow, road_enum.null],
|
||||||
|
# "╓": [road_enum.null, road_enum.narrow, road_enum.wide, road_enum.null],
|
||||||
|
"╔": [road_enum.null, road_enum.wide, road_enum.wide, road_enum.null],
|
||||||
|
# "╕": [road_enum.null, road_enum.null, road_enum.narrow, road_enum.wide],
|
||||||
|
# "╖": [road_enum.null, road_enum.null, road_enum.wide, road_enum.narrow],
|
||||||
|
"╗": [road_enum.null, road_enum.null, road_enum.wide, road_enum.wide],
|
||||||
|
# "╘": [road_enum.narrow, road_enum.wide, road_enum.null, road_enum.null],
|
||||||
|
# "╙": [road_enum.wide, road_enum.narrow, road_enum.null, road_enum.null],
|
||||||
|
"╚": [road_enum.wide, road_enum.wide, road_enum.null, road_enum.null],
|
||||||
|
# "╛": [road_enum.narrow, road_enum.null, road_enum.null, road_enum.wide],
|
||||||
|
# "╜": [road_enum.wide, road_enum.null, road_enum.null, road_enum.narrow],
|
||||||
|
"╝": [road_enum.wide, road_enum.null, road_enum.null, road_enum.wide],
|
||||||
|
"╞": [road_enum.narrow, road_enum.wide, road_enum.narrow, road_enum.null],
|
||||||
|
"╟": [road_enum.wide, road_enum.narrow, road_enum.wide, road_enum.null],
|
||||||
|
"╠": [road_enum.wide, road_enum.wide, road_enum.wide, road_enum.null],
|
||||||
|
"╡": [road_enum.narrow, road_enum.null, road_enum.narrow, road_enum.wide],
|
||||||
|
"╢": [road_enum.wide, road_enum.null, road_enum.wide, road_enum.narrow],
|
||||||
|
"╣": [road_enum.wide, road_enum.null, road_enum.wide, road_enum.wide],
|
||||||
|
"╤": [road_enum.null, road_enum.wide, road_enum.narrow, road_enum.wide],
|
||||||
|
"╥": [road_enum.null, road_enum.narrow, road_enum.wide, road_enum.narrow],
|
||||||
|
"╦": [road_enum.null, road_enum.wide, road_enum.wide, road_enum.wide],
|
||||||
|
"╧": [road_enum.narrow, road_enum.wide, road_enum.null, road_enum.wide],
|
||||||
|
"╨": [road_enum.wide, road_enum.narrow, road_enum.null, road_enum.narrow],
|
||||||
|
"╩": [road_enum.wide, road_enum.wide, road_enum.null, road_enum.wide],
|
||||||
|
" ": [road_enum.null, road_enum.null, road_enum.null, road_enum.null]
|
||||||
|
};
|
||||||
|
|
||||||
|
var choice = func(above_block_char,
|
||||||
|
left_block_char,
|
||||||
|
flag_no_road_at_right,
|
||||||
|
flag_no_road_at_bottom) {
|
||||||
|
var above_block = block[above_block_char];
|
||||||
|
var left_block = block[left_block_char];
|
||||||
|
var block_char_set = keys(block);
|
||||||
|
|
||||||
|
var possible = [];
|
||||||
|
foreach(var bcs; block_char_set) {
|
||||||
|
var this_block = block[bcs];
|
||||||
|
if (this_block[0] == above_block[2] and
|
||||||
|
this_block[3] == left_block[1]) {
|
||||||
|
if (flag_no_road_at_right and this_block[1]!=road_enum.null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (flag_no_road_at_bottom and this_block[2]!=road_enum.null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
append(possible, bcs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!size(possible)) {
|
||||||
|
return " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
func() {
|
||||||
|
if (vecindex(possible, " ")!=nil) {
|
||||||
|
for(var i = 0; i < 64; i+= 1) {
|
||||||
|
append(possible, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
return possible[rand()*size(possible)];
|
||||||
|
}
|
||||||
|
|
||||||
|
var print_whole_line = func(this_line) {
|
||||||
|
var res = "";
|
||||||
|
foreach(var i; this_line) {
|
||||||
|
res ~= i;
|
||||||
|
}
|
||||||
|
println(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
srand();
|
||||||
|
var last_line = [];
|
||||||
|
for(var i = 0; i<100; i+=1) {
|
||||||
|
append(last_line, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var iteration_times = 0; iteration_times < 25; iteration_times += 1) {
|
||||||
|
var this_line = [];
|
||||||
|
var left_block = " ";
|
||||||
|
for(var i = 0; i < 100; i += 1) {
|
||||||
|
var this_block = choice(
|
||||||
|
last_line[i],
|
||||||
|
left_block,
|
||||||
|
i==99,
|
||||||
|
iteration_times==24
|
||||||
|
);
|
||||||
|
left_block = this_block;
|
||||||
|
append(this_line, this_block);
|
||||||
|
}
|
||||||
|
print_whole_line(this_line);
|
||||||
|
last_line = this_line;
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
# wave collapse function 2022/4/10
|
# wave collapse function 2022/4/10
|
||||||
# by ValKmjolnir
|
# by ValKmjolnir
|
||||||
use std.os;
|
use std.runtime;
|
||||||
|
|
||||||
srand();
|
srand();
|
||||||
var table=[
|
var table=[
|
||||||
|
@ -96,8 +96,7 @@ var map = func() {
|
||||||
}();
|
}();
|
||||||
|
|
||||||
# enable unicode
|
# enable unicode
|
||||||
if (os.platform()=="windows")
|
runtime.windows.set_utf8_output();
|
||||||
system("chcp 65001");
|
|
||||||
map.new(90);
|
map.new(90);
|
||||||
|
|
||||||
for(var iter=0;iter<40;iter+=1) {
|
for(var iter=0;iter<40;iter+=1) {
|
||||||
|
|
Loading…
Reference in New Issue