From 343684f9ce5012c967449fdf353671f2431794ea Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Wed, 22 Jan 2025 03:57:32 +0200 Subject: [PATCH] move more instructions as intrinsics --- .../me/topchetoeu/j2s/common/Instruction.java | 18 +------ .../j2s/compilation/control/ForInNode.java | 11 ++-- .../members/PropertyMemberNode.java | 15 ++++-- .../j2s/compilation/scope/VariableIndex.java | 6 +-- lib/src/stdlib/_entry.ts | 17 +++++- lib/src/stdlib/primordials.ts | 4 +- lib/src/stdlib/values/object.ts | 24 ++++----- .../me/topchetoeu/j2s/repl/SimpleRepl.java | 8 +-- .../j2s/runtime/InstructionRunner.java | 53 ------------------- 9 files changed, 59 insertions(+), 97 deletions(-) diff --git a/common/src/main/java/me/topchetoeu/j2s/common/Instruction.java b/common/src/main/java/me/topchetoeu/j2s/common/Instruction.java index 8746478..59487dd 100644 --- a/common/src/main/java/me/topchetoeu/j2s/common/Instruction.java +++ b/common/src/main/java/me/topchetoeu/j2s/common/Instruction.java @@ -51,9 +51,6 @@ public class Instruction { STORE_MEMBER_INT(0x4A), STORE_MEMBER_STR(0x4B), - DEF_PROP(0x50), - DEF_FIELD(0x51), - KEYS(0x52), TYPEOF(0x53), OPERATION(0x54), @@ -307,8 +304,8 @@ public class Instruction { return new Instruction(Type.DUP, count, offset); } - public static Instruction storeVar(int i, boolean keep, boolean initialize) { - return new Instruction(Type.STORE_VAR, i, keep, initialize); + public static Instruction storeVar(int i, boolean keep) { + return new Instruction(Type.STORE_VAR, i, keep); } public static Instruction storeMember() { @@ -343,17 +340,6 @@ public class Instruction { return new Instruction(Type.TYPEOF, varName); } - public static Instruction keys(boolean own, boolean onlyEnumerable) { - return new Instruction(Type.KEYS, own, onlyEnumerable); - } - - public static Instruction defProp(boolean setter) { - return new Instruction(Type.DEF_PROP, setter); - } - public static Instruction defField() { - return new Instruction(Type.DEF_FIELD); - } - public static Instruction operation(Operation op) { return new Instruction(Type.OPERATION, op); } diff --git a/compilation/src/main/java/me/topchetoeu/j2s/compilation/control/ForInNode.java b/compilation/src/main/java/me/topchetoeu/j2s/compilation/control/ForInNode.java index a11bce8..7d9d017 100644 --- a/compilation/src/main/java/me/topchetoeu/j2s/compilation/control/ForInNode.java +++ b/compilation/src/main/java/me/topchetoeu/j2s/compilation/control/ForInNode.java @@ -31,13 +31,18 @@ public class ForInNode extends Node { body.compileFunctions(target); } @Override public void compile(CompileResult target, boolean pollute) { + target.add(Instruction.loadIntrinsics("keys")); object.compile(target, true, BreakpointType.STEP_OVER); - target.add(Instruction.keys(false, true)); + target.add(Instruction.pushValue(false)); + target.add(Instruction.pushValue(true)); + target.add(Instruction.call(3, false)); int start = target.size(); target.add(Instruction.dup()); + target.add(Instruction.call(0, false)); + target.add(Instruction.dup()); + target.add(Instruction.loadMember("done")); int mid = target.temp(); - target.add(Instruction.loadMember("value")).setLocation(binding.loc()); target.add(VariableNode.toSet(target, loc(), binding.name, false, true)).setLocation(binding.loc()); @@ -52,7 +57,7 @@ public class ForInNode extends Node { target.add(Instruction.jmp(start - endI)); target.add(Instruction.discard()); - target.set(mid, Instruction.jmpIfNot(endI - mid + 1)); + target.set(mid, Instruction.jmpIf(endI - mid + 1)); end.set(endI + 1); LabelContext.popLoop(target.env, label); diff --git a/compilation/src/main/java/me/topchetoeu/j2s/compilation/members/PropertyMemberNode.java b/compilation/src/main/java/me/topchetoeu/j2s/compilation/members/PropertyMemberNode.java index 658b61b..965a023 100644 --- a/compilation/src/main/java/me/topchetoeu/j2s/compilation/members/PropertyMemberNode.java +++ b/compilation/src/main/java/me/topchetoeu/j2s/compilation/members/PropertyMemberNode.java @@ -38,11 +38,20 @@ public final class PropertyMemberNode extends FunctionNode implements Member { } @Override public void compile(CompileResult target, boolean pollute, String name, BreakpointType bp) { - if (pollute) target.add(Instruction.dup()); - key.compile(target, true); + if (isGetter()) { + target.add(Instruction.loadIntrinsics("defGetter")); + } + else { + target.add(Instruction.loadIntrinsics("defSetter")); + } + target.add(Instruction.dup(1, 1)); + key.compile(target, true); target.add(Instruction.loadFunc(target.childrenIndices.get(this), name(name), captures(target))).setLocation(loc()); - target.add(Instruction.defProp(isSetter())); + target.add(Instruction.call(3, false)); + target.add(Instruction.discard()); + + if (!pollute) target.add(Instruction.discard()); } public PropertyMemberNode(Location loc, Location end, Node key, VariableNode argument, CompoundNode body) { diff --git a/compilation/src/main/java/me/topchetoeu/j2s/compilation/scope/VariableIndex.java b/compilation/src/main/java/me/topchetoeu/j2s/compilation/scope/VariableIndex.java index 809037d..f0cf9fb 100644 --- a/compilation/src/main/java/me/topchetoeu/j2s/compilation/scope/VariableIndex.java +++ b/compilation/src/main/java/me/topchetoeu/j2s/compilation/scope/VariableIndex.java @@ -39,9 +39,9 @@ public final class VariableIndex { } public final Instruction toSet(boolean keep) { switch (type) { - case CAPTURES: return Instruction.storeVar(~index, keep, false); - case CAPTURABLES: return Instruction.storeVar(index, keep, false); - case LOCALS: return Instruction.storeVar(index, keep, false); + case CAPTURES: return Instruction.storeVar(~index, keep); + case CAPTURABLES: return Instruction.storeVar(index, keep); + case LOCALS: return Instruction.storeVar(index, keep); default: throw new UnsupportedOperationException("Unknown index type " + type); } } diff --git a/lib/src/stdlib/_entry.ts b/lib/src/stdlib/_entry.ts index 6aab2a8..e2dab74 100644 --- a/lib/src/stdlib/_entry.ts +++ b/lib/src/stdlib/_entry.ts @@ -88,4 +88,19 @@ setGlobalPrototypes({ uint8: Uint8Array.prototype, int32: Int32Array.prototype, }); -setIntrinsic("regex", RegExp); \ No newline at end of file +setIntrinsic("regex", RegExp); +setIntrinsic("keys", (obj: object, own: boolean, onlyEnumerable: boolean) => { + const members = object.getMembers(obj, own, onlyEnumerable); + + let i = 0; + return () => { + if (i >= members.length) return { done: true }; + else return { value: members[i++] }; + }; +}); +setIntrinsic("defGetter", (obj: object, key: any, func: Function) => { + object.defineProperty(obj, key, { g: func, e: true, c: true }); +}); +setIntrinsic("defSetter", (obj: object, key: any, func: Function) => { + object.defineProperty(obj, key, { s: func, e: true, c: true }); +}); \ No newline at end of file diff --git a/lib/src/stdlib/primordials.ts b/lib/src/stdlib/primordials.ts index 7c9c9ea..a7c170d 100644 --- a/lib/src/stdlib/primordials.ts +++ b/lib/src/stdlib/primordials.ts @@ -39,8 +39,8 @@ export interface ObjectPrimordials { defineProperty(obj: object, key: string | number | symbol, conf: { g?: Function, s?: Function, e?: boolean, c?: boolean }): boolean; defineField(obj: object, key: string | number | symbol, conf: { v?: any, e?: boolean, c?: boolean, w?: boolean }): boolean; getOwnMember(obj: object, key: any): PropertyDescriptor | undefined; - getOwnMembers(obj: object, onlyEnumerable: boolean): string[]; - getOwnSymbolMembers(obj: object, onlyEnumerable: boolean): symbol[]; + getMembers(obj: object, own: boolean, onlyEnumerable: boolean): string[]; + getSymbolMembers(obj: object, own: boolean, onlyEnumerable: boolean): symbol[]; getPrototype(obj: object): object | undefined; setPrototype(obj: object, proto?: object): object; preventExt(obj: object): void; diff --git a/lib/src/stdlib/values/object.ts b/lib/src/stdlib/values/object.ts index 3ebfba4..3b6b549 100644 --- a/lib/src/stdlib/values/object.ts +++ b/lib/src/stdlib/values/object.ts @@ -55,10 +55,10 @@ export const Object = (() => { return object.getOwnMember(obj, key); } public static getOwnPropertyNames(obj: object): string[] { - return object.getOwnMembers(obj, false); + return object.getMembers(obj, true, false); } public static getOwnPropertySymbols(obj: object): symbol[] { - return object.getOwnSymbolMembers(obj, false); + return object.getSymbolMembers(obj, true, false); } public static defineProperty(obj: object, key: string | symbol, desc: PropertyDescriptor) { @@ -98,8 +98,8 @@ export const Object = (() => { return obj; } public static defineProperties(obj: object, desc: PropertyDescriptorMap) { - const keys = object.getOwnMembers(desc, true) as ((keyof typeof obj) & string)[]; - const symbols = object.getOwnSymbolMembers(desc, true) as ((keyof typeof obj) & symbol)[]; + const keys = object.getMembers(desc, true, true) as ((keyof typeof obj) & string)[]; + const symbols = object.getSymbolMembers(desc, true, true) as ((keyof typeof obj) & symbol)[]; for (let i = 0; i < keys.length; i++) { Object.defineProperty(obj, keys[i], desc[keys[i]]); @@ -119,8 +119,8 @@ export const Object = (() => { public static assign(target: any) { for (let i = 1; i < arguments.length; i++) { const obj = arguments[i]; - const keys = object.getOwnMembers(obj, false); - const symbols = object.getOwnSymbolMembers(obj, false); + const keys = object.getMembers(obj, true, false); + const symbols = object.getSymbolMembers(obj, true, false); for (let j = 0; j < keys.length; j++) { target[keys[j]] = obj[keys[j]]; @@ -142,8 +142,8 @@ export const Object = (() => { public static keys(obj: any) { const res: any[] = []; - const keys = object.getOwnMembers(obj, true); - const symbols = object.getOwnSymbolMembers(obj, true); + const keys = object.getMembers(obj, true, true); + const symbols = object.getSymbolMembers(obj, true, true); for (let i = 0; i < keys.length; i++) { res[res.length] = keys[i]; @@ -156,8 +156,8 @@ export const Object = (() => { } public static values(obj: any) { const res: any[] = []; - const keys = object.getOwnMembers(obj, true); - const symbols = object.getOwnSymbolMembers(obj, true); + const keys = object.getMembers(obj, true, true); + const symbols = object.getSymbolMembers(obj, true, true); for (let i = 0; i < keys.length; i++) { res[res.length] = obj[keys[i]]; @@ -170,8 +170,8 @@ export const Object = (() => { } public static entries(obj: any) { const res: [any, any][] = []; - const keys = object.getOwnMembers(obj, true); - const symbols = object.getOwnSymbolMembers(obj, true); + const keys = object.getMembers(obj, true, true); + const symbols = object.getSymbolMembers(obj, true, true); for (let i = 0; i < keys.length; i++) { res[res.length] = [keys[i], obj[keys[i]]]; diff --git a/repl/src/main/java/me/topchetoeu/j2s/repl/SimpleRepl.java b/repl/src/main/java/me/topchetoeu/j2s/repl/SimpleRepl.java index 15e1108..9047c44 100644 --- a/repl/src/main/java/me/topchetoeu/j2s/repl/SimpleRepl.java +++ b/repl/src/main/java/me/topchetoeu/j2s/repl/SimpleRepl.java @@ -545,17 +545,17 @@ public class SimpleRepl { args.get(0).setPrototype(env, proto); return args.get(0); })); - res.defineOwnField(env, "getOwnMembers", new NativeFunction(args -> { + res.defineOwnField(env, "getMembers", new NativeFunction(args -> { var val = new ArrayValue(); - for (var key : args.get(0).getOwnMembers(env, args.get(1).toBoolean())) { + for (var key : args.get(0).getMembers(env, args.get(1).toBoolean(), args.get(2).toBoolean())) { val.set(args.env, val.size(), StringValue.of(key)); } return val; })); - res.defineOwnField(env, "getOwnSymbolMembers", new NativeFunction(args -> { - return ArrayValue.of(args.get(0).getOwnSymbolMembers(env, args.get(1).toBoolean())); + res.defineOwnField(env, "getSymbolMembers", new NativeFunction(args -> { + return ArrayValue.of(args.get(0).getSymbolMembers(env, args.get(1).toBoolean(), args.get(2).toBoolean())); })); res.defineOwnField(env, "getOwnMember", new NativeFunction(args -> { var obj = args.get(0); diff --git a/runtime/src/main/java/me/topchetoeu/j2s/runtime/InstructionRunner.java b/runtime/src/main/java/me/topchetoeu/j2s/runtime/InstructionRunner.java index 3fdf0d1..7d33795 100644 --- a/runtime/src/main/java/me/topchetoeu/j2s/runtime/InstructionRunner.java +++ b/runtime/src/main/java/me/topchetoeu/j2s/runtime/InstructionRunner.java @@ -1,16 +1,11 @@ package me.topchetoeu.j2s.runtime; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Optional; - import me.topchetoeu.j2s.common.Environment; import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Operation; import me.topchetoeu.j2s.runtime.exceptions.EngineException; import me.topchetoeu.j2s.runtime.values.Value; import me.topchetoeu.j2s.runtime.values.functions.CodeFunction; -import me.topchetoeu.j2s.runtime.values.functions.FunctionValue; import me.topchetoeu.j2s.runtime.values.objects.ArrayValue; import me.topchetoeu.j2s.runtime.values.objects.ObjectValue; import me.topchetoeu.j2s.runtime.values.primitives.BoolValue; @@ -48,51 +43,6 @@ public class InstructionRunner { return null; } - private static Value execDefProp(Environment env, Instruction instr, Frame frame) { - var val = frame.pop(); - var key = frame.pop(); - var obj = frame.pop(); - - FunctionValue accessor; - - if (val == Value.UNDEFINED) accessor = null; - else if (val instanceof FunctionValue func) accessor = func; - else throw EngineException.ofType("Getter must be a function or undefined"); - - if ((boolean)instr.get(0)) obj.defineOwnProperty(env, key, null, Optional.of(accessor), true, true); - else obj.defineOwnProperty(env, key, Optional.of(accessor), null, true, true); - - frame.codePtr++; - return null; - } - private static Value execDefField(Environment env, Instruction instr, Frame frame) { - var val = frame.pop(); - var key = frame.pop(); - var obj = frame.pop(); - - obj.defineOwnField(env, key, val, true, true, true); - - frame.codePtr++; - return null; - } - private static Value execKeys(Environment env, Instruction instr, Frame frame) { - var val = frame.pop(); - - var members = new ArrayList<>(val.getMembers(env, instr.get(0), instr.get(1))); - Collections.reverse(members); - - frame.push(Value.UNDEFINED); - - for (var el : members) { - var obj = new ObjectValue(); - obj.defineOwnField(env, "value", StringValue.of(el)); - frame.push(obj); - } - - frame.codePtr++; - return null; - } - private static Value execTryStart(Environment env, Instruction instr, Frame frame) { int start = frame.codePtr + 1; int catchStart = (int)instr.get(0); @@ -531,9 +481,6 @@ public class InstructionRunner { case STORE_MEMBER_INT: return execStoreMemberInt(env, instr, frame); case STORE_VAR: return execStoreVar(env, instr, frame); - case KEYS: return execKeys(env, instr, frame); - case DEF_PROP: return execDefProp(env, instr, frame); - case DEF_FIELD: return execDefField(env, instr, frame); case TYPEOF: return execTypeof(env, instr, frame); case DELETE: return execDelete(env, instr, frame);