Compare commits
9 Commits
0.9.10-bet
...
0.9.17-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
d38b600366
|
|||
|
0ac7af2ea3
|
|||
|
5185c93663
|
|||
|
510422cab7
|
|||
|
79e1d1cfaf
|
|||
|
e0f3274a95
|
|||
| ef5d29105f | |||
|
d8ea6557df
|
|||
|
5ba858545a
|
2
.github/workflows/tagged-release.yml
vendored
2
.github/workflows/tagged-release.yml
vendored
@@ -3,7 +3,7 @@ name: "tagged-release"
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
tagged-release:
|
||||
|
||||
@@ -23,7 +23,3 @@ engine.run(true);
|
||||
// Get our result
|
||||
System.out.println(awaitable.await());
|
||||
```
|
||||
|
||||
## NOTE:
|
||||
|
||||
To setup the typescript bundle in your sources, run `node build.js init-ts`. This will download the latest version of typescript, minify it, and add it to your src folder. If you are going to work with the `node build.js debug|release` command, this is not a necessary step.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
project_group = me.topchetoeu
|
||||
project_name = jscript
|
||||
project_version = 0.9.10-beta
|
||||
project_version = 0.9.12-beta
|
||||
main_class = me.topchetoeu.jscript.utils.JScriptRepl
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package me.topchetoeu.jscript.compilation.control;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.Location;
|
||||
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
|
||||
import me.topchetoeu.jscript.compilation.CompileResult;
|
||||
import me.topchetoeu.jscript.compilation.Statement;
|
||||
|
||||
public class ForOfStatement extends Statement {
|
||||
public final String varName;
|
||||
public final boolean isDeclaration;
|
||||
public final Statement iterable, body;
|
||||
public final String label;
|
||||
public final Location varLocation;
|
||||
|
||||
@Override
|
||||
public void declare(CompileResult target) {
|
||||
body.declare(target);
|
||||
if (isDeclaration) target.scope.define(varName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compile(CompileResult target, boolean pollute) {
|
||||
var key = target.scope.getKey(varName);
|
||||
|
||||
if (key instanceof String) target.add(Instruction.makeVar((String)key));
|
||||
|
||||
iterable.compile(target, true, BreakpointType.STEP_OVER);
|
||||
target.add(Instruction.dup());
|
||||
target.add(Instruction.loadVar("Symbol"));
|
||||
target.add(Instruction.pushValue("iterator"));
|
||||
target.add(Instruction.loadMember()).setLocation(iterable.loc());
|
||||
target.add(Instruction.loadMember()).setLocation(iterable.loc());
|
||||
target.add(Instruction.call(0)).setLocation(iterable.loc());
|
||||
|
||||
int start = target.size();
|
||||
target.add(Instruction.dup());
|
||||
target.add(Instruction.dup());
|
||||
target.add(Instruction.pushValue("next"));
|
||||
target.add(Instruction.loadMember()).setLocation(iterable.loc());
|
||||
target.add(Instruction.call(0)).setLocation(iterable.loc());
|
||||
target.add(Instruction.dup());
|
||||
target.add(Instruction.pushValue("done"));
|
||||
target.add(Instruction.loadMember()).setLocation(iterable.loc());
|
||||
int mid = target.temp();
|
||||
|
||||
target.add(Instruction.pushValue("value"));
|
||||
target.add(Instruction.loadMember()).setLocation(varLocation);
|
||||
target.add(Instruction.storeVar(key)).setLocationAndDebug(iterable.loc(), BreakpointType.STEP_OVER);
|
||||
|
||||
body.compile(target, false, BreakpointType.STEP_OVER);
|
||||
|
||||
int end = target.size();
|
||||
|
||||
WhileStatement.replaceBreaks(target, label, mid + 1, end, start, end + 1);
|
||||
|
||||
target.add(Instruction.jmp(start - end));
|
||||
target.add(Instruction.discard());
|
||||
target.add(Instruction.discard());
|
||||
target.set(mid, Instruction.jmpIf(end - mid + 1));
|
||||
if (pollute) target.add(Instruction.pushUndefined());
|
||||
}
|
||||
|
||||
public ForOfStatement(Location loc, Location varLocation, String label, boolean isDecl, String varName, Statement object, Statement body) {
|
||||
super(loc);
|
||||
this.varLocation = varLocation;
|
||||
this.label = label;
|
||||
this.isDeclaration = isDecl;
|
||||
this.varName = varName;
|
||||
this.iterable = object;
|
||||
this.body = body;
|
||||
}
|
||||
}
|
||||
@@ -1777,6 +1777,46 @@ public class Parsing {
|
||||
|
||||
return ParseRes.res(new ForInStatement(loc, nameLoc, labelRes.result, isDecl, nameRes.result, varVal, objRes.result, bodyRes.result), n);
|
||||
}
|
||||
public static ParseRes<ForOfStatement> parseForOf(Filename filename, List<Token> tokens, int i) {
|
||||
var loc = getLoc(filename, tokens, i);
|
||||
int n = 0;
|
||||
|
||||
var labelRes = parseLabel(tokens, i + n);
|
||||
var isDecl = false;
|
||||
n += labelRes.n;
|
||||
|
||||
if (!isIdentifier(tokens, i + n++, "for")) return ParseRes.failed();
|
||||
if (!isOperator(tokens, i + n++, Operator.PAREN_OPEN)) return ParseRes.error(loc, "Expected a open paren after 'for'.");
|
||||
|
||||
if (isIdentifier(tokens, i + n, "var")) {
|
||||
isDecl = true;
|
||||
n++;
|
||||
}
|
||||
|
||||
var nameRes = parseIdentifier(tokens, i + n);
|
||||
if (!nameRes.isSuccess()) return ParseRes.error(loc, "Expected a variable name for 'for' loop.");
|
||||
var nameLoc = getLoc(filename, tokens, i + n);
|
||||
n += nameRes.n;
|
||||
|
||||
if (!isIdentifier(tokens, i + n++, "of")) {
|
||||
if (nameRes.result.equals("const")) return ParseRes.error(loc, "'const' declarations are not supported.");
|
||||
else if (nameRes.result.equals("let")) return ParseRes.error(loc, "'let' declarations are not supported.");
|
||||
else return ParseRes.error(loc, "Expected 'of' keyword after variable declaration.");
|
||||
}
|
||||
|
||||
var objRes = parseValue(filename, tokens, i + n, 0);
|
||||
if (!objRes.isSuccess()) return ParseRes.error(loc, "Expected a value.", objRes);
|
||||
n += objRes.n;
|
||||
|
||||
if (!isOperator(tokens, i + n++, Operator.PAREN_CLOSE)) return ParseRes.error(loc, "Expected a closing paren after for.");
|
||||
|
||||
|
||||
var bodyRes = parseStatement(filename, tokens, i + n);
|
||||
if (!bodyRes.isSuccess()) return ParseRes.error(loc, "Expected a for body.", bodyRes);
|
||||
n += bodyRes.n;
|
||||
|
||||
return ParseRes.res(new ForOfStatement(loc, nameLoc, labelRes.result, isDecl, nameRes.result, objRes.result, bodyRes.result), n);
|
||||
}
|
||||
public static ParseRes<TryStatement> parseCatch(Filename filename, List<Token> tokens, int i) {
|
||||
var loc = getLoc(filename, tokens, i);
|
||||
int n = 0;
|
||||
@@ -1833,6 +1873,7 @@ public class Parsing {
|
||||
parseSwitch(filename, tokens, i),
|
||||
parseFor(filename, tokens, i),
|
||||
parseForIn(filename, tokens, i),
|
||||
parseForOf(filename, tokens, i),
|
||||
parseDoWhile(filename, tokens, i),
|
||||
parseCatch(filename, tokens, i),
|
||||
parseCompound(filename, tokens, i),
|
||||
|
||||
@@ -54,7 +54,7 @@ public class AsyncFunctionLib extends FunctionValue {
|
||||
public void onReject(EngineException err) {
|
||||
next(ctx, Values.NO_RETURN, err);
|
||||
}
|
||||
});
|
||||
}.defer(ctx));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ public class AsyncGeneratorLib {
|
||||
@Override public void onReject(EngineException err) {
|
||||
next(ctx, Values.NO_RETURN, Values.NO_RETURN, err);
|
||||
}
|
||||
});
|
||||
}.defer(ctx));
|
||||
}
|
||||
else if (state == 2) {
|
||||
var obj = new ObjectValue();
|
||||
|
||||
@@ -8,8 +8,16 @@ public class NativeWrapper extends ObjectValue {
|
||||
|
||||
@Override
|
||||
public ObjectValue getPrototype(Context ctx) {
|
||||
if (ctx.environment != null && prototype == NATIVE_PROTO) return ctx.environment.wrappers.getProto(wrapped.getClass());
|
||||
else return super.getPrototype(ctx);
|
||||
if (ctx.environment != null && prototype == NATIVE_PROTO) {
|
||||
var clazz = wrapped.getClass();
|
||||
|
||||
while (true) {
|
||||
var res = ctx.environment.wrappers.getProto(clazz);
|
||||
if (res != null) return res;
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
}
|
||||
return super.getPrototype(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -153,18 +153,18 @@ public class ObjectValue {
|
||||
}
|
||||
|
||||
public ObjectValue getPrototype(Context ctx) {
|
||||
if (prototype instanceof ObjectValue || prototype == null) return (ObjectValue)prototype;
|
||||
|
||||
try {
|
||||
if (prototype == OBJ_PROTO) return ctx.get(Environment.OBJECT_PROTO);
|
||||
if (prototype == ARR_PROTO) return ctx.get(Environment.ARRAY_PROTO);
|
||||
if (prototype == FUNC_PROTO) return ctx.get(Environment.FUNCTION_PROTO);
|
||||
if (prototype == ERR_PROTO) return ctx.get(Environment.ERROR_PROTO);
|
||||
if (prototype == RANGE_ERR_PROTO) return ctx.get(Environment.RANGE_ERR_PROTO);
|
||||
if (prototype == SYNTAX_ERR_PROTO) return ctx.get(Environment.SYNTAX_ERR_PROTO);
|
||||
if (prototype == TYPE_ERR_PROTO) return ctx.get(Environment.TYPE_ERR_PROTO);
|
||||
return ctx.get(Environment.OBJECT_PROTO);
|
||||
}
|
||||
catch (NullPointerException e) { return null; }
|
||||
|
||||
return (ObjectValue)prototype;
|
||||
}
|
||||
public final boolean setPrototype(PlaceholderProto val) {
|
||||
if (!extensible()) return false;
|
||||
|
||||
@@ -25,6 +25,7 @@ public class NativeWrapperProvider implements WrapperProvider {
|
||||
private final HashMap<Class<?>, FunctionValue> constructors = new HashMap<>();
|
||||
private final HashMap<Class<?>, ObjectValue> prototypes = new HashMap<>();
|
||||
private final HashMap<Class<?>, ObjectValue> namespaces = new HashMap<>();
|
||||
private final HashSet<Class<?>> ignore = new HashSet<>();
|
||||
private final Environment env;
|
||||
|
||||
private static Object call(Context ctx, String name, Method method, Object thisArg, Object... args) {
|
||||
@@ -106,11 +107,12 @@ public class NativeWrapperProvider implements WrapperProvider {
|
||||
else return name;
|
||||
}
|
||||
|
||||
private static void apply(ObjectValue obj, Environment env, ExposeTarget target, Class<?> clazz) {
|
||||
private static boolean apply(ObjectValue obj, Environment env, ExposeTarget target, Class<?> clazz) {
|
||||
var getters = new HashMap<Object, FunctionValue>();
|
||||
var setters = new HashMap<Object, FunctionValue>();
|
||||
var props = new HashSet<Object>();
|
||||
var nonProps = new HashSet<Object>();
|
||||
var any = false;
|
||||
|
||||
for (var method : clazz.getDeclaredMethods()) {
|
||||
for (var annotation : method.getAnnotationsByType(Expose.class)) {
|
||||
@@ -120,6 +122,7 @@ public class NativeWrapperProvider implements WrapperProvider {
|
||||
var name = getName(method, annotation.value());
|
||||
var key = getKey(name);
|
||||
var repeat = false;
|
||||
any = true;
|
||||
|
||||
switch (annotation.type()) {
|
||||
case INIT:
|
||||
@@ -168,6 +171,7 @@ public class NativeWrapperProvider implements WrapperProvider {
|
||||
var name = getName(method, annotation.value());
|
||||
var key = getKey(name);
|
||||
var repeat = false;
|
||||
any = true;
|
||||
|
||||
if (props.contains(key) || nonProps.contains(key)) repeat = true;
|
||||
else {
|
||||
@@ -191,11 +195,29 @@ public class NativeWrapperProvider implements WrapperProvider {
|
||||
var name = getName(field, annotation.value());
|
||||
var key = getKey(name);
|
||||
var repeat = false;
|
||||
any = true;
|
||||
|
||||
if (props.contains(key) || nonProps.contains(key)) repeat = true;
|
||||
else {
|
||||
try {
|
||||
obj.defineProperty(null, key, Values.normalize(new Context(env), field.get(null)), true, true, false);
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
obj.defineProperty(null, key, Values.normalize(new Context(env), field.get(null)), true, true, false);
|
||||
}
|
||||
else {
|
||||
obj.defineProperty(
|
||||
null, key,
|
||||
new NativeFunction("get " + key, args -> {
|
||||
try { return field.get(args.self(clazz)); }
|
||||
catch (IllegalAccessException e) { e.printStackTrace(); return null; }
|
||||
}),
|
||||
Modifier.isFinal(field.getModifiers()) ? null : new NativeFunction("get " + key, args -> {
|
||||
try { field.set(args.self(clazz), args.convert(0, field.getType())); }
|
||||
catch (IllegalAccessException e) { e.printStackTrace(); }
|
||||
return null;
|
||||
}),
|
||||
true, false
|
||||
);
|
||||
}
|
||||
nonProps.add(key);
|
||||
}
|
||||
catch (IllegalArgumentException | IllegalAccessException e) { }
|
||||
@@ -210,6 +232,8 @@ public class NativeWrapperProvider implements WrapperProvider {
|
||||
}
|
||||
|
||||
for (var key : props) obj.defineProperty(null, key, getters.get(key), setters.get(key), true, false);
|
||||
|
||||
return any;
|
||||
}
|
||||
|
||||
private static Method getConstructor(Environment env, Class<?> clazz) {
|
||||
@@ -231,7 +255,7 @@ public class NativeWrapperProvider implements WrapperProvider {
|
||||
public static ObjectValue makeProto(Environment env, Class<?> clazz) {
|
||||
var res = new ObjectValue();
|
||||
res.defineProperty(null, Symbol.get("Symbol.typeName"), getName(clazz));
|
||||
apply(res, env, ExposeTarget.PROTOTYPE, clazz);
|
||||
if (!apply(res, env, ExposeTarget.PROTOTYPE, clazz)) return null;
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
@@ -260,12 +284,12 @@ public class NativeWrapperProvider implements WrapperProvider {
|
||||
public static ObjectValue makeNamespace(Environment ctx, Class<?> clazz) {
|
||||
var res = new ObjectValue();
|
||||
res.defineProperty(null, Symbol.get("Symbol.typeName"), getName(clazz));
|
||||
apply(res, ctx, ExposeTarget.NAMESPACE, clazz);
|
||||
if (!apply(res, ctx, ExposeTarget.NAMESPACE, clazz)) return null;
|
||||
return res;
|
||||
}
|
||||
|
||||
private void initType(Class<?> clazz, FunctionValue constr, ObjectValue proto) {
|
||||
if (constr != null && proto != null) return;
|
||||
if (constr != null && proto != null || ignore.contains(clazz)) return;
|
||||
// i vomit
|
||||
if (
|
||||
clazz == Object.class ||
|
||||
@@ -284,20 +308,27 @@ public class NativeWrapperProvider implements WrapperProvider {
|
||||
if (constr == null) constr = makeConstructor(env, clazz);
|
||||
if (proto == null) proto = makeProto(env, clazz);
|
||||
|
||||
if (constr == null || proto == null) return;
|
||||
|
||||
proto.defineProperty(null, "constructor", constr, true, false, false);
|
||||
constr.defineProperty(null, "prototype", proto, true, false, false);
|
||||
|
||||
prototypes.put(clazz, proto);
|
||||
constructors.put(clazz, constr);
|
||||
|
||||
var parent = clazz.getSuperclass();
|
||||
if (parent == null) return;
|
||||
var parent = clazz;
|
||||
|
||||
var parentProto = getProto(parent);
|
||||
var parentConstr = getConstr(parent);
|
||||
while (true) {
|
||||
parent = parent.getSuperclass();
|
||||
if (parent == null) return;
|
||||
|
||||
if (parentProto != null) Values.setPrototype(Context.NULL, proto, parentProto);
|
||||
if (parentConstr != null) Values.setPrototype(Context.NULL, constr, parentConstr);
|
||||
var parentProto = getProto(parent);
|
||||
var parentConstr = getConstr(parent);
|
||||
|
||||
if (parentProto != null) Values.setPrototype(Context.NULL, proto, parentProto);
|
||||
if (parentConstr != null) Values.setPrototype(Context.NULL, constr, parentConstr);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectValue getProto(Class<?> clazz) {
|
||||
@@ -317,11 +348,23 @@ public class NativeWrapperProvider implements WrapperProvider {
|
||||
return new NativeWrapperProvider(env);
|
||||
}
|
||||
|
||||
public void setProto(Class<?> clazz, ObjectValue value) {
|
||||
prototypes.put(clazz, value);
|
||||
public void set(Class<?> clazz, Class<?> wrapper) {
|
||||
if (wrapper == null) set(clazz, null, null);
|
||||
else set(clazz, makeProto(env, wrapper), makeConstructor(env, wrapper));
|
||||
}
|
||||
public void setConstr(Class<?> clazz, FunctionValue value) {
|
||||
constructors.put(clazz, value);
|
||||
public void set(Class<?> clazz, ObjectValue proto, FunctionValue constructor) {
|
||||
if (proto != null && constructor != null) {
|
||||
prototypes.put(clazz, proto);
|
||||
constructors.put(clazz, constructor);
|
||||
ignore.remove(clazz);
|
||||
}
|
||||
else {
|
||||
prototypes.remove(clazz);
|
||||
constructors.remove(clazz);
|
||||
ignore.remove(clazz);
|
||||
|
||||
initType(clazz, constructor, proto);
|
||||
}
|
||||
}
|
||||
|
||||
private void initError() {
|
||||
@@ -337,8 +380,7 @@ public class NativeWrapperProvider implements WrapperProvider {
|
||||
proto.defineProperty(null, "constructor", constr, true, false, false);
|
||||
constr.defineProperty(null, "prototype", proto, true, false, false);
|
||||
|
||||
setProto(Throwable.class, proto);
|
||||
setConstr(Throwable.class, constr);
|
||||
set(Throwable.class, proto, constr);
|
||||
}
|
||||
|
||||
public NativeWrapperProvider(Environment env) {
|
||||
|
||||
Reference in New Issue
Block a user