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 {
replace EXITCHECK with if (ctx.exiting()) null; .
macro HANDLENULLREFERENCE {
settable bool allowNullReference;
O handleNullReference() {
if (allowNullReference)
null;
else
throw new NullPointerException();
}
}
// Base = any script element with a reference to its source code
asclass Base > HasTokenRangeWithSrc {
RuntimeException rethrowWithSrc(S msg default "", Throwable e) {
if (src != null)
throw rethrowAndAppendToMessage(e, squareBracketed(
joinNemptiesWithComma(msg, src)));
else
throw rethrow(e);
}
}
// Evaluable = a script element that can be evaluated
interface Evaluable extends IF0, IHasTokenRangeWithSrc {
public O get(VarContext ctx default new FlexibleVarContext);
public default LASValueDescriptor returnType() { null; }
public default Evaluable optimize() { this; }
// informs this object that its return value will not be needed
// so it can perform appropriate optimizations
public default Evaluable optimizeForReturnValueNotNeeded() { this; }
}
// Base + Evaluable + explicitly stored return type
asclass EvaluableBase > Base is Evaluable {
settable LASValueDescriptor returnType;
bool returnValueNeeded = true;
public Evaluable optimizeForReturnValueNotNeeded() {
returnValueNeeded = false;
ret optimize();
}
}
/*interface Cmd {
// returns true if a return was issued
public bool run(VarContext ctx default new FlexibleVarContext);
}*/
static new AtomicLong scriptIDCounter;
static long scriptID() { ret incAtomicLong(scriptIDCounter); }
sclass Script > EvaluableBase {
transient long id = scriptID(); // just for printing
Map functionDefs;
Evaluable[] steps;
settable LASScope scope;
public O get(VarContext ctx) {
O result = null;
var pingSource = pingSource();
for (step : steps) {
ping(pingSource);
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;
result = ctx.returnValue;
ctx.returnValue(null);
ret result;
}
// otherwise exit further
null;
}
}
ret result;
}
S toStringLong() { ret pnlToLines(steps); }
toString { ret "Script " + n2(id); }
FunctionDef getFunction(S name) { ret mapGet(functionDefs, name); }
public Script optimizeScript aka optimize() {
int n = returnValueNeeded ? steps.length-1 : steps.length;
for (int i = 0; i < n; i++)
steps[i] = steps[i].optimizeForReturnValueNotNeeded();
for (f : values(functionDefs))
f.optimize();
this;
}
} // end of Script
srecord noeq FunctionDef(S name, S[] args, Script body) > Base {
settable LASScope scope;
*(S *name, LS args, Script *body) {
this.args = toStringArray(args);
}
public O call(VarContext ctx, O... args) {
VarContext ctx2 = scope != null && scope.useFixedVars
? new FixedVarContext(ctx, scope.names) : new FlexibleVarContext(ctx);
int n = min(l(args), l(this.args));
for i to n:
ctx2.put(this.args[i], args[i]);
print ifdef GazelleV_LeftArrowScript_debug(ctx2 := ctx2.vars);
ret body.get(ctx2);
}
void optimize {
body = body.optimize();
}
}
srecord noeq Assignment(S var, Evaluable expression) > EvaluableBase {
public O get(VarContext ctx) {
O o = expression.get(ctx);
ctx.set(var, o);
ret o;
}
toString { ret var + " <- " + expression; }
}
asclass FixedVarBase > EvaluableBase {
settable LASScope scope;
S var;
int varIdx;
S varToStr() { ret var + " [" + varIdx + "]"; }
void assertResolved {
if (varIdx < 0)
fail("Unresolved variable access: " + var);
}
void resolve {
varIdx = scope.resolveVar(var);
}
}
persistable sclass FixedVarAssignment > FixedVarBase {
Evaluable expression;
*(LASScope *scope, S *var, Evaluable *expression) {}
public O get(VarContext ctx) {
O o = expression.get(ctx);
ctx/FixedVarContext.set(varIdx, o);
ret o;
}
toString { ret varToStr() + " <- " + expression; }
}
// type isn't used yet
srecord noeq VarDeclaration(S var, Class type, Evaluable expression) > EvaluableBase {
public O get(VarContext ctx) {
O o = expression?.get(ctx);
ctx.set(var, o);
ret o;
}
toString { ret "var " + var + " <- " + expression; }
}
srecord noeq AssignmentToOuterVar(S var, Evaluable expression) > EvaluableBase {
public O get(VarContext ctx) {
var parent = ctx.parent();
assertNotNull("No outer variable context", parent);
O o = expression.get(ctx);
parent.set(var, o);
ret o;
}
toString { ret "outer " + var + " <- " + expression; }
}
persistable sclass NewObject > EvaluableBase {
Class c;
Evaluable[] args;
*(Class *c) {}
*(Class *c, Evaluable[] *args) {}
public O get(VarContext ctx) {
try {
ret preciseNuObject(c, mapToArrayOrNull(args, arg -> arg.get(ctx)));
} catch e {
throw rethrowWithSrc(e);
}
}
toString { ret "new " + formatFunctionCall(className(c), args); }
}
// new object of a script-defined class
// (we don't generate/resolve these classes until after the complete
// parse is done so parsing stays lightweight)
persistable sclass NewObject_LASClass > NewObject {
ResolvableLASClass lasClass;
*(ResolvableLASClass *lasClass) {}
*(ResolvableLASClass *lasClass, Evaluable[] *args) {}
void resolve {
if (c == null)
c = lasClass!;
}
public O get(VarContext ctx) {
resolve();
ret super.get(ctx);
}
toString { ret "new " + formatFunctionCall(str(lasClass), args); }
}
// new object of a class defined in expression
srecord noeq NewObject_UnknownClass(Evaluable classExpr, Evaluable[] args) > NewObject {
public O get(VarContext ctx) {
try {
Class c = cast classExpr.get(ctx);
ret preciseNuObject(c, mapToArrayOrNull(args, arg -> arg.get(ctx)));
} catch e {
throw rethrowWithSrc(e);
}
}
toString { ret "new " + formatFunctionCall(classExpr, args); }
}
srecord noeq CallFunction(FunctionDef f, Evaluable[] args) > EvaluableBase {
public O get(VarContext ctx) {
var evaledArgs = mapToArrayOrNull(args, a -> a.get(ctx));
EXITCHECK
ret f.call(ctx, evaledArgs);
}
toString { ret formatFunctionCall(f.name, args); }
}
srecord noeq GetVar(S var) > EvaluableBase {
public O get(VarContext ctx) {
ret ctx.get(var);
}
toString { ret var; }
}
persistable sclass GetFixedVar > FixedVarBase {
*(LASScope *scope, S *var) {}
public O get(VarContext ctx) {
assertResolved();
try {
ret ctx/FixedVarContext.get(varIdx);
} catch ArrayIndexOutOfBoundsException e {
assertResolved();
throw e;
}
}
toString { ret var + " [" + varIdx + "]"; }
}
srecord noeq Const(O value) > EvaluableBase {
public O get(VarContext ctx) {
ret value;
}
toString { ret strOrClassName(value); }
public LASValueDescriptor returnType() {
ret new LASValueDescriptor.KnownValue(value);
}
// Structuring this object is only done to make a class def hash,
// so the structure just has to be unique, not serializable.
// As the contents of "value" could be an unpersistable object,
// we just stringify it.
S _serialize() { ret str(value); }
}
srecord noeq GetStaticField(Field field) > EvaluableBase {
public O get(VarContext ctx) ctex {
ret field.get(null);
}
// See Const._serialize
S _serialize() { ret str(field); }
}
srecord noeq CallMethodOrGetField(Evaluable target, S name) > EvaluableBase {
HANDLENULLREFERENCE
public O get(VarContext ctx) {
try {
O object = target.get(ctx);
if (object == null)
ret handleNullReference();
ret preciseGetOrCallMethod(object, name);
} catch e {
throw rethrowWithSrc("Was getting " + name, e);
}
}
}
sclass GetVarContext > EvaluableBase {
public O get(VarContext ctx) { ret ctx; }
}
srecord noeq ThrowMethodNotFoundException(CallMethod instruction) > EvaluableBase {
public O get(VarContext ctx) {
fail("Method not found: " + instruction);
}
}
srecord noeq ThrowNullPointerException(CallMethod instruction) > EvaluableBase {
public O get(VarContext ctx) {
fail("Null pointer exception: " + instruction);
}
}
srecord noeq CallMethod(Evaluable target, S methodName, Evaluable[] args) > EvaluableBase {
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 == null || !type.javaClassIsExact())
this;
argTypes[i] = type.javaClass();
}
// can't optimize varargs
L methods = findMethodsNamed_cached(o, methodName);
if (any(methods, m -> m.isVarArgs())) this;
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;
}
}
srecord noeq LambdaDef(Class intrface, S[] args, Evaluable body) > EvaluableBase {
Method implementedMethod;
// !customConstructor
*(Class *intrface, S[] *args, Evaluable *body) {
implementedMethod = findSingleInterfaceMethodOrFail(intrface);
if (implementedMethod.getParameterCount() != l(args))
fail("Bad parameter count for lambda: " + implementedMethod + " vs: " + joinWithComma(args));
}
// We have to create the proxy when the lambda definition is
// evaluated since we have to put the context in there
public O get(VarContext ctx) {
ret proxyFromInvocationHandler(intrface, (proxy, method, actualArgs) -> {
ping();
if (method.getDeclaringClass() == intrface) {
var ctx2 = new FlexibleVarContext(ctx);
var argNames = args;
// We already know that the count matches.
for i over args:
ctx2.put(argNames[i], actualArgs[i]);
ret body.get(ctx2);
} else
ret handleObjectMethodsInProxyInvocationHandler(
this, implementedMethod, method, proxy, actualArgs);
});
}
}
abstract srecord noeq CurriedLambdaBase(Class intrface, Evaluable[] curriedArgs) > EvaluableBase {
Method implementedMethod;
// !customConstructor
*(Class *intrface, Evaluable[] *curriedArgs) {
implementedMethod = findSingleInterfaceMethodOrFail(intrface);
}
public O get(VarContext ctx) {
O[] curriedArguments = mapToArrayOrNull(curriedArgs, arg -> arg.get(ctx));
ret proxyFromInvocationHandler(intrface, (proxy, method, actualArgs) -> {
// Comparing a Method is more expensive than just
// comparing the class (should be enough to distinguish
// methods since we are dealing with a single-method class).
// tl;dr So far we are getting away with this so all is good ^^
if (method.getDeclaringClass() == intrface)
ret forwardCall(ctx, concatMethodArgs(curriedArguments, actualArgs));
else
ret handleObjectMethodsInProxyInvocationHandler(
this, implementedMethod, method, proxy, actualArgs); });
}
abstract O forwardCall(VarContext ctx, O[] args);
}
sclass CurriedMethodLambda > CurriedLambdaBase {
O target;
S targetMethod;
*(Class intrface, O *target, S *targetMethod, Evaluable[] curriedArgs) {
super(intrface, curriedArgs);
}
O forwardCall(VarContext ctx, O[] args) {
ret call(target, targetMethod, args);
}
}
sclass CurriedScriptFunctionLambda > CurriedLambdaBase {
FunctionDef f;
*(Class intrface, FunctionDef *f, Evaluable[] curriedArgs) {
super(intrface, curriedArgs);
}
O forwardCall(VarContext ctx, O[] args) {
ret f.call(ctx, args);
}
}
sclass CurriedConstructorLambda > CurriedLambdaBase {
Constructor[] ctors;
*(Class intrface, Constructor[] *ctors, Evaluable[] curriedArgs) {
super(intrface, curriedArgs);
}
O forwardCall(VarContext ctx, O[] args) {
ret preciseNuObject(ctors, args);
}
}
srecord noeq DirectMethodCallOnKnownTarget(O target, Method method, Evaluable[] args) > EvaluableBase {
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) > EvaluableBase {
public O get(VarContext ctx) {
while (!ctx.exiting() && (Bool) condition.get(ctx)) {
body.get(ctx);
}
// while loops don't return anything
null;
}
}
abstract srecord noeq ForEachBase(Evaluable collection, Evaluable body) > EvaluableBase {
public O get(VarContext ctx) {
var coll = collection.get(ctx);
Iterator iterator;
L out;
try {
if (coll cast O[]) {
out = emptyList(coll.length);
for (element : coll) {
EXITCHECK
processElement(ctx, out, element);
}
} else if (coll cast Iterable) {
out = emptyList(coll);
for (element : coll) {
EXITCHECK
processElement(ctx, out, element);
}
} else if (coll == null)
out = new L;
else
fail("Not iterable: " + className(coll));
} finally {
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);
}
}
srecord ForIterator(Evaluable iterable, S var, Evaluable body) > EvaluableBase {
public O get(VarContext ctx) {
VarContext subContext = new FlexibleVarContext(ctx);
var iterable = this.iterable.get(ctx);
Iterator iterator = iterator_gen(iterable);
ret mapI(iterator, value -> {
subContext.set(var, value);
ret body.get(subContext);
});
}
}
srecord ForNested(Evaluable iterable, S var, Evaluable body) > EvaluableBase {
public O get(VarContext ctx) {
VarContext subContext = new FlexibleVarContext(ctx);
var iterable = this.iterable.get(ctx);
Iterator iterator = iterator_gen(iterable);
ret nestedIterator(iterator, value -> {
subContext.set(var, value);
ret iterator_gen(body.get(subContext));
});
}
}
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 ForKeyValue(Evaluable map, Evaluable body, S varA, S varB) > EvaluableBase {
public O get(VarContext ctx) {
Map, ?> theMap = (Map) map.get(ctx);
L out;
try {
if (theMap != null) {
out = emptyList(theMap.size());
for (entry : theMap.entrySet()) {
EXITCHECK
ctx.set(varA, entry.getKey());
ctx.set(varB, entry.getValue());
out.add(body.get(ctx));
}
} else
out = new L;
} finally {
ctx.unset(varA);
ctx.unset(varB);
}
ret out;
}
}
srecord noeq ForIntTo(Evaluable endValue, S var, Evaluable body) > EvaluableBase {
public Evaluable optimize() {
if (!returnValueNeeded)
body = body.optimizeForReturnValueNotNeeded();
this;
}
public O get(VarContext ctx) {
int n = (Int) endValue.get(ctx), i = 0;
L out = returnValueNeeded ? new L : null;
try {
ctx.put(var, i);
while (i < n) {
EXITCHECK
O o = body.get(ctx);
out?.add(o);
ctx.set(var, i = (Int) ctx.get(var)+1);
}
} finally {
ctx.unset(var);
}
ret out;
}
}
persistable sclass ForIndex > EvaluableBase {
Evaluable collection, body;
S varIndex, varElement;
*(Evaluable *collection, Evaluable *body, S *varIndex, S *varElement) {}
public O get(VarContext ctx) {
ret new ForIndex_instance(collection, body, varIndex, varElement).get(ctx);
}
}
sclass ForIndex_instance > ForEachBase {
S varIndex, varElement;
int index;
*(Evaluable *collection, Evaluable *body, S *varIndex, S *varElement) {}
void processElement(VarContext ctx, L out, O o) {
ctx.set(varIndex, index++);
ctx.set(varElement, o);
out.add(body.get(ctx));
}
void loopDone(VarContext ctx) {
ctx.unset(varIndex);
ctx.unset(varElement);
}
}
srecord noeq IfThen(Evaluable condition, Evaluable body,
Evaluable elseBranch) > EvaluableBase {
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) > EvaluableBase {
public O get(VarContext ctx) {
O result = value.get(ctx);
printVars ifdef ReturnFromScript_debug("ReturnFromScript",
+result, +ctx, +script);
ctx.exitFromScript(script);
ctx.returnValue(result);
null;
}
toString {
ret formatFunctionCall ReturnFromScript(script, value);
}
}
srecord noeq Continue(Script loopBody) > EvaluableBase {
public O get(VarContext ctx) {
ctx.exitFromScript(loopBody);
ctx.returnValue(null);
null;
}
toString {
ret formatFunctionCall Continue(loopBody);
}
}
srecord noeq RepeatN(Evaluable n, Evaluable body) > EvaluableBase {
public O get(VarContext ctx) {
long count = ((Number) n.get(ctx)).longValue();
repeat count {
EXITCHECK
body.get(ctx);
}
null;
}
}
persistable srecord BoolAnd(Evaluable a, Evaluable b) > EvaluableBase {
public O get(VarContext ctx) {
if (!((Bool) a.get(ctx))) false;
ret b.get(ctx);
}
}
persistable srecord BoolOr(Evaluable a, Evaluable b) > EvaluableBase {
public O get(VarContext ctx) {
if (((Bool) a.get(ctx))) true;
ret b.get(ctx);
}
}
srecord noeq TempBlock(Evaluable tempExpr,
Evaluable body) > EvaluableBase {
public O get(VarContext ctx) {
temp (AutoCloseable) tempExpr.get(ctx);
ret body.get(ctx);
}
}
srecord ClassDef(ResolvableLASClass lasClass) > EvaluableBase {
public O get(VarContext ctx) {
ret lasClass!;
}
}
srecord noeq SetField(Evaluable target, S name, Evaluable expr) > EvaluableBase {
HANDLENULLREFERENCE
public O get(VarContext ctx) {
try {
O value = expr.get(ctx);
O object = target.get(ctx);
if (object == null)
handleNullReference();
else
set(object, name, value);
ret value;
} catch e {
throw rethrowWithSrc(e);
}
}
}
srecord noeq Throw(Evaluable expr) > EvaluableBase {
public O get(VarContext ctx) {
throw asRuntimeException((Throwable) expr.get(ctx));
}
}
srecord noeq TryCatch(Evaluable body, S var, Evaluable catchBlock) > EvaluableBase {
public O get(VarContext ctx) {
try {
ret body.get(ctx);
} catch e {
temp ctx.tempPut(var, e);
ret catchBlock.get(ctx);
}
}
}
static structure_Data structureDataForLAS() {
new structure_Data d;
d.shouldIncludeField = field -> {
S c = shortClassName(field.getDeclaringClass());
S f = field.getName();
bool shouldInclude = !(eq(c, "HasTokenRangeWithSrc") && eq(f, "src"));
//printVars("shouldIncludeField", +c, +f, +shouldInclude);
ret shouldInclude;
};
ret d;
}
} // end of GazelleV_LeftArrowScript