sclass ConvertLASToJava > Meta { replace Tk with GazelleV_LeftArrowScript. delegate Evaluable to Tk. S typeToJava(Type type) { ret type == null ?: shortenClassNames(type.getTypeName()); } S typeToJava(LASValueDescriptor desc) { ret typeToJava(or(desc == null ?: desc.javaClass(), O)); } O convert(LASClassDef.FieldDef field) { ret "settable " + typeToJava(field.type()) + " " + field.name() + (field.initializer == null ? "" : " = " + convert(field.initializer)) + ";"; } S convert(Tk.FunctionDef f) { if (f.synthetic()) ret ""; ret typeToJava(f.returnType) + " " + f.name + "(" + joinWithComma( countIterator(l(f.args), i -> typeToJava(f.argTypes[i]) + " " + f.args[i]) ) + ") {\n" + indentx(convert(f.body, true)) + "}\n\n"; } O convertWithLeadingSpace(Evaluable o) { ret leadingSpace(o, "") + convert(o); } O convertWithLeadingSpace2(Evaluable o) { ret replaceIfEqual(leadingSpace(o, ""), " ", "") + convert(o); } S leadingSpace(Evaluable o, S defaultSpace) { S space = null; var src = o.tokenRangeWithSrc(); if (src != null) space = src.startPtr().mapIdx(idx -> idx & ~1)!; ret or2(space, defaultSpace); } S trailingSpace(Evaluable o, S defaultSpace) { S space = null; var src = o.tokenRangeWithSrc(); if (src != null) { S rawSpace = src.endPtr().mapIdx(idx -> idx & ~1)!; space = replaceRegexp(rawSpace, "\n[ \t]+$", "\n"); if (scaffoldingEnabled()) printVars trailingSpace(rawSpace := quote(rawSpace), space := quote(space)); } ret or2(space, defaultSpace); } O getInstruction(Evaluable o) { O inner = convert(o); bool needSemicolon = !o instanceof Tk.ClassDef && !o instanceof Tk.ForEachBase; S space = trailingSpace(o, "\n"); if (scaffoldingEnabled()) printVars(+space, o := className(o), srcText := quote(o.srcText()), +inner); ret inner + (needSemicolon ? ";" : "") + space; } O convert(Tk.Script script, bool returnLastResult) { var steps = asList(script.steps); if (returnLastResult) { if (empty(steps)) ret "return null;"; var last = last(steps); if (!last instanceof Tk.ReturnFromScript && !last instanceof Tk.ClassDef) setLast(steps, new Tk.ReturnFromScript(script, last)); } ret concatMapStrings(i -> str(getInstruction(i)), steps); } O convert(Evaluable o, bool returnLastResult) { if (o cast Tk.Script) ret convert(o, returnLastResult); ret convert(o); } O convert(Evaluable o) { if (o == null) null; // These are the properly implemented cases if (o cast Tk.GetVar) ret o.var; if (o cast Tk.Script) ret convert(o, false); if (o cast Tk.ClassDef) { LASClassDef c = o.lasClass.classDef; ret spaceCombine( "class", c.userGivenName, eqOneOf(c.superClass, null, O) ? null : "extends " + typeToJava(c.superClass), empty(c.interfaces) ? null : "is " + joinWithComma(map typeToJava(c.interfaces)), curly("\n" + appendNewLineIfNempty(indentx( joinNemptiesWithEmptyLines( lines_rtrim(map convert(c.fields)), convertInitializers(c), paragraphs(nempties(map convert(c.methods)))) )))); } if (o cast Tk.Assignment) ret o.var + " = " + convert(o.expression); if (o cast Tk.VarDeclaration) ret "var " + o.var + " = " + convert(o.expression); if (o cast Tk.CallMethod) { S targetStr = null; var targetType = o.target.returnType(); if (targetType != null && targetType.knownValue()) { O target = targetType.value(); if (target cast Class && eqOneOf(shortClassName(target), "main", "utils")) targetStr = ""; } if (targetStr == null) targetStr = str(convert(o.target)); ret (empty(targetStr) ? "" : targetStr + ".") + FunctionCall(o.methodName, map convertWithLeadingSpace2(o.args)); } if (o cast Tk.SetField) ret convert(o.target) + "." + o.name + " = " + convert(o.expr); if (o cast Tk.CallMethodOrGetField) ret convert(o.target) + "." + o.name + "()"; if (o cast Tk.DirectMethodCallOnKnownTarget) ret o.target + "." + FunctionCall(o.method.getName(), map convert(o.args)); if (o cast Tk.NewObject) { S className; var o2 = o; if (o2 cast Tk.NewObject_LASClass) { className = o2.lasClass.userGivenName(); } else className = typeToJava(o.c); ret "new " + FunctionCall(className, map convert(o.args)); } if (o cast Tk.IfThen) ret "if (" + convert(o.condition) + ") " + curlyIfScript(o.body) + (o.elseBranch == null ? "" : " else " + curlyIfScript(o.elseBranch)); if (o cast Tk.Const) { O val = o.value; if (val cast Tk.FunctionDef) ret convert(val); var c = o; try object c?.srcText(); pcall { ret toJava(val); } } if (o cast Tk.ForEach) ret "fOr (" + o.var + " : " + convert(o.collection) + ") {\n" + indentx(convert(o.body, false)) + "\n}"; if (o cast Tk.ForIntTo) ret "for " + o.var + " to " + convert(o.endValue) + ": {\n" + indentx(convert(o.body, false)) + "\n}"; if (o cast Tk.CurriedScriptFunctionLambda) { int nArgs = o.implementedMethod.getParameterCount(); LS args = countIteratorToList_incl(1, nArgs, i ->"_" + i); L fullArgs = concatLists(allToString(map convert(o.curriedArgs)), args); ret roundBracketed(typeToJava(o.intrface)) + " " + lambdaArgsToString_pureJava(args) + " -> " + FunctionCall(o.f.name, fullArgs); } if (o cast Tk.LambdaDef) ret roundBracketed(typeToJava(o.intrface)) + " " + joinNemptiesWithSpace(lambdaArgsToString_pureJava(o.args), "-> " + curlyIfScript(o.body)); if (o cast Tk.ReturnFromScript) ret "ret " + convert(o.value); if (o cast Tk.GetStaticField) ret typeToJava(o.field.getDeclaringClass()) + "." + o.field.getName(); if (o cast Tk.BoolAnd) ret roundBracketed(str(convert(o.a))) + " && " + roundBracketed(str(convert(o.b))); if (o cast Tk.BoolOr) ret roundBracketed(str(convert(o.a))) + " || " + roundBracketed(str(convert(o.b))); if (o cast Tk.GetField) ret convert(o.target) + "." + o.name; if (o cast Tk.CallFunction) ret FunctionCall(o.f.name, map convert(o.args)); if (o cast Tk.While) ret "while (" + convert(o.condition) + ") {\n" + indentx(convert(o.body, false)) + "\n}"; if (o cast Tk.TryCatch) ret "try {\n" + indentx(convert(o.body, false)) + "\n" + "} catch " + o.var + " {\n" + indentx(convert(o.catchBlock, false)) + "\n}"; if (o cast Tk.TryFinally) ret "try {\n" + indentx(convert(o.body, false)) + "\n" + "} finally {\n" + indentx(convert(o.finallyBlock, false)) + "\n}"; // add more explicitly handled cases here warn("Can't convert to Java: " + className(o)); // Retain original script text as a default if (o cast Tk.Base) { var b = o; try object b?.srcText(); } // If that fails (it shouldn't), just return the toString warn("No source reference in script object: " + className(o)); ret str(o); } O curlyIfScript(Evaluable o) { if (o cast Tk.Script) ret "{\n" + indentx(convert(o)) + "\n}"; ret convert(o); } // get is convert + postProcess S get(Evaluable o, bool returnLastResult) { S src = strOrEmpty(convert(o, returnLastResult)); LS tok = javaTok(src); jreplace(tok, "this.", ""); JavaXPeepholeShortener shortener = new(tok); shortener.run(); ret join(shortener.tok); } S convertInitializers(LASClassDef c) { ret lines_rtrim(nempties(mapWithIndex(c.initializers, (idx, i) -> { if (c.isFieldInitializer.get(idx)) null; ret "{ " + addSuffix(rtrim(str(convert(i))), ";") + " }"; }))); } }