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;
|
||||
}
|
||||
|
||||
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) {
|
||||
out << "<coroutine at 0x" << std::hex;
|
||||
out << reinterpret_cast<u64>(&co) << std::dec << ">";
|
||||
|
||||
@@ -298,6 +298,12 @@ public:
|
||||
T convert() const { return reinterpret_cast<T>(pointer); }
|
||||
};
|
||||
|
||||
struct callsite {
|
||||
var caller;
|
||||
u64 file_index = 0;
|
||||
u64 line = 0;
|
||||
};
|
||||
|
||||
struct context {
|
||||
u64 pc = 0;
|
||||
var* localr = nullptr;
|
||||
@@ -309,8 +315,39 @@ struct context {
|
||||
var* stack = nullptr;
|
||||
var* top = nullptr;
|
||||
|
||||
var* func_stack = nullptr;
|
||||
var* func_top = nullptr;
|
||||
callsite* func_stack = 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 {
|
||||
@@ -323,16 +360,9 @@ struct nas_co {
|
||||
context ctx;
|
||||
status status;
|
||||
|
||||
nas_co() {
|
||||
ctx.stack = new var[VM_STACK_DEPTH];
|
||||
ctx.func_stack = new var[VM_STACK_DEPTH];
|
||||
clear();
|
||||
}
|
||||
~nas_co() {
|
||||
delete[] ctx.stack;
|
||||
delete[] ctx.func_stack;
|
||||
}
|
||||
void clear();
|
||||
nas_co() { ctx.ctor(); }
|
||||
~nas_co() { ctx.dtor(); }
|
||||
void clear() { ctx.clear(); status = status::suspended; }
|
||||
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() {
|
||||
/* set canary and program counter */
|
||||
ctx.pc = 0;
|
||||
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 context status */
|
||||
ctx.clear();
|
||||
|
||||
/* clear main stack and global */
|
||||
for (u32 i = 0; i < VM_STACK_DEPTH; ++i) {
|
||||
ctx.stack[i] = nil;
|
||||
global[i] = nil;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,13 +287,11 @@ public:
|
||||
|
||||
/* constructor of vm instance */
|
||||
vm() {
|
||||
ctx.stack = new var[VM_STACK_DEPTH];
|
||||
ctx.func_stack = new var[VM_STACK_DEPTH];
|
||||
ctx.ctor();
|
||||
global = new var[VM_STACK_DEPTH];
|
||||
}
|
||||
~vm() {
|
||||
delete[] ctx.stack;
|
||||
delete[] ctx.func_stack;
|
||||
ctx.dtor();
|
||||
delete[] global;
|
||||
}
|
||||
|
||||
@@ -902,7 +900,11 @@ inline void vm::o_callfv() {
|
||||
var tmp = local[-1];
|
||||
local[-1] = ctx.funcr;
|
||||
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)
|
||||
if (ctx.top-argc+func.local_size+3>=ctx.canary) {
|
||||
@@ -972,7 +974,11 @@ inline void vm::o_callfh() {
|
||||
var tmp = ctx.top[-1];
|
||||
ctx.top[-1] = ctx.funcr;
|
||||
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)
|
||||
if (ctx.top+func.local_size+2>= ctx.canary) {
|
||||
@@ -1015,6 +1021,9 @@ inline void vm::o_callb() {
|
||||
// this code is written for coroutine
|
||||
(++ctx.top)[0] = nil;
|
||||
|
||||
// set file list into ctx
|
||||
ctx.files = files;
|
||||
|
||||
// if running a native function about coroutine
|
||||
// (top) will be set to another context.top, instead of main_context.top
|
||||
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) {
|
||||
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) {
|
||||
|
||||
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;
|
||||
for (var i = 0; i < t + 1; i += 1)
|
||||
coroutine.resume(co);
|
||||
if (counter - int(counter / 1000) * 1000 == 0) {
|
||||
if (counter - int(counter / 2500) * 2500 == 0) {
|
||||
var rate = counter / 2e5;
|
||||
print(" ", bar.bar(rate), " ",
|
||||
padding.leftpad(str(int(rate*100)),3), "% | ",
|
||||
@@ -120,7 +120,7 @@ for (var t = 0; t < 10; t += 1) {
|
||||
}
|
||||
|
||||
tm.stamp();
|
||||
for (var i = 0; i < 1e5; i += 1)
|
||||
for (var i = 0; i < 2e5; i += 1)
|
||||
consumer();
|
||||
println(" ", bar.bar(1), " 100% | ",
|
||||
str(int(1e3 * counter / tm.elapsedMSec())),
|
||||
|
||||
Reference in New Issue
Block a user