📝 format

This commit is contained in:
ValKmjolnir 2024-12-26 21:02:35 +08:00
parent 94d0ce9c2d
commit 985dee8001
5 changed files with 144 additions and 157 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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 "
);
} }