Merge pull request #58 from ValKmjolnir/develop
🎨 format & adjust cmake for windows build
This commit is contained in:
commit
4062c40bb3
|
@ -2,7 +2,8 @@
|
||||||
build/
|
build/
|
||||||
out/
|
out/
|
||||||
dist/
|
dist/
|
||||||
cmake-build-*/
|
cmake-build-*
|
||||||
|
cmake-windows-*
|
||||||
|
|
||||||
# IDE and editor files
|
# IDE and editor files
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
|
@ -11,7 +11,7 @@ set(CMAKE_CXX_FLAGS_RELEASE_INIT "-Wshadow -Wall")
|
||||||
|
|
||||||
add_compile_options(-fPIC)
|
add_compile_options(-fPIC)
|
||||||
# MSVC needs this command option to really enable utf-8 output
|
# MSVC needs this command option to really enable utf-8 output
|
||||||
if(MSVC)
|
if (MSVC)
|
||||||
add_compile_options(/utf-8)
|
add_compile_options(/utf-8)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -103,16 +103,21 @@ target_link_libraries(mat module-used-object)
|
||||||
|
|
||||||
add_library(nasock SHARED ${CMAKE_SOURCE_DIR}/module/nasocket.cpp)
|
add_library(nasock SHARED ${CMAKE_SOURCE_DIR}/module/nasocket.cpp)
|
||||||
target_include_directories(nasock PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
target_include_directories(nasock PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||||
|
if (WIN32)
|
||||||
|
target_link_libraries(nasock ws2_32)
|
||||||
|
endif()
|
||||||
target_link_libraries(nasock module-used-object)
|
target_link_libraries(nasock module-used-object)
|
||||||
|
|
||||||
# Add web library
|
# Add web library, not for MSVC now
|
||||||
add_library(nasal-web SHARED
|
if (NOT MSVC)
|
||||||
src/nasal_web.cpp
|
add_library(nasal-web SHARED
|
||||||
${NASAL_OBJECT_SOURCE_FILE}
|
src/nasal_web.cpp
|
||||||
)
|
${NASAL_OBJECT_SOURCE_FILE}
|
||||||
target_include_directories(nasal-web PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
)
|
||||||
set_target_properties(nasal-web PROPERTIES
|
target_include_directories(nasal-web PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||||
C_VISIBILITY_PRESET hidden
|
set_target_properties(nasal-web PROPERTIES
|
||||||
CXX_VISIBILITY_PRESET hidden
|
C_VISIBILITY_PRESET hidden
|
||||||
VISIBILITY_INLINES_HIDDEN ON
|
CXX_VISIBILITY_PRESET hidden
|
||||||
)
|
VISIBILITY_INLINES_HIDDEN ON
|
||||||
|
)
|
||||||
|
endif()
|
|
@ -88,7 +88,7 @@ Make sure thread model is `posix thread model`, otherwise no thread library exis
|
||||||
|
|
||||||
### __Windows (Visual Studio)__
|
### __Windows (Visual Studio)__
|
||||||
|
|
||||||
There is a [__CMakelists.txt__](./CMakeLists.txt) to create project.
|
There is a [__CMakelists.txt__](./CMakeLists.txt) to create project. Recently we find how to build it with command line tools: [__Build Nasal-Interpreter on Windows]__(./doc/windows-build.md).
|
||||||
|
|
||||||
### __Linux / macOS / Unix__
|
### __Linux / macOS / Unix__
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,7 @@ Windows 平台的预览版解释器现在还没配置相关流水线,
|
||||||
### __Windows 平台 (Vistual Studio)__
|
### __Windows 平台 (Vistual Studio)__
|
||||||
|
|
||||||
项目提供了 [__CMakeLists.txt__](../CMakeLists.txt) 用于在`Visual Studio`中创建项目。
|
项目提供了 [__CMakeLists.txt__](../CMakeLists.txt) 用于在`Visual Studio`中创建项目。
|
||||||
|
最近我们总结了命令行编译的方法 [__如何在 Windows 平台编译 Nasal-Interpreter__](./windows-build.md)。
|
||||||
|
|
||||||
### __Linux / macOS / Unix 平台__
|
### __Linux / macOS / Unix 平台__
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Build Nasal-Interpreter on Windows
|
||||||
|
|
||||||
|
## MSVC / Visual Studio
|
||||||
|
|
||||||
|
Need CMake and Visual Studio 2022. Remember to add MSBuild.exe to Path.
|
||||||
|
|
||||||
|
Valid on powershell:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mkdir cmake-windows-msvc
|
||||||
|
cd cmake-windows-msvc
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 17 2022"
|
||||||
|
MSbuild.exe nasal.sln /p:Configuration=Release /p:Platform=x64
|
||||||
|
```
|
||||||
|
|
||||||
|
## MingW-W64
|
||||||
|
|
||||||
|
Need CMake and MingW-W64. Remember to add MingW-W64 bin to Path.
|
||||||
|
|
||||||
|
Valid on powershell:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mkdir cmake-windows-mingw
|
||||||
|
cd cmake-windows-mingw
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=Release -G "MinGW Makefiles" -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++
|
||||||
|
mingw32-make.exe -j6
|
||||||
|
```
|
|
@ -317,41 +317,4 @@ std::ostream& operator<<(std::ostream& out, var& ref) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool var::object_check(const std::string& name) const {
|
|
||||||
return is_ghost() && ghost().type_name == name && ghost().pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
var var::none() {
|
|
||||||
return {vm_type::vm_none, static_cast<u64>(0)};
|
|
||||||
}
|
|
||||||
|
|
||||||
var var::nil() {
|
|
||||||
return {vm_type::vm_nil, static_cast<u64>(0)};
|
|
||||||
}
|
|
||||||
|
|
||||||
var var::ret(u64 pc) {
|
|
||||||
return {vm_type::vm_ret, pc};
|
|
||||||
}
|
|
||||||
|
|
||||||
var var::cnt(i64 n) {
|
|
||||||
return {vm_type::vm_cnt, n};
|
|
||||||
}
|
|
||||||
|
|
||||||
var var::num(f64 n) {
|
|
||||||
return {vm_type::vm_num, n};
|
|
||||||
}
|
|
||||||
|
|
||||||
var var::gcobj(nas_val* p) {
|
|
||||||
return {p->type, p};
|
|
||||||
}
|
|
||||||
|
|
||||||
var var::addr(var* p) {
|
|
||||||
return {vm_type::vm_addr, p};
|
|
||||||
}
|
|
||||||
|
|
||||||
var nas_err(const std::string& error_function_name, const std::string& info) {
|
|
||||||
std::cerr << "[vm] " << error_function_name << ": " << info << "\n";
|
|
||||||
return var::none();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -86,31 +86,45 @@ public:
|
||||||
} val;
|
} val;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
var(vm_type t, u64 pc) {type = t; val.ret = pc;}
|
var(vm_type t, u64 pc) { type = t; val.ret = pc; }
|
||||||
var(vm_type t, i64 ct) {type = t; val.cnt = ct;}
|
var(vm_type t, i64 ct) { type = t; val.cnt = ct; }
|
||||||
var(vm_type t, f64 n) {type = t; val.num = n;}
|
var(vm_type t, f64 n) { type = t; val.num = n; }
|
||||||
var(vm_type t, var* p) {type = t; val.addr = p;}
|
var(vm_type t, var* p) { type = t; val.addr = p; }
|
||||||
var(vm_type t, nas_val* p) {type = t; val.gcobj = p;}
|
var(vm_type t, nas_val* p) { type = t; val.gcobj = p; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
var() = default;
|
var() = default;
|
||||||
var(const var&) = default;
|
var(const var&) = default;
|
||||||
bool operator==(const var& nr) const {
|
bool operator==(const var& nr) const {
|
||||||
return type==nr.type && val.gcobj==nr.val.gcobj;
|
return type == nr.type && val.gcobj == nr.val.gcobj;
|
||||||
}
|
}
|
||||||
bool operator!=(const var& nr) const {
|
bool operator!=(const var& nr) const {
|
||||||
return type!=nr.type || val.gcobj!=nr.val.gcobj;
|
return type != nr.type || val.gcobj != nr.val.gcobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// create new var object
|
// create new var object
|
||||||
static var none();
|
static var none() {
|
||||||
static var nil();
|
return var(vm_type::vm_none, static_cast<u64>(0));
|
||||||
static var ret(u64);
|
}
|
||||||
static var cnt(i64);
|
static var nil() {
|
||||||
static var num(f64);
|
return var(vm_type::vm_nil, static_cast<u64>(0));
|
||||||
static var gcobj(nas_val*);
|
}
|
||||||
static var addr(var*);
|
static var ret(u64 pc) {
|
||||||
|
return var(vm_type::vm_ret, pc);
|
||||||
|
}
|
||||||
|
static var cnt(i64 n) {
|
||||||
|
return var(vm_type::vm_cnt, n);
|
||||||
|
}
|
||||||
|
static var num(f64 n) {
|
||||||
|
return var(vm_type::vm_num, n);
|
||||||
|
}
|
||||||
|
static var gcobj(nas_val* p) {
|
||||||
|
return var(p->type, p);
|
||||||
|
}
|
||||||
|
static var addr(var* p) {
|
||||||
|
return var(vm_type::vm_addr, p);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// get value
|
// get value
|
||||||
|
@ -143,26 +157,27 @@ public:
|
||||||
const nas_map& map() const { return *val.gcobj->ptr.map; }
|
const nas_map& map() const { return *val.gcobj->ptr.map; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool is_none() const { return type==vm_type::vm_none; }
|
bool is_none() const { return type == vm_type::vm_none; }
|
||||||
bool is_cnt() const { return type==vm_type::vm_cnt; }
|
bool is_cnt() const { return type == vm_type::vm_cnt; }
|
||||||
bool is_addr() const { return type==vm_type::vm_addr; }
|
bool is_addr() const { return type == vm_type::vm_addr; }
|
||||||
bool is_ret() const { return type==vm_type::vm_ret; }
|
bool is_ret() const { return type == vm_type::vm_ret; }
|
||||||
bool is_nil() const { return type==vm_type::vm_nil; }
|
bool is_nil() const { return type == vm_type::vm_nil; }
|
||||||
bool is_num() const { return type==vm_type::vm_num; }
|
bool is_num() const { return type == vm_type::vm_num; }
|
||||||
bool is_str() const { return type==vm_type::vm_str; }
|
bool is_str() const { return type == vm_type::vm_str; }
|
||||||
bool is_vec() const { return type==vm_type::vm_vec; }
|
bool is_vec() const { return type == vm_type::vm_vec; }
|
||||||
bool is_hash() const { return type==vm_type::vm_hash; }
|
bool is_hash() const { return type == vm_type::vm_hash; }
|
||||||
bool is_func() const { return type==vm_type::vm_func; }
|
bool is_func() const { return type == vm_type::vm_func; }
|
||||||
bool is_upval() const { return type==vm_type::vm_upval; }
|
bool is_upval() const { return type == vm_type::vm_upval; }
|
||||||
bool is_ghost() const { return type==vm_type::vm_ghost; }
|
bool is_ghost() const { return type == vm_type::vm_ghost; }
|
||||||
bool is_coroutine() const { return type==vm_type::vm_co; }
|
bool is_coroutine() const { return type == vm_type::vm_co; }
|
||||||
bool is_map() const { return type==vm_type::vm_map; }
|
bool is_map() const { return type == vm_type::vm_map; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// number and string can be translated to each other
|
// number and string can be translated to each other
|
||||||
f64 to_num() const;
|
f64 to_num() const;
|
||||||
std::string to_str();
|
std::string to_str();
|
||||||
bool object_check(const std::string&) const;
|
inline bool object_check(const std::string&) const;
|
||||||
|
friend std::ostream& operator<<(std::ostream&, var&);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_vec {
|
struct nas_vec {
|
||||||
|
@ -174,6 +189,7 @@ struct nas_vec {
|
||||||
auto size() const { return elems.size(); }
|
auto size() const { return elems.size(); }
|
||||||
var get_value(const i32);
|
var get_value(const i32);
|
||||||
var* get_memory(const i32);
|
var* get_memory(const i32);
|
||||||
|
friend std::ostream& operator<<(std::ostream&, nas_vec&);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_hash {
|
struct nas_hash {
|
||||||
|
@ -185,6 +201,7 @@ struct nas_hash {
|
||||||
auto size() const { return elems.size(); }
|
auto size() const { return elems.size(); }
|
||||||
var get_value(const std::string&);
|
var get_value(const std::string&);
|
||||||
var* get_memory(const std::string&);
|
var* get_memory(const std::string&);
|
||||||
|
friend std::ostream& operator<<(std::ostream&, nas_hash&);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_func {
|
struct nas_func {
|
||||||
|
@ -206,6 +223,7 @@ struct nas_func {
|
||||||
parameter_size(0), local_size(0),
|
parameter_size(0), local_size(0),
|
||||||
dynamic_parameter_name("") {}
|
dynamic_parameter_name("") {}
|
||||||
void clear();
|
void clear();
|
||||||
|
friend std::ostream& operator<<(std::ostream&, nas_func&);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_upval {
|
struct nas_upval {
|
||||||
|
@ -222,7 +240,7 @@ public:
|
||||||
nas_upval(): on_stack(true), size(0), stack_frame_offset(nullptr) {}
|
nas_upval(): on_stack(true), size(0), stack_frame_offset(nullptr) {}
|
||||||
|
|
||||||
var& operator[](usize n) {
|
var& operator[](usize n) {
|
||||||
return on_stack? stack_frame_offset[n]:elems[n];
|
return on_stack? stack_frame_offset[n] : elems[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
|
@ -250,6 +268,7 @@ public:
|
||||||
~nas_ghost() { clear(); }
|
~nas_ghost() { clear(); }
|
||||||
void set(const std::string&, destructor, marker, void*);
|
void set(const std::string&, destructor, marker, void*);
|
||||||
void clear();
|
void clear();
|
||||||
|
friend std::ostream& operator<<(std::ostream&, const nas_ghost&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const auto& get_ghost_name() const { return type_name; }
|
const auto& get_ghost_name() const { return type_name; }
|
||||||
|
@ -290,6 +309,7 @@ struct nas_co {
|
||||||
delete[] ctx.stack;
|
delete[] ctx.stack;
|
||||||
}
|
}
|
||||||
void clear();
|
void clear();
|
||||||
|
friend std::ostream& operator<<(std::ostream&, const nas_co&);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_map {
|
struct nas_map {
|
||||||
|
@ -304,21 +324,21 @@ public:
|
||||||
|
|
||||||
var get_value(const std::string&);
|
var get_value(const std::string&);
|
||||||
var* get_memory(const std::string&);
|
var* get_memory(const std::string&);
|
||||||
|
friend std::ostream& operator<<(std::ostream&, nas_map&);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream&, nas_vec&);
|
|
||||||
std::ostream& operator<<(std::ostream&, nas_hash&);
|
|
||||||
std::ostream& operator<<(std::ostream&, nas_func&);
|
|
||||||
std::ostream& operator<<(std::ostream&, nas_map&);
|
|
||||||
std::ostream& operator<<(std::ostream&, const nas_ghost&);
|
|
||||||
std::ostream& operator<<(std::ostream&, const nas_co&);
|
|
||||||
std::ostream& operator<<(std::ostream&, var&);
|
|
||||||
|
|
||||||
const var zero = var::num(0);
|
const var zero = var::num(0);
|
||||||
const var one = var::num(1);
|
const var one = var::num(1);
|
||||||
const var nil = var::nil();
|
const var nil = var::nil();
|
||||||
|
|
||||||
|
inline bool var::object_check(const std::string& name) const {
|
||||||
|
return is_ghost() && ghost().type_name == name && ghost().pointer;
|
||||||
|
}
|
||||||
|
|
||||||
// use to print error log and return error value
|
// use to print error log and return error value
|
||||||
var nas_err(const std::string&, const std::string&);
|
static var nas_err(const std::string& func, const std::string& info) {
|
||||||
|
std::cerr << "[vm] " << func << ": " << info << "\n";
|
||||||
|
return var::none();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -536,12 +536,12 @@ void vm::die(const std::string& str) {
|
||||||
if (!ngc.cort) {
|
if (!ngc.cort) {
|
||||||
// in main context, exit directly
|
// in main context, exit directly
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
} else {
|
|
||||||
// in coroutine, shut down the coroutine and return to main context
|
|
||||||
ctx.pc = 0; // mark coroutine 'dead'
|
|
||||||
ngc.context_reserve(); // switch context to main
|
|
||||||
ctx.top[0] = nil; // generate return value 'nil'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// in coroutine, shut down the coroutine and return to main context
|
||||||
|
ctx.pc = 0; // mark coroutine 'dead'
|
||||||
|
ngc.context_reserve(); // switch context to main
|
||||||
|
ctx.top[0] = nil; // generate return value 'nil'
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm::run(const codegen& gen,
|
void vm::run(const codegen& gen,
|
||||||
|
|
|
@ -359,8 +359,8 @@ inline void vm::o_loadl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_loadu() {
|
inline void vm::o_loadu() {
|
||||||
ctx.funcr.func().upval[(imm[ctx.pc]>>16)&0xffff]
|
ctx.funcr.func().upval[(imm[ctx.pc]>>16) & 0xffff]
|
||||||
.upval()[imm[ctx.pc]&0xffff] = (ctx.top--)[0];
|
.upval()[imm[ctx.pc] & 0xffff] = (ctx.top--)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_dup() {
|
inline void vm::o_dup() {
|
||||||
|
@ -452,7 +452,7 @@ inline void vm::o_lnot() {
|
||||||
var val = ctx.top[0];
|
var val = ctx.top[0];
|
||||||
switch(val.type) {
|
switch(val.type) {
|
||||||
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 = util::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)) {
|
||||||
|
@ -462,7 +462,7 @@ inline void vm::o_lnot() {
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
die("cannot do not-operation on "+type_name_string(val));
|
die("cannot do not-operation on " + type_name_string(val));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -477,7 +477,7 @@ inline void vm::o_bnot() {
|
||||||
|
|
||||||
inline void vm::o_btor() {
|
inline void vm::o_btor() {
|
||||||
ctx.top[-1] = var::num(
|
ctx.top[-1] = var::num(
|
||||||
static_cast<i32>(ctx.top[-1].to_num())|
|
static_cast<i32>(ctx.top[-1].to_num()) |
|
||||||
static_cast<i32>(ctx.top[0].to_num())
|
static_cast<i32>(ctx.top[0].to_num())
|
||||||
);
|
);
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
|
@ -485,7 +485,7 @@ inline void vm::o_btor() {
|
||||||
|
|
||||||
inline void vm::o_btxor() {
|
inline void vm::o_btxor() {
|
||||||
ctx.top[-1] = var::num(
|
ctx.top[-1] = var::num(
|
||||||
static_cast<i32>(ctx.top[-1].to_num())^
|
static_cast<i32>(ctx.top[-1].to_num()) ^
|
||||||
static_cast<i32>(ctx.top[0].to_num())
|
static_cast<i32>(ctx.top[0].to_num())
|
||||||
);
|
);
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
|
@ -493,7 +493,7 @@ inline void vm::o_btxor() {
|
||||||
|
|
||||||
inline void vm::o_btand() {
|
inline void vm::o_btand() {
|
||||||
ctx.top[-1] = var::num(
|
ctx.top[-1] = var::num(
|
||||||
static_cast<i32>(ctx.top[-1].to_num())&
|
static_cast<i32>(ctx.top[-1].to_num()) &
|
||||||
static_cast<i32>(ctx.top[0].to_num())
|
static_cast<i32>(ctx.top[0].to_num())
|
||||||
);
|
);
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
|
@ -503,10 +503,10 @@ inline void vm::o_btand() {
|
||||||
ctx.top[-1] = var::num(ctx.top[-1].to_num() type ctx.top[0].to_num());\
|
ctx.top[-1] = var::num(ctx.top[-1].to_num() type ctx.top[0].to_num());\
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
|
|
||||||
inline void vm::o_add() {op_calc(+);}
|
inline void vm::o_add() { op_calc(+); }
|
||||||
inline void vm::o_sub() {op_calc(-);}
|
inline void vm::o_sub() { op_calc(-); }
|
||||||
inline void vm::o_mul() {op_calc(*);}
|
inline void vm::o_mul() { op_calc(*); }
|
||||||
inline void vm::o_div() {op_calc(/);}
|
inline void vm::o_div() { op_calc(/); }
|
||||||
inline void vm::o_lnk() {
|
inline void vm::o_lnk() {
|
||||||
// concat two vectors into one
|
// concat two vectors into one
|
||||||
if (ctx.top[-1].is_vec() && ctx.top[0].is_vec()) {
|
if (ctx.top[-1].is_vec() && ctx.top[0].is_vec()) {
|
||||||
|
@ -535,7 +535,7 @@ inline void vm::o_subc() {op_calc_const(-);}
|
||||||
inline void vm::o_mulc() {op_calc_const(*);}
|
inline void vm::o_mulc() {op_calc_const(*);}
|
||||||
inline void vm::o_divc() {op_calc_const(/);}
|
inline void vm::o_divc() {op_calc_const(/);}
|
||||||
inline void vm::o_lnkc() {
|
inline void vm::o_lnkc() {
|
||||||
ctx.top[0] = ngc.newstr(ctx.top[0].to_str()+const_string[imm[ctx.pc]]);
|
ctx.top[0] = ngc.newstr(ctx.top[0].to_str() + const_string[imm[ctx.pc]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// top[0] stores the value of memr[0], to avoid being garbage-collected
|
// top[0] stores the value of memr[0], to avoid being garbage-collected
|
||||||
|
@ -575,7 +575,7 @@ inline void vm::o_lnkeq() {
|
||||||
ctx.memr[0].to_str()+ctx.top[-1].to_str()
|
ctx.memr[0].to_str()+ctx.top[-1].to_str()
|
||||||
);
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc] + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_bandeq() {
|
inline void vm::o_bandeq() {
|
||||||
|
@ -598,11 +598,11 @@ inline void vm::o_boreq() {
|
||||||
|
|
||||||
inline void vm::o_bxoreq() {
|
inline void vm::o_bxoreq() {
|
||||||
ctx.top[-1] = ctx.memr[0] = var::num(
|
ctx.top[-1] = ctx.memr[0] = var::num(
|
||||||
static_cast<i32>(ctx.memr[0].to_num())^
|
static_cast<i32>(ctx.memr[0].to_num()) ^
|
||||||
static_cast<i32>(ctx.top[-1].to_num())
|
static_cast<i32>(ctx.top[-1].to_num())
|
||||||
);
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc] + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// top[0] stores the value of memr[0], to avoid being garbage-collected
|
// top[0] stores the value of memr[0], to avoid being garbage-collected
|
||||||
|
@ -1083,8 +1083,8 @@ inline void vm::o_mcalll() {
|
||||||
inline void vm::o_mupval() {
|
inline void vm::o_mupval() {
|
||||||
ctx.memr = &(
|
ctx.memr = &(
|
||||||
ctx.funcr.func()
|
ctx.funcr.func()
|
||||||
.upval[(imm[ctx.pc]>>16)&0xffff]
|
.upval[(imm[ctx.pc]>>16) & 0xffff]
|
||||||
.upval()[imm[ctx.pc]&0xffff]
|
.upval()[imm[ctx.pc] & 0xffff]
|
||||||
);
|
);
|
||||||
(++ctx.top)[0] = ctx.memr[0];
|
(++ctx.top)[0] = ctx.memr[0];
|
||||||
// push value in this memory space on stack
|
// push value in this memory space on stack
|
||||||
|
@ -1102,7 +1102,7 @@ inline void vm::o_mcallv() {
|
||||||
}
|
}
|
||||||
} else if (vec.is_hash()) { // do mcallh but use the mcallv way
|
} else if (vec.is_hash()) { // do mcallh but use the mcallv way
|
||||||
if (!val.is_str()) {
|
if (!val.is_str()) {
|
||||||
die("must use string as the key but get "+type_name_string(val));
|
die("must use string as the key but get " + type_name_string(val));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& ref = vec.hash();
|
auto& ref = vec.hash();
|
||||||
|
@ -1114,7 +1114,7 @@ inline void vm::o_mcallv() {
|
||||||
}
|
}
|
||||||
} else if (vec.is_map()) {
|
} else if (vec.is_map()) {
|
||||||
if (!val.is_str()) {
|
if (!val.is_str()) {
|
||||||
die("must use string as the key but get "+type_name_string(val));
|
die("must use string as the key but get " + type_name_string(val));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& ref = vec.map();
|
auto& ref = vec.map();
|
||||||
|
@ -1192,7 +1192,7 @@ inline void vm::o_ret() {
|
||||||
auto size = func.func().local_size;
|
auto size = func.func().local_size;
|
||||||
upval.on_stack = false;
|
upval.on_stack = false;
|
||||||
upval.elems.resize(size);
|
upval.elems.resize(size);
|
||||||
for(u64 i = 0; i<size; ++i) {
|
for(u64 i = 0; i < size; ++i) {
|
||||||
upval.elems[i] = local[i];
|
upval.elems[i] = local[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
std/csv.nas
10
std/csv.nas
|
@ -2,14 +2,14 @@
|
||||||
# ValKmjolnir 2022/10/15
|
# ValKmjolnir 2022/10/15
|
||||||
use std.io;
|
use std.io;
|
||||||
|
|
||||||
var read = func(path, delimeter=",", endline="\n") {
|
var read = func(path, delimeter = ",", endline = "\n") {
|
||||||
var context = io.readfile(path);
|
var context = io.readfile(path);
|
||||||
context = split(endline, context);
|
context = split(endline, context);
|
||||||
forindex(var i;context) {
|
forindex(var i; context) {
|
||||||
context[i] = split(delimeter,context[i]);
|
context[i] = split(delimeter, context[i]);
|
||||||
}
|
}
|
||||||
if (size(context)<=1) {
|
if (size(context) <= 1) {
|
||||||
die("incorrect csv file <"~path~">: "~size(context)~" line(s).");
|
die("incorrect csv file <" ~ path ~ ">: " ~ size(context) ~ " line(s).");
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
property: context[0],
|
property: context[0],
|
||||||
|
|
24
std/file.nas
24
std/file.nas
|
@ -4,12 +4,10 @@ use std.io;
|
||||||
use std.unix;
|
use std.unix;
|
||||||
|
|
||||||
var SEEK_SET = io.SEEK_SET;
|
var SEEK_SET = io.SEEK_SET;
|
||||||
|
|
||||||
var SEEK_CUR = io.SEEK_CUR;
|
var SEEK_CUR = io.SEEK_CUR;
|
||||||
|
|
||||||
var SEEK_END = io.SEEK_END;
|
var SEEK_END = io.SEEK_END;
|
||||||
|
|
||||||
var new = func(filename, mode="r") {
|
var new = func(filename, mode = "r") {
|
||||||
if (!io.exists(filename)) {
|
if (!io.exists(filename)) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +54,7 @@ var find_all_files = func(path) {
|
||||||
var dd = unix.opendir(path);
|
var dd = unix.opendir(path);
|
||||||
var res = [];
|
var res = [];
|
||||||
while(var n = unix.readdir(dd)) {
|
while(var n = unix.readdir(dd)) {
|
||||||
if (unix.isfile(path~"/"~n)) {
|
if (unix.isfile(path ~ "/" ~ n)) {
|
||||||
append(res, n);
|
append(res, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,11 +72,11 @@ var recursive_find_files = func(path) {
|
||||||
files: []
|
files: []
|
||||||
};
|
};
|
||||||
while(var n = unix.readdir(dd)) {
|
while(var n = unix.readdir(dd)) {
|
||||||
if (unix.isfile(path~"/"~n)) {
|
if (unix.isfile(path ~ "/" ~ n)) {
|
||||||
append(res.files, n);
|
append(res.files, n);
|
||||||
} elsif (unix.isdir(path~"/"~n) and n!="." and n!="..") {
|
} elsif (unix.isdir(path ~ "/" ~ n) and n != "." and n != "..") {
|
||||||
var tmp = recursive_find_files(path~"/"~n);
|
var tmp = recursive_find_files(path ~ "/" ~ n);
|
||||||
if (tmp!=nil) {
|
if (tmp != nil) {
|
||||||
append(res.files, tmp);
|
append(res.files, tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,19 +87,19 @@ var recursive_find_files = func(path) {
|
||||||
|
|
||||||
var recursive_find_files_flat = func(path) {
|
var recursive_find_files_flat = func(path) {
|
||||||
var tree_files = recursive_find_files(path);
|
var tree_files = recursive_find_files(path);
|
||||||
if (tree_files==nil) {
|
if (tree_files == nil) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
var flat = [];
|
var flat = [];
|
||||||
var bfs = [tree_files];
|
var bfs = [tree_files];
|
||||||
while(size(bfs)!=0) {
|
while(size(bfs) != 0) {
|
||||||
var first = pop(bfs);
|
var first = pop(bfs);
|
||||||
foreach(var file_record; first.files) {
|
foreach(var file_record; first.files) {
|
||||||
if (ishash(file_record)) {
|
if (ishash(file_record)) {
|
||||||
append(bfs, file_record);
|
append(bfs, file_record);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
append(flat, first.dir~"/"~file_record);
|
append(flat, first.dir ~ "/" ~ file_record);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return flat;
|
return flat;
|
||||||
|
@ -110,7 +108,7 @@ var recursive_find_files_flat = func(path) {
|
||||||
var recursive_find_files_with_extension = func(path, extensions...) {
|
var recursive_find_files_with_extension = func(path, extensions...) {
|
||||||
var in_vec = func(ext) {
|
var in_vec = func(ext) {
|
||||||
foreach(var i; extensions) {
|
foreach(var i; extensions) {
|
||||||
if (ext==i) {
|
if (ext == i) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,7 +119,7 @@ var recursive_find_files_with_extension = func(path, extensions...) {
|
||||||
var res = [];
|
var res = [];
|
||||||
foreach(var filename; files) {
|
foreach(var filename; files) {
|
||||||
var tmp = split('.', filename);
|
var tmp = split('.', filename);
|
||||||
if (size(tmp)>1 and in_vec(tmp[-1])) {
|
if (size(tmp) > 1 and in_vec(tmp[-1])) {
|
||||||
append(res, filename);
|
append(res, filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,32 +4,32 @@ var new = func() {
|
||||||
var (begin, end) = (nil, nil);
|
var (begin, end) = (nil, nil);
|
||||||
return{
|
return{
|
||||||
push: func(elem) {
|
push: func(elem) {
|
||||||
var new_node={
|
var new_node = {
|
||||||
elem:elem,
|
elem:elem,
|
||||||
next:nil
|
next:nil
|
||||||
};
|
};
|
||||||
if (begin==nil)
|
if (begin == nil)
|
||||||
begin=end=new_node;
|
begin = end = new_node;
|
||||||
else {
|
else {
|
||||||
end.next=new_node;
|
end.next = new_node;
|
||||||
end=new_node;
|
end = new_node;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pop: func() {
|
pop: func() {
|
||||||
if (begin!=nil)
|
if (begin != nil)
|
||||||
begin=begin.next;
|
begin = begin.next;
|
||||||
if (begin==nil)
|
if (begin == nil)
|
||||||
end=nil;
|
end = nil;
|
||||||
},
|
},
|
||||||
front: func() {
|
front: func() {
|
||||||
if (begin!=nil)
|
if (begin != nil)
|
||||||
return begin.elem;
|
return begin.elem;
|
||||||
},
|
},
|
||||||
clear: func() {
|
clear: func() {
|
||||||
begin=end=nil;
|
begin = end = nil;
|
||||||
},
|
},
|
||||||
empty: func() {
|
empty: func() {
|
||||||
return begin==nil;
|
return begin == nil;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ var stack = func() {
|
||||||
return pop(vec);
|
return pop(vec);
|
||||||
},
|
},
|
||||||
top: func() {
|
top: func() {
|
||||||
if (size(vec)!=0) {
|
if (size(vec) != 0) {
|
||||||
return vec[-1];
|
return vec[-1];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -18,7 +18,7 @@ var stack = func() {
|
||||||
vec = [];
|
vec = [];
|
||||||
},
|
},
|
||||||
empty: func() {
|
empty: func() {
|
||||||
return size(vec)==0;
|
return size(vec) == 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,11 +33,13 @@ func() {
|
||||||
}();
|
}();
|
||||||
|
|
||||||
var to_char = func(number) {
|
var to_char = func(number) {
|
||||||
return 0<=number and number<256? __num_to_char[number]:"";
|
return 0 <= number and number < 256? __num_to_char[number] : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
var to_num = func(character) {
|
var to_num = func(character) {
|
||||||
return __temp_contains(__char_to_num, character)? __char_to_num[character]:-1;
|
return __temp_contains(__char_to_num, character)
|
||||||
|
? __char_to_num[character]
|
||||||
|
: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var __string_split_with_empty_substr = func(separator, str) {
|
var __string_split_with_empty_substr = func(separator, str) {
|
||||||
|
|
|
@ -6,75 +6,77 @@ use std.padding;
|
||||||
use std.os;
|
use std.os;
|
||||||
use std.runtime;
|
use std.runtime;
|
||||||
|
|
||||||
if (os.platform()=="windows") {
|
if (os.platform() == "windows") {
|
||||||
runtime.windows.set_utf8_output();
|
runtime.windows.set_utf8_output();
|
||||||
system("color");
|
system("color");
|
||||||
}
|
}
|
||||||
|
|
||||||
var fib = func() {
|
var fib = func() {
|
||||||
var (a,b)=(1,1);
|
var (a, b) = (1, 1);
|
||||||
coroutine.yield(a);
|
coroutine.yield(a);
|
||||||
coroutine.yield(b);
|
coroutine.yield(b);
|
||||||
while(1) {
|
while(1) {
|
||||||
(a,b)=(b,a+b);
|
(a, b) = (b, a + b);
|
||||||
coroutine.yield(b);
|
coroutine.yield(b);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var co=[coroutine.create(fib),coroutine.create(fib)];
|
var co = [coroutine.create(fib), coroutine.create(fib)];
|
||||||
for(var i=0;i<45;i+=1) {
|
for(var i = 0; i < 45; i += 1) {
|
||||||
var res=[coroutine.resume(co[0]),coroutine.resume(co[1])];
|
var res = [coroutine.resume(co[0]), coroutine.resume(co[1])];
|
||||||
if (res[0]==nil or res[1]==nil or res[0][0]!=res[1][0])
|
if (res[0] == nil or res[1] == nil or res[0][0] != res[1][0])
|
||||||
die("different coroutines don't share the same local scope");
|
die("different coroutines don't share the same local scope");
|
||||||
}
|
}
|
||||||
|
|
||||||
# test if coroutine can get upvalues
|
# test if coroutine can get upvalues
|
||||||
func() {
|
func() {
|
||||||
var x=1;
|
var x = 1;
|
||||||
var co=coroutine.create(func() {
|
var co = coroutine.create(func() {
|
||||||
for(var j=0;j<128;j+=1) {
|
for(var j = 0; j < 128; j += 1) {
|
||||||
coroutine.yield(x,i,j);
|
coroutine.yield(x, i, j);
|
||||||
x+=1;
|
x += 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for(var i=0;i<16;i+=1) {
|
for(var i = 0; i < 16; i += 1) {
|
||||||
var res=coroutine.resume(co);
|
var res = coroutine.resume(co);
|
||||||
if (res==nil or res[0]!=x or res[1]!=i)
|
if (res == nil or res[0] != x or res[1] != i)
|
||||||
die("coroutine should have the ability to get upvalues");
|
die("coroutine should have the ability to get upvalues");
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
# test coroutine.resume passing arguments to coroutine
|
# test coroutine.resume passing arguments to coroutine
|
||||||
func {
|
func {
|
||||||
var co=coroutine.create(func() {
|
var co = coroutine.create(func() {
|
||||||
var (a,b)=coroutine.yield(a+b);
|
var (a, b) = coroutine.yield(a + b);
|
||||||
println("coroutine.yield get ",a," ",b);
|
println("[0] coroutine.yield get ", a, " ", b);
|
||||||
(a,b)=coroutine.yield(a+b);
|
(a, b) = coroutine.yield(a + b);
|
||||||
println("coroutine.yield get ",a," ",b);
|
println("[0] coroutine.yield get ", a, " ", b);
|
||||||
return "end";
|
return "end";
|
||||||
});
|
});
|
||||||
|
|
||||||
for(var i=0;i<5;i+=1)
|
for(var i = 0; i < 5; i += 1)
|
||||||
println("coroutine.resume get ",coroutine.resume(co,i,i+1));
|
println("[0] coroutine.resume get ", coroutine.resume(co, i, i + 1));
|
||||||
|
print("\n");
|
||||||
}();
|
}();
|
||||||
|
|
||||||
# test crash in coroutines
|
# test crash in coroutines
|
||||||
var co=coroutine.create(func {
|
var co = coroutine.create(func {
|
||||||
var b = func() {b()}
|
var b = func() { b() }
|
||||||
coroutine.yield(b);
|
coroutine.yield(b);
|
||||||
b();
|
b();
|
||||||
coroutine.yield(0);
|
coroutine.yield(0); # unreachable
|
||||||
});
|
});
|
||||||
|
|
||||||
println("coroutine yield: ",coroutine.resume(co));
|
println("[1] coroutine yield: ", coroutine.resume(co));
|
||||||
println("coroutine state:\e[32m ",coroutine.status(co),"\e[0m");
|
println("[1] coroutine state after yield:\e[32m ", coroutine.status(co), "\e[0m");
|
||||||
println("coroutine error: ",coroutine.resume(co));
|
println("[1] coroutine stackoverflow error: ", coroutine.resume(co));
|
||||||
println("coroutine state:\e[91m ",coroutine.status(co),"\e[0m");
|
println("[1] coroutine state after error:\e[91m ", coroutine.status(co), "\e[0m");
|
||||||
println("coroutine yield: ",coroutine.resume(co));
|
println("[1] coroutine yield after error: ", coroutine.resume(co));
|
||||||
println("coroutine state:\e[91m ",coroutine.status(co),"\e[0m");
|
println("[1] coroutine state after error:\e[91m ", coroutine.status(co), "\e[0m");
|
||||||
|
print("\n");
|
||||||
|
|
||||||
var co = coroutine.create(func {
|
var co = coroutine.create(func {
|
||||||
var a=1;
|
var a = 1;
|
||||||
var b = func() {
|
var b = func() {
|
||||||
b();
|
b();
|
||||||
}
|
}
|
||||||
|
@ -82,44 +84,46 @@ var co = coroutine.create(func {
|
||||||
coroutine.yield(b());
|
coroutine.yield(b());
|
||||||
});
|
});
|
||||||
|
|
||||||
println("coroutine yield: ",coroutine.resume(co));
|
println("[2] coroutine yield: ", coroutine.resume(co));
|
||||||
println("coroutine state:\e[32m ",coroutine.status(co),"\e[0m");
|
println("[2] coroutine state:\e[32m ", coroutine.status(co), "\e[0m");
|
||||||
println("coroutine error: ",coroutine.resume(co));
|
println("[2] coroutine error: ", coroutine.resume(co));
|
||||||
println("coroutine state:\e[91m ",coroutine.status(co),"\e[0m");
|
println("[2] coroutine state:\e[91m ", coroutine.status(co), "\e[0m");
|
||||||
println("coroutine yield: ",coroutine.resume(co));
|
println("[2] coroutine yield: ", coroutine.resume(co));
|
||||||
println("coroutine state:\e[91m ",coroutine.status(co),"\e[0m");
|
println("[2] coroutine state:\e[91m ", coroutine.status(co), "\e[0m");
|
||||||
println("ok");
|
println("[2] ok\n");
|
||||||
|
|
||||||
# pressure test
|
# pressure test
|
||||||
for(var t=0;t<10;t+=1) {
|
for(var t = 0; t < 10; t += 1) {
|
||||||
var productor = func() {
|
var productor = func() {
|
||||||
while(1) {
|
while(1) {
|
||||||
coroutine.yield(i);
|
coroutine.yield(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var co=coroutine.create(productor);
|
var co = coroutine.create(productor);
|
||||||
var tm=maketimestamp();
|
var tm = maketimestamp();
|
||||||
|
|
||||||
var counter=0;
|
var counter = 0;
|
||||||
var bar=process_bar.high_resolution_bar(40);
|
var bar = process_bar.high_resolution_bar(40);
|
||||||
var consumer = func() {
|
var consumer = func() {
|
||||||
counter+=1;
|
counter += 1;
|
||||||
for(var i=0;i<t+1;i+=1)
|
for(var i = 0; i < t + 1; i += 1)
|
||||||
coroutine.resume(co);
|
coroutine.resume(co);
|
||||||
if (counter-int(counter/1000)*1000==0) {
|
if (counter - int(counter / 1000) * 1000 == 0) {
|
||||||
var rate=counter/2e5;
|
var rate = counter / 2e5;
|
||||||
print(" ",bar.bar(rate)," ",
|
print(" ", bar.bar(rate), " ",
|
||||||
padding.leftpad(str(int(rate*100)),3),"% | ",
|
padding.leftpad(str(int(rate*100)),3), "% | ",
|
||||||
str(1e3*int(counter/tm.elapsedMSec())),
|
str(1e3 * int(counter / tm.elapsedMSec())),
|
||||||
" tasks/s \r");
|
" tasks/s \r"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tm.stamp();
|
tm.stamp();
|
||||||
for(var i=0;i<1e5;i+=1)
|
for(var i = 0; i < 1e5; i += 1)
|
||||||
consumer();
|
consumer();
|
||||||
println(" ",bar.bar(1)," 100% | ",
|
println(" ", bar.bar(1), " 100% | ",
|
||||||
str(int(1e3*counter/tm.elapsedMSec())),
|
str(int(1e3 * counter / tm.elapsedMSec())),
|
||||||
" tasks/s ");
|
" tasks/s "
|
||||||
|
);
|
||||||
}
|
}
|
Loading…
Reference in New Issue