Warning: session_start(): open(/var/lib/php/sessions/sess_qb9t33qefl6vb43a72l2hisvdu, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
// See GazelleV_LeftArrowScriptParser
// TODO: decide whether we allow calling methods/getting fields on
// a null reference (just returning null), or whether we throw a
// NullPointerException. Currently we just return null. Probably
// that's pretty cool. Null propagation as a default, just like in
// JavaX. Just more automatic!
sclass GazelleV_LeftArrowScript {
// Base = any script element with a reference to its source code
asclass Base is IHasTokenRangeWithSrc {
TokenRangeWithSrc src;
public void setTokenRangeWithSrc(TokenRangeWithSrc src) { this.src = src; }
public TokenRangeWithSrc tokenRangeWithSrc() { ret src; }
RuntimeException rethrowWithSrc(Throwable e) {
if (src != null)
throw rethrowAndAppendToMessage(e, squareBracketed(str(src)));
else
throw rethrow(e);
}
}
// Evaluable = a script element that can be evaluated
interface Evaluable extends IF0 {
public O get(VarContext ctx default new);
public default LASValueDescriptor returnType() { null; }
public default Evaluable optimize() { this; }
}
// Base + Evaluable + explicitly stored return type
asclass BaseEvaluable > Base is Evaluable {
settable LASValueDescriptor returnType;
}
/*interface Cmd {
// returns true if a return was issued
public bool run(VarContext ctx default new);
}*/
static new AtomicLong scriptIDCounter;
static long scriptID() { ret incAtomicLong(scriptIDCounter); }
sclass Script > Base is Evaluable {
long id = scriptID(); // just for printing
Map functionDefs;
Evaluable[] steps;
public O get(VarContext ctx) {
O result = null;
for (step : steps) {
ping();
result = step.get(ctx);
// exiting from anything?
var exiting = ctx.exitFromScript;
if (exiting != null) {
printVars ifdef ReturnFromScript_debug("Checking exitFromScript",
+ctx, +exiting, script := this);
// we're the exit point
if (exiting == this)
ctx.exitFromScript = null;
// exit further
break;
}
}
ret result;
}
S toStringLong() { ret pnlToLines(steps); }
toString { ret "Script " + n2(id); }
FunctionDef getFunction(S name) { ret mapGet(functionDefs, name); }
} // end of Script
srecord noeq FunctionDef(S name, LS args, Evaluable body) > Base {
public O call(VarContext ctx, O... args) {
var ctx2 = new VarContext(ctx);
int n = min(l(args), l(this.args));
for i to n:
ctx2.put(this.args.get(i), args[i]);
print ifdef GazelleV_LeftArrowScript_debug(ctx2 := ctx2.vars);
ret body.get(ctx2);
}
}
srecord noeq Assignment(S var, Evaluable expression) > Base is Evaluable {
public O get(VarContext ctx) {
O o = expression.get(ctx);
ctx.set(var, o);
ret o;
}
toString { ret var + " <- " + expression; }
}
persistable sclass NewObject > Base is Evaluable {
Class c;
Evaluable[] args;
*(Class *c) {}
*(Class *c, Evaluable[] *args) {}
public O get(VarContext ctx) {
ret callConstructor(c, mapToArrayOrNull(args, arg -> arg.get(ctx)));
}
toString { ret "new " + formatFunctionCall(className(c), args); }
}
srecord noeq CallFunction(FunctionDef f, Evaluable[] args) > Base is Evaluable {
public O get(VarContext ctx) {
//ping();
ret f.call(ctx, mapToArrayOrNull(args, a -> a.get(ctx));
}
toString { ret formatFunctionCall(f.name, args); }
}
srecord noeq GetVar(S var) > BaseEvaluable {
public O get(VarContext ctx) {
ret ctx.get(var);
}
toString { ret var; }
}
srecord noeq Const(O value) > Base is Evaluable {
public O get(VarContext ctx) {
ret value;
}
toString { ret strOrClassName(value); }
public LASValueDescriptor returnType() {
ret new LASValueDescriptor.KnownValue(value);
}
}
srecord noeq GetStaticField(Field field) > Base is Evaluable {
public O get(VarContext ctx) ctex {
ret field.get(null);
}
}
srecord noeq CallMethodOrGetField(Evaluable target, S name) > Base is Evaluable {
public O get(VarContext ctx) {
try {
O object = target.get(ctx);
if (object == null)
null; // throw new NullPointerException();
// could optimize more for sure
if (canCallWithVarargs(object, name))
ret call(object, name);
// TODO: better error message when neither field nor method found
ret _get(object, name);
} catch e {
throw rethrowWithSrc(e);
}
}
}
sclass GetVarContext > Base is Evaluable {
public O get(VarContext ctx) { ret ctx; }
}
srecord noeq ThrowMethodNotFoundException(CallMethod instruction) > Base is Evaluable {
public O get(VarContext ctx) {
fail("Method not found: " + instruction);
}
}
srecord noeq ThrowNullPointerException(CallMethod instruction) > Base is Evaluable {
public O get(VarContext ctx) {
fail("Null pointer exception: " + instruction);
}
}
srecord noeq CallMethod(Evaluable target, S methodName, Evaluable[] args) > Base is Evaluable {
public O get(VarContext ctx) {
ret /*call*/newPreciseCall(target.get(ctx), methodName, mapToArrayOrNull(args, arg -> arg.get(ctx)));
}
toString { ret target + "." + formatFunctionCall(methodName, args); }
public Evaluable optimize() {
var targetType = target.returnType();
if (targetType.knownValue()) {
O o = targetType.value();
if (o == null) ret new ThrowNullPointerException(this);
Class[] argTypes = new[l(args)];
for i over args: {
var type = args[i].returnType();
if (!type.javaClassIsExact())
this;
argTypes[i] = type.javaClass();
}
// TODO: varargs
var method = findMethod_precise_onTypes(o, methodName, argTypes);
if (method == null) ret new ThrowMethodNotFoundException(this);
ret new DirectMethodCallOnKnownTarget(o instanceof Class ? null : o, method, args);
}
this;
}
}
abstract srecord noeq CurriedLambdaBase(Class intrface, Evaluable[] curriedArgs) > Base is Evaluable {
Class declaringClass;
Method implementedMethod;
// !customConstructor
*(Class *intrface, Evaluable[] *curriedArgs) {
implementedMethod = findSingleInterfaceMethod(intrface);
if (implementedMethod == null)
fail(intrface + " is not a single method interface");
declaringClass = implementedMethod.getDeclaringClass();
}
public O get(VarContext ctx) {
O[] curriedArguments = mapToArrayOrNull(curriedArgs, arg -> arg.get(ctx));
ret proxyFromInvocationHandler(intrface, (proxy, method, args) -> {
if (method.getDeclaringClass() != declaringClass)
fail("No handler for method " + method + " (only have " + implementedMethod + ")");
ret forwardCall(concatMethodArgs(curriedArguments, args));
});
}
abstract O forwardCall(O args);
}
sclass CurriedMethodLambda > CurriedLambdaBase {
O target;
S targetMethod;
// !customConstructor
*(Class intrface, O *target, S *targetMethod, Evaluable[] curriedArgs) {
super(intrface, curriedArgs);
}
O forwardCall(O... args) {
ret call(target, targetMethod, args);
}
}
srecord noeq DirectMethodCallOnKnownTarget(O target, Method method, Evaluable[] args) > Base is Evaluable {
public O get(VarContext ctx) {
ret invokeMethod(method, target, mapToArrayOrNull(args, arg -> arg.get(ctx)));
}
toString { ret (target == null ? "" : target + ".") + formatFunctionCall(str(method), args); }
public LASValueDescriptor returnType() {
ret LASValueDescriptor.fromClass(method.getReturnType());
}
}
srecord noeq While(Evaluable condition, Evaluable body) > Base is Evaluable {
public O get(VarContext ctx) {
while (ping() && (Bool) condition.get(ctx)) {
body.get(ctx);
}
// while loops don't return anything
null;
}
}
abstract srecord noeq ForEachBase(Evaluable collection, Evaluable body) > Base is Evaluable {
public O get(VarContext ctx) {
var coll = collection.get(ctx);
Iterator iterator;
new L out;
if (coll cast O[])
for (element : coll) {
ping();
processElement(ctx, out, element);
}
else if (coll cast Iterable) {
for (element : coll) {
ping();
processElement(ctx, out, element);
}
} else if (coll == null) {} // ok
else
fail("Not iterable: " + className(coll));
loopDone(ctx);
ret out;
}
abstract void processElement(VarContext ctx, L out, O o);
abstract void loopDone(VarContext ctx);
}
persistable sclass ForEach > ForEachBase {
S var;
*(Evaluable *collection, S *var, Evaluable *body) {}
void processElement(VarContext ctx, L out, O o) {
ctx.set(var, o);
out.add(body.get(ctx));
}
void loopDone(VarContext ctx) {
ctx.unset(var);
}
}
persistable sclass ForPairs > ForEachBase {
S varA, varB;
*(Evaluable *collection, Evaluable *body, S *varA, S *varB) {}
void processElement(VarContext ctx, L out, O o) {
Pair p = cast o;
ctx.set(varA, p.a);
ctx.set(varB, p.b);
out.add(body.get(ctx));
}
void loopDone(VarContext ctx) {
ctx.unset(varA);
ctx.unset(varB);
}
}
srecord noeq IfThen(Evaluable condition, Evaluable body,
Evaluable elseBranch) > Base is Evaluable {
IfThen(Evaluable condition, Evaluable body) {
this.condition = condition;
this.body = body;
}
public O get(VarContext ctx) {
if ((Bool) condition.get(ctx))
ret body.get(ctx);
else if (elseBranch != null)
ret elseBranch.get(ctx);
else
null;
}
}
srecord noeq ReturnFromScript(Script script, Evaluable value) > Base is Evaluable {
public O get(VarContext ctx) {
O result = value.get(ctx);
printVars ifdef ReturnFromScript_debug("ReturnFromScript",
+result, +ctx, +script);
ctx.exitFromScript(script);
ret result;
}
toString {
ret formatFunctionCall ReturnFromScript(script, value);
}
}
}