From 4ae314e55159305627969468259aa7f2b1099077 Mon Sep 17 00:00:00 2001 From: paulklint Date: Mon, 8 Jun 2026 23:04:23 +0200 Subject: [PATCH 1/3] Gradually adapting compiler to logical locations --- .../lang/rascalcore/check/CheckerCommon.rsc | 6 +- .../rascalcore/check/CollectExpression.rsc | 3 - .../rascalcore/check/LogicalLocations.rsc | 12 +- .../lang/rascalcore/check/TestConfigs.rsc | 2 +- .../lang/rascalcore/compile/Examples/A.rsc | 16 +- .../lang/rascalcore/compile/Examples/Tst6.rsc | 3 - .../Rascal2muRascal/RascalDeclaration.rsc | 90 +++++------ .../Rascal2muRascal/RascalExpression.rsc | 57 ++++--- .../compile/Rascal2muRascal/RascalPattern.rsc | 32 ++-- .../Rascal2muRascal/RascalStatement.rsc | 28 ++-- .../compile/Rascal2muRascal/TmpAndLabel.rsc | 19 ++- .../compile/Rascal2muRascal/TypeUtils.rsc | 60 ++++---- .../lang/rascalcore/compile/muRascal/AST.rsc | 76 +++++----- .../compile/muRascal2Java/CodeGen.rsc | 141 +++++++++--------- .../compile/muRascal2Java/Interface.rsc | 18 ++- .../compile/muRascal2Java/JGenie.rsc | 69 +++++---- .../compile/muRascal2Java/Resolvers.rsc | 28 ++-- .../compile/muRascal2Java/Tests.rsc | 5 +- .../lang/rascalcore/compile/util/Names.rsc | 10 ++ 19 files changed, 341 insertions(+), 334 deletions(-) diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/CheckerCommon.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/CheckerCommon.rsc index 69ab4f43eaf..eb7be1c4b4f 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/CheckerCommon.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/CheckerCommon.rsc @@ -492,9 +492,9 @@ rel[loc from, PathRole r, loc to] getPaths(rel[MODID from, PathRole r, MODID to] return paths; } -int closureCounter = 0; +private int closureCounter = 0; -int nextClosure(){ +private int nextClosure(){ counter = closureCounter; closureCounter += 1; return counter; @@ -503,3 +503,5 @@ int nextClosure(){ void resetClosureCounter(){ closureCounter = 0; } + +str generateClosureName() = "$CLOSURE_"; diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectExpression.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectExpression.rsc index 106b590388f..c4fae5bd748 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectExpression.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectExpression.rsc @@ -213,8 +213,6 @@ void collect(current: (Expression) `( )`, Collector c){ // ---- closure -str generateClosureName() = "$CLOSURE_"; - void collect(current: (Expression) ` { }`, Collector c){ // TODO: experimental check //if(!isEmpty(c.getScopeInfo(loopScope())) || inPatternScope(c)){ @@ -252,7 +250,6 @@ void collectClosure(Expression current, Type returnType, Parameters parameters, alwaysSucceeds = all(pat <- formals, pat is typedVariable && /(Statement) `fail ;` := stats); if(!alwaysSucceeds) dt.canFail = true; - c.defineInScope(parentScope, clos_name, functionId(), current, dt); if(!returnsViaAll && "" != "void"){ diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/LogicalLocations.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/LogicalLocations.rsc index 82e07a08255..2c0cb7741d6 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/LogicalLocations.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/LogicalLocations.rsc @@ -25,10 +25,20 @@ alias FUNID = loc; // function identification bool isFunctionId(loc l) = l.scheme == "rascal+function"; +str getFunctionName(FUNID fuid){ + assert isFunctionId(fuid); + k = findLast(fuid.path, "/"); + return fuid.path[k+1..]; +} + alias CONSID = loc; // constructor identification bool isConstructorId(loc l) = l.scheme == "rascal+constructor"; alias FLDID = loc; // field identification -bool isFieldId(loc l) = l.scheme == "rascal+field"; \ No newline at end of file +bool isFieldId(loc l) = l.scheme == "rascal+field"; + + +alias ADTID = loc; // ADT +bool isADTId(loc l) = l.scheme == "rascal+adt"; diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/TestConfigs.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/TestConfigs.rsc index 6a001646f96..9e28048727f 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/TestConfigs.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/TestConfigs.rsc @@ -170,7 +170,7 @@ public PathConfig getAllSrcREPOPathConfig(bool keep = false) { REPO + "typepal/src", LSP_REPO + "src/main/rascal/library", LSP_REPO + "src/main/rascal/lsp", - LSP_REPO + "src/test/rascal", + //LSP_REPO + "src/test/rascal", REPO + "php-analysis/src/main/rascal" ], [ ], diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/A.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/A.rsc index 2691ad4b174..792ba0b42cb 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/A.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/A.rsc @@ -25,5 +25,17 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } module lang::rascalcore::compile::Examples::A - -extend lang::rascalcore::compile::Examples::B; \ No newline at end of file + + + +@javaClass{org.rascalmpl.library.Prelude} +public java bool isEmpty(set[&T] st); + + +// list[&T] sort(list[&T] lst) = +// sort(lst, bool (&T a, &T b) { return a < b; } ); + +// @javaClass{org.rascalmpl.library.Prelude} +// java list[&T] sort(list[&T] l, bool (&T a, &T b) less) ; + + \ No newline at end of file diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/Tst6.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/Tst6.rsc index 86ee83a2ebd..12a6f22e8f6 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/Tst6.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/Tst6.rsc @@ -27,6 +27,3 @@ POSSIBILITY OF SUCH DAMAGE. @bootstrapParser module lang::rascalcore::compile::Examples::Tst6 -data Symbol - = \label(str name, Symbol symbol); - diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/compile/Rascal2muRascal/RascalDeclaration.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/compile/Rascal2muRascal/RascalDeclaration.rsc index cca68334fa5..9eccc2c2785 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/compile/Rascal2muRascal/RascalDeclaration.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/compile/Rascal2muRascal/RascalDeclaration.rsc @@ -72,14 +72,16 @@ public void translateToplevel((Toplevel) ``) { // -- variable declaration ------------------------------------------ void translateDecl(d: (Declaration) ` <{Variable ","}+ variables> ;`) { - str module_name = asUnqualifiedName(getRascalModuleName()); - enterFunctionScope("_init"); + // str module_name = asUnqualifiedName(getRascalModuleName()); + // enterFunctionScope("_init"); + MODID mid = moduleName2moduleId(getRascalModuleName()); + enterFunctionScope(mid + "/init"); for(var <- variables){ unescapedVarName = unescapeName(""); addVariableToModule(muModuleVar(getType(tp), unescapedVarName)); if(var is initialized) { init_code = translate(var.initial); - asg = muAssign( muVar(unescapedVarName, getRascalModuleNameUnderscores(), -1, filterOverloads(getType(tp), {variableId()}), variableId()), init_code); + asg = muAssign( muVar(unescapedVarName, mid, -1, filterOverloads(getType(tp), {variableId()}), variableId()), init_code); addVariableInitializationToModule(asg); } } @@ -146,16 +148,17 @@ private void generateGettersForAdt(AType adtType, loc module_scope, set[AType] c kwfield2cons += ; //str fuid = getGetterNameForKwpField(consType, kwFieldName); str getterName = unescapeAndStandardize("$getkw___"); + getterId = |rascal+kwfield:///| + getterName; if(getterName notin generated_getters){ generated_getters += getterName; getterType = afunc(kwType, [consType], []); - consVar = muVar(consName, getterName, 0, consType, constructorId()); + consVar = muVar(consName, getterId, 0, consType, constructorId()); defExpCode = promoteVarsToFieldReferences(translate(defaultExp), consType, consVar, kw.definingModule); body = muReturn1(kwType, muIfElse(muIsKwpConstructorDefined(consVar, kwFieldName), muGetKwFieldFromConstructor(kwType, consVar, kwFieldName), defExpCode)); - addFunctionToModule(muFunction(getterName, getterName, getterType, [consVar], [], [], "", false, true, false, {}, {}, {}, getModuleScope(), [], (), body)); + addFunctionToModule(muFunction(getterName, getterId, getterType, [consVar], [], [], |global-scope:///|, false, true, false, {}, {}, {}, getModuleScope(), [], (), body)); } else { println("In generated_getters: "); @@ -171,10 +174,11 @@ private void generateGettersForAdt(AType adtType, loc module_scope, set[AType] c conses = kwfield2cons[kwFieldName]; //str fuid = getGetterNameForKwpField(adtType, kwFieldName); str getterName = unescapeAndStandardize("$getkw__"); + getterId = |rascal+kwfield:///| + getterName; returnType = lubList(conses<0>); getterType = afunc(returnType, [adtType], []); - adtVar = muVar(adtName, getterName, 0, adtType, dataId()); + adtVar = muVar(adtName, getterId, 0, adtType, dataId()); failCode = muFailReturn(returnType); for(Keyword kw <- common_keyword_fields, kw has defaultExp, isContainedIn(kw.defaultExp.src, module_scope, l2p)){ kwType = kw.fieldType; @@ -191,7 +195,7 @@ private void generateGettersForAdt(AType adtType, loc module_scope, set[AType] c ] + failCode ); - addFunctionToModule(muFunction(getterName, getterName, getterType, [adtVar], [], [], "", false, true, false, {}, {}, {}, getModuleScope(), [], (), body)); + addFunctionToModule(muFunction(getterName, getterId, getterType, [adtVar], [], [], |global-scope:///|, false, true, false, {}, {}, {}, getModuleScope(), [], (), body)); } /* @@ -208,16 +212,17 @@ private void generateGettersForAdt(AType adtType, loc module_scope, set[AType] c //str fuid = getGetterNameForKwpField(adtType, kwFieldName); str getterName = unescapeAndStandardize("$getkw__"); + getterId = |rascal+kwfield:///| + getterName; if(getterName == "$getkw_Tree_message"){ // TODO: remove when annotations are gone continue; } getterType = afunc(kwType, [adtType], []); - adtVar = muVar(getterName, getterName, 0, adtType, variableId()); + adtVar = muVar(getterName, getterId, 0, adtType, variableId()); defExprCode = promoteVarsToFieldReferences(translate(defaultExp), adtType, adtVar, kw.definingModule); body = muReturn1(kwType, muIfElse(muIsKwpConstructorDefined(adtVar, kwFieldName), muGetKwFieldFromConstructor(kwType, adtVar, kwFieldName), defExprCode)); - addFunctionToModule(muFunction(getterName, getterName, getterType, [adtVar], [], [], "", false, true, false, {}, {}, {}, getModuleScope(), [], (), body)); + addFunctionToModule(muFunction(getterName, getterId, getterType, [adtVar], [], [], |global-scope:///|, false, true, false, {}, {}, {}, getModuleScope(), [], (), body)); } @@ -241,43 +246,26 @@ private set[TypeVar] getTypeVarsinFunction(FunctionDeclaration fd){ public void translateFunctionDeclaration(FunctionDeclaration fd){ //println("r2mu: Compiling \uE007[]()"); - inScope = topFunctionScope(); - funsrc = fd.src; - useTypeParams = getTypeVarsinFunction(fd); - enterFunctionDeclaration(funsrc, !isEmpty(useTypeParams)); - try { ttags = translateTags(fd.tags); tmods = translateModifiers(fd.signature.modifiers); - // if(ignoreTest(ttags)){ - // // The type checker does not generate type information for ignored functions - // addFunctionToModule(muFunction("$ignored__", - // prettyPrintName(fd.signature.name), - // afunc(abool(),[],[]), - // [], - // [], - // [], - // inScope, - // false, - // true, - // false, - // {}, - // {}, - // {}, - // fd.src, - // tmods, - // ttags, - // muReturn1(abool(), muCon(false)))); - // return; - // } + + if(ttags["ignore"]? || ttags["ignoreCompiler"]?){ + return; + } + inScope = topFunctionScope(); + funsrc = fd.src; + funId = getLogicalLoc(funsrc); + useTypeParams = getTypeVarsinFunction(fd); + enterFunctionDeclaration(funId, !isEmpty(useTypeParams)); + fname = prettyPrintName(fd.signature.name); - ftype = getFunctionType(funsrc); + ftype = getFunctionType(funId); resultType = ftype.ret; bool isVarArgs = ftype.varArgs; nformals = size(ftype.formals); - fuid = convert2fuid(funsrc); - enterFunctionScope(fuid); + enterFunctionScope(funId); //// Keyword parameters lrel[str name, AType atype, MuExp defaultExp] kwps = translateKeywordParameters(fd.signature.parameters); @@ -285,8 +273,8 @@ public void translateFunctionDeclaration(FunctionDeclaration fd){ my_btscopes = getBTScopesParams([ft | ft <- fd.signature.parameters.formals.formals], fname); mubody = muBlock([]); if(ttags["javaClass"]?){ - params = [ muVar(ftype.formals[i].alabel, fuid, i, ftype.formals[i], formalId()) | i <- [ 0 .. nformals] ]; - mubody = muReturn1(resultType, muCallJava("", ttags["javaClass"], ftype, params, fuid)); + params = [ muVar(ftype.formals[i].alabel, funId, i, ftype.formals[i], formalId()) | i <- [ 0 .. nformals] ]; + mubody = muReturn1(resultType, muCallJava("", ttags["javaClass"], ftype, params, funId)); } else if(fd is \default){ // function declaration with statements body_code = [ translate(stat, my_btscopes) | stat <- fd.body.statements ]; if(isVoidAType(ftype.ret)) body_code += muReturn0(); @@ -313,12 +301,12 @@ public void translateFunctionDeclaration(FunctionDeclaration fd){ } leaveSignatureSection(); - externals = getExternalRefs(tbody, fuid, formalVars); - extendedFormalVars = getExtendedFunctionFormals(fd.src, fuid); + externals = getExternalRefs(tbody, funId, formalVars); + extendedFormalVars = getExtendedFunctionFormals(funId, funId); localRefs = getLocalRefs(tbody); addFunctionToModule(muFunction(prettyPrintName(fd.signature.name), - fuid, + funId, ftype, formalVars, extendedFormalVars, @@ -329,7 +317,7 @@ public void translateFunctionDeclaration(FunctionDeclaration fd){ isMemo, externals, localRefs, - getKeywordParameterRefs(tbody, fuid), + getKeywordParameterRefs(tbody, funId), fd.src, tmods, ttags, @@ -395,18 +383,18 @@ public set[MuExp] getLocalRefs(MuExp exp) /* * Get all variables that have been introduced outside the given function scope */ -public set[MuExp] getExternalRefs(MuExp exp, str fuid, list[MuExp] formals){ +public set[MuExp] getExternalRefs(MuExp exp, loc fuid, list[MuExp] formals){ formalNames = {f.name | f <- formals}; - res = { v1 | /v:muVar(str name2, str fuid2, int pos, AType t, IdRole idRole) := exp, pos >= 0, name2 notin formalNames, fuid2 != fuid, fuid2 != "", t1 := unsetRec(t, "alabel"), v1 := v[atype=t1]}; + res = { v1 | /v:muVar(str name2, loc fuid2, int pos, AType t, IdRole idRole) := exp, pos >= 0, name2 notin formalNames, fuid2 != fuid, fuid2 != |rascal:///|, t1 := unsetRec(t, "alabel"), v1 := v[atype=t1]}; //println("getExternalRefs, , : "); return res; } /* * Get all keyword variables that have introduced outside the given function scope */ -public set[MuExp] getKeywordParameterRefs(MuExp exp, str fuid){ +public set[MuExp] getKeywordParameterRefs(MuExp exp, loc fuid){ //println("getKeywordParameterRefs(, )"); - res = { unsetRec(v, "alabel") | /v:muVarKwp(str _, str fuid2, AType _) := exp, fuid2 != fuid }; + res = { unsetRec(v, "alabel") | /v:muVarKwp(str _, loc fuid2, AType _) := exp, fuid2 != fuid }; //println("getKeywordParameterRefs =\> "); return res; } @@ -451,7 +439,7 @@ private MuExp returnFromFunction(MuExp body, AType ftype, list[MuExp] formalVars parameters = { unset(par, "alabel") | /par:aparameter(name, bound) := ftype }; if(!isEmpty(parameters) && /muReturn1(_,_) := res){ - str fuid = topFunctionScope(); + loc fuid = topFunctionScope(); result = muTmpIValue(nextTmp("result"), fuid, ftype.ret); res = visit(res){ case muReturn1(_, e) => muBlock([ muConInit(result, e), @@ -468,7 +456,7 @@ private MuExp returnFromFunction(MuExp body, AType ftype, list[MuExp] formalVars private MuExp functionBody(MuExp body, AType ftype, list[MuExp] formalVars, bool isMemo){ if(isMemo){ - str fuid = topFunctionScope(); + loc fuid = topFunctionScope(); result = muTmpIValue(nextTmp("result"), fuid, avalue()); return muCheckMemo(ftype, formalVars, body); } else { @@ -480,7 +468,7 @@ public tuple[list[MuExp] formalVars, MuExp funBody] translateFunction(str fname, // Create a loop label to deal with potential backtracking induced by the formal parameter patterns list[Pattern] formalsList = [f | f <- formals]; - str fuid = topFunctionScope(); + loc fuid = topFunctionScope(); my_btscopes = getBTScopesParams(formalsList, fname); parameters = { unset(par, "alabel") | /par:aparameter(name, bound) := ftype }; diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/compile/Rascal2muRascal/RascalExpression.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/compile/Rascal2muRascal/RascalExpression.rsc index b302b0ea2dc..58de7f2cba0 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/compile/Rascal2muRascal/RascalExpression.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/compile/Rascal2muRascal/RascalExpression.rsc @@ -128,9 +128,9 @@ private MuExp translateAddFunction(Expression e){ resType = getResult(eType); // Generate and add a function ADD<...> - str scopeId = topFunctionScope(); + loc scopeId = topFunctionScope(); str add_name = "$ADDAL"; - str add_fuid = scopeId + "_" + add_name; + loc add_fuid = scopeId + "_" + add_name; MuExp lhsReceiver = translate(e.lhs); MuExp rhsReceiver = translate(e.rhs); @@ -150,7 +150,7 @@ private MuExp translateAddFunction(Expression e){ leaveFunctionScope(); funType = afunc(resType, lhsFormals, []); - fun = muFunction(add_name, add_name, funType, lactuals, [], [], scopeId, false, false, false, getExternalRefs(body, add_fuid, []), {}, {}, e.src, [], (), body); + fun = muFunction(add_name, add_fuid, funType, lactuals, [], [], scopeId, false, false, false, getExternalRefs(body, add_fuid, []), {}, {}, e.src, [], (), body); loc uid = declareGeneratedFunction(add_name, add_fuid, funType, e.src); addFunctionToModule(fun); addDefineAndType(, funType); // TODO: replace arbitrary number @@ -211,7 +211,7 @@ MuExp translateLiteral((Literal) ``) { private MuExp translateStringLiteral(s: (StringLiteral) ` `) { preIndent = computeIndent(pre); - str fuid = topFunctionScope(); + loc fuid = topFunctionScope(); template = muTmpTemplate(nextTmp("template"), fuid); return muValueBlock( astr(), [ muConInit(template, muTemplate(translatePreChars(pre))), @@ -223,7 +223,7 @@ private MuExp translateStringLiteral(s: (StringLiteral) ` `) { preIndent = computeIndent(pre); - str fuid = topFunctionScope(); + loc fuid = topFunctionScope(); template = muTmpTemplate(nextTmp("template"), fuid); return muValueBlock( astr(), [ muConInit(template, muTemplate(translatePreChars(pre))), @@ -539,7 +539,7 @@ private MuExp translateConcreteExpressionList(Symbol eltType, list[Tree] elems, if(elems == []){ return muCon([]); } else { - str fuid = topFunctionScope(); + loc fuid = topFunctionScope(); writer = muTmpListWriter(nextTmp("writer"), fuid); @@ -564,7 +564,7 @@ private MuExp translateConcreteExpressionList(Symbol eltType, list[Tree] elems, private MuExp translateConcreteExpressionSeparatedList(Symbol _, list[Symbol] _, [], loc _) = muCon([]); private MuExp translateConcreteExpressionSeparatedList(Symbol eltType, list[Symbol] _, [Tree single], loc src) { - str fuid = topFunctionScope(); + loc fuid = topFunctionScope(); writer = muTmpListWriter(nextTmp("writer"), fuid); @@ -585,7 +585,7 @@ private MuExp translateConcreteExpressionSeparatedList(Symbol eltType, list[Symb } private MuExp translateConcreteExpressionSeparatedList(Symbol eltType, list[Symbol] sepTypes, list[Tree] elems:[_,_,*_], loc src) { - str fuid = topFunctionScope(); + loc fuid = topFunctionScope(); writer = muTmpListWriter(nextTmp("writer"), fuid); @@ -684,30 +684,29 @@ MuExp translate (e:(Expression) ` { = translateFunction(fuid, parameters.formals.formals, ftype, muBlock([translate(stat, ()) | stat <- cbody]), false, []); + = translateFunction(cname, parameters.formals.formals, ftype, muBlock([translate(stat, ()) | stat <- cbody]), false, []); leaveSignatureSection(); - cname = "$CLOSURE_"; - addFunctionToModule(muFunction(cname, //"$CLOSURE_A", - cname, //fuid, //"$CLOSURE_A", + addFunctionToModule(muFunction(cname, + fuid, ftype, formalVars, [], @@ -726,13 +725,13 @@ MuExp translate (e:(Expression) ` { .. ]`) { - str fuid = topFunctionScope(); + loc fuid = topFunctionScope(); writer = muTmpListWriter(nextTmp("range_writer"), fuid); elemType = alub(getType(first), getType(last)); elem = muTmpIValue(nextTmp("range_elem"), fuid,elemType); @@ -749,7 +748,7 @@ MuExp translate (e:(Expression) `[ .. ]`) { // -- range with step expression ------------------------------------ MuExp translate (e:(Expression) `[ , .. ]`) { - str fuid = topFunctionScope(); + loc fuid = topFunctionScope(); writer = muTmpListWriter(nextTmp("range_writer"), fuid); elemType = lubList([getType(first), getType(second), getType(last)]); elem = muTmpIValue(nextTmp("range_elem"), fuid, elemType); @@ -767,7 +766,7 @@ MuExp translate (e:(Expression) `[ , .. < MuExp translate (e:(Expression) `