Merge pull request #39 from ValKmjolnir/develop

👍 add regex lib & CI will pack executable in nightly build release
This commit is contained in:
ValK 2024-03-03 23:40:59 +08:00 committed by GitHub
commit 539e4c4964
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
51 changed files with 430 additions and 180 deletions

View File

@ -4,7 +4,7 @@ on:
schedule:
- cron: "0 16 * * *"
push:
branches: [ master,develop ]
branches: [ master, develop ]
pull_request:
branches: [ master ]
workflow_dispatch:
@ -22,6 +22,7 @@ jobs:
cd ..
make test
tar -czf nasal-mac-nightly.tgz .
python3 tools/pack.py
- name: Release file
# You may pin to the exact commit or the version.
# uses: djnicholson/release-action@e9a535b3eced09c460e07a84118fb74ae9b53236
@ -34,7 +35,9 @@ jobs:
# Name of the tag for the release (will be associated with current branch)
automatic_release_tag: next_macOS
# File to release
files: nasal-mac-nightly.tgz
files: |
nasal-mac-nightly.tgz
nasal-Darwin.tar
linux-x86_64-build:
runs-on: ubuntu-latest
@ -48,7 +51,8 @@ jobs:
cd ..
make test
touch nasal-linux-x86_64-nightly.tgz
tar -czf nasal-linux-x86_64-nightly.tgz --exclude=nasal-linux-x86_64-nightly.tgz .
tar -czf nasal-linux-x86_64-nightly.tgz --exclude=nasal-linux-x86_64-nightly.tgz .
python3 tools/pack.py
- name: Release file
# You may pin to the exact commit or the version.
# uses: djnicholson/release-action@e9a535b3eced09c460e07a84118fb74ae9b53236
@ -61,5 +65,7 @@ jobs:
# Name of the tag for the release (will be associated with current branch)
automatic_release_tag: next_linux_x86_64
# File to release
files: nasal-linux-x86_64-nightly.tgz
files: |
nasal-linux-x86_64-nightly.tgz
nasal-Linux.tar

View File

@ -19,15 +19,16 @@ set(NASAL_OBJECT_SOURCE_FILE
${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_builtin.cpp
${CMAKE_SOURCE_DIR}/src/coroutine.cpp
${CMAKE_SOURCE_DIR}/src/fg_props.cpp
${CMAKE_SOURCE_DIR}/src/bits_lib.cpp
${CMAKE_SOURCE_DIR}/src/io_lib.cpp
${CMAKE_SOURCE_DIR}/src/json_lib.cpp
${CMAKE_SOURCE_DIR}/src/math_lib.cpp
${CMAKE_SOURCE_DIR}/src/dylib_lib.cpp
${CMAKE_SOURCE_DIR}/src/unix_lib.cpp
${CMAKE_SOURCE_DIR}/src/natives/nasal_builtin.cpp
${CMAKE_SOURCE_DIR}/src/natives/coroutine.cpp
${CMAKE_SOURCE_DIR}/src/natives/fg_props.cpp
${CMAKE_SOURCE_DIR}/src/natives/bits_lib.cpp
${CMAKE_SOURCE_DIR}/src/natives/io_lib.cpp
${CMAKE_SOURCE_DIR}/src/natives/json_lib.cpp
${CMAKE_SOURCE_DIR}/src/natives/math_lib.cpp
${CMAKE_SOURCE_DIR}/src/natives/dylib_lib.cpp
${CMAKE_SOURCE_DIR}/src/natives/regex_lib.cpp
${CMAKE_SOURCE_DIR}/src/natives/unix_lib.cpp
${CMAKE_SOURCE_DIR}/src/nasal_codegen.cpp
${CMAKE_SOURCE_DIR}/src/nasal_dbg.cpp
${CMAKE_SOURCE_DIR}/src/nasal_err.cpp

View File

@ -6,6 +6,7 @@
![GitHub release(latest by date)](https://img.shields.io/github/v/release/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github)
[![license](https://img.shields.io/badge/license-GPLv2-green?style=flat-square&logo=github)](./LICENSE)
![downloads](https://img.shields.io/github/downloads/ValKmjolnir/Nasal-Interpreter/total.svg?style=flat-square&logo=github)
[![C/C++ CI](https://github.com/ValKmjolnir/Nasal-Interpreter/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/ValKmjolnir/Nasal-Interpreter/actions/workflows/c-cpp.yml)
> This document is also available in: [__中文__](./doc/README_zh.md) | [__English__](./README.md)

View File

@ -6,6 +6,7 @@
![GitHub release(latest by date)](https://img.shields.io/github/v/release/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github)
[![license](https://img.shields.io/badge/license-GPLv2-green?style=flat-square&logo=github)](../LICENSE)
![downloads](https://img.shields.io/github/downloads/ValKmjolnir/Nasal-Interpreter/total.svg?style=flat-square&logo=github)
[![C/C++ CI](https://github.com/ValKmjolnir/Nasal-Interpreter/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/ValKmjolnir/Nasal-Interpreter/actions/workflows/c-cpp.yml)
> 这篇文档包含多语言版本: [__中文__](../doc/README_zh.md) | [__English__](../README.md)

View File

@ -4,16 +4,16 @@ ifndef OS
OS = $(shell uname)
endif
ifeq ($(OS), Darwin)
CXXFLAGS = -std=$(STD) -c -O3 -fno-exceptions -fPIC -mmacosx-version-min=10.15
CXXFLAGS = -std=$(STD) -c -O3 -fPIC -mmacosx-version-min=10.15 -I src
else
CXXFLAGS = -std=$(STD) -c -O3 -fno-exceptions -fPIC
CXXFLAGS = -std=$(STD) -c -O3 -fPIC -I src
endif
NASAL_HEADER = \
src/ast_dumper.h\
src/ast_visitor.h\
src/nasal_ast.h\
src/nasal_builtin.h\
src/natives/nasal_builtin.h\
src/nasal_codegen.h\
src/nasal_dbg.h\
src/nasal_err.h\
@ -27,15 +27,16 @@ NASAL_HEADER = \
src/nasal.h\
src/optimizer.h\
src/symbol_finder.h\
src/fg_props.h\
src/bits_lib.h\
src/io_lib.h\
src/math_lib.h\
src/dylib_lib.h\
src/json_lib.h\
src/unix_lib.h\
src/coroutine.h\
src/repl.h
src/natives/fg_props.h\
src/natives/bits_lib.h\
src/natives/io_lib.h\
src/natives/math_lib.h\
src/natives/dylib_lib.h\
src/natives/json_lib.h\
src/natives/unix_lib.h\
src/natives/coroutine.h\
src/repl.h\
src/natives/regex_lib.h
NASAL_OBJECT = \
build/nasal_err.o\
@ -64,6 +65,7 @@ NASAL_OBJECT = \
build/nasal_vm.o\
build/nasal_dbg.o\
build/repl.o\
build/regex_lib.o\
build/main.o
@ -124,72 +126,79 @@ build/nasal_builtin.o: \
src/nasal.h\
src/nasal_type.h\
src/nasal_gc.h\
src/nasal_builtin.h src/nasal_builtin.cpp | build
$(CXX) $(CXXFLAGS) src/nasal_builtin.cpp -o build/nasal_builtin.o
src/natives/nasal_builtin.h src/natives/nasal_builtin.cpp | build
$(CXX) $(CXXFLAGS) src/natives/nasal_builtin.cpp -o build/nasal_builtin.o
build/coroutine.o: \
src/nasal.h\
src/nasal_type.h\
src/nasal_gc.h\
src/coroutine.h src/coroutine.cpp | build
$(CXX) $(CXXFLAGS) src/coroutine.cpp -o build/coroutine.o
src/natives/coroutine.h src/natives/coroutine.cpp | build
$(CXX) $(CXXFLAGS) src/natives/coroutine.cpp -o build/coroutine.o
build/bits_lib.o: \
src/nasal.h\
src/nasal_type.h\
src/nasal_gc.h\
src/bits_lib.h src/bits_lib.cpp | build
$(CXX) $(CXXFLAGS) src/bits_lib.cpp -o build/bits_lib.o
src/natives/bits_lib.h src/natives/bits_lib.cpp | build
$(CXX) $(CXXFLAGS) src/natives/bits_lib.cpp -o build/bits_lib.o
build/math_lib.o: \
src/nasal.h\
src/nasal_type.h\
src/nasal_gc.h\
src/math_lib.h src/math_lib.cpp | build
$(CXX) $(CXXFLAGS) src/math_lib.cpp -o build/math_lib.o
src/natives/math_lib.h src/natives/math_lib.cpp | build
$(CXX) $(CXXFLAGS) src/natives/math_lib.cpp -o build/math_lib.o
build/io_lib.o: \
src/nasal.h\
src/nasal_type.h\
src/nasal_gc.h\
src/io_lib.h src/io_lib.cpp | build
$(CXX) $(CXXFLAGS) src/io_lib.cpp -o build/io_lib.o
src/natives/io_lib.h src/natives/io_lib.cpp | build
$(CXX) $(CXXFLAGS) src/natives/io_lib.cpp -o build/io_lib.o
build/dylib_lib.o: \
src/nasal.h\
src/nasal_type.h\
src/nasal_gc.h\
src/dylib_lib.h src/dylib_lib.cpp | build
$(CXX) $(CXXFLAGS) src/dylib_lib.cpp -o build/dylib_lib.o
src/natives/dylib_lib.h src/natives/dylib_lib.cpp | build
$(CXX) $(CXXFLAGS) src/natives/dylib_lib.cpp -o build/dylib_lib.o
build/json_lib.o: \
src/nasal.h\
src/nasal_type.h\
src/nasal_gc.h\
src/json_lib.h src/json_lib.cpp | build
$(CXX) $(CXXFLAGS) src/json_lib.cpp -o build/json_lib.o
src/natives/json_lib.h src/natives/json_lib.cpp | build
$(CXX) $(CXXFLAGS) src/natives/json_lib.cpp -o build/json_lib.o
build/unix_lib.o: \
src/nasal.h\
src/nasal_type.h\
src/nasal_gc.h\
src/unix_lib.h src/unix_lib.cpp | build
$(CXX) $(CXXFLAGS) src/unix_lib.cpp -o build/unix_lib.o
src/natives/unix_lib.h src/natives/unix_lib.cpp | build
$(CXX) $(CXXFLAGS) src/natives/unix_lib.cpp -o build/unix_lib.o
build/regex_lib.o: \
src/nasal.h\
src/nasal_type.h\
src/nasal_gc.h\
src/natives/regex_lib.h src/natives/regex_lib.cpp | build
$(CXX) $(CXXFLAGS) src/natives/regex_lib.cpp -o build/regex_lib.o
build/fg_props.o: \
src/nasal.h\
src/nasal_type.h\
src/nasal_gc.h\
src/fg_props.h src/fg_props.cpp | build
$(CXX) $(CXXFLAGS) src/fg_props.cpp -o build/fg_props.o
src/natives/fg_props.h src/natives/fg_props.cpp | build
$(CXX) $(CXXFLAGS) src/natives/fg_props.cpp -o build/fg_props.o
build/nasal_codegen.o: $(NASAL_HEADER) src/nasal_codegen.h src/nasal_codegen.cpp | build
$(CXX) $(CXXFLAGS) src/nasal_codegen.cpp -o build/nasal_codegen.o
build/nasal_opcode.o: \
src/nasal.h\
src/nasal_builtin.h\
src/natives/nasal_builtin.h\
src/nasal_opcode.h src/nasal_opcode.cpp | build
$(CXX) $(CXXFLAGS) src/nasal_opcode.cpp -o build/nasal_opcode.o
@ -279,6 +288,7 @@ test:nasal
@ ./nasal -t -d test/prime.nas
@ ./nasal -e test/qrcode.nas
@ ./nasal -t -d test/quick_sort.nas
@ ./nasal -t -d test/regex_test.nas
@ ./nasal -e test/scalar.nas hello world
@ ./nasal -e test/trait.nas
@ ./nasal -t -d test/turingmachine.nas

View File

@ -11,6 +11,7 @@
#endif
#ifdef _WIN32
// load socket library on windows platform
#include <winsock.h>
#pragma comment(lib,"ws2_32")
@ -25,8 +26,9 @@ public:
WSACleanup();
}
};
// use static object to do WSAStartup and WSACleanup
static WSAmanager win;
#else
#include <netdb.h>
#include <sys/socket.h>

View File

@ -19,18 +19,18 @@
#include <thread>
#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;
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) {
out

View File

@ -68,7 +68,7 @@ public:
const char* c_str() const {
return file_system_path.c_str();
}
std::string str() const {
const std::string& str() const {
return file_system_path;
}
};

View File

@ -8,7 +8,7 @@
namespace nasal {
enum class expr_type:u32 {
enum class expr_type: u32 {
ast_null = 0, // null node
ast_use, // use statement
ast_block, // code block

View File

@ -37,6 +37,7 @@ void codegen::init_native_function() {
load_native_function_table(dylib_lib_native);
load_native_function_table(unix_lib_native);
load_native_function_table(json_lib_native);
load_native_function_table(regex_lib_native);
}
void codegen::check_id_exist(identifier* node) {

View File

@ -8,15 +8,16 @@
#include "nasal_parse.h"
#include "nasal_import.h"
#include "nasal_builtin.h"
#include "coroutine.h"
#include "bits_lib.h"
#include "math_lib.h"
#include "fg_props.h"
#include "io_lib.h"
#include "json_lib.h"
#include "dylib_lib.h"
#include "unix_lib.h"
#include "natives/nasal_builtin.h"
#include "natives/coroutine.h"
#include "natives/bits_lib.h"
#include "natives/math_lib.h"
#include "natives/fg_props.h"
#include "natives/io_lib.h"
#include "natives/json_lib.h"
#include "natives/dylib_lib.h"
#include "natives/regex_lib.h"
#include "natives/unix_lib.h"
#include <iomanip>
#include <list>
@ -36,9 +37,11 @@ private:
error err;
// repl output flag, will generate op_repl to output stack top value if true
bool need_repl_output;
bool need_repl_output = false;
// limit mode flag
bool flag_limited_mode;
bool flag_limited_mode = false;
// under limited mode, unsafe system api will be banned
const std::unordered_set<std::string> unsafe_system_api = {
// builtin
"__system", "__input",

View File

@ -2,13 +2,13 @@
namespace nasal {
void debug_prof_data::init_counter() {
for(usize i = 0; i<debug_prof_data::operand_size; ++i) {
void operand_line_counter::init_counter() {
for(usize i = 0; i<operand_line_counter::operand_size; ++i) {
operand_counter[i] = 0;
}
}
void debug_prof_data::load_file_line_counter(
void operand_line_counter::load_file_line_counter(
const std::vector<std::string>& file_list) {
file_name_list = file_list;
file_line_counter = {};
@ -22,16 +22,16 @@ void debug_prof_data::load_file_line_counter(
}
}
void debug_prof_data::init(const std::vector<std::string>& file_list) {
void operand_line_counter::init(const std::vector<std::string>& file_list) {
init_counter();
load_file_line_counter(file_list);
}
void debug_prof_data::dump_counter() const {
void operand_line_counter::dump_operand_count() const {
typedef std::pair<u32, u64> op_count;
std::vector<op_count> opcall;
u64 total = 0;
for(usize i = 0; i<debug_prof_data::operand_size; ++i) {
for(usize i = 0; i<operand_line_counter::operand_size; ++i) {
total += operand_counter[i];
opcall.push_back({i, operand_counter[i]});
}
@ -52,7 +52,7 @@ void debug_prof_data::dump_counter() const {
std::clog << " total : " << total << '\n';
}
void debug_prof_data::dump_code_line_counter(std::ostream& os) const {
void operand_line_counter::dump_all_code_line_counter(std::ostream& os) const {
u64 max_call_time = 0;
for(const auto& context : file_line_counter) {
for(const auto& count : context) {
@ -73,7 +73,7 @@ void debug_prof_data::dump_code_line_counter(std::ostream& os) const {
}
}
void debug_prof_data::dump_this_file_line_counter(std::ostream& os) const {
void operand_line_counter::dump_this_file_line_counter(std::ostream& os) const {
u64 max_call_time = 0;
for(const auto& count : file_line_counter[0]) {
max_call_time = count>max_call_time? count:max_call_time;
@ -178,7 +178,7 @@ void dbg::interact() {
}
// do not need interact while doing profiling
if (do_profiling) {
if (do_operand_count) {
return;
}
@ -199,24 +199,24 @@ void dbg::interact() {
step_info();
} else if (res.size()==1) {
switch(get_cmd_type(res[0])) {
case dbg_cmd::cmd_help: help(); break;
case dbg_cmd::cmd_backtrace:
case cmd_kind::cmd_help: help(); break;
case cmd_kind::cmd_backtrace:
function_call_trace();
trace_back();
break;
case dbg_cmd::cmd_continue: return;
case dbg_cmd::cmd_list_file: list_file(); break;
case dbg_cmd::cmd_global: global_state(); break;
case dbg_cmd::cmd_local: local_state(); break;
case dbg_cmd::cmd_upval: upvalue_state(); break;
case dbg_cmd::cmd_register: register_info(); break;
case dbg_cmd::cmd_show_all: all_state_detail(); break;
case dbg_cmd::cmd_next: next = true; return;
case dbg_cmd::cmd_exit: std::exit(0);
case cmd_kind::cmd_continue: return;
case cmd_kind::cmd_list_file: list_file(); break;
case cmd_kind::cmd_global: global_state(); break;
case cmd_kind::cmd_local: local_state(); break;
case cmd_kind::cmd_upval: upvalue_state(); break;
case cmd_kind::cmd_register: register_info(); break;
case cmd_kind::cmd_show_all: all_state_detail(); break;
case cmd_kind::cmd_next: next = true; return;
case cmd_kind::cmd_exit: std::exit(0);
default: err(); break;
}
} else if (res.size()==3 &&
get_cmd_type(res[0])==dbg_cmd::cmd_break_point) {
get_cmd_type(res[0])==cmd_kind::cmd_break_point) {
break_file_index = file_index(res[1]);
if (break_file_index==65535) {
std::clog << "cannot find file named `" << res[1] << "`\n";
@ -242,7 +242,7 @@ void dbg::run(
bool show_all_prof_result) {
set_detail_report_info(true);
do_profiling = profile || show_all_prof_result;
do_operand_count = profile || show_all_prof_result;
const auto& file_list = linker.get_file_list();
fsize = file_list.size();
@ -255,7 +255,7 @@ void dbg::run(
file_list,
argv
);
data.init(file_list);
counter.init(file_list);
std::vector<u32> code;
std::vector<u16> code_file_index;
@ -268,8 +268,8 @@ void dbg::run(
}
while(operand_function[code[ctx.pc]]) {
interact();
data.add_operand_counter(code[ctx.pc]);
data.add_code_line_counter(code_file_index[ctx.pc], code_line[ctx.pc]);
counter.add_operand_counter(code[ctx.pc]);
counter.add_code_line_counter(code_file_index[ctx.pc], code_line[ctx.pc]);
(this->*operand_function[code[ctx.pc]])();
if (ctx.top>=ctx.canary) {
die("stack overflow");
@ -277,11 +277,11 @@ void dbg::run(
++ctx.pc;
}
data.dump_counter();
if (do_profiling) {
counter.dump_operand_count();
if (do_operand_count) {
show_all_prof_result?
data.dump_code_line_counter(std::clog):
data.dump_this_file_line_counter(std::clog);
counter.dump_all_code_line_counter(std::clog):
counter.dump_this_file_line_counter(std::clog);
}
ngc.info();
ngc.clear();

View File

@ -11,7 +11,9 @@
namespace nasal {
class debug_prof_data {
// count detail operand calling
// and show them before each line of the source file
class operand_line_counter {
private:
static const usize operand_size = op_code_type::op_ret + 1;
u64 operand_counter[operand_size];
@ -25,8 +27,8 @@ private:
public:
void init(const std::vector<std::string>&);
void dump_counter() const;
void dump_code_line_counter(std::ostream&) const;
void dump_operand_count() const;
void dump_all_code_line_counter(std::ostream&) const;
void dump_this_file_line_counter(std::ostream&) const;
void add_operand_counter(usize index) {
operand_counter[index] += index<operand_size? 1:0;
@ -88,7 +90,7 @@ private:
};
private:
enum class dbg_cmd {
enum class cmd_kind {
cmd_error,
cmd_help,
cmd_backtrace,
@ -105,35 +107,35 @@ private:
};
private:
const std::unordered_map<std::string, dbg_cmd> command_table = {
{"h", dbg_cmd::cmd_help},
{"help", dbg_cmd::cmd_help},
{"bt", dbg_cmd::cmd_backtrace},
{"backtrace", dbg_cmd::cmd_backtrace},
{"c", dbg_cmd::cmd_continue},
{"continue", dbg_cmd::cmd_continue},
{"f", dbg_cmd::cmd_list_file},
{"file", dbg_cmd::cmd_list_file},
{"g", dbg_cmd::cmd_global},
{"global", dbg_cmd::cmd_global},
{"l", dbg_cmd::cmd_local},
{"local", dbg_cmd::cmd_local},
{"u", dbg_cmd::cmd_upval},
{"upval", dbg_cmd::cmd_upval},
{"r", dbg_cmd::cmd_register},
{"register", dbg_cmd::cmd_register},
{"a", dbg_cmd::cmd_show_all},
{"all", dbg_cmd::cmd_show_all},
{"n", dbg_cmd::cmd_next},
{"next", dbg_cmd::cmd_next},
{"bk", dbg_cmd::cmd_break_point},
{"break", dbg_cmd::cmd_break_point},
{"q", dbg_cmd::cmd_exit},
{"exit", dbg_cmd::cmd_exit}
const std::unordered_map<std::string, cmd_kind> command_table = {
{"h", cmd_kind::cmd_help},
{"help", cmd_kind::cmd_help},
{"bt", cmd_kind::cmd_backtrace},
{"backtrace", cmd_kind::cmd_backtrace},
{"c", cmd_kind::cmd_continue},
{"continue", cmd_kind::cmd_continue},
{"f", cmd_kind::cmd_list_file},
{"file", cmd_kind::cmd_list_file},
{"g", cmd_kind::cmd_global},
{"global", cmd_kind::cmd_global},
{"l", cmd_kind::cmd_local},
{"local", cmd_kind::cmd_local},
{"u", cmd_kind::cmd_upval},
{"upval", cmd_kind::cmd_upval},
{"r", cmd_kind::cmd_register},
{"register", cmd_kind::cmd_register},
{"a", cmd_kind::cmd_show_all},
{"all", cmd_kind::cmd_show_all},
{"n", cmd_kind::cmd_next},
{"next", cmd_kind::cmd_next},
{"bk", cmd_kind::cmd_break_point},
{"break", cmd_kind::cmd_break_point},
{"q", cmd_kind::cmd_exit},
{"exit", cmd_kind::cmd_exit}
};
dbg_cmd get_cmd_type(const std::string& cmd) const {
cmd_kind get_cmd_type(const std::string& cmd) const {
return command_table.count(cmd)?
command_table.at(cmd):dbg_cmd::cmd_error;
command_table.at(cmd):cmd_kind::cmd_error;
}
private:
@ -144,8 +146,8 @@ private:
error src;
private:
debug_prof_data data;
bool do_profiling;
operand_line_counter counter;
bool do_operand_count;
private:
std::vector<std::string> parse(const std::string&);
@ -160,7 +162,7 @@ public:
dbg():
next(true), fsize(0),
break_file_index(0), break_line(0),
do_profiling(false) {}
do_operand_count(false) {}
void run(
const codegen&,
const linker&,

View File

@ -1,13 +1,13 @@
#pragma once
#include "nasal.h"
#include "nasal_builtin.h"
#include "natives/nasal_builtin.h"
#include <iostream>
namespace nasal {
enum op_code_type:u8 {
enum op_code_type: u8 {
op_exit, // stop the virtual machine
op_repl, // in repl mode: print value on stack top
op_intl, // local scope size

View File

@ -58,7 +58,7 @@ void parse::easter_egg() {
<< " `\"` `\"` \n";
}
void parse::die(const span& loc, std::string info) {
void parse::die(const span& loc, const std::string& info) {
err.err("parse", loc, info);
}

View File

@ -79,9 +79,9 @@ private:
};
private:
void die(const span&,std::string);
void die(const span&, const std::string&);
void next();
void match(tok, const char* info=nullptr);
void match(tok, const char* info = nullptr);
bool lookahead(tok);
bool is_call(tok);
bool check_comma(const tok*);

View File

@ -249,7 +249,7 @@ std::string var::to_str() {
if (type==vm_type::vm_str) {
return str();
} else if (type==vm_type::vm_num) {
std::string tmp = std::to_string(num());
auto tmp = std::to_string(num());
tmp.erase(tmp.find_last_not_of('0')+1, std::string::npos);
tmp.erase(tmp.find_last_not_of('.')+1, std::string::npos);
return tmp;

View File

@ -414,10 +414,16 @@ void vm::die(const std::string& str) {
void vm::run(
const codegen& gen,
const linker& linker,
const std::vector<std::string>& argv
) {
init(gen.strs(), gen.nums(), gen.natives(),
gen.codes(), gen.globals(), linker.get_file_list(), argv);
const std::vector<std::string>& argv) {
init(
gen.strs(),
gen.nums(),
gen.natives(),
gen.codes(),
gen.globals(),
linker.get_file_list(),
argv
);
#ifndef _MSC_VER
// using labels as values/computed goto
const void* oprs[] = {

View File

@ -21,7 +21,7 @@ class vm {
protected:
/* registers of vm */
context ctx;
context ctx; // running context
/* constants */
const f64* const_number = nullptr; // constant numbers
@ -33,8 +33,8 @@ protected:
gc ngc;
/* main stack */
var* global = nullptr;
usize global_size = 0;
var* global = nullptr; // used to store global variables
usize global_size = 0; // mark size of global variables
/* values used for debugger */
const std::string* files = nullptr; // file name list
@ -45,7 +45,7 @@ protected:
bool first_exec_flag = true;
bool allow_repl_output = false;
/* limited mode, will not load unsafe system api if switch on */
/* limited mode, will not load unsafe system api if switched on */
bool flag_limited_mode = false;
/* vm initializing function */
@ -184,9 +184,9 @@ public:
/* execution entry */
void run(
const codegen&,
const linker&,
const std::vector<std::string>&
const codegen&, // get generated code
const linker&, // get list of used files
const std::vector<std::string>& // get arguments input by command line
);
/* set detail report info flag */

View File

@ -1,4 +1,4 @@
#include "bits_lib.h"
#include "natives/bits_lib.h"
namespace nasal {

View File

@ -2,7 +2,7 @@
#include "nasal.h"
#include "nasal_gc.h"
#include "nasal_builtin.h"
#include "natives/nasal_builtin.h"
namespace nasal {

View File

@ -1,4 +1,4 @@
#include "coroutine.h"
#include "natives/coroutine.h"
namespace nasal {

View File

@ -2,7 +2,7 @@
#include "nasal.h"
#include "nasal_gc.h"
#include "nasal_builtin.h"
#include "natives/nasal_builtin.h"
namespace nasal {

View File

@ -1,4 +1,4 @@
#include "dylib_lib.h"
#include "natives/dylib_lib.h"
namespace nasal {

View File

@ -2,7 +2,7 @@
#include "nasal.h"
#include "nasal_gc.h"
#include "nasal_builtin.h"
#include "natives/nasal_builtin.h"
#ifdef _WIN32
#include <windows.h>

View File

@ -1,4 +1,4 @@
#include "fg_props.h"
#include "natives/fg_props.h"
#include <fstream>

View File

@ -2,7 +2,7 @@
#include "nasal.h"
#include "nasal_gc.h"
#include "nasal_builtin.h"
#include "natives/nasal_builtin.h"
namespace nasal {

View File

@ -1,4 +1,4 @@
#include "io_lib.h"
#include "natives/io_lib.h"
#include <sys/stat.h>

View File

@ -2,7 +2,7 @@
#include "nasal.h"
#include "nasal_gc.h"
#include "nasal_builtin.h"
#include "natives/nasal_builtin.h"
#ifndef _MSC_VER
#include <unistd.h>

View File

@ -1,4 +1,4 @@
#include "json_lib.h"
#include "natives/json_lib.h"
#include <iostream>
#include <cstring>

View File

@ -2,7 +2,7 @@
#include "nasal.h"
#include "nasal_gc.h"
#include "nasal_builtin.h"
#include "natives/nasal_builtin.h"
namespace nasal {

View File

@ -1,4 +1,4 @@
#include "math_lib.h"
#include "natives/math_lib.h"
namespace nasal {

View File

@ -2,7 +2,7 @@
#include "nasal.h"
#include "nasal_gc.h"
#include "nasal_builtin.h"
#include "natives/nasal_builtin.h"
namespace nasal {

View File

@ -1,4 +1,4 @@
#include "nasal_builtin.h"
#include "natives/nasal_builtin.h"
#include <chrono>
namespace nasal {

99
src/natives/regex_lib.cpp Normal file
View File

@ -0,0 +1,99 @@
#include "natives/regex_lib.h"
namespace nasal {
var builtin_regex_match(context* ctx, gc* ngc) {
auto source = ctx->localr[1];
auto reg_str = ctx->localr[2];
if (!source.is_str()) {
return nas_err("regex::match", "\"src\" must be a string");
}
if (!reg_str.is_str()) {
return nas_err("regex::match", "\"reg\" must be a format string");
}
try {
auto res = std::regex_match(source.str(), std::regex(reg_str.str()));
return res? one:zero;
} catch(const std::regex_error& e) {
return nas_err("regex::match", e.what());
}
return zero;
}
var builtin_regex_search(context* ctx, gc* ngc) {
auto source = ctx->localr[1];
auto reg_str = ctx->localr[2];
if (!source.is_str()) {
return nas_err("regex::search", "\"src\" must be a string");
}
if (!reg_str.is_str()) {
return nas_err("regex::search", "\"reg\" must be a format string");
}
try {
auto res = std::regex_search(source.str(), std::regex(reg_str.str()));
return res? one:zero;
} catch(const std::regex_error& e) {
return nas_err("regex::search", e.what());
}
return nil;
}
var builtin_regex_replace(context* ctx, gc* ngc) {
auto source = ctx->localr[1];
auto reg_str = ctx->localr[2];
auto fmt = ctx->localr[3];
if (!source.is_str()) {
return nas_err("regex::replace", "\"src\" must be a string");
}
if (!reg_str.is_str()) {
return nas_err("regex::replace", "\"reg\" must be a format string");
}
if (!fmt.is_str()) {
return nas_err("regex::replace", "\"fmt\" must be a format string");
}
try {
auto res = std::regex_replace(
source.str(),
std::regex(reg_str.str()),
fmt.str()
);
return ngc->newstr(res);
} catch(const std::regex_error& e) {
return nas_err("regex::replace", e.what());
}
return ngc->newstr(source.str());
}
var builtin_regex_match_all(context* ctx, gc* ngc) {
auto source = ctx->localr[1];
auto reg_str = ctx->localr[2];
if (!source.is_str()) {
return nas_err("regex::match_all", "\"src\" must be a string");
}
if (!reg_str.is_str()) {
return nas_err("regex::match_all", "\"reg\" must be a format string");
}
auto res = ngc->temp = ngc->alloc(vm_type::vm_vec);
try {
const auto& src = source.str();
auto words_regex = std::regex(reg_str.str());
auto begin = std::sregex_iterator(src.begin(), src.end(), words_regex);
auto end = std::sregex_iterator();
for (auto i = begin; i!=end; ++i) {
res.vec().elems.push_back(ngc->newstr((*i).str()));
}
} catch(const std::regex_error& e) {
return nas_err("regex::match_all", e.what());
}
return res;
}
nasal_builtin_table regex_lib_native[] = {
{"__regex_match", builtin_regex_match},
{"__regex_search", builtin_regex_search},
{"__regex_replace", builtin_regex_replace},
{"__regex_match_all", builtin_regex_match_all},
{nullptr, nullptr}
};
}

18
src/natives/regex_lib.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include <regex>
#include "nasal.h"
#include "nasal_gc.h"
#include "natives/nasal_builtin.h"
namespace nasal {
var builtin_regex_match(context*, gc*);
var builtin_regex_search(context*, gc*);
var builtin_regex_replace(context*, gc*);
var builtin_regex_match_all(context*, gc*);
extern nasal_builtin_table regex_lib_native[];
}

View File

@ -1,4 +1,4 @@
#include "unix_lib.h"
#include "natives/unix_lib.h"
namespace nasal {

View File

@ -2,7 +2,7 @@
#include "nasal.h"
#include "nasal_gc.h"
#include "nasal_builtin.h"
#include "natives/nasal_builtin.h"
#ifndef _MSC_VER
#include <unistd.h>

View File

@ -7,6 +7,7 @@
namespace nasal {
// experimental optimizer for constant calculation
class optimizer: public ast_visitor {
private:
void const_string(binary_operator*, string_literal*, string_literal*);

View File

@ -19,10 +19,10 @@ void repl::add_command_history(const std::string& history) {
}
}
std::string repl::readline(std::string prompt = ">>> ") {
std::string repl::readline(const std::string& prompt = ">>> ") {
auto line = std::string("");
std::cout << prompt;
std::getline(std::cin, line,'\n');
std::getline(std::cin, line, '\n');
return line;
}

View File

@ -33,7 +33,7 @@ private:
private:
void add_command_history(const std::string&);
std::string readline(std::string);
std::string readline(const std::string&);
bool check_need_more_input();
void update_temp_file();
void help();

View File

@ -4,11 +4,15 @@ namespace nasal {
bool symbol_finder::visit_definition_expr(definition_expr* node) {
if (node->get_variable_name()) {
// single variable definition
// example: var a = 1;
symbols.push_back({
node->get_variable_name()->get_name(),
node->get_variable_name()->get_location()
});
} else {
// multiple variable definition
// example: var (a, b, c) = (0, 1, 2);
for(auto i : node->get_variables()->get_variables()) {
symbols.push_back({
i->get_name(),
@ -25,6 +29,7 @@ bool symbol_finder::visit_definition_expr(definition_expr* node) {
}
bool symbol_finder::visit_function(function* node) {
// do not scan variables defined in function inside this code block
return true;
}

View File

@ -3,7 +3,7 @@
# and use this script to get property tree
# 2023/11/06 ValKmjolnir
use module.libsock;
use module.libnasock;
use std.json;
use std.os;
use std.unix;
@ -30,7 +30,7 @@ var _get_time = func() {
}
var _connect = func(hostname, port) {
var socket = libsock.socket;
var socket = libnasock.socket;
var sd = socket.socket(
socket.AF_INET,
socket.SOCK_STREAM,
@ -46,7 +46,7 @@ var _connect = func(hostname, port) {
}
var new = func(hostname, port) {
var socket = libsock.socket;
var socket = libnasock.socket;
var sd = _connect(hostname, port);
var getprop = func(path) {

18
std/regex.nas Normal file
View File

@ -0,0 +1,18 @@
# regex.nas
# 2024/3/1 by ValKmjolnir
var match = func(src, reg) {
return __regex_match(src, reg);
}
var search = func(src, reg) {
return __regex_search(src, reg);
}
var replace = func(src, reg, fmt) {
return __regex_replace(src, reg, fmt);
}
var match_all = func(src, reg) {
return __regex_match_all(src, reg);
}

View File

@ -1,9 +1,9 @@
use module.libsock;
use module.libnasock;
use std.os;
use std.unix;
var udp_server = func(hostname, port, retry_delay = 5) {
var socket = libsock.socket;
var socket = libnasock.socket;
var server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM);
while(socket.bind(server, hostname, port) < 0) {
println("[", os.time(), "] failed to bind socket "~server~" at ", hostname, ":", port, ".");
@ -26,7 +26,7 @@ var udp_server = func(hostname, port, retry_delay = 5) {
}
var udp_client = func(hostname = "", port = -1, retry_delay = 5) {
var socket = libsock.socket;
var socket = libnasock.socket;
var client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM);
if (port > 0 and size(hostname) != 0) {
while(socket.bind(client, hostname, port)<0) {

View File

@ -1,9 +1,9 @@
use module.libsock;
use module.libnasock;
use std.os;
use std.io;
use std.unix;
var socket = libsock.socket;
var socket = libnasock.socket;
var http = func() {
var sd=nil;

View File

@ -1,10 +1,10 @@
use module.libsock;
use module.libnasock;
use std.json;
use std.runtime;
use std.os;
use std.unix;
var socket = libsock.socket;
var socket = libnasock.socket;
var gettime = func() {
return split(" ",os.time())[1];

10
test/regex_test.nas Normal file
View File

@ -0,0 +1,10 @@
use std.regex;
println(regex.match("aaa", "[a]*"));
println(regex.search("aabcaa", "abc"));
var s = "aaaaa";
println(regex.replace(s, "a", "[$&]"));
println(s);
println(regex.match_all("a,b,c,d,e,f,g,h,i", "[a-z]"));

66
tools/pack.py Normal file
View File

@ -0,0 +1,66 @@
import tarfile
import pathlib
import os
import platform
import shutil
nasal_version = "11.1"
build_directory = pathlib.Path("build")
if not os.path.exists(build_directory):
print("pack binaries failed: build directory not found")
exit(-1)
nasal_executable = pathlib.Path("nasal")
nasal_standard_library = pathlib.Path("std")
if not os.path.exists(nasal_executable):
print("pack binaries failed: nasal executable not found")
exit(-1)
if not os.path.exists(nasal_standard_library):
print("pack binaries failed: nasal standard library not found")
exit(-1)
nasal_module_directory = pathlib.Path("module")
if not os.path.exists(nasal_module_directory):
print("pack binaries failed: nasal module directory not found")
exit(-1)
dynamic_library_suffix = ""
if platform.system()=="Windows":
dynamic_library_suffix = ".dll"
else:
dynamic_library_suffix = ".so"
nasal_modules = []
for m in ["libfib", "libkey", "libmat", "libnasock"]:
path = pathlib.Path("module").joinpath(m + dynamic_library_suffix)
if not os.path.exists(path):
print("pack binaries failed: nasal module `{}` not found".format(m))
exit(-1)
lib = pathlib.Path("module").joinpath(m + ".nas")
if not os.path.exists(lib):
print("pack binaries failed: nasal module lib `{}.nas` not found".format(m))
exit(-1)
nasal_modules.append(path)
nasal_modules.append(lib)
tar_file_name = "nasal-{}".format(platform.system())
# create package directory in build directory and copy files needed
package_directory = build_directory.joinpath(tar_file_name)
if not os.path.exists(package_directory):
os.mkdir(package_directory)
os.mkdir(package_directory.joinpath("module"))
print("pack nasal executable")
shutil.copy(nasal_executable, package_directory.joinpath(nasal_executable))
print("pack nasal standard library")
shutil.copytree(nasal_standard_library, package_directory.joinpath(nasal_standard_library))
for m in nasal_modules:
print("pack nasal module:", m)
shutil.copy(m, package_directory.joinpath(m))
file = tarfile.open(name=tar_file_name + ".tar", mode="w")
file.add(package_directory)
print("pack succeeded")
file.close()