feat: add old data to both subcontexts

This commit is contained in:
TopchetoEU 2023-10-04 08:30:33 +03:00
parent 68f3b6d926
commit 6c7fe6deaf
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
7 changed files with 87 additions and 11 deletions

View File

@ -102,7 +102,7 @@ public class Main {
var raw = in.readLine();
if (raw == null) break;
engine.pushMsg(false, new Context(env, new Message(engine)), "<stdio>", raw, null).toObservable().once(valuePrinter);
engine.pushMsg(false, env.context(new Message(engine)), "<stdio>", raw, null).toObservable().once(valuePrinter);
}
catch (EngineException e) {
try {

View File

@ -0,0 +1,58 @@
package me.topchetoeu.jscript.engine;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
@SuppressWarnings("unchecked")
public class Data implements Iterable<Entry<DataKey<?>, ?>> {
private HashMap<DataKey<Object>, Object> data = new HashMap<>();
public Data copy() {
return new Data().addAll(this);
}
public Data addAll(Iterable<Entry<DataKey<?>, ?>> data) {
for (var el : data) {
add((DataKey<Object>)el.getKey(), (Object)el.getValue());
}
return this;
}
public <T> Data set(DataKey<T> key, T val) {
if (val == null) data.remove(key);
else data.put((DataKey<Object>)key, (Object)val);
return this;
}
public <T> T add(DataKey<T> key, T val) {
if (data.containsKey(key)) return (T)data.get(key);
else {
if (val == null) data.remove(key);
else data.put((DataKey<Object>)key, (Object)val);
return val;
}
}
public <T> T get(DataKey<T> key) {
return get(key, null);
}
public <T> T get(DataKey<T> key, T defaultVal) {
if (!has(key)) return defaultVal;
else return (T)data.get(key);
}
public boolean has(DataKey<?> key) { return data.containsKey(key); }
public Data increase(DataKey<Integer> key, int n, int start) {
return set(key, get(key, start) + n);
}
public Data increase(DataKey<Integer> key, int n) {
return increase(key, n, 0);
}
public Data increase(DataKey<Integer> key) {
return increase(key, 1, 0);
}
@Override
public Iterator<Entry<DataKey<?>, ?>> iterator() {
return (Iterator<Entry<DataKey<?>, ?>>)data.entrySet();
}
}

View File

@ -0,0 +1,3 @@
package me.topchetoeu.jscript.engine;
public class DataKey<T> { }

View File

@ -11,19 +11,19 @@ public class Engine {
private class UncompiledFunction extends FunctionValue {
public final String filename;
public final String raw;
public final Environment ctx;
public final Environment env;
@Override
public Object call(Context ctx, Object thisArg, Object ...args) throws InterruptedException {
ctx = new Context(this.ctx, ctx.message);
ctx = ctx.setEnv(env);
return ctx.compile(filename, raw).call(ctx, thisArg, args);
}
public UncompiledFunction(Environment ctx, String filename, String raw) {
public UncompiledFunction(Environment env, String filename, String raw) {
super(filename, 0);
this.filename = filename;
this.raw = raw;
this.ctx = ctx;
this.env = env;
}
}
@ -32,10 +32,10 @@ public class Engine {
public final Object thisArg;
public final Object[] args;
public final DataNotifier<Object> notifier = new DataNotifier<>();
public final Message ctx;
public final Message msg;
public Task(Message ctx, FunctionValue func, Object thisArg, Object[] args) {
this.ctx = ctx;
this.msg = ctx;
this.func = func;
this.thisArg = thisArg;
this.args = args;
@ -52,7 +52,7 @@ public class Engine {
private void runTask(Task task) throws InterruptedException {
try {
task.notifier.next(task.func.call(new Context(null, task.ctx), task.thisArg, task.args));
task.notifier.next(task.func.call(task.msg.context(null), task.thisArg, task.args));
}
catch (InterruptedException e) {
task.notifier.error(new RuntimeException(e));

View File

@ -15,15 +15,23 @@ import me.topchetoeu.jscript.interop.NativeWrapperProvider;
public class Environment {
private HashMap<String, ObjectValue> prototypes = new HashMap<>();
public final Data data = new Data();
public final HashMap<String, Symbol> symbols = new HashMap<>();
public GlobalScope global;
public WrappersProvider wrappersProvider;
/** NOTE: This is not the register for Symbol.for, but for the symbols like Symbol.iterator */
public HashMap<String, Symbol> symbols = new HashMap<>();
@Native public FunctionValue compile;
@Native public FunctionValue regexConstructor = new NativeFunction("RegExp", (ctx, thisArg, args) -> {
throw EngineException.ofError("Regular expressions not supported.").setContext(ctx);
});
public Environment addData(Data data) {
this.data.addAll(data);
return this;
}
@Native public ObjectValue proto(String name) {
return prototypes.get(name);
}

View File

@ -13,8 +13,15 @@ public class Message {
private final ArrayList<CodeFrame> frames = new ArrayList<>();
public int maxStackFrames = 1000;
public final Data data = new Data();
public List<CodeFrame> frames() { return Collections.unmodifiableList(frames); }
public Message addData(Data data) {
this.data.addAll(data);
return this;
}
public Message pushFrame(Context ctx, CodeFrame frame) throws InterruptedException {
this.frames.add(frame);
if (this.frames.size() > maxStackFrames) throw EngineException.ofRange("Stack overflow!");

View File

@ -29,7 +29,7 @@ public class CodeFunction extends FunctionValue {
@Override
public Object call(Context ctx, Object thisArg, Object ...args) throws InterruptedException {
return new CodeFrame(ctx, thisArg, args, this).run(new Context(environment, ctx.message));
return new CodeFrame(ctx, thisArg, args, this).run(ctx.setEnv(environment));
}
public CodeFunction(Environment environment, String name, int localsN, int length, ValueVariable[] captures, Instruction[] body) {