diff --git a/deep-rebuild b/deep-rebuild index 761f6ea8b..23c8f086f 100755 --- a/deep-rebuild +++ b/deep-rebuild @@ -33,6 +33,7 @@ fi echo "Before we start, let's get this thing built ..." java -Xss8M -Xmx2000M -jar ../jars/RunSilver.jar --clean silver:support:monto java -Xss8M -Xmx2000M -jar ../jars/RunSilver.jar --clean lib:xml:ast +java -Xss8M -Xmx2000M -jar ../jars/RunSilver.jar --clean core:reflect echo "Start ..." time java -Xss8M -Xmx2000M -jar ../jars/RunSilver.jar --relative-jar --clean silver:composed:Default diff --git a/grammars/core/reflect/AST.sv b/grammars/core/reflect/AST.sv new file mode 100644 index 000000000..dcdb05e54 --- /dev/null +++ b/grammars/core/reflect/AST.sv @@ -0,0 +1,86 @@ +grammar core:reflect; + +imports silver:langutil; +imports silver:langutil:pp; + +synthesized attribute pps :: [Document]; -- TODO: Move to langutil + +nonterminal AST with pp; + +abstract production nonterminalAST +top::AST ::= prodName::String children::ASTs annotations::NamedASTs +{ + top.pp = cat(text(prodName), parens(ppImplode(pp", ", children.pps ++ annotations.pps))); +} + +abstract production listAST +top::AST ::= vals::ASTs +{ + top.pp = brackets(ppImplode(pp", ", vals.pps)); +} + +abstract production stringAST +top::AST ::= s::String +{ + top.pp = pp"\"${text(s)}\""; +} + +abstract production integerAST +top::AST ::= i::Integer +{ + top.pp = text(toString(i)); +} + +abstract production floatAST +top::AST ::= f::Float +{ + top.pp = text(toString(f)); +} + +abstract production booleanAST +top::AST ::= b::Boolean +{ + top.pp = text(toString(b)); +} + +abstract production foreignAST +top::AST ::= x::a +{ + top.pp = pp""; +} + +nonterminal ASTs with pps; + +abstract production consAST +top::ASTs ::= h::AST t::ASTs +{ + top.pps = h.pp :: t.pps; +} + +abstract production nilAST +top::ASTs ::= +{ + top.pps = []; +} + +nonterminal NamedASTs with pps; + +abstract production consNamedAST +top::NamedASTs ::= h::NamedAST t::NamedASTs +{ + top.pps = h.pp :: t.pps; +} + +abstract production nilNamedAST +top::NamedASTs ::= +{ + top.pps = []; +} + +nonterminal NamedAST with pp; + +abstract production namedAST +top::NamedAST ::= n::String v::AST +{ + top.pp = pp"${text(n)}=${v.pp}"; +} diff --git a/grammars/core/reflect/Reflect.sv b/grammars/core/reflect/Reflect.sv new file mode 100644 index 000000000..a4e049a43 --- /dev/null +++ b/grammars/core/reflect/Reflect.sv @@ -0,0 +1,9 @@ +grammar core:reflect; + +function reflect +AST ::= x::a +{ + return error("Foreign function"); +} foreign { + "java" : return "(common.Reflection.reflect(%x%))"; +} diff --git a/grammars/silver/translation/java/core/Annotation.sv b/grammars/silver/translation/java/core/Annotation.sv index 4f56c5551..8beb116a3 100644 --- a/grammars/silver/translation/java/core/Annotation.sv +++ b/grammars/silver/translation/java/core/Annotation.sv @@ -9,14 +9,15 @@ top::AGDcl ::= 'annotation' a::QName tl::BracketedOptTypeExprs '::' te::TypeExpr -- It should be fine, though. If we're a tv, then it's 'Object' and anything -- else will be a subtype... - top.genFiles := [pair(className ++ ".java", + top.genFiles := [pair(className ++ ".java", s""" -"package " ++ makeName(top.grammarName) ++ ";\n\n" ++ +package ${makeName(top.grammarName)}; -"public interface " ++ className ++ " {\n\n" ++ +public interface ${className} { -"\tpublic " ++ te.typerep.transType ++ " getAnno_" ++ makeIdName(fName) ++ "();\n\n" ++ + public ${te.typerep.transType} getAnno_${makeIdName(fName)}(); -"}\n")]; +} +""")]; } diff --git a/grammars/silver/translation/java/core/AspectDcl.sv b/grammars/silver/translation/java/core/AspectDcl.sv index 017073a72..5794c9927 100644 --- a/grammars/silver/translation/java/core/AspectDcl.sv +++ b/grammars/silver/translation/java/core/AspectDcl.sv @@ -4,7 +4,7 @@ aspect production aspectProductionDcl top::AGDcl ::= 'aspect' 'production' id::QName ns::AspectProductionSignature body::ProductionBody { top.setupInh := body.setupInh; - top.initProd := "\t\t//ASPECT PRODUCTION " ++ id.name ++ " " ++ ns.pp ++ "\n" ++ body.translation; + top.initProd := s"\t\t//ASPECT PRODUCTION ${id.name} ${ns.pp}\n${body.translation}"; top.valueWeaving := body.valueWeaving; } @@ -12,6 +12,6 @@ aspect production aspectFunctionDcl top::AGDcl ::= 'aspect' 'function' id::QName ns::AspectFunctionSignature body::ProductionBody { top.setupInh := body.setupInh; - top.initProd := "\t\t//ASPECT FUNCTION " ++ id.name ++ " " ++ ns.pp ++ "\n" ++ body.translation; + top.initProd := s"\t\t//ASPECT FUNCTION ${id.name} ${ns.pp}\n${body.translation}"; top.valueWeaving := body.valueWeaving; } diff --git a/grammars/silver/translation/java/core/BuiltInFunctions.sv b/grammars/silver/translation/java/core/BuiltInFunctions.sv index 3a3d53c82..6ee05ad6b 100644 --- a/grammars/silver/translation/java/core/BuiltInFunctions.sv +++ b/grammars/silver/translation/java/core/BuiltInFunctions.sv @@ -10,7 +10,7 @@ top::Expr ::= e::Decorated Expr aspect production stringLength top::Expr ::= e::Decorated Expr { - top.translation = "Integer.valueOf(((common.StringCatter)" ++ e.translation ++ ").length())"; + top.translation = s"Integer.valueOf(((common.StringCatter)${e.translation}).length())"; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); } @@ -20,8 +20,8 @@ top::Expr ::= 'toInt' '(' e::Expr ')' { top.translation = case finalType(e) of | intType() -> e.translation - | floatType() -> "Integer.valueOf(((Float)" ++ e.translation ++ ").intValue())" - | stringType() -> "Integer.valueOf(" ++ e.translation ++ ".toString())" + | floatType() -> s"Integer.valueOf(((Float)${e.translation}).intValue())" + | stringType() -> s"Integer.valueOf(${e.translation}.toString())" | t -> error("INTERNAL ERROR: no toInt translation for type " ++ prettyType(t)) end; @@ -31,9 +31,9 @@ aspect production toFloatFunction top::Expr ::= 'toFloat' '(' e::Expr ')' { top.translation = case finalType(e) of - | intType() -> "Float.valueOf(((Integer)" ++ e.translation ++ ").floatValue())" + | intType() -> s"Float.valueOf(((Integer)${e.translation}).floatValue())" | floatType() -> e.translation - | stringType() -> "Float.valueOf(" ++ e.translation ++ ".toString())" + | stringType() -> s"Float.valueOf(${e.translation}.toString())" | t -> error("INTERNAL ERROR: no toFloat translation for type " ++ prettyType(t)) end; @@ -42,7 +42,7 @@ top::Expr ::= 'toFloat' '(' e::Expr ')' aspect production toStringFunction top::Expr ::= 'toString' '(' e::Expr ')' { - top.translation = "new common.StringCatter(String.valueOf(" ++ e.translation ++ "))"; + top.translation = s"new common.StringCatter(String.valueOf(${e.translation}))"; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); } @@ -50,7 +50,7 @@ top::Expr ::= 'toString' '(' e::Expr ')' aspect production newFunction top::Expr ::= 'new' '(' e::Expr ')' { - top.translation = "((" ++ finalType(top).transType ++ ")" ++ e.translation ++ ".undecorate())"; + top.translation = s"((${finalType(top).transType})${e.translation}.undecorate())"; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); } @@ -58,7 +58,7 @@ top::Expr ::= 'new' '(' e::Expr ')' aspect production terminalConstructor top::Expr ::= 'terminal' '(' t::TypeExpr ',' es::Expr ',' el::Expr ')' { - top.translation = "new " ++ makeTerminalName(t.typerep.typeName) ++ "(" ++ es.translation ++ ", (core.NLocation)" ++ el.translation ++ ")"; + top.translation = s"new ${makeTerminalName(t.typerep.typeName)}(${es.translation}, (core.NLocation)${el.translation})"; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); } diff --git a/grammars/silver/translation/java/core/Expr.sv b/grammars/silver/translation/java/core/Expr.sv index 02ca613da..c4ac8ab26 100644 --- a/grammars/silver/translation/java/core/Expr.sv +++ b/grammars/silver/translation/java/core/Expr.sv @@ -47,18 +47,18 @@ top::Expr ::= q::Decorated QName top.translation = if q.lookupValue.typerep.isDecorable then if finalType(top).isDecorable - then {- type Node -} "context.childDecorated(" ++ childIDref ++ ").undecorate()" - else {- type DecoratedNode -} "context.childDecorated(" ++ childIDref ++ ")" - else "((" ++ finalType(top).transType ++ ")context.childAsIs(" ++ childIDref ++ "))"; + then {- type Node -} s"context.childDecorated(${childIDref}).undecorate()" + else {- type DecoratedNode -} s"context.childDecorated(${childIDref})" + else s"((${finalType(top).transType})context.childAsIs(${childIDref}))"; -- reminder: the reason we do .childDecorated().undecorate() is that it's not safe to mix asis/decorated accesses. top.lazyTranslation = if !top.frame.lazyApplication then top.translation else if q.lookupValue.typerep.isDecorable then if finalType(top).isDecorable - then "common.Thunk.transformUndecorate(context.childDecoratedLazy(" ++ childIDref ++ "))" - else "context.childDecoratedLazy(" ++ childIDref ++ ")" - else "context.childAsIsLazy(" ++ childIDref ++ ")"; + then s"common.Thunk.transformUndecorate(context.childDecoratedLazy(${childIDref}))" + else s"context.childDecoratedLazy(${childIDref})" + else s"context.childAsIsLazy(${childIDref})"; } aspect production lhsReference @@ -80,18 +80,18 @@ top::Expr ::= q::Decorated QName top.translation = if q.lookupValue.typerep.isDecorable then if finalType(top).isDecorable - then {- type Node -} "context.localDecorated(" ++ q.lookupValue.dcl.attrOccursIndex ++ ").undecorate()" - else {- type DecoratedNode -} "context.localDecorated(" ++ q.lookupValue.dcl.attrOccursIndex ++ ")" - else "((" ++ finalType(top).transType ++ ")context.localAsIs(" ++ q.lookupValue.dcl.attrOccursIndex ++ "))"; + then {- type Node -} s"context.localDecorated(${q.lookupValue.dcl.attrOccursIndex}).undecorate()" + else {- type DecoratedNode -} s"context.localDecorated(${q.lookupValue.dcl.attrOccursIndex})" + else s"((${finalType(top).transType})context.localAsIs(${q.lookupValue.dcl.attrOccursIndex}))"; -- reminder: the reason we do .localDecorated().undecorate() is that it's not safe to mix asis/decorated accesses. top.lazyTranslation = if !top.frame.lazyApplication then top.translation else if q.lookupValue.typerep.isDecorable then if finalType(top).isDecorable - then "common.Thunk.transformUndecorate(context.localDecoratedLazy(" ++ q.lookupValue.dcl.attrOccursIndex ++ "))" - else "context.localDecoratedLazy(" ++ q.lookupValue.dcl.attrOccursIndex ++ ")" - else "context.localAsIsLazy(" ++ q.lookupValue.dcl.attrOccursIndex ++ ")"; + then s"common.Thunk.transformUndecorate(context.localDecoratedLazy(${q.lookupValue.dcl.attrOccursIndex}))" + else s"context.localDecoratedLazy(${q.lookupValue.dcl.attrOccursIndex})" + else s"context.localAsIsLazy(${q.lookupValue.dcl.attrOccursIndex})"; } aspect production productionReference @@ -124,12 +124,12 @@ top::Expr ::= q::Decorated QName aspect production globalValueReference top::Expr ::= q::Decorated QName { - top.translation = "((" ++ finalType(top).transType ++ ")" ++ - makeName(q.lookupValue.dcl.sourceGrammar) ++ ".Init." ++ fullNameToShort(q.lookupValue.fullName) ++ ".eval())"; + top.translation = s"((${finalType(top).transType})${ + makeName(q.lookupValue.dcl.sourceGrammar)}.Init.${fullNameToShort(q.lookupValue.fullName)}.eval())"; top.lazyTranslation = if top.frame.lazyApplication - then makeName(q.lookupValue.dcl.sourceGrammar) ++ ".Init." ++ fullNameToShort(q.lookupValue.fullName) + then s"${makeName(q.lookupValue.dcl.sourceGrammar)}.Init.${fullNameToShort(q.lookupValue.fullName)}" else top.translation; } @@ -146,11 +146,11 @@ top::Expr ::= e::Decorated Expr es::Decorated AppExprs annos::Decorated AnnoAppE top.translation = case e of | functionReference(q) -> -- static method invocation - "((" ++ finalType(top).transType ++ ")" ++ makeClassName(q.lookupValue.fullName) ++ ".invoke(" ++ argsTranslation(es) ++ "))" + s"((${finalType(top).transType})${makeClassName(q.lookupValue.fullName)}.invoke(${argsTranslation(es)}))" | productionReference(q) -> -- static constructor invocation - "((" ++ finalType(top).transType ++ ")new " ++ makeClassName(q.lookupValue.fullName) ++ "(" ++ implode(", ", map((.lazyTranslation), es.exprs ++ reorderedAnnoAppExprs(annos))) ++ "))" + s"((${finalType(top).transType})new ${makeClassName(q.lookupValue.fullName)}(${implode(", ", map((.lazyTranslation), es.exprs ++ reorderedAnnoAppExprs(annos)))}))" | _ -> -- dynamic method invocation - "((" ++ finalType(top).transType ++ ")" ++ e.translation ++ ".invoke(new Object[]{" ++ argsTranslation(es) ++ "}, " ++ namedargsTranslation(annos) ++ "))" + s"((${finalType(top).transType})${e.translation}.invoke(new Object[]{${argsTranslation(es)}}, ${namedargsTranslation(annos)}))" end ; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); @@ -167,14 +167,14 @@ String ::= e::Decorated AnnoAppExprs { -- TODO: This is the ONLY use of .exprs We could eliminate that, if we fix this. return if null(e.exprs) then "null" - else "new Object[]{" ++ implode(", ", map((.lazyTranslation), reorderedAnnoAppExprs(e))) ++ "}"; + else s"new Object[]{${implode(", ", map((.lazyTranslation), reorderedAnnoAppExprs(e)))}}"; } function namedargsTranslationNOReorder String ::= e::Decorated AnnoAppExprs { -- TODO: This is the ONLY use of .exprs We could eliminate that, if we fix this. return if null(e.exprs) then "null" - else "new Object[]{" ++ implode(", ", map((.lazyTranslation), e.exprs)) ++ "}"; + else s"new Object[]{${implode(", ", map((.lazyTranslation), e.exprs))}}"; } function int2str String ::= i::Integer { return toString(i); } @@ -189,16 +189,16 @@ top::Expr ::= e::Decorated Expr es::Decorated AppExprs annos::Decorated AnnoAppE local step2 :: String = if !null(es.appExprIndicies) then step1 ++ ".invokePartial(" ++ - "new int[]{" ++ implode(", ", map(int2str, es.appExprIndicies)) ++ "}, " ++ - "new Object[]{" ++ argsTranslation(es) ++ "})" + s"new int[]{${implode(", ", map(int2str, es.appExprIndicies))}}, " ++ + s"new Object[]{${argsTranslation(es)}})" else step1; local step3 :: String = if !null(annos.annoIndexConverted) || !null(annos.annoIndexSupplied) then step2 ++ ".invokeNamedPartial(" ++ (if null(annos.annoIndexConverted) then "null" - else "new int[]{" ++ implode(", ", map(int2str, annos.annoIndexConverted)) ++ "}") ++ ", " ++ + else s"new int[]{${implode(", ", map(int2str, annos.annoIndexConverted))}}") ++ ", " ++ (if null(annos.annoIndexSupplied) then "null" - else "new int[]{" ++ implode(", ", map(int2str, annos.annoIndexSupplied)) ++ "}") ++ ", " ++ + else s"new int[]{${implode(", ", map(int2str, annos.annoIndexSupplied))}}") ++ ", " ++ namedargsTranslationNOReorder(annos) ++ ")" else step2; @@ -212,7 +212,7 @@ top::Expr ::= '(' '.' q::QName ')' { top.translation = if inputType.isDecorated then - "new common.AttributeSection(" ++ occursCheck.dcl.attrOccursIndex ++ ")" + s"new common.AttributeSection(${occursCheck.dcl.attrOccursIndex})" else -- Please note: context is not actually required here, we do so to make runtime error messages -- more comprehensible. This is a similar situation to the code for 'decorate E with {}'. @@ -221,7 +221,7 @@ top::Expr ::= '(' '.' q::QName ')' -- That error would be more comprehensible! (the trouble with this is that we're reporting as context the -- function/production we appear within here. The function *may* be applied elsewhere. However, the most common -- case is something like map((.attr), list) so, that's probably best to report here instead of within map.) - "new common.AttributeSection.Undecorated(" ++ occursCheck.dcl.attrOccursIndex ++ ", context)"; + s"new common.AttributeSection.Undecorated(${occursCheck.dcl.attrOccursIndex}, context)"; top.lazyTranslation = top.translation; } @@ -243,25 +243,25 @@ top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur aspect production forwardAccess top::Expr ::= e::Expr '.' 'forward' { - top.translation = "((" ++ finalType(top).transType ++ ")" ++ e.translation ++ ".forwardOrThis())"; + top.translation = s"((${finalType(top).transType})${e.translation}.forwardOrThis())"; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); } aspect production synDecoratedAccessHandler top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur { - top.translation = "((" ++ finalType(top).transType ++ ")" ++ e.translation ++ ".synthesized(" ++ q.dcl.attrOccursIndex ++ "))"; + top.translation = s"((${finalType(top).transType})${e.translation}.synthesized(${q.dcl.attrOccursIndex}))"; top.lazyTranslation = case e, top.frame.lazyApplication of | childReference(cqn), true -> if cqn.lookupValue.typerep.isDecorable then - "context.childDecoratedSynthesizedLazy(" ++ top.frame.className ++ ".i_" ++ cqn.lookupValue.fullName ++ ", " ++ q.dcl.attrOccursIndex ++ ")" + s"context.childDecoratedSynthesizedLazy(${top.frame.className}.i_${cqn.lookupValue.fullName}, ${q.dcl.attrOccursIndex})" else - "context.childAsIsSynthesizedLazy(" ++ top.frame.className ++ ".i_" ++ cqn.lookupValue.fullName ++ ", " ++ q.dcl.attrOccursIndex ++ ")" + s"context.childAsIsSynthesizedLazy(${top.frame.className}.i_${cqn.lookupValue.fullName}, ${q.dcl.attrOccursIndex})" | lhsReference(_), true -> - "context.contextSynthesizedLazy(" ++ q.dcl.attrOccursIndex ++ ")" + s"context.contextSynthesizedLazy(${q.dcl.attrOccursIndex})" | _, _ -> wrapThunk(top.translation, top.frame.lazyApplication) end; } @@ -269,11 +269,11 @@ top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur aspect production inhDecoratedAccessHandler top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur { - top.translation = "((" ++ finalType(top).transType ++ ")" ++ e.translation ++ ".inherited(" ++ q.dcl.attrOccursIndex ++ "))"; + top.translation = s"((${finalType(top).transType})${e.translation}.inherited(${q.dcl.attrOccursIndex}))"; top.lazyTranslation = case e, top.frame.lazyApplication of - | lhsReference(_), true -> "context.contextInheritedLazy(" ++ q.dcl.attrOccursIndex ++ ")" + | lhsReference(_), true -> s"context.contextInheritedLazy(${q.dcl.attrOccursIndex})" | _, _ -> wrapThunk(top.translation, top.frame.lazyApplication) end; } @@ -292,7 +292,7 @@ top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur then "getFilename()" else error("Not possible -- an error should have been raised about " ++ q.pp); - top.translation = "((" ++ finalType(top).transType ++ ")" ++ e.translation ++ "." ++ accessor ++ ")"; + top.translation = s"((${finalType(top).transType})${e.translation}.${accessor})"; top.lazyTranslation = top.translation; } @@ -301,7 +301,7 @@ aspect production annoAccessHandler top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur { -- Note that the transType is specific to the nonterminal we're accessing from. - top.translation = "((" ++ finalType(top).transType ++ ")" ++ e.translation ++ ".getAnno_" ++ makeIdName(q.attrDcl.fullName) ++ "())"; + top.translation = s"((${finalType(top).transType})${e.translation}.getAnno_${makeIdName(q.attrDcl.fullName)}())"; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); } @@ -318,9 +318,9 @@ top::Expr ::= 'decorate' e::Expr 'with' '{' inh::ExprInhs '}' -- (especially important because we're implicitly inserted when accessing attributes -- from undecorated nodes, and this is a common error for new silverers.) | _ -> ".decorate(context, common.Util.populateInh(" ++ - makeNTClassName(finalType(e).typeName) ++ ".num_inh_attrs, " ++ - "new int[]{" ++ implode(", ", inh.nameTrans) ++ "}, " ++ - "new common.Lazy[]{" ++ implode(", ", inh.valueTrans) ++ "}))" + s"${makeNTClassName(finalType(e).typeName)}.num_inh_attrs, " ++ + s"new int[]{${implode(", ", inh.nameTrans)}}, " ++ + s"new common.Lazy[]{${implode(", ", inh.valueTrans)}}))" end; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); @@ -385,7 +385,7 @@ top::Expr ::= 'false' aspect production and top::Expr ::= e1::Expr '&&' e2::Expr { - top.translation = "(" ++ e1.translation ++ " && " ++ e2.translation ++ ")"; + top.translation = s"(${e1.translation} && ${e2.translation})"; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); } @@ -393,7 +393,7 @@ top::Expr ::= e1::Expr '&&' e2::Expr aspect production or top::Expr ::= e1::Expr '||' e2::Expr { - top.translation = "(" ++ e1.translation ++ " || " ++ e2.translation ++ ")"; + top.translation = s"(${e1.translation} || ${e2.translation})"; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); } @@ -401,7 +401,7 @@ top::Expr ::= e1::Expr '||' e2::Expr aspect production not top::Expr ::= '!' e::Expr { - top.translation = "(!" ++ e.translation ++ ")"; + top.translation = s"(!${e.translation})"; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); } @@ -416,9 +416,9 @@ aspect production gt top::Expr ::= e1::Expr '>' e2::Expr { top.translation = case finalType(e1) of - | intType() -> "(" ++ e1.translation ++ " > " ++ e2.translation ++ ")" - | floatType() -> "(" ++ e1.translation ++ " > " ++ e2.translation ++ ")" - | stringType() -> "(" ++ e1.translation ++ ".toString().compareTo(" ++ e2.translation ++ ".toString()) > 0)" + | intType() -> s"(${e1.translation} > ${e2.translation})" + | floatType() -> s"(${e1.translation} > ${e2.translation})" + | stringType() -> s"(${e1.translation}.toString().compareTo(${e2.translation}.toString()) > 0)" | t -> error("INTERNAL ERROR: no > trans for type " ++ prettyType(t)) end; @@ -429,9 +429,9 @@ aspect production lt top::Expr ::= e1::Expr '<' e2::Expr { top.translation = case finalType(e1) of - | intType() -> "(" ++ e1.translation ++ " < " ++ e2.translation ++ ")" - | floatType() -> "(" ++ e1.translation ++ " < " ++ e2.translation ++ ")" - | stringType() -> "(" ++ e1.translation ++ ".toString().compareTo(" ++ e2.translation ++ ".toString()) < 0)" + | intType() -> s"(${e1.translation} < ${e2.translation})" + | floatType() -> s"(${e1.translation} < ${e2.translation})" + | stringType() -> s"(${e1.translation}.toString().compareTo(${e2.translation}.toString()) < 0)" | t -> error("INTERNAL ERROR: no < trans for type " ++ prettyType(t)) end; @@ -442,9 +442,9 @@ aspect production gteq top::Expr ::= e1::Expr '>=' e2::Expr { top.translation = case finalType(e1) of - | intType() -> "(" ++ e1.translation ++ " >= " ++ e2.translation ++ ")" - | floatType() -> "(" ++ e1.translation ++ " >= " ++ e2.translation ++ ")" - | stringType() -> "(" ++ e1.translation ++ ".toString().compareTo(" ++ e2.translation ++ ".toString()) >= 0)" + | intType() -> s"(${e1.translation} >= ${e2.translation})" + | floatType() -> s"(${e1.translation} >= ${e2.translation})" + | stringType() -> s"(${e1.translation}.toString().compareTo(${e2.translation}.toString()) >= 0)" | t -> error("INTERNAL ERROR: no >= trans for type " ++ prettyType(t)) end; @@ -455,9 +455,9 @@ aspect production lteq top::Expr ::= e1::Expr '<=' e2::Expr { top.translation = case finalType(e1) of - | intType() -> "(" ++ e1.translation ++ " <= " ++ e2.translation ++ ")" - | floatType() -> "(" ++ e1.translation ++ " <= " ++ e2.translation ++ ")" - | stringType() -> "(" ++ e1.translation ++ ".toString().compareTo(" ++ e2.translation ++ ".toString()) <= 0)" + | intType() -> s"(${e1.translation} <= ${e2.translation})" + | floatType() -> s"(${e1.translation} <= ${e2.translation})" + | stringType() -> s"(${e1.translation}.toString().compareTo(${e2.translation}.toString()) <= 0)" | t -> error("INTERNAL ERROR: no <= trans for type " ++ prettyType(t)) end; @@ -467,7 +467,7 @@ top::Expr ::= e1::Expr '<=' e2::Expr aspect production eqeq top::Expr ::= e1::Expr '==' e2::Expr { - top.translation = e1.translation ++ ".equals(" ++ e2.translation ++ ")"; + top.translation = s"${e1.translation}.equals(${e2.translation})"; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); } @@ -475,7 +475,7 @@ top::Expr ::= e1::Expr '==' e2::Expr aspect production neq top::Expr ::= e1::Expr '!=' e2::Expr { - top.translation = "!" ++ e1.translation ++ ".equals(" ++ e2.translation ++ ")"; + top.translation = s"!${e1.translation}.equals(${e2.translation})"; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); } @@ -483,7 +483,7 @@ top::Expr ::= e1::Expr '!=' e2::Expr aspect production ifThenElse top::Expr ::= 'if' e1::Expr 'then' e2::Expr 'else' e3::Expr { - top.translation = "(" ++ e1.translation ++ " ? " ++ e2.translation ++ " : " ++ e3.translation ++ ")"; + top.translation = s"(${e1.translation} ? ${e2.translation} : ${e3.translation})"; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); } @@ -491,14 +491,14 @@ top::Expr ::= 'if' e1::Expr 'then' e2::Expr 'else' e3::Expr aspect production intConst top::Expr ::= i::Int_t { - top.translation = "Integer.valueOf((int)" ++ i.lexeme ++ ")"; + top.translation = s"Integer.valueOf((int)${i.lexeme})"; top.lazyTranslation = top.translation; } aspect production floatConst top::Expr ::= f::Float_t { - top.translation = "Float.valueOf((float)" ++ f.lexeme ++ ")"; + top.translation = s"Float.valueOf((float)${f.lexeme})"; top.lazyTranslation = top.translation; } @@ -506,8 +506,8 @@ aspect production plus top::Expr ::= e1::Expr '+' e2::Expr { top.translation = case finalType(top) of - | intType() -> "Integer.valueOf(" ++ e1.translation ++ " + " ++ e2.translation ++ ")" - | floatType() -> "Float.valueOf(" ++ e1.translation ++ " + " ++ e2.translation ++ ")" + | intType() -> s"Integer.valueOf(${e1.translation} + ${e2.translation})" + | floatType() -> s"Float.valueOf(${e1.translation} + ${e2.translation})" | t -> error("INTERNAL ERROR: no + trans for type " ++ prettyType(t)) end; @@ -517,8 +517,8 @@ aspect production minus top::Expr ::= e1::Expr '-' e2::Expr { top.translation = case finalType(top) of - | intType() -> "Integer.valueOf(" ++ e1.translation ++ " - " ++ e2.translation ++ ")" - | floatType() -> "Float.valueOf(" ++ e1.translation ++ " - " ++ e2.translation ++ ")" + | intType() -> s"Integer.valueOf(${e1.translation} - ${e2.translation})" + | floatType() -> s"Float.valueOf(${e1.translation} - ${e2.translation})" | t -> error("INTERNAL ERROR: no - trans for type " ++ prettyType(t)) end; @@ -528,8 +528,8 @@ aspect production multiply top::Expr ::= e1::Expr '*' e2::Expr { top.translation = case finalType(top) of - | intType() -> "Integer.valueOf(" ++ e1.translation ++ " * " ++ e2.translation ++ ")" - | floatType() -> "Float.valueOf(" ++ e1.translation ++ " * " ++ e2.translation ++ ")" + | intType() -> s"Integer.valueOf(${e1.translation} * ${e2.translation})" + | floatType() -> s"Float.valueOf(${e1.translation} * ${e2.translation})" | t -> error("INTERNAL ERROR: no * trans for type " ++ prettyType(t)) end; @@ -539,8 +539,8 @@ aspect production divide top::Expr ::= e1::Expr '/' e2::Expr { top.translation = case finalType(top) of - | intType() -> "Integer.valueOf(" ++ e1.translation ++ " / " ++ e2.translation ++ ")" - | floatType() -> "Float.valueOf(" ++ e1.translation ++ " / " ++ e2.translation ++ ")" + | intType() -> s"Integer.valueOf(${e1.translation} / ${e2.translation})" + | floatType() -> s"Float.valueOf(${e1.translation} / ${e2.translation})" | t -> error("INTERNAL ERROR: no / trans for type " ++ prettyType(t)) end; @@ -550,8 +550,8 @@ aspect production modulus top::Expr ::= e1::Expr '%' e2::Expr { top.translation = case finalType(top) of - | intType() -> "Integer.valueOf(" ++ e1.translation ++ " % " ++ e2.translation ++ ")" - | floatType() -> "Float.valueOf(" ++ e1.translation ++ " % " ++ e2.translation ++ ")" + | intType() -> s"Integer.valueOf(${e1.translation} % ${e2.translation})" + | floatType() -> s"Float.valueOf(${e1.translation} % ${e2.translation})" | t -> error("INTERNAL ERROR: no % trans for type " ++ prettyType(t)) end; @@ -561,8 +561,8 @@ aspect production neg top::Expr ::= '-' e::Expr { top.translation = case finalType(top) of - | intType() -> "Integer.valueOf(-" ++ e.translation ++ ")" - | floatType() -> "Float.valueOf(-" ++ e.translation ++ ")" + | intType() -> s"Integer.valueOf(-${e.translation})" + | floatType() -> s"Float.valueOf(-${e.translation})" | t -> error("INTERNAL ERROR: no unary - trans for type " ++ prettyType(t)) end; @@ -572,7 +572,7 @@ top::Expr ::= '-' e::Expr aspect production stringConst top::Expr ::= s::String_t { - top.translation = "(new common.StringCatter(" ++ s.lexeme ++ "))"; + top.translation = s"(new common.StringCatter(${s.lexeme}))"; top.lazyTranslation = top.translation; } @@ -588,7 +588,7 @@ top::Expr ::= e1::Decorated Expr e2::Decorated Expr { -- cast, rather than toString. Otherwise we don't gain anything with StringCatter -- literal here, rather than transType. why not? Catch bugs, just in case. - top.translation = "new common.StringCatter((common.StringCatter)" ++ e1.translation ++ ", (common.StringCatter)" ++ e2.translation ++ ")"; + top.translation = s"new common.StringCatter((common.StringCatter)${e1.translation}, (common.StringCatter)${e2.translation})"; top.lazyTranslation = wrapThunk(top.translation, top.frame.lazyApplication); } @@ -627,11 +627,11 @@ String ::= exp::String beLazy::Boolean function wrapThunkText String ::= ct::String exp::String ty::String { - return "new common.Thunk<" ++ ty ++ ">(" ++ ct ++ ") { public final " ++ ty ++ " doEval(final common.DecoratedNode context) { return " ++ exp ++ "; } }"; + return s"new common.Thunk<${ty}>(${ct}) { public final ${ty} doEval(final common.DecoratedNode context) { return ${exp}; } }"; } function wrapLazy String ::= e::Decorated Expr { - return "new common.Lazy() { public final Object eval(final common.DecoratedNode context) { return " ++ e.translation ++ "; } }"; + return s"new common.Lazy() { public final Object eval(final common.DecoratedNode context) { return ${e.translation}; } }"; } diff --git a/grammars/silver/translation/java/core/FunctionDcl.sv b/grammars/silver/translation/java/core/FunctionDcl.sv index f0191effc..f094a9fb4 100644 --- a/grammars/silver/translation/java/core/FunctionDcl.sv +++ b/grammars/silver/translation/java/core/FunctionDcl.sv @@ -7,23 +7,24 @@ aspect production functionDcl top::AGDcl ::= 'function' id::Name ns::FunctionSignature body::ProductionBody { top.setupInh := body.setupInh; - top.initProd := "\t\t//FUNCTION " ++ id.name ++ " " ++ ns.pp ++ "\n" ++ body.translation; + top.initProd := s"\t\t//FUNCTION ${id.name} ${ns.pp}\n" ++ body.translation; local localVar :: String = "count_local__ON__" ++ makeIdName(fName); - top.initWeaving := "\tpublic static int " ++ localVar ++ " = 0;\n"; + top.initWeaving := s"\tpublic static int ${localVar} = 0;\n"; top.valueWeaving := body.valueWeaving; local argsAccess :: String = implode(", ", map((.childRefElem), namedSig.inputElements)); local funBody :: String = - "final common.DecoratedNode context = new P" ++ id.name ++ "(" ++ argsAccess ++ ").decorate();\n" ++ - "\t\t//" ++ head(body.uniqueSignificantExpression).pp ++ "\n" ++ - "\t\treturn (" ++ namedSig.outputElement.typerep.transType ++ ")(" ++ head(body.uniqueSignificantExpression).translation ++ ");\n"; +s"""final common.DecoratedNode context = new P${id.name}(${argsAccess}).decorate(); + //${head(body.uniqueSignificantExpression).pp} + return (${namedSig.outputElement.typerep.transType})(${head(body.uniqueSignificantExpression).translation}); +"""; top.genFiles := - [pair("P" ++ id.name ++ ".java", generateFunctionClassString(top.grammarName, id.name, namedSig, funBody))] ++ + [pair(s"P${id.name}.java", generateFunctionClassString(top.grammarName, id.name, namedSig, funBody))] ++ if id.name == "main" then [pair("Main.java", generateMainClassString(top.grammarName))] else []; @@ -44,7 +45,7 @@ String ::= whatGrammar::String whatName::String whatSig::NamedSignature whatResu local className :: String = "P" ++ whatName; local localVar :: String = - "count_local__ON__" ++ makeIdName(whatGrammar) ++ "_" ++ whatName; + s"count_local__ON__${makeIdName(whatGrammar)}_${whatName}"; return s""" package ${makeName(whatGrammar)}; @@ -63,7 +64,7 @@ ${makeIndexDcls(0, whatSig.inputElements)} public static final common.Lazy[] localAttributes = new common.Lazy[num_local_attrs]; public static final common.Lazy[][] localInheritedAttributes = new common.Lazy[num_local_attrs][]; - static{ + static { ${implode("", map((.childStaticElem), whatSig.inputElements))} } diff --git a/grammars/silver/translation/java/core/GlobalDcl.sv b/grammars/silver/translation/java/core/GlobalDcl.sv index d794ed8da..636d66337 100644 --- a/grammars/silver/translation/java/core/GlobalDcl.sv +++ b/grammars/silver/translation/java/core/GlobalDcl.sv @@ -4,7 +4,7 @@ aspect production globalValueDclConcrete top::AGDcl ::= 'global' id::Name '::' t::TypeExpr '=' e::Expr ';' { -- TODO: would be nice to use more specific types. double TODO: figure out what the problem was? - top.initValues := "\tpublic static final common.Thunk " ++ id.name - ++ " = " ++ wrapThunkText("common.TopNode.singleton", e.translation, "Object") ++ ";\n"; + top.initValues := + s"\tpublic static final common.Thunk ${id.name}" ++ + s" = ${wrapThunkText("common.TopNode.singleton", e.translation, "Object")};\n"; } - diff --git a/grammars/silver/translation/java/core/NamedSignature.sv b/grammars/silver/translation/java/core/NamedSignature.sv index 9e93af484..c50ab149d 100644 --- a/grammars/silver/translation/java/core/NamedSignature.sv +++ b/grammars/silver/translation/java/core/NamedSignature.sv @@ -15,6 +15,10 @@ synthesized attribute childStaticElem :: String occurs on NamedSignatureElement; -- "private Object child_signame..." synthesized attribute childDeclElem :: String occurs on NamedSignatureElement; synthesized attribute annoDeclElem :: String occurs on NamedSignatureElement; +-- "signame" +synthesized attribute annoNameElem :: String occurs on NamedSignatureElement; +-- "if (name.equals("signame")) { return getAnno_signame(); }" +synthesized attribute annoLookupElem :: String occurs on NamedSignatureElement; aspect production namedSignature top::NamedSignature ::= fn::String ie::[NamedSignatureElement] oe::NamedSignatureElement np::[NamedSignatureElement] @@ -29,15 +33,16 @@ top::NamedSignatureElement ::= n::String ty::Type top.childSigElem = "final Object c_" ++ n; top.childRefElem = "c_" ++ n; top.childDeclElem = - "\tprivate Object child_" ++ n ++ ";\n" ++ - "\tpublic final " ++ ty.transType ++ " getChild_" ++ n ++ "() {\n" ++ - "\t\treturn (" ++ ty.transType ++ ") (child_" ++ n ++ " = common.Util.demand(child_" ++ n ++ "));\n" ++ - "\t}\n\n"; +s""" private Object child_${n}; + public final ${ty.transType} getChild_${n}() { + return (${ty.transType}) (child_${n} = common.Util.demand(child_${n})); + } + +"""; top.childStaticElem = if !ty.isDecorable then "" - else "\tchildInheritedAttributes[i_" ++ n ++ "] = " ++ - "new common.Lazy[" ++ makeNTClassName(ty.typeName) ++ ".num_inh_attrs];\n"; + else s"\tchildInheritedAttributes[i_${n}] = new common.Lazy[${makeNTClassName(ty.typeName)}.num_inh_attrs];\n"; -- annos are full names: @@ -46,18 +51,26 @@ top::NamedSignatureElement ::= n::String ty::Type top.annoSigElem = "final Object a_" ++ fn; top.annoRefElem = "a_" ++ fn; top.annoDeclElem = - "\tprivate Object anno_" ++ fn ++ ";\n" ++ - "\t@Override\n" ++ - "\tpublic final " ++ ty.transType ++ " getAnno_" ++ fn ++ "() {\n" ++ - "\t\treturn (" ++ ty.transType ++ ") (anno_" ++ fn ++ " = common.Util.demand(anno_" ++ fn ++ "));\n" ++ - "\t}\n\n"; +s""" private Object anno_${fn}; + @Override + public final ${ty.transType} getAnno_${fn}() { + return (${ty.transType}) (anno_${fn} = common.Util.demand(anno_${fn})); + } + +"""; + + top.annoNameElem = s"\"${n}\""; + top.annoLookupElem = +s"""if (name.equals("${n}")) { + return getAnno_${fn}(); + } else """; } function makeIndexDcls String ::= i::Integer s::[NamedSignatureElement] { return if null(s) then "" - else "\tpublic static final int i_" ++ head(s).elementName ++ " = " ++ toString(i) ++ ";\n" ++ makeIndexDcls(i+1, tail(s)); + else s"\tpublic static final int i_${head(s).elementName} = ${toString(i)};\n" ++ makeIndexDcls(i+1, tail(s)); } -- TODO I'd really like to just get rid of this. @@ -70,35 +83,35 @@ function unpackChildren [String] ::= i::Integer ns::[NamedSignatureElement] { return if null(ns) then [] - else ("children[" ++ toString(i) ++ "]") :: unpackChildren(i + 1, tail(ns)); + else (s"children[${toString(i)}]") :: unpackChildren(i + 1, tail(ns)); } function unpackAnnotations [String] ::= i::Integer ns::[NamedSignatureElement] { return if null(ns) then [] - else ("annotations[" ++ toString(i) ++ "]") :: unpackAnnotations(i + 1, tail(ns)); + else (s"annotations[${toString(i)}]") :: unpackAnnotations(i + 1, tail(ns)); } function makeChildAccessCase String ::= n::NamedSignatureElement { - return "\t\t\tcase i_" ++ n.elementName ++ ": return getChild_" ++ n.elementName ++ "();\n"; + return s"\t\t\tcase i_${n.elementName}: return getChild_${n.elementName}();\n"; } function makeChildAccessCaseLazy String ::= n::NamedSignatureElement { - return "\t\t\tcase i_" ++ n.elementName ++ ": return child_" ++ n.elementName ++ ";\n"; + return s"\t\t\tcase i_${n.elementName}: return child_${n.elementName};\n"; } function makeAnnoAssign String ::= n::NamedSignatureElement { local fn :: String = makeIdName(n.elementName); - return "\t\tthis.anno_" ++ fn ++ " = a_" ++ fn ++ ";\n"; + return s"\t\tthis.anno_${fn} = a_${fn};\n"; } function makeChildAssign String ::= n::NamedSignatureElement { - return "\t\tthis.child_" ++ n.elementName ++ " = c_" ++ n.elementName ++ ";\n"; + return s"\t\tthis.child_${n.elementName} = c_${n.elementName};\n"; } diff --git a/grammars/silver/translation/java/core/NonTerminalDcl.sv b/grammars/silver/translation/java/core/NonTerminalDcl.sv index 6f5c68832..c813e2631 100644 --- a/grammars/silver/translation/java/core/NonTerminalDcl.sv +++ b/grammars/silver/translation/java/core/NonTerminalDcl.sv @@ -11,61 +11,73 @@ top::AGDcl ::= cl::ClosedOrNot 'nonterminal' id::Name tl::BracketedOptTypeExprs local myAnnos :: [NamedSignatureElement] = annotationsForNonterminal(nonterminalType(fName, tl.types), top.env); - top.initWeaving := "\tpublic static int " ++ inhVar ++ " = 0;\n" - ++ "\tpublic static int " ++ synVar ++ " = 0;\n"; + top.initWeaving := s""" + public static int ${inhVar} = 0; + public static int ${synVar} = 0;"""; - top.genFiles := [pair(className ++ ".java", - -"package " ++ makeName(top.grammarName) ++ ";\n\n" ++ + top.genFiles := [pair(className ++ ".java", s""" +package ${makeName(top.grammarName)}; -"import java.util.*;\n\n" ++ +import java.util.*; -"public abstract class " ++ className ++ " extends common.Node" ++ +public abstract class ${className} extends common.Node${ (if null(myAnnos) then "" else " implements " ++ implode(", ", map(makeAnnoClassName, map((.elementName), myAnnos))) - ) ++ " {\n\n" ++ + )} { -"\tpublic static final int num_inh_attrs = Init." ++ inhVar ++ ";\n" ++ -"\tpublic static final int num_syn_attrs = Init." ++ synVar ++ ";\n\n" ++ + public static final int num_inh_attrs = Init.${inhVar}; + public static final int num_syn_attrs = Init.${synVar}; -"\tpublic static final String[] occurs_inh = new String[num_inh_attrs];\n" ++ -"\tpublic static final String[] occurs_syn = new String[num_syn_attrs];\n" ++ -"\tpublic static final LinkedList decorators = new LinkedList();\n\n" ++ + public static final String[] occurs_inh = new String[num_inh_attrs]; + public static final String[] occurs_syn = new String[num_syn_attrs]; + public static final LinkedList decorators = new LinkedList(); -"\tpublic static final common.Lazy[] defaultSynthesizedAttributes = new common.Lazy[num_syn_attrs];\n\n" ++ + public static final common.Lazy[] defaultSynthesizedAttributes = new common.Lazy[num_syn_attrs]; -"\tprotected " ++ className ++ "(" ++ implode(", ", map((.annoSigElem), myAnnos)) ++ ") {\n" ++ -implode("", map(makeAnnoAssign, myAnnos)) ++ -"\t}\n\n" ++ + protected ${className}(${implode(", ", map((.annoSigElem), myAnnos))}) { +${implode("", map(makeAnnoAssign, myAnnos))} + } -implode("", map((.annoDeclElem), myAnnos)) ++ "\n" ++ +${implode("", map((.annoDeclElem), myAnnos))} -"\t@Override\n" ++ -"\tpublic final int getNumberOfInhAttrs() {\n" ++ -"\t\treturn num_inh_attrs;\n" ++ -"\t}\n\n" ++ + @Override + public final int getNumberOfInhAttrs() { + return num_inh_attrs; + } -"\t@Override\n" ++ -"\tpublic final int getNumberOfSynAttrs() {\n" ++ -"\t\treturn num_syn_attrs;\n" ++ -"\t}\n\n" ++ + @Override + public final int getNumberOfSynAttrs() { + return num_syn_attrs; + } -"\t@Override\n" ++ -"\tpublic final common.Lazy getDefaultSynthesized(final int index) {\n" ++ -"\t\treturn defaultSynthesizedAttributes[index];\n" ++ -"\t}\n\n" ++ + @Override + public final common.Lazy getDefaultSynthesized(final int index) { + return defaultSynthesizedAttributes[index]; + } -"\t@Override\n" ++ -"\tpublic final String getNameOfInhAttr(final int index) {\n" ++ -"\t\treturn occurs_inh[index];\n" ++ -"\t}\n\n" ++ + @Override + public final String getNameOfInhAttr(final int index) { + return occurs_inh[index]; + } -"\t@Override\n" ++ -"\tpublic final String getNameOfSynAttr(final int index) {\n" ++ -"\t\treturn occurs_syn[index];\n" ++ -"\t}\n\n" ++ + @Override + public final String getNameOfSynAttr(final int index) { + return occurs_syn[index]; + } -"}\n")]; + @Override + public final String[] getAnnoNames() { + return new String[]{${implode(", ", map((.annoNameElem), myAnnos))}}; + } + + @Override + public final Object getAnno(final String name) { + ${sconcat(map((.annoLookupElem), myAnnos))}{ + throw new common.exceptions.SilverInternalError("Invalid annotation " + name); + } + } +} +""")]; } diff --git a/grammars/silver/translation/java/core/OccursDcl.sv b/grammars/silver/translation/java/core/OccursDcl.sv index 8a9e40e9b..b97a7ea83 100644 --- a/grammars/silver/translation/java/core/OccursDcl.sv +++ b/grammars/silver/translation/java/core/OccursDcl.sv @@ -13,13 +13,13 @@ top::AGDcl ::= 'attribute' at::QName attl::BracketedOptTypeExprs 'occurs' 'on' n if at.lookupAttribute.dcl.isAnnotation then "" else - "\t\t" ++ makeNTClassName(ntfn) ++ ".occurs_" ++ occursType ++ "[" ++ head(occursCheck).attrOccursIndex ++ "] = \"" ++ at.lookupAttribute.fullName ++ "\";\n"; + s"\t\t${makeNTClassName(ntfn)}.occurs_${occursType}[${head(occursCheck).attrOccursIndex}] = \"${at.lookupAttribute.fullName}\";\n"; top.valueWeaving := if at.lookupAttribute.dcl.isAnnotation then "" else - "public static final int " ++ head(occursCheck).attrOccursIndexName ++ " = " ++ - makeName(ntgrammar) ++ ".Init.count_" ++ occursType ++ "__ON__" ++ ntname ++ "++;\n"; + s"public static final int ${head(occursCheck).attrOccursIndexName} = " ++ + s"${makeName(ntgrammar)}.Init.count_${occursType}__ON__${ntname}++;\n"; } diff --git a/grammars/silver/translation/java/core/ProductionBody.sv b/grammars/silver/translation/java/core/ProductionBody.sv index 69d0cf44d..790b9946c 100644 --- a/grammars/silver/translation/java/core/ProductionBody.sv +++ b/grammars/silver/translation/java/core/ProductionBody.sv @@ -77,8 +77,8 @@ aspect production forwardInh top::ForwardInh ::= lhs::ForwardLHSExpr '=' e::Expr ';' { top.translation = - "\t\t//" ++ top.pp ++ "\n" ++ - "\t\t" ++ top.frame.className ++ ".forwardInheritedAttributes[" ++ lhs.attrName ++ "] = " ++ wrapLazy(e) ++ ";\n"; + s"\t\t//${top.pp}\n" ++ + s"\t\t${top.frame.className}.forwardInheritedAttributes[${lhs.attrName}] = ${wrapLazy(e)};\n"; } @@ -106,15 +106,15 @@ top::ProductionStmt ::= 'local' 'attribute' a::Name '::' te::TypeExpr ';' local attribute ugh_dcl_hack :: DclInfo; ugh_dcl_hack = head(getValueDclAll(fName, top.env)); -- TODO really, we should have a DclInfo for ourselves no problem. but out current approach of constructing it via localDef makes this annoyingly difficult. this suggests a probably environment refactoring... - top.valueWeaving := "public static final int " ++ ugh_dcl_hack.attrOccursIndexName ++ " = " ++ top.frame.prodLocalCountName ++ "++;\n"; + top.valueWeaving := s"public static final int ${ugh_dcl_hack.attrOccursIndexName} = ${top.frame.prodLocalCountName}++;\n"; top.setupInh := if !te.typerep.isDecorable then "" else - "\t\t//" ++ top.pp ++ "\n" ++ - "\t\t" ++ top.frame.className ++ ".localInheritedAttributes[" ++ ugh_dcl_hack.attrOccursIndex ++ "] = " ++ - "new common.Lazy[" ++ makeNTClassName(te.typerep.typeName) ++ ".num_inh_attrs];\n"; + s"\t\t//${top.pp}\n" ++ + s"\t\t${top.frame.className}.localInheritedAttributes[${ugh_dcl_hack.attrOccursIndex}] = " ++ + s"new common.Lazy[${makeNTClassName(te.typerep.typeName)}.num_inh_attrs];\n"; - top.setupInh <- "\t\t" ++ top.frame.className ++ ".occurs_local[" ++ ugh_dcl_hack.attrOccursIndex ++ "] = \"" ++ fName ++ "\";\n"; + top.setupInh <- s"\t\t${top.frame.className}.occurs_local[${ugh_dcl_hack.attrOccursIndex}] = \"${fName}\";\n"; top.translation = ""; } @@ -122,25 +122,25 @@ top::ProductionStmt ::= 'local' 'attribute' a::Name '::' te::TypeExpr ';' aspect production childDefLHS top::DefLHS ::= q::Decorated QName { - top.translation = top.frame.className ++ ".childInheritedAttributes[" ++ top.frame.className ++ ".i_" ++ q.lookupValue.fullName ++ "]"; + top.translation = s"${top.frame.className}.childInheritedAttributes[${top.frame.className}.i_${q.lookupValue.fullName}]"; } aspect production lhsDefLHS top::DefLHS ::= q::Decorated QName { - top.translation = top.frame.className ++ ".synthesizedAttributes"; + top.translation = s"${top.frame.className}.synthesizedAttributes"; } aspect production localDefLHS top::DefLHS ::= q::Decorated QName { - top.translation = top.frame.className ++ ".localInheritedAttributes[" ++ q.lookupValue.dcl.attrOccursIndex ++ "]"; + top.translation = s"${top.frame.className}.localInheritedAttributes[${q.lookupValue.dcl.attrOccursIndex}]"; } aspect production forwardDefLHS top::DefLHS ::= q::Decorated QName { - top.translation = top.frame.className ++ ".forwardInheritedAttributes"; + top.translation = s"${top.frame.className}.forwardInheritedAttributes"; } aspect production errorDefLHS @@ -159,16 +159,16 @@ aspect production synthesizedAttributeDef top::ProductionStmt ::= dl::Decorated DefLHS attr::Decorated QNameAttrOccur e::Expr { top.translation = - "\t\t// " ++ dl.pp ++ "." ++ attr.pp ++ " = " ++ e.pp ++ "\n" ++ - "\t\t" ++ dl.translation ++ "[" ++ attr.dcl.attrOccursIndex ++ "] = " ++ wrapLazy(e) ++ ";\n"; + s"\t\t// ${dl.pp}.${attr.pp} = ${e.pp}\n" ++ + s"\t\t${dl.translation}[${attr.dcl.attrOccursIndex}] = ${wrapLazy(e)};\n"; } aspect production inheritedAttributeDef top::ProductionStmt ::= dl::Decorated DefLHS attr::Decorated QNameAttrOccur e::Expr { top.translation = - "\t\t// " ++ dl.pp ++ "." ++ attr.pp ++ " = " ++ e.pp ++ "\n" ++ - "\t\t" ++ dl.translation ++ "[" ++ attr.dcl.attrOccursIndex ++ "] = " ++ wrapLazy(e) ++ ";\n"; + s"\t\t// ${dl.pp}.${attr.pp} = ${e.pp}\n" ++ + s"\t\t${dl.translation}[${attr.dcl.attrOccursIndex}] = ${wrapLazy(e)};\n"; } @@ -182,8 +182,8 @@ aspect production localValueDef top::ProductionStmt ::= val::Decorated QName e::Expr { top.translation = - "\t\t// " ++ val.pp ++ " = " ++ e.pp ++ "\n" ++ - "\t\t" ++ top.frame.className ++ ".localAttributes[" ++ val.lookupValue.dcl.attrOccursIndex ++ "] = " ++ wrapLazy(e) ++ ";\n"; + s"\t\t// ${val.pp} = ${e.pp}\n" ++ + s"\t\t${top.frame.className}.localAttributes[${val.lookupValue.dcl.attrOccursIndex}] = ${wrapLazy(e)};\n"; } aspect production returnDef diff --git a/grammars/silver/translation/java/core/ProductionDcl.sv b/grammars/silver/translation/java/core/ProductionDcl.sv index d58510ac7..56bc6d0b3 100644 --- a/grammars/silver/translation/java/core/ProductionDcl.sv +++ b/grammars/silver/translation/java/core/ProductionDcl.sv @@ -8,17 +8,16 @@ top::AGDcl ::= 'abstract' 'production' id::Name ns::ProductionSignature body::Pr local className :: String = "P" ++ id.name; top.setupInh := body.setupInh; - top.initProd := "\t\t" ++ makeName(top.grammarName) ++ "." ++ className ++ ".initProductionAttributeDefinitions();\n"; - top.postInit := "\t\tcommon.Decorator.applyDecorators(" ++ fnnt ++ ".decorators, " ++ className ++ ".class);\n"; + top.initProd := s"\t\t${makeName(top.grammarName)}.${className}.initProductionAttributeDefinitions();\n"; + top.postInit := s"\t\tcommon.Decorator.applyDecorators(${fnnt}.decorators, ${className}.class);\n"; - top.initWeaving := "\tpublic static int " ++ localVar ++ " = 0;\n"; + top.initWeaving := s"\tpublic static int ${localVar} = 0;\n"; top.valueWeaving := body.valueWeaving; local localVar :: String = "count_local__ON__" ++ makeIdName(fName); local fnnt :: String = makeNTClassName(namedSig.outputElement.typerep.typeName); - top.genFiles := [pair(className ++ ".java", -s""" + top.genFiles := [pair(className ++ ".java", s""" package ${makeName(top.grammarName)}; // ${ns.pp} @@ -94,7 +93,7 @@ ${implode("", map(makeChildAccessCaseLazy, namedSig.inputElements))} @Override public common.Node evalForward(final common.DecoratedNode context) { ${if null(body.uniqueSignificantExpression) - then "throw new common.exceptions.SilverInternalError(\"Production " ++ fName ++ " erroneously claimed to forward\")" + then s"throw new common.exceptions.SilverInternalError(\"Production ${fName} erroneously claimed to forward\")" else "return " ++ head(body.uniqueSignificantExpression).translation}; } diff --git a/grammars/silver/translation/java/core/RootSpec.sv b/grammars/silver/translation/java/core/RootSpec.sv index 45f6c78b6..1a56e2cfb 100644 --- a/grammars/silver/translation/java/core/RootSpec.sv +++ b/grammars/silver/translation/java/core/RootSpec.sv @@ -21,53 +21,53 @@ top::RootSpec ::= g::Grammar _ _ _ { top.genFiles := g.genFiles ++ [pair("Silver.svi", unparseRootSpec(top)), - pair("Init.java", -"package " ++ makeName(g.declaredName) ++ ";\n\n" ++ + pair("Init.java", s""" +package ${makeName(g.declaredName)}; -"public class Init{\n\n" ++ +public class Init{ + private static boolean preInit = false; + private static boolean init = false; + private static boolean postInit = false; -"\tprivate static boolean preInit = false;\n" ++ -"\tprivate static boolean init = false;\n" ++ -"\tprivate static boolean postInit = false;\n\n" ++ + public static void initAllStatics(){ + if(preInit) return; + preInit = true; +${makeOthers(top.allGrammarDependencies, "initAllStatics")} + } -"\tpublic static void initAllStatics(){\n" ++ -"\t\tif(preInit) return;\n" ++ -"\t\tpreInit = true;\n\n" ++ - makeOthers(top.allGrammarDependencies, "initAllStatics") ++ "\n" ++ -"\t}\n\n" ++ + public static void init(){ + if(init) return; + init = true; + setupInheritedAttributes(); +${makeOthers(top.allGrammarDependencies, "init")} + initProductionAttributeDefinitions(); + } -"\tpublic static void init(){\n" ++ -"\t\tif(init) return;\n" ++ -"\t\tinit = true;\n\n" ++ -"\t\tsetupInheritedAttributes();\n\n" ++ - makeOthers(top.allGrammarDependencies, "init") ++ "\n" ++ -"\t\tinitProductionAttributeDefinitions();\n" ++ -"\t}\n\n" ++ + public static void postInit(){ + if(postInit) return; + postInit = true; +${makeOthers(top.allGrammarDependencies, "postInit")} +${g.postInit} + } -"\tpublic static void postInit(){\n" ++ -"\t\tif(postInit) return;\n" ++ -"\t\tpostInit = true;\n\n" ++ - makeOthers(top.allGrammarDependencies, "postInit") ++ "\n\n" ++ - g.postInit ++ -"\t}\n\n" ++ + private static void setupInheritedAttributes(){ +${g.setupInh} + } -"\tprivate static void setupInheritedAttributes(){\n" ++ - g.setupInh ++ -"\t}\n\n" ++ + private static void initProductionAttributeDefinitions(){ +${g.initProd} + } -"\tprivate static void initProductionAttributeDefinitions(){\n" ++ - g.initProd ++ -"\t}\n\n" ++ - - g.initWeaving ++ - g.valueWeaving ++ - g.initValues ++ -"}\n")]; +${g.initWeaving} +${g.valueWeaving} +${g.initValues} +} +""")]; } function makeOthers String ::= others::[String] nme::String { - return if null(others) then "" else "\t\t" ++ makeName(head(others)) ++ ".Init."++nme++"();\n" ++ makeOthers(tail(others),nme); + return if null(others) then "" else s"\t\t${makeName(head(others))}.Init.${nme}();\n${makeOthers(tail(others),nme)}"; } diff --git a/grammars/silver/translation/java/core/TerminalDcl.sv b/grammars/silver/translation/java/core/TerminalDcl.sv index 013b5e2cc..718a71772 100644 --- a/grammars/silver/translation/java/core/TerminalDcl.sv +++ b/grammars/silver/translation/java/core/TerminalDcl.sv @@ -13,8 +13,7 @@ tm::TerminalModifiers local lexerClassesStr :: String = implode(", ", map(quote, tm.lexerClasses)); - top.genFiles := [pair(className ++ ".java", -s""" + top.genFiles := [pair(className ++ ".java", s""" package ${makeName(top.grammarName)}; import edu.umn.cs.melt.copper.runtime.engines.semantics.VirtualLocation; diff --git a/runtime/java/src/common/FunctionNode.java b/runtime/java/src/common/FunctionNode.java index b3351125f..9a8f24ddc 100644 --- a/runtime/java/src/common/FunctionNode.java +++ b/runtime/java/src/common/FunctionNode.java @@ -72,4 +72,13 @@ public final String getNameOfSynAttr(final int index) { throw new SilverInternalError("Functions do not possess synthesized attributes! (Requested name of index " + index + ")"); } + @Override + public final String[] getAnnoNames() { + throw new SilverInternalError("Functions do not possess annotations!"); + } + + @Override + public final Object getAnno(final String name) { + throw new SilverInternalError("Functions do not possess annotations! (Requested name " + name + ")"); + } } diff --git a/runtime/java/src/common/Node.java b/runtime/java/src/common/Node.java index f2928d946..2530fb841 100644 --- a/runtime/java/src/common/Node.java +++ b/runtime/java/src/common/Node.java @@ -96,6 +96,21 @@ public DecoratedNode decorate() { */ public abstract String getNameOfInhAttr(final int index); + /** + * Used for reflection. + * + * @return An array of the names of all annotations. + */ + public abstract String[] getAnnoNames(); + + /** + * Used for reflection. + * + * @param name The name of any annotation returned by getAnnoNames() + * @return The annotation object. (Thunk already evaluated) + */ + public abstract Object getAnno(final String name); + // These methods are to be provided by the *production* diff --git a/runtime/java/src/common/Reflection.java b/runtime/java/src/common/Reflection.java new file mode 100644 index 000000000..2487b1530 --- /dev/null +++ b/runtime/java/src/common/Reflection.java @@ -0,0 +1,55 @@ +package common; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; + +import common.exceptions.*; + +import core.reflect.*; + + +/** + * Implementation of the Silver reflection library + * + * @author krame505 + */ +public final class Reflection { + public static NAST reflect(Object o) { + if(o instanceof Node) { + Node n = (Node)o; + NASTs children = new PnilAST(); + for (int i = n.getNumberOfChildren() - 1; i >= 0; i--) { + Object value = reflect(n.getChild(i)); + children = new PconsAST(value, children); + } + String[] annotationNames = n.getAnnoNames(); + NNamedASTs annotations = new PnilNamedAST(); + for (int i = annotationNames.length - 1; i >= 0; i--) { + String name = annotationNames[i]; + Object value = reflect(n.getAnno(name)); + annotations = new PconsNamedAST(new PnamedAST(new StringCatter(name), value), annotations); + } + return new PnonterminalAST(new StringCatter(n.getName()), children, annotations); + } else if(o instanceof ConsCell) { + return new PlistAST(reflectList((ConsCell)o)); + } else if(o instanceof StringCatter) { + return new PstringAST((StringCatter)o); + } else if(o instanceof Integer) { + return new PintegerAST((Integer)o); + } else if(o instanceof Float) { + return new PfloatAST((Float)o); + } else if(o instanceof Boolean) { + return new PbooleanAST((Boolean)o); + } else { + return new PforeignAST(o); + } + } + private static NASTs reflectList(ConsCell l) { + if (!l.nil()) { + return new PconsAST(reflect(l.head()), reflectList(l.tail())); + } else { + return new PnilAST(); + } + } +} diff --git a/test/silver_features/Reflection.sv b/test/silver_features/Reflection.sv new file mode 100644 index 000000000..fb412277b --- /dev/null +++ b/test/silver_features/Reflection.sv @@ -0,0 +1,32 @@ + +import core:reflect; +import silver:langutil; +import silver:langutil:pp; + +annotation lineNum::Integer; + +nonterminal Expr with lineNum; + +abstract production addExpr +top::Expr ::= e1::Expr e2::Expr +{} + +abstract production intConstExpr +top::Expr ::= i::Integer +{} + +abstract production idExpr +top::Expr ::= id::String +{} + +abstract production decExpr +top::Expr ::= d::Decorated Expr +{} + +global testExpr::Expr = addExpr(intConstExpr(2, lineNum=1), idExpr("asdf", lineNum=2), lineNum=3); + +equalityTest( + show(80, reflect([testExpr, intConstExpr(5, lineNum=4), decExpr(decorate testExpr with {}, lineNum=4)]).pp), + s"""[silver_features:addExpr(silver_features:intConstExpr(2, silver_features:lineNum=1), silver_features:idExpr("asdf", silver_features:lineNum=2), silver_features:lineNum=3), silver_features:intConstExpr(5, silver_features:lineNum=4), silver_features:decExpr(, silver_features:lineNum=4)]""", + String, silver_tests); +