mirror of
https://github.com/ValKmjolnir/Nasal-Interpreter.git
synced 2026-05-02 19:00:47 +08:00
@@ -159,26 +159,6 @@ std::ostream& operator<<(std::ostream& out, const nas_ghost& ghost) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nas_co::clear() {
|
|
||||||
if (!ctx.stack) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (u32 i = 0; i < VM_STACK_DEPTH; ++i) {
|
|
||||||
ctx.stack[i] = var::nil();
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.pc = 0;
|
|
||||||
ctx.localr = nullptr;
|
|
||||||
ctx.memr = nullptr;
|
|
||||||
ctx.canary = ctx.stack+VM_STACK_DEPTH-1;
|
|
||||||
ctx.top = ctx.stack;
|
|
||||||
ctx.func_top = ctx.func_stack;
|
|
||||||
ctx.funcr = var::nil();
|
|
||||||
ctx.upvalr = var::nil();
|
|
||||||
|
|
||||||
status = status::suspended;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, const nas_co& co) {
|
std::ostream& operator<<(std::ostream& out, const nas_co& co) {
|
||||||
out << "<coroutine at 0x" << std::hex;
|
out << "<coroutine at 0x" << std::hex;
|
||||||
out << reinterpret_cast<u64>(&co) << std::dec << ">";
|
out << reinterpret_cast<u64>(&co) << std::dec << ">";
|
||||||
|
|||||||
@@ -298,6 +298,12 @@ public:
|
|||||||
T convert() const { return reinterpret_cast<T>(pointer); }
|
T convert() const { return reinterpret_cast<T>(pointer); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct callsite {
|
||||||
|
var caller;
|
||||||
|
u64 file_index = 0;
|
||||||
|
u64 line = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct context {
|
struct context {
|
||||||
u64 pc = 0;
|
u64 pc = 0;
|
||||||
var* localr = nullptr;
|
var* localr = nullptr;
|
||||||
@@ -309,8 +315,39 @@ struct context {
|
|||||||
var* stack = nullptr;
|
var* stack = nullptr;
|
||||||
var* top = nullptr;
|
var* top = nullptr;
|
||||||
|
|
||||||
var* func_stack = nullptr;
|
callsite* func_stack = nullptr;
|
||||||
var* func_top = nullptr;
|
callsite* func_top = nullptr;
|
||||||
|
|
||||||
|
const std::string* files = nullptr;
|
||||||
|
|
||||||
|
void ctor() {
|
||||||
|
stack = new var[VM_STACK_DEPTH];
|
||||||
|
func_stack = new callsite[VM_STACK_DEPTH];
|
||||||
|
}
|
||||||
|
void dtor() {
|
||||||
|
delete[] stack;
|
||||||
|
delete[] func_stack;
|
||||||
|
}
|
||||||
|
void clear() {
|
||||||
|
/* set canary and program counter */
|
||||||
|
pc = 0;
|
||||||
|
localr = nullptr;
|
||||||
|
memr = nullptr;
|
||||||
|
funcr = var::nil();
|
||||||
|
upvalr = var::nil();
|
||||||
|
|
||||||
|
/* set canary = stack[VM_STACK_DEPTH-1] */
|
||||||
|
canary = stack + VM_STACK_DEPTH - 1;
|
||||||
|
|
||||||
|
/* nothing is on stack */
|
||||||
|
top = stack;
|
||||||
|
func_top = func_stack - 1;
|
||||||
|
|
||||||
|
/* clear main stack */
|
||||||
|
for (u32 i = 0; i < VM_STACK_DEPTH; ++i) {
|
||||||
|
stack[i] = var::nil();
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_co {
|
struct nas_co {
|
||||||
@@ -323,16 +360,9 @@ struct nas_co {
|
|||||||
context ctx;
|
context ctx;
|
||||||
status status;
|
status status;
|
||||||
|
|
||||||
nas_co() {
|
nas_co() { ctx.ctor(); }
|
||||||
ctx.stack = new var[VM_STACK_DEPTH];
|
~nas_co() { ctx.dtor(); }
|
||||||
ctx.func_stack = new var[VM_STACK_DEPTH];
|
void clear() { ctx.clear(); status = status::suspended; }
|
||||||
clear();
|
|
||||||
}
|
|
||||||
~nas_co() {
|
|
||||||
delete[] ctx.stack;
|
|
||||||
delete[] ctx.func_stack;
|
|
||||||
}
|
|
||||||
void clear();
|
|
||||||
friend std::ostream& operator<<(std::ostream&, const nas_co&);
|
friend std::ostream& operator<<(std::ostream&, const nas_co&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -45,23 +45,11 @@ void vm::vm_init_enrty(const std::vector<std::string>& strs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void vm::context_and_global_init() {
|
void vm::context_and_global_init() {
|
||||||
/* set canary and program counter */
|
/* clear context status */
|
||||||
ctx.pc = 0;
|
ctx.clear();
|
||||||
ctx.localr = nullptr;
|
|
||||||
ctx.memr = nullptr;
|
|
||||||
ctx.funcr = nil;
|
|
||||||
ctx.upvalr = nil;
|
|
||||||
|
|
||||||
/* set canary = stack[VM_STACK_DEPTH-1] */
|
|
||||||
ctx.canary = ctx.stack+VM_STACK_DEPTH-1;
|
|
||||||
|
|
||||||
/* nothing is on stack */
|
|
||||||
ctx.top = ctx.stack - 1;
|
|
||||||
ctx.func_top = ctx.func_stack - 1;
|
|
||||||
|
|
||||||
/* clear main stack and global */
|
/* clear main stack and global */
|
||||||
for (u32 i = 0; i < VM_STACK_DEPTH; ++i) {
|
for (u32 i = 0; i < VM_STACK_DEPTH; ++i) {
|
||||||
ctx.stack[i] = nil;
|
|
||||||
global[i] = nil;
|
global[i] = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -287,13 +287,11 @@ public:
|
|||||||
|
|
||||||
/* constructor of vm instance */
|
/* constructor of vm instance */
|
||||||
vm() {
|
vm() {
|
||||||
ctx.stack = new var[VM_STACK_DEPTH];
|
ctx.ctor();
|
||||||
ctx.func_stack = new var[VM_STACK_DEPTH];
|
|
||||||
global = new var[VM_STACK_DEPTH];
|
global = new var[VM_STACK_DEPTH];
|
||||||
}
|
}
|
||||||
~vm() {
|
~vm() {
|
||||||
delete[] ctx.stack;
|
ctx.dtor();
|
||||||
delete[] ctx.func_stack;
|
|
||||||
delete[] global;
|
delete[] global;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -902,7 +900,11 @@ inline void vm::o_callfv() {
|
|||||||
var tmp = local[-1];
|
var tmp = local[-1];
|
||||||
local[-1] = ctx.funcr;
|
local[-1] = ctx.funcr;
|
||||||
ctx.funcr = tmp;
|
ctx.funcr = tmp;
|
||||||
(++ctx.func_top)[0] = tmp;
|
(++ctx.func_top)[0] = {
|
||||||
|
tmp,
|
||||||
|
bytecode[ctx.pc].fidx,
|
||||||
|
bytecode[ctx.pc].line
|
||||||
|
};
|
||||||
|
|
||||||
// top-argc+lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
// top-argc+lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
||||||
if (ctx.top-argc+func.local_size+3>=ctx.canary) {
|
if (ctx.top-argc+func.local_size+3>=ctx.canary) {
|
||||||
@@ -972,7 +974,11 @@ inline void vm::o_callfh() {
|
|||||||
var tmp = ctx.top[-1];
|
var tmp = ctx.top[-1];
|
||||||
ctx.top[-1] = ctx.funcr;
|
ctx.top[-1] = ctx.funcr;
|
||||||
ctx.funcr = tmp;
|
ctx.funcr = tmp;
|
||||||
(++ctx.func_top)[0] = tmp;
|
(++ctx.func_top)[0] = {
|
||||||
|
tmp,
|
||||||
|
bytecode[ctx.pc].fidx,
|
||||||
|
bytecode[ctx.pc].line
|
||||||
|
};
|
||||||
|
|
||||||
// top -1(hash) +lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
// top -1(hash) +lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
||||||
if (ctx.top+func.local_size+2>= ctx.canary) {
|
if (ctx.top+func.local_size+2>= ctx.canary) {
|
||||||
@@ -1015,6 +1021,9 @@ inline void vm::o_callb() {
|
|||||||
// this code is written for coroutine
|
// this code is written for coroutine
|
||||||
(++ctx.top)[0] = nil;
|
(++ctx.top)[0] = nil;
|
||||||
|
|
||||||
|
// set file list into ctx
|
||||||
|
ctx.files = files;
|
||||||
|
|
||||||
// if running a native function about coroutine
|
// if running a native function about coroutine
|
||||||
// (top) will be set to another context.top, instead of main_context.top
|
// (top) will be set to another context.top, instead of main_context.top
|
||||||
auto function_pointer = native_function[imm[ctx.pc]].func;
|
auto function_pointer = native_function[imm[ctx.pc]].func;
|
||||||
|
|||||||
@@ -538,7 +538,14 @@ var builtin_caller(context* ctx, gc* ngc) {
|
|||||||
if (ctx->func_top - level_num - 1 < ctx->func_stack) {
|
if (ctx->func_top - level_num - 1 < ctx->func_stack) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
return ctx->func_top[-level_num - 1];
|
const auto& cs = ctx->func_top[-level_num - 1];
|
||||||
|
var res = ngc->temp = ngc->alloc(vm_type::vm_vec);
|
||||||
|
res.vec().elems.push_back(ngc->alloc(vm_type::vm_hash));
|
||||||
|
res.vec().elems.push_back(cs.caller);
|
||||||
|
res.vec().elems.push_back(ngc->newstr(ctx->files[cs.file_index]));
|
||||||
|
res.vec().elems.push_back(var::num(cs.line));
|
||||||
|
ngc->temp = nil;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_arch(context* ctx, gc* ngc) {
|
var builtin_arch(context* ctx, gc* ngc) {
|
||||||
|
|||||||
24
test/caller.nas
Normal file
24
test/caller.nas
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
var a = func(x, y, z) {
|
||||||
|
for (var i = 0; i < 20; i += 1) {
|
||||||
|
var cl = caller(i);
|
||||||
|
if (cl == nil) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
print("[", i, "]\t", cl[1], "\t -> called from ", cl[2], ":", cl[3], "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var b = func(x, y) {
|
||||||
|
a(1, 2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
var c = func(x) b(1, 2);
|
||||||
|
var d = func c(1);
|
||||||
|
var e = func d();
|
||||||
|
var f = func e();
|
||||||
|
var g = func f();
|
||||||
|
var h = func g();
|
||||||
|
var i = func h();
|
||||||
|
var j = func i();
|
||||||
|
|
||||||
|
j();
|
||||||
@@ -109,7 +109,7 @@ for (var t = 0; t < 10; t += 1) {
|
|||||||
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 / 2500) * 2500 == 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), "% | ",
|
||||||
@@ -120,7 +120,7 @@ for (var t = 0; t < 10; t += 1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tm.stamp();
|
tm.stamp();
|
||||||
for (var i = 0; i < 1e5; i += 1)
|
for (var i = 0; i < 2e5; 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())),
|
||||||
|
|||||||
Reference in New Issue
Block a user