From 51a31c4999caab616d2cda7d889a815d0b5e788e Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Wed, 4 Mar 2020 16:02:36 -0600 Subject: [PATCH 01/57] New keyword for old functor extension --- .../extension/functorattrib/ProductionBody.sv | 18 ++++++++++++++++++ .../extension/functorattrib/Terminals.sv | 1 + 2 files changed, 19 insertions(+) diff --git a/grammars/silver/extension/functorattrib/ProductionBody.sv b/grammars/silver/extension/functorattrib/ProductionBody.sv index 73e207f97..ca1e60d86 100644 --- a/grammars/silver/extension/functorattrib/ProductionBody.sv +++ b/grammars/silver/extension/functorattrib/ProductionBody.sv @@ -21,6 +21,24 @@ top::ProductionStmt ::= 'propagate' ns::NameList ';' location=top.location) end; } +concrete production propagateAttrDclOld +top::ProductionStmt ::= 'propagate_functor' ns::NameList ';' +{ + top.unparse = s"propagate ${ns.unparse};"; + + -- Forwards to productionStmtAppend of propagating the first element in ns + -- and propagateAttrDcl containing the remaining names + forwards to + case ns of + | nameListOne(n) -> + propagateOne(n, location=top.location) + | nameListCons(n, _, rest) -> + productionStmtAppend( + propagateOne(n, location=top.location), + propagateAttrDclOld($1, rest, $3, location=top.location), + location=top.location) + end; +} {-- - Generates the expression we should use for an argument diff --git a/grammars/silver/extension/functorattrib/Terminals.sv b/grammars/silver/extension/functorattrib/Terminals.sv index d546b7971..d8908dcfd 100644 --- a/grammars/silver/extension/functorattrib/Terminals.sv +++ b/grammars/silver/extension/functorattrib/Terminals.sv @@ -1,3 +1,4 @@ terminal Propagate_kwd 'propagate' lexer classes {KEYWORD,RESERVED}; +terminal PropagateOld_kwd 'propagate_functor' lexer classes {KEYWORD,RESERVED}; terminal Functor_kwd 'functor' lexer classes {KEYWORD,RESERVED}; From c11ecec76b796e3ee63cc7daefceddb6f0009371 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Wed, 4 Mar 2020 16:23:26 -0600 Subject: [PATCH 02/57] Use temp keyword for old functor extension --- .../extension/functorattrib/ProductionBody.sv | 18 ------------------ .../extension/functorattrib/Terminals.sv | 2 -- grammars/silver/extension/rewriting/Expr.sv | 6 +++--- 3 files changed, 3 insertions(+), 23 deletions(-) diff --git a/grammars/silver/extension/functorattrib/ProductionBody.sv b/grammars/silver/extension/functorattrib/ProductionBody.sv index ca1e60d86..522350a16 100644 --- a/grammars/silver/extension/functorattrib/ProductionBody.sv +++ b/grammars/silver/extension/functorattrib/ProductionBody.sv @@ -3,24 +3,6 @@ - Propagates a list of functor attributes on the current production. - Actual implementation in propagateOne -} -concrete production propagateAttrDcl -top::ProductionStmt ::= 'propagate' ns::NameList ';' -{ - top.unparse = s"propagate ${ns.unparse};"; - - -- Forwards to productionStmtAppend of propagating the first element in ns - -- and propagateAttrDcl containing the remaining names - forwards to - case ns of - | nameListOne(n) -> - propagateOne(n, location=top.location) - | nameListCons(n, _, rest) -> - productionStmtAppend( - propagateOne(n, location=top.location), - propagateAttrDcl($1, rest, $3, location=top.location), - location=top.location) - end; -} concrete production propagateAttrDclOld top::ProductionStmt ::= 'propagate_functor' ns::NameList ';' { diff --git a/grammars/silver/extension/functorattrib/Terminals.sv b/grammars/silver/extension/functorattrib/Terminals.sv index d8908dcfd..7bffd4f6b 100644 --- a/grammars/silver/extension/functorattrib/Terminals.sv +++ b/grammars/silver/extension/functorattrib/Terminals.sv @@ -1,4 +1,2 @@ -terminal Propagate_kwd 'propagate' lexer classes {KEYWORD,RESERVED}; terminal PropagateOld_kwd 'propagate_functor' lexer classes {KEYWORD,RESERVED}; -terminal Functor_kwd 'functor' lexer classes {KEYWORD,RESERVED}; diff --git a/grammars/silver/extension/rewriting/Expr.sv b/grammars/silver/extension/rewriting/Expr.sv index 7c2b30f29..7ae9b5207 100644 --- a/grammars/silver/extension/rewriting/Expr.sv +++ b/grammars/silver/extension/rewriting/Expr.sv @@ -260,7 +260,7 @@ top::ExprInhs ::= { top.transform = nilASTExpr(); top.lambdaParams = productionRHSNil(location=builtin); - propagate bodyExprInhTransform; + propagate_functor bodyExprInhTransform; } aspect production exprInhsOne @@ -269,7 +269,7 @@ top::ExprInhs ::= lhs::ExprInh top.transform = consASTExpr(lhs.transform, nilASTExpr()); top.lambdaParams = productionRHSCons(lhs.lambdaParam, productionRHSNil(location=builtin), location=builtin); - propagate bodyExprInhTransform; + propagate_functor bodyExprInhTransform; } aspect production exprInhsCons @@ -277,7 +277,7 @@ top::ExprInhs ::= lhs::ExprInh inh::ExprInhs { top.transform = consASTExpr(lhs.transform, inh.transform); top.lambdaParams = productionRHSCons(lhs.lambdaParam, inh.lambdaParams, location=builtin); - propagate bodyExprInhTransform; + propagate_functor bodyExprInhTransform; } attribute transform occurs on ExprInh; From 54e0ed6e3d4496a6a383c39a0ab1ff4489014361 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Thu, 5 Mar 2020 14:42:37 -0600 Subject: [PATCH 03/57] Add dispatching extension point for attribution, split oDef into a seperate occursDefs attribute from defs to fix annoying circular dependency bug --- grammars/silver/definition/core/AGDcl.sv | 9 ++- grammars/silver/definition/core/DclInfo.sv | 12 +++- .../silver/definition/core/GrammarParts.sv | 9 ++- .../silver/definition/core/ModuleStmts.sv | 38 +++++++++--- grammars/silver/definition/core/OccursDcl.sv | 62 ++++++++++++++++--- grammars/silver/definition/core/QName.sv | 1 + grammars/silver/definition/core/Root.sv | 6 +- grammars/silver/definition/env/Attributes.sv | 5 ++ grammars/silver/definition/env/Defs.sv | 21 +------ grammars/silver/definition/env/Env.sv | 24 ++++++- grammars/silver/driver/CompileGrammar.sv | 2 +- grammars/silver/driver/util/RootSpec.sv | 35 ++++++++--- grammars/silver/extension/easyterminal/Env.sv | 6 ++ grammars/silver/modification/copper/Env.sv | 6 ++ grammars/silver/modification/impide/Env.sv | 6 ++ .../silver/translation/java/core/OccursDcl.sv | 10 ++- 16 files changed, 198 insertions(+), 54 deletions(-) diff --git a/grammars/silver/definition/core/AGDcl.sv b/grammars/silver/definition/core/AGDcl.sv index 88ce1af59..9a709bae1 100644 --- a/grammars/silver/definition/core/AGDcl.sv +++ b/grammars/silver/definition/core/AGDcl.sv @@ -3,8 +3,8 @@ grammar silver:definition:core; {-- - Top-level declarations of a Silver grammar. The "meat" of a file. -} -nonterminal AGDcls with config, grammarName, env, location, unparse, errors, defs, moduleNames, compiledGrammars, grammarDependencies, jarName; -nonterminal AGDcl with config, grammarName, env, location, unparse, errors, defs, moduleNames, compiledGrammars, grammarDependencies, jarName; +nonterminal AGDcls with config, grammarName, env, location, unparse, errors, defs, occursDefs, moduleNames, compiledGrammars, grammarDependencies, jarName; +nonterminal AGDcl with config, grammarName, env, location, unparse, errors, defs, occursDefs, moduleNames, compiledGrammars, grammarDependencies, jarName; flowtype forward {grammarName, env} on AGDcl; @@ -14,6 +14,7 @@ top::AGDcls ::= top.unparse = ""; top.defs = []; + top.occursDefs = []; top.errors := []; top.moduleNames = []; top.jarName = nothing(); @@ -25,6 +26,7 @@ top::AGDcls ::= h::AGDcl t::AGDcls top.unparse = h.unparse ++ "\n" ++ t.unparse; top.defs = h.defs ++ t.defs; + top.occursDefs = h.occursDefs ++ t.occursDefs; top.errors := h.errors ++ t.errors ++ warnIfMultJarName(h.jarName, t.jarName, top.location); top.moduleNames = h.moduleNames ++ t.moduleNames; top.jarName = orElse(h.jarName, t.jarName); @@ -63,6 +65,7 @@ top::AGDcl ::= h::AGDcl t::AGDcl top.unparse = h.unparse ++ "\n" ++ t.unparse; top.defs = h.defs ++ t.defs; + top.occursDefs = h.occursDefs ++ t.occursDefs; top.errors := h.errors ++ t.errors ++ warnIfMultJarName(h.jarName, t.jarName, top.location); top.moduleNames = h.moduleNames ++ t.moduleNames; top.jarName = orElse(h.jarName, t.jarName); @@ -75,6 +78,7 @@ top::AGDcl ::= n::Name top.errors := []; top.moduleNames = []; top.defs = []; + top.occursDefs = []; top.jarName = just(n.name); } @@ -84,6 +88,7 @@ top::AGDcl ::= -- can't provide unparse or location! top.moduleNames = []; top.defs = []; + top.occursDefs = []; top.jarName = nothing(); --top.errors := []; -- should never be omitted, really. } diff --git a/grammars/silver/definition/core/DclInfo.sv b/grammars/silver/definition/core/DclInfo.sv index bc1d42d62..6a828a20e 100644 --- a/grammars/silver/definition/core/DclInfo.sv +++ b/grammars/silver/definition/core/DclInfo.sv @@ -29,9 +29,13 @@ synthesized attribute decoratedAccessHandler :: (Expr ::= Decorated Expr Decora -} synthesized attribute undecoratedAccessHandler :: (Expr ::= Decorated Expr Decorated QNameAttrOccur Location) occurs on DclInfo; {-- - - The production an "equation" shuld forward to for this type of attribute (i.e. the 'a' in 'x.a = e') + - The production an "equation" should forward to for this type of attribute (i.e. the 'a' in 'x.a = e') -} synthesized attribute attrDefDispatcher :: (ProductionStmt ::= Decorated DefLHS Decorated QNameAttrOccur Expr Location) occurs on DclInfo; +{-- + - The production an "occurs on" decl should forward to for this type of attribute (for extension use, defaultAttributionDcl for all syn/inh/autocopy attrs.) + -} +synthesized attribute attributionDispatcher :: (AGDcl ::= Decorated QName BracketedOptTypeExprs QName BracketedOptTypeExprs Location) occurs on DclInfo; aspect default production top::DclInfo ::= @@ -45,7 +49,8 @@ top::DclInfo ::= -- all attributes must provide decoratedAccessHandler, attrDefDispatcher. top.decoratedAccessHandler = error("Internal compiler error: must be defined for all attribute declarations"); top.undecoratedAccessHandler = error("Internal compiler error: must be defined for all attribute declarations"); - top.attrDefDispatcher = error("Internal compiler error: must be defined for all attribute declarations"); + top.attrDefDispatcher = error("Internal compiler error: must be defined for all attribute declarations"); + top.attributionDispatcher = error("Internal compiler error: must be defined for all attribute declarations"); } -- -- non-interface values @@ -103,6 +108,7 @@ top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type top.decoratedAccessHandler = synDecoratedAccessHandler(_, _, location=_); top.undecoratedAccessHandler = accessBounceDecorate(synDecoratedAccessHandler(_, _, location=_), _, _, _); top.attrDefDispatcher = synthesizedAttributeDef(_, _, _, location=_); + top.attributionDispatcher = defaultAttributionDcl(_, _, _, _, location=_); } aspect production inhDcl top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type @@ -110,6 +116,7 @@ top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type top.decoratedAccessHandler = inhDecoratedAccessHandler(_, _, location=_); top.undecoratedAccessHandler = accessBounceDecorate(inhDecoratedAccessHandler(_, _, location=_), _, _, _); -- TODO: above should probably be an error handler! access inh from undecorated? top.attrDefDispatcher = inheritedAttributeDef(_, _, _, location=_); + top.attributionDispatcher = defaultAttributionDcl(_, _, _, _, location=_); } aspect production annoDcl top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type @@ -119,6 +126,7 @@ top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type top.attrDefDispatcher = \ dl::Decorated DefLHS attr::Decorated QNameAttrOccur e::Expr l::Location -> errorAttributeDef([err(l, "Annotations are not defined as equations within productions")], dl, attr, e, location=l); + top.attributionDispatcher = defaultAttributionDcl(_, _, _, _, location=_); } -- -- interface Production attr (values) diff --git a/grammars/silver/definition/core/GrammarParts.sv b/grammars/silver/definition/core/GrammarParts.sv index f2a5cdf26..48ea3cd41 100644 --- a/grammars/silver/definition/core/GrammarParts.sv +++ b/grammars/silver/definition/core/GrammarParts.sv @@ -7,7 +7,7 @@ nonterminal Grammar with grammarName, env, globalImports, grammarDependencies, -- Synthesized attributes declaredName, moduleNames, exportedGrammars, optionalGrammars, condBuild, - defs, importedDefs, grammarErrors, jarName; + defs, occursDefs, importedDefs, importedOccursDefs, grammarErrors, jarName; {-- - A list of grammars that this grammar depends upon, @@ -26,6 +26,7 @@ autocopy attribute globalImports :: Decorated Env; - At the top of a grammar, these are echoed down as globalImports -} synthesized attribute importedDefs :: [Def]; +synthesized attribute importedOccursDefs :: [DclInfo]; {-- - An overall listing of error messages for a grammar -} @@ -43,7 +44,9 @@ top::Grammar ::= top.condBuild = []; top.importedDefs = []; + top.importedOccursDefs = []; top.defs = []; + top.occursDefs = []; top.grammarErrors = []; top.jarName = nothing(); @@ -58,8 +61,10 @@ top::Grammar ::= h::Root t::Grammar top.optionalGrammars = h.optionalGrammars ++ t.optionalGrammars; top.condBuild = h.condBuild ++ t.condBuild; - top.importedDefs = h.importedDefs ++ t.importedDefs; top.defs = h.defs ++ t.defs; + top.occursDefs = h.occursDefs ++ t.occursDefs; + top.importedDefs = h.importedDefs ++ t.importedDefs; + top.importedOccursDefs = h.importedOccursDefs ++ t.importedOccursDefs; top.grammarErrors = if null(h.errors ++ jarNameErrors) then t.grammarErrors else pair(h.location.filename, h.errors ++ jarNameErrors) :: t.grammarErrors; diff --git a/grammars/silver/definition/core/ModuleStmts.sv b/grammars/silver/definition/core/ModuleStmts.sv index 29668cc8c..51cc39e7a 100644 --- a/grammars/silver/definition/core/ModuleStmts.sv +++ b/grammars/silver/definition/core/ModuleStmts.sv @@ -2,14 +2,14 @@ grammar silver:definition:core; imports silver:driver:util; -nonterminal ModuleStmts with config, grammarName, location, unparse, errors, moduleNames, defs, exportedGrammars, optionalGrammars, condBuild, compiledGrammars, grammarDependencies; -nonterminal ModuleStmt with config, grammarName, location, unparse, errors, moduleNames, defs, exportedGrammars, optionalGrammars, condBuild, compiledGrammars, grammarDependencies; +nonterminal ModuleStmts with config, grammarName, location, unparse, errors, moduleNames, defs, occursDefs, exportedGrammars, optionalGrammars, condBuild, compiledGrammars, grammarDependencies; +nonterminal ModuleStmt with config, grammarName, location, unparse, errors, moduleNames, defs, occursDefs, exportedGrammars, optionalGrammars, condBuild, compiledGrammars, grammarDependencies; -nonterminal ImportStmt with config, grammarName, location, unparse, errors, moduleNames, defs, compiledGrammars, grammarDependencies; -nonterminal ImportStmts with config, grammarName, location, unparse, errors, moduleNames, defs, compiledGrammars, grammarDependencies; +nonterminal ImportStmt with config, grammarName, location, unparse, errors, moduleNames, defs, occursDefs, compiledGrammars, grammarDependencies; +nonterminal ImportStmts with config, grammarName, location, unparse, errors, moduleNames, defs, occursDefs, compiledGrammars, grammarDependencies; -nonterminal ModuleExpr with config, grammarName, location, unparse, errors, moduleNames, defs, compiledGrammars, grammarDependencies; -nonterminal ModuleName with config, grammarName, location, unparse, errors, moduleNames, defs, compiledGrammars, grammarDependencies; +nonterminal ModuleExpr with config, grammarName, location, unparse, errors, moduleNames, defs, occursDefs, compiledGrammars, grammarDependencies; +nonterminal ModuleName with config, grammarName, location, unparse, errors, moduleNames, defs, occursDefs, compiledGrammars, grammarDependencies; nonterminal NameList with config, grammarName, location, unparse, names; @@ -26,7 +26,7 @@ synthesized attribute names :: [String]; synthesized attribute envMaps :: [Pair]; -- TODO: eliminate, fold into ModuleName, make filter parameters inh attrs. -nonterminal Module with defs, errors; +nonterminal Module with defs, occursDefs, errors; abstract production module top::Module ::= l::Location @@ -61,11 +61,12 @@ top::Module ::= l::Location else map(mapDefOnEnvItem(envItemPrepend(_, asPrepend ++ ":"), _), defs_after_renames); top.defs = defs_after_prepend; + top.occursDefs = med.occursDefs; top.errors := med.errors; } -- recurses through exportedGrammars, grabbing all definitions -nonterminal ModuleExportedDefs with defs, errors; +nonterminal ModuleExportedDefs with defs, occursDefs, errors; {-- - Computes the set of defs we get from an import @@ -99,6 +100,9 @@ top::ModuleExportedDefs ::= l::Location compiledGrammars::EnvTree> ::= if null(gramCompile.iovalue.snd) then grammarRootSpec(foldRoot(gramCompile.iovalue.fst), grammarName, grammarLocation.iovalue.fromJust, grammarTime.iovalue, benv.silverGen) else - errorRootSpec(gramCompile.iovalue.snd, grammarName, grammarLocation.iovalue.fromJust, grammarTime.iovalue, benv.silverGen); + errorRootSpec(gramCompile.iovalue.snd, grammarName, grammarLocation.iovalue.fromJust, grammarTime.iovalue, benv.silverGen); return if !grammarLocation.iovalue.isJust then diff --git a/grammars/silver/driver/util/RootSpec.sv b/grammars/silver/driver/util/RootSpec.sv index d5f0bd472..eccf73b53 100644 --- a/grammars/silver/driver/util/RootSpec.sv +++ b/grammars/silver/driver/util/RootSpec.sv @@ -4,7 +4,7 @@ import silver:reflect; import silver:langutil only pp; import silver:langutil:pp only show; -import silver:definition:core only Grammar, grammarErrors, grammarName, importedDefs, grammarDependencies, globalImports, Message, err; +import silver:definition:core only Grammar, grammarErrors, grammarName, importedDefs, importedOccursDefs, grammarDependencies, globalImports, Message, err; import silver:definition:flow:env only flowEnv, flowDefs, fromFlowDefs; import silver:definition:flow:ast only nilFlow, consFlow, FlowDef; @@ -18,7 +18,7 @@ nonterminal RootSpec with config, compiledGrammars, productionFlowGraphs, grammarFlowTypes, -- synthesized attributes declaredName, moduleNames, exportedGrammars, optionalGrammars, condBuild, allGrammarDependencies, - defs, grammarErrors, grammarSource, grammarTime, interfaceTime, recheckGrammars, translateGrammars, + defs, occursDefs, grammarErrors, grammarSource, grammarTime, interfaceTime, recheckGrammars, translateGrammars, parsingErrors, jarName, generateLocation; @@ -44,10 +44,14 @@ top::RootSpec ::= g::Grammar grammarName::String grammarSource::String gramma g.grammarName = grammarName; -- Create the environments for this grammar - g.env = toEnv(g.defs); - g.globalImports = toEnv( - if contains("core", g.moduleNames) || grammarName == "core" then g.importedDefs - else g.importedDefs ++ head(searchEnvTree("core", top.compiledGrammars)).defs); + g.env = occursEnv(g.occursDefs, toEnv(g.defs)); + g.globalImports = + occursEnv( + if contains("core", g.moduleNames) || grammarName == "core" then g.importedOccursDefs + else g.importedOccursDefs ++ head(searchEnvTree("core", top.compiledGrammars)).occursDefs, + toEnv( + if contains("core", g.moduleNames) || grammarName == "core" then g.importedDefs + else g.importedDefs ++ head(searchEnvTree("core", top.compiledGrammars)).defs)); -- This grammar, its direct imports, and only transitively close over exports and TRIGGERED conditional imports. -- i.e. these are the things that we really, truly depend upon. (in the sense that we get their symbols) @@ -79,6 +83,7 @@ top::RootSpec ::= g::Grammar grammarName::String grammarSource::String gramma top.allGrammarDependencies = actualDependencies; top.defs = g.defs; + top.occursDefs = g.occursDefs; top.grammarErrors = g.grammarErrors; top.parsingErrors = []; @@ -108,6 +113,7 @@ top::RootSpec ::= p::GrammarProperties interfaceTime::Integer generateLocation top.allGrammarDependencies = p.allGrammarDependencies; top.defs = p.defs; + top.occursDefs = p.occursDefs; top.grammarErrors = []; -- TODO: consider getting grammarName and comparing against declaredName? top.parsingErrors = []; @@ -136,6 +142,7 @@ top::RootSpec ::= e::[ParseError] grammarName::String grammarSource::String g top.allGrammarDependencies = []; top.defs = []; + top.occursDefs = []; top.grammarErrors = []; top.parsingErrors = map(parseErrorToMessage(grammarSource, _), e); @@ -161,7 +168,7 @@ Pair ::= grammarSource::String e::ParseError - Representation of all properties of a grammar, to be serialized/deserialize to/from an interface - file. -} -nonterminal GrammarProperties with declaredName, grammarSource, grammarTime, moduleNames, exportedGrammars, optionalGrammars, condBuild, allGrammarDependencies, defs; +nonterminal GrammarProperties with declaredName, grammarSource, grammarTime, moduleNames, exportedGrammars, optionalGrammars, condBuild, allGrammarDependencies, defs, occursDefs; abstract production consGrammarProperties top::GrammarProperties ::= h::GrammarProperty t::GrammarProperties @@ -175,6 +182,7 @@ top::GrammarProperties ::= h::GrammarProperty t::GrammarProperties top.condBuild = fromMaybe(t.condBuild, h.maybeCondBuild); top.allGrammarDependencies = fromMaybe(t.allGrammarDependencies, h.maybeAllGrammarDependencies); top.defs = fromMaybe(t.defs, h.maybeDefs); + top.occursDefs = fromMaybe(t.occursDefs, h.maybeOccursDefs); } abstract production nilGrammarProperties @@ -189,6 +197,7 @@ top::GrammarProperties ::= top.condBuild = error("Grammar property condBuild missing from interface file"); top.allGrammarDependencies = error("Grammar property allGrammarDependencies missing from interface file"); top.defs = error("Grammar property defs missing from interface file"); + top.occursDefs = error("Grammar property occursDefs missing from interface file"); } synthesized attribute maybeGrammarSource::Maybe; @@ -200,8 +209,9 @@ synthesized attribute maybeOptionalGrammars::Maybe<[String]>; synthesized attribute maybeCondBuild::Maybe<[[String]]>; synthesized attribute maybeAllGrammarDependencies::Maybe<[String]>; synthesized attribute maybeDefs::Maybe<[Def]>; +synthesized attribute maybeOccursDefs::Maybe<[DclInfo]>; -closed nonterminal GrammarProperty with maybeGrammarSource, maybeGrammarTime, maybeDeclaredName, maybeModuleNames, maybeExportedGrammars, maybeOptionalGrammars, maybeCondBuild, maybeAllGrammarDependencies, maybeDefs; +closed nonterminal GrammarProperty with maybeGrammarSource, maybeGrammarTime, maybeDeclaredName, maybeModuleNames, maybeExportedGrammars, maybeOptionalGrammars, maybeCondBuild, maybeAllGrammarDependencies, maybeDefs, maybeOccursDefs; aspect default production top::GrammarProperty ::= @@ -271,6 +281,12 @@ top::GrammarProperty ::= val::[Def] top.maybeDefs = just(val); } +abstract production occursDefsGrammarProperty +top::GrammarProperty ::= val::[DclInfo] +{ + top.maybeOccursDefs = just(val); +} + {-- - How RootSpecs are turned into interface files shouldn't change - depending on what the source it, so we give this function externally @@ -289,7 +305,8 @@ String ::= r::Decorated RootSpec optionalGrammarsGrammarProperty(r.optionalGrammars), condBuildGrammarProperty(r.condBuild), allDepsGrammarProperty(r.allGrammarDependencies), - defsGrammarProperty(r.defs) + defsGrammarProperty(r.defs), + occursDefsGrammarProperty(r.occursDefs) ]; return diff --git a/grammars/silver/extension/easyterminal/Env.sv b/grammars/silver/extension/easyterminal/Env.sv index ceada02f6..c54e4322b 100644 --- a/grammars/silver/extension/easyterminal/Env.sv +++ b/grammars/silver/extension/easyterminal/Env.sv @@ -54,3 +54,9 @@ top::Env ::= d::Defs e::Decorated Env top.terminalTree = oneEnvScope(buildTerminalTree(d.typeList)) :: e.terminalTree; } +aspect production i_occursEnv +top::Env ::= _ e::Decorated Env +{ + top.terminalTree = e.terminalTree; +} + diff --git a/grammars/silver/modification/copper/Env.sv b/grammars/silver/modification/copper/Env.sv index 8cdf12962..a3da8d605 100644 --- a/grammars/silver/modification/copper/Env.sv +++ b/grammars/silver/modification/copper/Env.sv @@ -92,6 +92,12 @@ top::Env ::= d::Defs e::Decorated Env top.lexerClassTree = consEnvScope(buildTree(d.lexerClassList), e.lexerClassTree); } +aspect production i_occursEnv +top::Env ::= _ e::Decorated Env +{ + top.lexerClassTree = e.lexerClassTree; +} + function getLexerClassDcl [DclInfo] ::= search::String e::Decorated Env { diff --git a/grammars/silver/modification/impide/Env.sv b/grammars/silver/modification/impide/Env.sv index d58cda87d..282291e15 100644 --- a/grammars/silver/modification/impide/Env.sv +++ b/grammars/silver/modification/impide/Env.sv @@ -76,6 +76,12 @@ top::Env ::= d::Defs e::Decorated Env top.fontDefTree = consEnvScope(buildTree(d.fontDefList), e.fontDefTree); } +aspect production i_occursEnv +top::Env ::= _ e::Decorated Env +{ + top.fontDefTree = e.fontDefTree; +} + function getFontDcl [DclInfo] ::= search::String e::Decorated Env { diff --git a/grammars/silver/translation/java/core/OccursDcl.sv b/grammars/silver/translation/java/core/OccursDcl.sv index b97a7ea83..106c1d7f3 100644 --- a/grammars/silver/translation/java/core/OccursDcl.sv +++ b/grammars/silver/translation/java/core/OccursDcl.sv @@ -1,7 +1,7 @@ grammar silver:translation:java:core; -aspect production attributionDcl -top::AGDcl ::= 'attribute' at::QName attl::BracketedOptTypeExprs 'occurs' 'on' nt::QName nttl::BracketedOptTypeExprs ';' +aspect production defaultAttributionDcl +top::AGDcl ::= at::Decorated QName attl::BracketedOptTypeExprs nt::QName nttl::BracketedOptTypeExprs { local ntfn :: String = nt.lookupType.fullName; local occursType :: String = if at.lookupAttribute.dcl.isSynthesized then "syn" else "inh"; @@ -23,3 +23,9 @@ top::AGDcl ::= 'attribute' at::QName attl::BracketedOptTypeExprs 'occurs' 'on' n s"${makeName(ntgrammar)}.Init.count_${occursType}__ON__${ntname}++;\n"; } +aspect production errorAttributionDcl +top::AGDcl ::= msg::[Message] at::Decorated QName attl::BracketedOptTypeExprs nt::QName nttl::BracketedOptTypeExprs +{ + top.setupInh := error("Internal compiler error: translation not defined in the presence of errors"); + top.valueWeaving := error("Internal compiler error: translation not defined in the presence of errors"); +} From 67c7bd002e0825d437929d24f269e1a8fabe6b4a Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Thu, 5 Mar 2020 15:06:05 -0600 Subject: [PATCH 04/57] Add quote productions for AGDcl and ProductionStmt --- .../silver/extension/silverconstruction/Syntax.sv | 14 ++++++++++++++ .../extension/silverconstruction/Terminals.sv | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/grammars/silver/extension/silverconstruction/Syntax.sv b/grammars/silver/extension/silverconstruction/Syntax.sv index c482e1ec1..e2c546864 100644 --- a/grammars/silver/extension/silverconstruction/Syntax.sv +++ b/grammars/silver/extension/silverconstruction/Syntax.sv @@ -7,6 +7,20 @@ imports silver:definition:env; imports silver:definition:type:syntax; imports silver:extension:list; +concrete production quoteAGDcl +top::Expr ::= 'Silver_AGDcl' LCurly_t ast::AGDcl RCurly_t +{ + top.unparse = s"Silver_AGDcl {${ast.unparse}}"; + forwards to translate(top.location, reflect(new(ast))); +} + +concrete production quoteProductionStmt +top::Expr ::= 'Silver_ProductionStmt' LCurly_t ast::ProductionStmt RCurly_t +{ + top.unparse = s"Silver_ProductionStmt {${ast.unparse}}"; + forwards to translate(top.location, reflect(new(ast))); +} + concrete production quoteExpr top::Expr ::= 'Silver_Expr' LCurly_t ast::Expr RCurly_t { diff --git a/grammars/silver/extension/silverconstruction/Terminals.sv b/grammars/silver/extension/silverconstruction/Terminals.sv index 04ec7bf9e..f43aaa15a 100644 --- a/grammars/silver/extension/silverconstruction/Terminals.sv +++ b/grammars/silver/extension/silverconstruction/Terminals.sv @@ -1,6 +1,8 @@ grammar silver:extension:silverconstruction; -marking terminal SilverExpr_t 'Silver_Expr' lexer classes {KEYWORD, RESERVED}; +marking terminal SilverExpr_t 'Silver_Expr' lexer classes {KEYWORD, RESERVED}; +marking terminal SilverAGDcl_t 'Silver_AGDcl' lexer classes {KEYWORD, RESERVED}; +marking terminal SilverProductionStmt_t 'Silver_ProductionStmt' lexer classes {KEYWORD, RESERVED}; temp_imp_ide_font font_escape color(160, 32, 240) bold italic; lexer class Escape font=font_escape; From a138ba9de179b20fb690561f71001a54b9d7f227 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Thu, 5 Mar 2020 19:51:56 -0600 Subject: [PATCH 05/57] Add missing default equation --- grammars/silver/driver/util/RootSpec.sv | 1 + 1 file changed, 1 insertion(+) diff --git a/grammars/silver/driver/util/RootSpec.sv b/grammars/silver/driver/util/RootSpec.sv index eccf73b53..c3e1093a2 100644 --- a/grammars/silver/driver/util/RootSpec.sv +++ b/grammars/silver/driver/util/RootSpec.sv @@ -225,6 +225,7 @@ top::GrammarProperty ::= top.maybeCondBuild = nothing(); top.maybeAllGrammarDependencies = nothing(); top.maybeDefs = nothing(); + top.maybeOccursDefs = nothing(); } abstract production grammarSourceGrammarProperty From 8d1d2e2902d6e3bd06aaf94c879c766073b2fe4a Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Thu, 5 Mar 2020 19:53:05 -0600 Subject: [PATCH 06/57] Cleanup - use easy terminal literals for braces --- .../extension/silverconstruction/Syntax.sv | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/grammars/silver/extension/silverconstruction/Syntax.sv b/grammars/silver/extension/silverconstruction/Syntax.sv index e2c546864..0af251a3a 100644 --- a/grammars/silver/extension/silverconstruction/Syntax.sv +++ b/grammars/silver/extension/silverconstruction/Syntax.sv @@ -8,28 +8,28 @@ imports silver:definition:type:syntax; imports silver:extension:list; concrete production quoteAGDcl -top::Expr ::= 'Silver_AGDcl' LCurly_t ast::AGDcl RCurly_t +top::Expr ::= 'Silver_AGDcl' '{' ast::AGDcl '}' { top.unparse = s"Silver_AGDcl {${ast.unparse}}"; forwards to translate(top.location, reflect(new(ast))); } concrete production quoteProductionStmt -top::Expr ::= 'Silver_ProductionStmt' LCurly_t ast::ProductionStmt RCurly_t +top::Expr ::= 'Silver_ProductionStmt' '{' ast::ProductionStmt '}' { top.unparse = s"Silver_ProductionStmt {${ast.unparse}}"; forwards to translate(top.location, reflect(new(ast))); } concrete production quoteExpr -top::Expr ::= 'Silver_Expr' LCurly_t ast::Expr RCurly_t +top::Expr ::= 'Silver_Expr' '{' ast::Expr '}' { top.unparse = s"Silver_Expr {${ast.unparse}}"; forwards to translate(top.location, reflect(new(ast))); } concrete production antiquoteExpr -top::Expr ::= '$Expr' silver:definition:core:LCurly_t e::Expr silver:definition:core:RCurly_t +top::Expr ::= '$Expr' '{' e::Expr '}' { top.unparse = s"$$Expr{${e.unparse}}"; forwards to @@ -39,7 +39,7 @@ top::Expr ::= '$Expr' silver:definition:core:LCurly_t e::Expr silver:definition: } concrete production antiquoteTypeExpr -top::TypeExpr ::= '$TypeExpr' silver:definition:core:LCurly_t e::Expr silver:definition:core:RCurly_t +top::TypeExpr ::= '$TypeExpr' '{' e::Expr '}' { top.unparse = s"$$TypeExpr{${e.unparse}}"; forwards to @@ -49,7 +49,7 @@ top::TypeExpr ::= '$TypeExpr' silver:definition:core:LCurly_t e::Expr silver:def } concrete production antiquoteQName -top::QName ::= '$QName' silver:definition:core:LCurly_t e::Expr silver:definition:core:RCurly_t +top::QName ::= '$QName' '{' e::Expr '}' { top.unparse = s"$$QName{${e.unparse}}"; forwards to @@ -59,7 +59,7 @@ top::QName ::= '$QName' silver:definition:core:LCurly_t e::Expr silver:definitio } concrete production antiquoteName -top::Name ::= '$Name' silver:definition:core:LCurly_t e::Expr silver:definition:core:RCurly_t +top::Name ::= '$Name' '{' e::Expr '}' { top.unparse = s"$$Name{${e.unparse}}"; -- TODO: [err(top.location, "$Name should not occur outside of Silver_Expr")] @@ -67,7 +67,7 @@ top::Name ::= '$Name' silver:definition:core:LCurly_t e::Expr silver:definition: } concrete production antiquote_qName -top::QName ::= '$qName' silver:definition:core:LCurly_t e::Expr silver:definition:core:RCurly_t +top::QName ::= '$qName' '{' e::Expr '}' { top.unparse = s"$$qName{${e.unparse}}"; forwards to @@ -77,7 +77,7 @@ top::QName ::= '$qName' silver:definition:core:LCurly_t e::Expr silver:definitio } concrete production antiquote_name -top::Name ::= '$name' silver:definition:core:LCurly_t e::Expr silver:definition:core:RCurly_t +top::Name ::= '$name' '{' e::Expr '}' { top.unparse = s"$$name{${e.unparse}}"; -- TODO: [err(top.location, "$Name should not occur outside of Silver_Expr")] From ecd991b50cbe57ef6535eabc2b5ef9601d26a2da Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 6 Mar 2020 00:06:47 -0600 Subject: [PATCH 07/57] Add occursDefs to env in wromgCode tests --- grammars/silver/extension/testing/WrongCode.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grammars/silver/extension/testing/WrongCode.sv b/grammars/silver/extension/testing/WrongCode.sv index 37cde55c1..19e7be9ab 100644 --- a/grammars/silver/extension/testing/WrongCode.sv +++ b/grammars/silver/extension/testing/WrongCode.sv @@ -17,7 +17,7 @@ top::AGDcl ::= 'wrongCode' s::String_t '{' ags::AGDcls '}' else []; -- do extend its environment with its defs - ags.env = newScopeEnv(ags.defs, top.env); + ags.env = occursEnv(ags.occursDefs, newScopeEnv(ags.defs, top.env)); forwards to emptyAGDcl(location=top.location); } @@ -33,7 +33,7 @@ top::AGDcl ::= 'wrongFlowCode' s::String_t '{' ags::AGDcls '}' else []; -- do extend its environment with its defs - ags.env = newScopeEnv(ags.defs, top.env); + ags.env = occursEnv(ags.occursDefs, newScopeEnv(ags.defs, top.env)); -- let's ALSO propagate up flow info, so these kinds of errors are checked/caught top.flowDefs = ags.flowDefs; From ac2d2d887d838e05e19a97548aa9cdcba7b53441 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 6 Mar 2020 00:07:53 -0600 Subject: [PATCH 08/57] Initial work on more general auto attr extension, functor attributes work --- grammars/silver/definition/core/AGDcl.sv | 10 +- grammars/silver/definition/core/QName.sv | 7 +- grammars/silver/extension/autoattr/Env.sv | 27 ++++ grammars/silver/extension/autoattr/Functor.sv | 133 ++++++++++++++++++ grammars/silver/extension/autoattr/Project.sv | 9 ++ .../silver/extension/autoattr/Propagate.sv | 40 ++++++ .../silver/extension/autoattr/Terminals.sv | 6 + grammars/silver/host/Project.sv | 3 +- test/silver_features/Functor.sv | 6 +- 9 files changed, 234 insertions(+), 7 deletions(-) create mode 100644 grammars/silver/extension/autoattr/Env.sv create mode 100644 grammars/silver/extension/autoattr/Functor.sv create mode 100644 grammars/silver/extension/autoattr/Project.sv create mode 100644 grammars/silver/extension/autoattr/Propagate.sv create mode 100644 grammars/silver/extension/autoattr/Terminals.sv diff --git a/grammars/silver/definition/core/AGDcl.sv b/grammars/silver/definition/core/AGDcl.sv index 9a709bae1..56d630a9f 100644 --- a/grammars/silver/definition/core/AGDcl.sv +++ b/grammars/silver/definition/core/AGDcl.sv @@ -45,7 +45,6 @@ top::AGDcl ::= top.unparse = ""; top.errors := []; - top.jarName = nothing(); } abstract production errorAGDcl @@ -53,7 +52,14 @@ top::AGDcl ::= e::[Message] { top.unparse = s"{- Errors:\n${messagesToString(e)} -}"; top.errors := e; - top.jarName = nothing(); +} + +abstract production defsAGDcl +top::AGDcl ::= d::[Def] +{ + top.unparse = s"{- Defs -}"; + top.errors := []; + top.defs = d; } {-- diff --git a/grammars/silver/definition/core/QName.sv b/grammars/silver/definition/core/QName.sv index 74b657e04..b97321526 100644 --- a/grammars/silver/definition/core/QName.sv +++ b/grammars/silver/definition/core/QName.sv @@ -3,7 +3,7 @@ grammar silver:definition:core; {-- - Qualified names of the form 'a:b:c:d...' -} -nonterminal QName with config, name, location, grammarName, env, unparse; +nonterminal QName with config, name, location, grammarName, env, unparse, qNameType; {-- - Qualified names where the LAST name has an upper case first letter. -} @@ -14,6 +14,8 @@ nonterminal QNameType with config, name, location, grammarName, env, unparse; -} synthesized attribute dcls :: [DclInfo]; +synthesized attribute qNameType::QNameType; + -- TODO: for consistency, the order of these args should be flipped: function qName QName ::= l::Location s::String @@ -26,6 +28,7 @@ top::QName ::= id::Name { top.name = id.name; top.unparse = id.unparse; + top.qNameType = qNameTypeId(terminal(IdUpper_t, id.name, id.location), location=id.location); top.lookupValue = decorate customLookup("value", getValueDcl(top.name, top.env), top.name, top.location) with {}; top.lookupType = decorate customLookup("type", getTypeDcl(top.name, top.env), top.name, top.location) with {}; @@ -37,6 +40,7 @@ top::QName ::= id::Name ':' qn::QName { top.name = id.name ++ ":" ++ qn.name; top.unparse = id.unparse ++ ":" ++ qn.unparse; + top.qNameType = qNameTypeCons(id, ':', qn.qNameType, location=top.location); top.lookupValue = decorate customLookup("value", getValueDcl(top.name, top.env), top.name, top.location) with {}; top.lookupType = decorate customLookup("type", getTypeDcl(top.name, top.env), top.name, top.location) with {}; @@ -48,6 +52,7 @@ top::QName ::= msg::[Message] { top.name = "err"; top.unparse = ""; + top.qNameType = qNameTypeId(terminal(IdUpper_t, "Err", top.location), location=top.location); top.lookupValue = decorate errorLookup(msg) with {}; top.lookupType = decorate errorLookup(msg) with {}; diff --git a/grammars/silver/extension/autoattr/Env.sv b/grammars/silver/extension/autoattr/Env.sv new file mode 100644 index 000000000..7d6306108 --- /dev/null +++ b/grammars/silver/extension/autoattr/Env.sv @@ -0,0 +1,27 @@ +grammar silver:extension:autoattr; + +synthesized attribute propagateDispatcher :: (ProductionStmt ::= Decorated QName Location) occurs on DclInfo; + +aspect default production +top::DclInfo ::= +{ + top.propagateDispatcher = propagateError(_, location=_); +} + +abstract production functorDcl +top::DclInfo ::= sg::String sl::Location fn::String tyVar::TyVar +{ + top.sourceGrammar = sg; + top.sourceLocation = sl; + top.fullName = fn; + + top.typerep = varType(tyVar); + top.dclBoundVars = [tyVar]; + top.isSynthesized = true; + + top.decoratedAccessHandler = synDecoratedAccessHandler(_, _, location=_); + top.undecoratedAccessHandler = accessBounceDecorate(synDecoratedAccessHandler(_, _, location=_), _, _, _); + top.attrDefDispatcher = synthesizedAttributeDef(_, _, _, location=_); -- Allow normal syn equations + top.attributionDispatcher = functorAttributionDcl(_, _, _, _, location=_); + top.propagateDispatcher = propagateFunctor(_, location=_); +} diff --git a/grammars/silver/extension/autoattr/Functor.sv b/grammars/silver/extension/autoattr/Functor.sv new file mode 100644 index 000000000..90e64691b --- /dev/null +++ b/grammars/silver/extension/autoattr/Functor.sv @@ -0,0 +1,133 @@ +grammar silver:extension:autoattr; + +concrete production functorAttributeDcl +top::AGDcl ::= 'functor' 'attribute' a::Name ';' +{ + top.unparse = "functor attribute " ++ a.unparse ++ ";"; + + production attribute fName :: String; + fName = top.grammarName ++ ":" ++ a.name; + + top.errors <- + if length(getAttrDclAll(fName, top.env)) > 1 + then [err(a.location, "Attribute '" ++ fName ++ "' is already bound.")] + else []; + + forwards to + defsAGDcl( + [attrDef(defaultEnvItem(functorDcl(top.grammarName, a.location, fName, freshTyVar())))], + location=top.location); +} + +abstract production functorAttributionDcl +top::AGDcl ::= at::Decorated QName attl::BracketedOptTypeExprs nt::QName nttl::BracketedOptTypeExprs +{ + top.errors <- + if length(attl.types) > 0 + then [err(attl.location, "Functor attributes do not expect explicit type parameters.")] + else []; + + forwards to + defaultAttributionDcl( + at, + botlSome( + '<', + typeListSingle( + nominalTypeExpr(nt.qNameType, nttl, location=top.location), + location=top.location), + '>', location=top.location), + nt, nttl, + location=top.location); +} + +{-- + - Propagate a functor attribute on the enclosing production + - @param attr The name of the attribute to propagate + -} +abstract production propagateFunctor +top::ProductionStmt ::= attr::Decorated QName +{ + -- No explicit errors, for now. The only conceivable issue is the attribute not + -- occuring on the LHS but this should be caught by the forward errors. + + -- Generate the arguments for the constructor + local topName::QName = qName(top.location, top.frame.signature.outputElement.elementName); + local prodName::QName = qName(top.location, top.frame.fullName); + prodName.grammarName = top.grammarName; + prodName.config = top.config; + prodName.env = top.env; + + local inputs :: [Expr] = + map(makeArg(top.location, top.env, attr, _), top.frame.signature.inputElements); + local annotations :: [Pair] = + map(makeAnnoArg(top.location, topName, _), top.frame.signature.namedInputElements); + + -- Construct an attribute def and call with the generated arguments + forwards to + attributeDef( + concreteDefLHS(topName, location=top.location), + '.', + qNameAttrOccur(new(attr), location=top.location), + '=', + mkFullFunctionInvocation( + top.location, + baseExpr(prodName, location=top.location), + inputs, + annotations), + ';', + location=top.location); +} + +{-- + - Generates the expression we should use for an argument + - @param loc The parent location to use in construction + - @param env The environment + - @param attrName The name of the attribute being propagated + - @param input The NamedSignatureElement being propagated + - @return Either this the child, or accessing `attrName` on the child + -} +function makeArg +Expr ::= loc::Location env::Decorated Env attrName::Decorated QName input::NamedSignatureElement +{ + local at::QName = qName(loc, input.elementName); + at.env = env; + + -- Check if the attribute occurs on the first child + local attrOccursOnHead :: Boolean = + !null( + -- The occurs dcls on this nonterminal for + flatMap(getOccursDcl(_, input.typerep.typeName, env), + -- the full names of each candidate + map((.fullName), attrName.lookupAttribute.dcls))); + local validTypeHead :: Boolean = input.typerep.isDecorable; + + return + if validTypeHead && attrOccursOnHead + then access( + baseExpr(at, location=loc), '.', + qNameAttrOccur(new(attrName), location=loc), + location=loc) + else baseExpr(at, location=loc); +} + +{-- + - Generates the list of AnnoExprs used in calling the constructor + - @param loc The parent location to use in construction + - @param baseName The name of the parent from the signature + - @param input The NamedSignatureElement for an annotation + - @return A list of AnnoExprs to be used to build the named arguments + -} +function makeAnnoArg +Pair ::= loc::Location baseName::QName input::NamedSignatureElement +{ + -- TODO: This is a hacky way of getting the base name, not sure if correct + -- trouble is the annotations are listed as fullnames, but have to be supplied as shortnames. weird. + local annoName :: String = last(explode(":", input.elementName)); + + return + pair(annoName, + access( + baseExpr(baseName, location=loc), '.', + qNameAttrOccur(qName(loc, annoName), location=loc), + location=loc)); +} diff --git a/grammars/silver/extension/autoattr/Project.sv b/grammars/silver/extension/autoattr/Project.sv new file mode 100644 index 000000000..b1ee83b99 --- /dev/null +++ b/grammars/silver/extension/autoattr/Project.sv @@ -0,0 +1,9 @@ +grammar silver:extension:autoattr; + +imports silver:definition:core; +imports silver:definition:type:syntax; + +imports silver:definition:env; +imports silver:definition:type; + +import silver:util; \ No newline at end of file diff --git a/grammars/silver/extension/autoattr/Propagate.sv b/grammars/silver/extension/autoattr/Propagate.sv new file mode 100644 index 000000000..11d94f9f3 --- /dev/null +++ b/grammars/silver/extension/autoattr/Propagate.sv @@ -0,0 +1,40 @@ +grammar silver:extension:autoattr; + +concrete production propagateAttrList +top::ProductionStmt ::= 'propagate' ns::NameList ';' +{ + top.unparse = s"propagate ${ns.unparse};"; + + -- Forwards to productionStmtAppend of propagating the first element in ns + -- and propagateAttrDcl containing the remaining names + forwards to + case ns of + | nameListOne(n) -> propagateOneAttr(n, location=top.location) + | nameListCons(n, _, rest) -> + productionStmtAppend( + propagateOneAttr(n, location=top.location), + propagateAttrList($1, rest, $3, location=top.location), + location=top.location) + end; +} + +abstract production propagateOneAttr +top::ProductionStmt ::= attr::QName +{ + -- Ugh, workaround for circular dependency + top.defs = []; + top.productionAttributes = []; + forwards to + if !attr.lookupAttribute.found + then errorProductionStmt(attr.lookupAttribute.errors, location=top.location) + else attr.lookupAttribute.dcl.propagateDispatcher(attr, top.location); +} + +abstract production propagateError +top::ProductionStmt ::= attr::Decorated QName +{ + forwards to + errorProductionStmt( + [err(attr.location, s"Attribute ${attr.name} cannot be propagated")], + location=top.location); +} diff --git a/grammars/silver/extension/autoattr/Terminals.sv b/grammars/silver/extension/autoattr/Terminals.sv new file mode 100644 index 000000000..b24a8512c --- /dev/null +++ b/grammars/silver/extension/autoattr/Terminals.sv @@ -0,0 +1,6 @@ +grammar silver:extension:autoattr; + +terminal Propagate_kwd 'propagate' lexer classes {KEYWORD,RESERVED}; + +terminal Functor_kwd 'functor' lexer classes {KEYWORD,RESERVED}; +terminal Monoid_kwd 'monoid' lexer classes {KEYWORD,RESERVED}; diff --git a/grammars/silver/host/Project.sv b/grammars/silver/host/Project.sv index 81c28419f..5c0650f6e 100644 --- a/grammars/silver/host/Project.sv +++ b/grammars/silver/host/Project.sv @@ -40,7 +40,8 @@ exports silver:extension:templating; exports silver:extension:patternmatching; exports silver:extension:treegen; exports silver:extension:doc; -exports silver:extension:functorattrib; +exports silver:extension:functorattrib; -- Deprecated +exports silver:extension:autoattr; exports silver:extension:monad; exports silver:extension:reflection; exports silver:extension:rewriting; diff --git a/test/silver_features/Functor.sv b/test/silver_features/Functor.sv index 200b14fc8..65048c068 100644 --- a/test/silver_features/Functor.sv +++ b/test/silver_features/Functor.sv @@ -1,10 +1,10 @@ -synthesized attribute functorSyn :: a; +functor attribute functorSyn; synthesized attribute functorTestAnnoSum :: Integer; annotation functorTestAnno::Integer; -nonterminal FunctorTestNT with functorSyn, functorTestAnnoSum, functorTestAnno; -nonterminal FunctorTestNT2 with functorSyn, functorTestAnnoSum, functorTestAnno; +nonterminal FunctorTestNT with functorSyn, functorTestAnnoSum, functorTestAnno; +nonterminal FunctorTestNT2 with functorSyn, functorTestAnnoSum, functorTestAnno; abstract production consFTNT top::FunctorTestNT ::= h::FunctorTestNT t::FunctorTestNT From c2d3a6b1e27fb97a597a4d0013b50f57ba4768c1 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 6 Mar 2020 10:37:12 -0600 Subject: [PATCH 09/57] Convinence syntax for functor attributes --- grammars/silver/extension/autoattr/Project.sv | 5 ++--- .../autoattr/convenience/Convenience.sv | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 grammars/silver/extension/autoattr/convenience/Convenience.sv diff --git a/grammars/silver/extension/autoattr/Project.sv b/grammars/silver/extension/autoattr/Project.sv index b1ee83b99..49653b891 100644 --- a/grammars/silver/extension/autoattr/Project.sv +++ b/grammars/silver/extension/autoattr/Project.sv @@ -1,9 +1,8 @@ grammar silver:extension:autoattr; imports silver:definition:core; -imports silver:definition:type:syntax; - imports silver:definition:env; imports silver:definition:type; +imports silver:definition:type:syntax; -import silver:util; \ No newline at end of file +exports silver:extension:autoattr:convenience; diff --git a/grammars/silver/extension/autoattr/convenience/Convenience.sv b/grammars/silver/extension/autoattr/convenience/Convenience.sv new file mode 100644 index 000000000..4c5a12d73 --- /dev/null +++ b/grammars/silver/extension/autoattr/convenience/Convenience.sv @@ -0,0 +1,20 @@ +grammar silver:extension:autoattr:convenience; + +import silver:extension:autoattr; +import silver:extension:convenience; +import silver:definition:core; +import silver:definition:concrete_syntax; +import silver:definition:type:syntax; +import silver:definition:type; +import silver:definition:env; + +concrete production functorAttributeDclMultiple +top::AGDcl ::= 'functor' 'attribute' a::Name 'occurs' 'on' qs::QNames ';' +{ + top.unparse = "functor attribute " ++ a.name ++ " occurs on " ++ qs.unparse ++ ";"; + forwards to + appendAGDcl( + functorAttributeDcl($1, $2, a, $7, location=a.location), + makeOccursDclsHelp($1.location, qNameWithTL(qNameId(a, location=a.location), botlNone(location=top.location)), qs.qnames), + location=top.location); +} From 6a32d993e20c8278fc956978328f03417a7d91a1 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 6 Mar 2020 10:45:29 -0600 Subject: [PATCH 10/57] Use new functor attribute extension in silver compiler --- grammars/silver/extension/rewriting/Expr.sv | 10 ++++------ test/silver_features/Functor.sv | 6 +++++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/grammars/silver/extension/rewriting/Expr.sv b/grammars/silver/extension/rewriting/Expr.sv index 7ae9b5207..a8b4a10bb 100644 --- a/grammars/silver/extension/rewriting/Expr.sv +++ b/grammars/silver/extension/rewriting/Expr.sv @@ -252,15 +252,14 @@ top::Expr ::= 'decorate' e::Expr 'with' '{' inh::ExprInhs '}' attribute transform occurs on ExprInhs; synthesized attribute lambdaParams::ProductionRHS occurs on ExprInhs; -synthesized attribute bodyExprInhTransform::a; -attribute bodyExprInhTransform occurs on ExprInhs; +functor attribute bodyExprInhTransform occurs on ExprInhs, ExprInh; aspect production exprInhsEmpty top::ExprInhs ::= { top.transform = nilASTExpr(); top.lambdaParams = productionRHSNil(location=builtin); - propagate_functor bodyExprInhTransform; + propagate bodyExprInhTransform; } aspect production exprInhsOne @@ -269,7 +268,7 @@ top::ExprInhs ::= lhs::ExprInh top.transform = consASTExpr(lhs.transform, nilASTExpr()); top.lambdaParams = productionRHSCons(lhs.lambdaParam, productionRHSNil(location=builtin), location=builtin); - propagate_functor bodyExprInhTransform; + propagate bodyExprInhTransform; } aspect production exprInhsCons @@ -277,12 +276,11 @@ top::ExprInhs ::= lhs::ExprInh inh::ExprInhs { top.transform = consASTExpr(lhs.transform, inh.transform); top.lambdaParams = productionRHSCons(lhs.lambdaParam, inh.lambdaParams, location=builtin); - propagate_functor bodyExprInhTransform; + propagate bodyExprInhTransform; } attribute transform occurs on ExprInh; synthesized attribute lambdaParam::ProductionRHSElem occurs on ExprInh; -attribute bodyExprInhTransform occurs on ExprInh; aspect production exprInh top::ExprInh ::= lhs::ExprLHSExpr '=' e::Expr ';' diff --git a/test/silver_features/Functor.sv b/test/silver_features/Functor.sv index 65048c068..783853d28 100644 --- a/test/silver_features/Functor.sv +++ b/test/silver_features/Functor.sv @@ -34,6 +34,10 @@ top::FunctorTestNT2 ::= s::String top.functorTestAnnoSum = top.functorTestAnno; } +wrongCode "Functor attributes do not expect explicit type parameters" { + nonterminal Foo23 with functorSyn; +} + global functorValue :: FunctorTestNT = consFTNT( consFTNT2( @@ -61,4 +65,4 @@ global functorValueRes :: FunctorTestNT = -- Test to ensure it reaches all nils: equalityTest(hackUnparse(functorValueRes), hackUnparse(functorValue.functorSyn), String, silver_tests); -- Test to ensure annotations are copied correctly -equalityTest(functorValueRes.functorTestAnnoSum, functorValue.functorSyn.functorTestAnnoSum, Integer, silver_tests); \ No newline at end of file +equalityTest(functorValueRes.functorTestAnnoSum, functorValue.functorSyn.functorTestAnnoSum, Integer, silver_tests); From 425b1013ba9ce51291f24e04e9ec9011148d298d Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 6 Mar 2020 10:52:16 -0600 Subject: [PATCH 11/57] Remove deprecated functor attribute extension --- .../extension/functorattrib/DocConfig.sv | 6 - .../extension/functorattrib/ProductionBody.sv | 118 ------------------ .../silver/extension/functorattrib/Project.sv | 9 -- .../extension/functorattrib/Terminals.sv | 2 - grammars/silver/host/Project.sv | 1 - 5 files changed, 136 deletions(-) delete mode 100644 grammars/silver/extension/functorattrib/DocConfig.sv delete mode 100644 grammars/silver/extension/functorattrib/ProductionBody.sv delete mode 100644 grammars/silver/extension/functorattrib/Project.sv delete mode 100644 grammars/silver/extension/functorattrib/Terminals.sv diff --git a/grammars/silver/extension/functorattrib/DocConfig.sv b/grammars/silver/extension/functorattrib/DocConfig.sv deleted file mode 100644 index c5ad0876e..000000000 --- a/grammars/silver/extension/functorattrib/DocConfig.sv +++ /dev/null @@ -1,6 +0,0 @@ -grammar silver:extension:functorattrib; - -{@config - header:"---\nlayout: sv_wiki\ntitle: Functor Attributes\nmenu_title: Functor Attributes\nmenu_weight: 100\n---" -@} - diff --git a/grammars/silver/extension/functorattrib/ProductionBody.sv b/grammars/silver/extension/functorattrib/ProductionBody.sv deleted file mode 100644 index 522350a16..000000000 --- a/grammars/silver/extension/functorattrib/ProductionBody.sv +++ /dev/null @@ -1,118 +0,0 @@ - -{-- - - Propagates a list of functor attributes on the current production. - - Actual implementation in propagateOne - -} -concrete production propagateAttrDclOld -top::ProductionStmt ::= 'propagate_functor' ns::NameList ';' -{ - top.unparse = s"propagate ${ns.unparse};"; - - -- Forwards to productionStmtAppend of propagating the first element in ns - -- and propagateAttrDcl containing the remaining names - forwards to - case ns of - | nameListOne(n) -> - propagateOne(n, location=top.location) - | nameListCons(n, _, rest) -> - productionStmtAppend( - propagateOne(n, location=top.location), - propagateAttrDclOld($1, rest, $3, location=top.location), - location=top.location) - end; -} - -{-- - - Generates the expression we should use for an argument - - @param loc The parent location to use in construction - - @param env The environment - - @param attrName The name of the attribute being propagated - - @param input The NamedSignatureElement being propagated - - @return Either this the child, or accessing `attrName` on the child - -} -function makeArg -Expr ::= loc::Location env::Decorated Env attrName::QName input::NamedSignatureElement -{ - attrName.env = env; - - local at::QName = qName(loc, input.elementName); - at.env = env; - - -- Check if the attribute occurs on the first child - local attrOccursOnHead :: Boolean = - !null( - -- The occurs dcls on this nonterminal for - flatMap(getOccursDcl(_, input.typerep.typeName, env), - -- the full names of each candidate - map((.fullName), attrName.lookupAttribute.dcls))); - local validTypeHead :: Boolean = input.typerep.isDecorable; - - return - if validTypeHead && attrOccursOnHead - then access( - baseExpr(at, location=loc), '.', - qNameAttrOccur(attrName, location=loc), - location=loc) - else baseExpr(at, location=loc); -} - -{-- - - Generates the list of AnnoExprs used in calling the constructor - - @param loc The parent location to use in construction - - @param baseName The name of the parent from the signature - - @param input The NamedSignatureElement for an annotation - - @return A list of AnnoExprs to be used to build the named arguments - -} -function makeAnnoArg -Pair ::= loc::Location baseName::QName input::NamedSignatureElement -{ - -- TODO: This is a hacky way of getting the base name, not sure if correct - -- trouble is the annotations are listed as fullnames, but have to be supplied as shortnames. weird. - local annoName :: String = last(explode(":", input.elementName)); - - return - pair(annoName, - access( - baseExpr(baseName, location=loc), '.', - qNameAttrOccur(qName(loc, annoName), location=loc), - location=loc)); -} - --- In the future, this should maybe be dispatch for different types of attributes (e.g. monoid) -{-- - - Propagate a functor attribute on the enclosing production - - @param attr The name of the attribute to propagate - -} -abstract production propagateOne -top::ProductionStmt ::= attr::QName -{ - -- No explicit errors, for now. The only conceivable issue is the attribute not - -- occuring on the LHS but this should be caught by the forward errors. - - -- Generate the arguments for the constructor - local topName::QName = qName(top.location, top.frame.signature.outputElement.elementName); - local prodName::QName = qName(top.location, top.frame.fullName); - prodName.grammarName = top.grammarName; - prodName.config = top.config; - prodName.env = top.env; - - local inputs :: [Expr] = - map(makeArg(top.location, top.env, attr, _), top.frame.signature.inputElements); - local annotations :: [Pair] = - map(makeAnnoArg(top.location, topName, _), top.frame.signature.namedInputElements); - - -- Construct an attribute def and call with the generated arguments - forwards to - attributeDef( - concreteDefLHS(topName, location=top.location), - '.', - qNameAttrOccur(attr, location=top.location), - '=', - mkFullFunctionInvocation( - top.location, - baseExpr(prodName, location=top.location), - inputs, - annotations), - ';', - location=top.location); -} diff --git a/grammars/silver/extension/functorattrib/Project.sv b/grammars/silver/extension/functorattrib/Project.sv deleted file mode 100644 index 2a57413bc..000000000 --- a/grammars/silver/extension/functorattrib/Project.sv +++ /dev/null @@ -1,9 +0,0 @@ -grammar silver:extension:functorattrib; - -imports silver:definition:core; -imports silver:definition:type:syntax; - -imports silver:definition:env; -imports silver:definition:type; - -import silver:util; \ No newline at end of file diff --git a/grammars/silver/extension/functorattrib/Terminals.sv b/grammars/silver/extension/functorattrib/Terminals.sv deleted file mode 100644 index 7bffd4f6b..000000000 --- a/grammars/silver/extension/functorattrib/Terminals.sv +++ /dev/null @@ -1,2 +0,0 @@ - -terminal PropagateOld_kwd 'propagate_functor' lexer classes {KEYWORD,RESERVED}; diff --git a/grammars/silver/host/Project.sv b/grammars/silver/host/Project.sv index 5c0650f6e..2656bb17a 100644 --- a/grammars/silver/host/Project.sv +++ b/grammars/silver/host/Project.sv @@ -40,7 +40,6 @@ exports silver:extension:templating; exports silver:extension:patternmatching; exports silver:extension:treegen; exports silver:extension:doc; -exports silver:extension:functorattrib; -- Deprecated exports silver:extension:autoattr; exports silver:extension:monad; exports silver:extension:reflection; From 2a10cba4f6becbc295e5f11961bed634f68fb5de Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 6 Mar 2020 11:21:15 -0600 Subject: [PATCH 12/57] Allow explicit type parameter for functor attribute occurs --- grammars/silver/extension/autoattr/Functor.sv | 20 +++++++++---------- test/silver_features/Functor.sv | 18 +++++++++++++---- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/grammars/silver/extension/autoattr/Functor.sv b/grammars/silver/extension/autoattr/Functor.sv index 90e64691b..8f6f189c3 100644 --- a/grammars/silver/extension/autoattr/Functor.sv +++ b/grammars/silver/extension/autoattr/Functor.sv @@ -22,20 +22,18 @@ top::AGDcl ::= 'functor' 'attribute' a::Name ';' abstract production functorAttributionDcl top::AGDcl ::= at::Decorated QName attl::BracketedOptTypeExprs nt::QName nttl::BracketedOptTypeExprs { - top.errors <- - if length(attl.types) > 0 - then [err(attl.location, "Functor attributes do not expect explicit type parameters.")] - else []; - forwards to defaultAttributionDcl( at, - botlSome( - '<', - typeListSingle( - nominalTypeExpr(nt.qNameType, nttl, location=top.location), - location=top.location), - '>', location=top.location), + if length(attl.types) > 0 + then attl + else + botlSome( + '<', + typeListSingle( + nominalTypeExpr(nt.qNameType, nttl, location=top.location), + location=top.location), + '>', location=top.location), nt, nttl, location=top.location); } diff --git a/test/silver_features/Functor.sv b/test/silver_features/Functor.sv index 783853d28..c8474f4f5 100644 --- a/test/silver_features/Functor.sv +++ b/test/silver_features/Functor.sv @@ -34,10 +34,6 @@ top::FunctorTestNT2 ::= s::String top.functorTestAnnoSum = top.functorTestAnno; } -wrongCode "Functor attributes do not expect explicit type parameters" { - nonterminal Foo23 with functorSyn; -} - global functorValue :: FunctorTestNT = consFTNT( consFTNT2( @@ -66,3 +62,17 @@ global functorValueRes :: FunctorTestNT = equalityTest(hackUnparse(functorValueRes), hackUnparse(functorValue.functorSyn), String, silver_tests); -- Test to ensure annotations are copied correctly equalityTest(functorValueRes.functorTestAnnoSum, functorValue.functorSyn.functorTestAnnoSum, Integer, silver_tests); + +nonterminal FunctorTestNT3 with functorSyn; + +abstract production ftnt3 +top::FunctorTestNT3 ::= +{ + top.functorSyn = 42; +} + +equalityTest(ftnt3().functorSyn, 42, Integer, silver_tests); + +wrongCode "expects 1 type variables, but 2 were provided" { + nonterminal Foo23 with functorSyn; +} From 87dda74eaa6206566ee47c9f5e0df0b447409fe6 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 6 Mar 2020 13:18:52 -0600 Subject: [PATCH 13/57] add missing equation --- grammars/silver/composed/idetest/Main.sv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grammars/silver/composed/idetest/Main.sv b/grammars/silver/composed/idetest/Main.sv index 5afb906b7..fabf6aa0c 100644 --- a/grammars/silver/composed/idetest/Main.sv +++ b/grammars/silver/composed/idetest/Main.sv @@ -88,7 +88,8 @@ IOVal<[Message]> ::= project::IdeProject args::[IdeProperty] i::IO function fold [Location] ::= cst::Root { - return cst.foldableRanges; -- see ./Folding.sv + cst.env = emptyEnv(); + return cst.foldableRanges; -- see ./Folding.sv } function getStubForNewFile From 795badbfd67a3e13a4993187e44144f37c65d389 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 6 Mar 2020 14:03:56 -0600 Subject: [PATCH 14/57] Refactoring to interface file deserialization, add completeness check that falls back to parsing the source grammar rather than raising an fatal error --- .../definition/concrete_syntax/RootSpec.sv | 46 ++--- .../silver/definition/flow/env/RootSpec.sv | 31 +-- grammars/silver/driver/CompileInterface.sv | 11 +- grammars/silver/driver/util/RootSpec.sv | 185 ++++++++++-------- 4 files changed, 149 insertions(+), 124 deletions(-) diff --git a/grammars/silver/definition/concrete_syntax/RootSpec.sv b/grammars/silver/definition/concrete_syntax/RootSpec.sv index f2c3caa14..e321ac2d6 100644 --- a/grammars/silver/definition/concrete_syntax/RootSpec.sv +++ b/grammars/silver/definition/concrete_syntax/RootSpec.sv @@ -2,40 +2,42 @@ grammar silver:definition:concrete_syntax; import silver:driver:util; -attribute syntaxAst, parserSpecs occurs on RootSpec, ModuleExportedDefs, Grammar, GrammarProperties; +attribute syntaxAst, parserSpecs occurs on RootSpec, ModuleExportedDefs, Grammar; -aspect production consGrammarProperties -top::GrammarProperties ::= h::GrammarProperty t::GrammarProperties +synthesized attribute maybeSyntaxAst::Maybe<[SyntaxDcl]> occurs on InterfaceItems, InterfaceItem; +synthesized attribute maybeParserSpecs::Maybe<[ParserSpec]> occurs on InterfaceItems, InterfaceItem; + +aspect production consInterfaceItem +top::InterfaceItems ::= h::InterfaceItem t::InterfaceItems { - top.syntaxAst = fromMaybe(t.syntaxAst, h.maybeSyntaxAst); - top.parserSpecs = fromMaybe(t.parserSpecs, h.maybeParserSpecs); + top.maybeSyntaxAst = orElse(t.maybeSyntaxAst, h.maybeSyntaxAst); + top.maybeParserSpecs = orElse(t.maybeParserSpecs, h.maybeParserSpecs); + top.interfaceErrors <- if !top.maybeSyntaxAst.isJust then ["Missing item syntaxAst"] else []; + top.interfaceErrors <- if !top.maybeParserSpecs.isJust then ["Missing item parserSpecs"] else []; } -aspect production nilGrammarProperties -top::GrammarProperties ::= +aspect production nilInterfaceItem +top::InterfaceItems ::= { - top.syntaxAst = error("Grammar property syntaxAst missing from interface file"); - top.parserSpecs = error("Grammar property parserSpecs missing from interface file"); + top.maybeSyntaxAst = nothing(); + top.maybeParserSpecs = nothing(); } -synthesized attribute maybeSyntaxAst::Maybe<[SyntaxDcl]> occurs on GrammarProperty; -synthesized attribute maybeParserSpecs::Maybe<[ParserSpec]> occurs on GrammarProperty; - aspect default production -top::GrammarProperty ::= +top::InterfaceItem ::= { top.maybeSyntaxAst = nothing(); top.maybeParserSpecs = nothing(); } -abstract production syntaxAstGrammarProperty -top::GrammarProperty ::= val::[SyntaxDcl] +abstract production syntaxAstInterfaceItem +top::InterfaceItem ::= val::[SyntaxDcl] { top.maybeSyntaxAst = just(val); } -abstract production parserSpecsGrammarProperty -top::GrammarProperty ::= val::[ParserSpec] +abstract production parserSpecsInterfaceItem +top::InterfaceItem ::= val::[ParserSpec] { top.maybeParserSpecs = just(val); } @@ -43,8 +45,8 @@ top::GrammarProperty ::= val::[ParserSpec] aspect function unparseRootSpec String ::= r::Decorated RootSpec { - grammarProperties <- [syntaxAstGrammarProperty(r.syntaxAst)]; - grammarProperties <- [parserSpecsGrammarProperty(r.parserSpecs)]; + interfaceItems <- [syntaxAstInterfaceItem(r.syntaxAst)]; + interfaceItems <- [parserSpecsInterfaceItem(r.parserSpecs)]; } aspect production errorRootSpec @@ -62,10 +64,10 @@ top::RootSpec ::= c1::Grammar _ _ _ _ } aspect production interfaceRootSpec -top::RootSpec ::= p::GrammarProperties interfaceTime::Integer _ +top::RootSpec ::= i::InterfaceItems interfaceTime::Integer _ { - top.syntaxAst = p.syntaxAst; - top.parserSpecs = p.parserSpecs; + top.syntaxAst = i.maybeSyntaxAst.fromJust; + top.parserSpecs = i.maybeParserSpecs.fromJust; } aspect production nilGrammar diff --git a/grammars/silver/definition/flow/env/RootSpec.sv b/grammars/silver/definition/flow/env/RootSpec.sv index b9df82442..633c5308a 100644 --- a/grammars/silver/definition/flow/env/RootSpec.sv +++ b/grammars/silver/definition/flow/env/RootSpec.sv @@ -2,30 +2,29 @@ grammar silver:definition:flow:env; import silver:driver:util; -attribute flowDefs occurs on RootSpec, GrammarProperties; +synthesized attribute maybeFlowDefs::Maybe<[FlowDef]> occurs on InterfaceItems, InterfaceItem; -aspect production consGrammarProperties -top::GrammarProperties ::= h::GrammarProperty t::GrammarProperties +aspect production consInterfaceItem +top::InterfaceItems ::= h::InterfaceItem t::InterfaceItems { - top.flowDefs = fromMaybe(t.flowDefs, h.maybeFlowDefs); + top.maybeFlowDefs = orElse(t.maybeFlowDefs, h.maybeFlowDefs); + top.interfaceErrors <- if !top.maybeFlowDefs.isJust then ["Missing item flowDefs"] else []; } -aspect production nilGrammarProperties -top::GrammarProperties ::= +aspect production nilInterfaceItem +top::InterfaceItems ::= { - top.flowDefs = error("Grammar property flowDefs missing from interface file"); + top.maybeFlowDefs = nothing(); } -synthesized attribute maybeFlowDefs::Maybe<[FlowDef]> occurs on GrammarProperty; - aspect default production -top::GrammarProperty ::= +top::InterfaceItem ::= { top.maybeFlowDefs = nothing(); } -abstract production flowDefsGrammarProperty -top::GrammarProperty ::= val::[FlowDef] +abstract production flowDefsInterfaceItem +top::InterfaceItem ::= val::[FlowDef] { top.maybeFlowDefs = just(val); } @@ -33,7 +32,7 @@ top::GrammarProperty ::= val::[FlowDef] aspect function unparseRootSpec String ::= r::Decorated RootSpec { - grammarProperties <- [flowDefsGrammarProperty(r.flowDefs)]; + interfaceItems <- [flowDefsInterfaceItem(r.flowDefs)]; } aspect production errorRootSpec @@ -48,10 +47,12 @@ top::RootSpec ::= g::Grammar _ _ _ _ top.flowDefs = g.flowDefs; } +attribute flowDefs occurs on RootSpec; + aspect production interfaceRootSpec -top::RootSpec ::= p::GrammarProperties interfaceTime::Integer _ +top::RootSpec ::= i::InterfaceItems interfaceTime::Integer _ { - top.flowDefs = p.flowDefs; + top.flowDefs = i.maybeFlowDefs.fromJust; } aspect production nilGrammar diff --git a/grammars/silver/driver/CompileInterface.sv b/grammars/silver/driver/CompileInterface.sv index 91626b07e..f3656c9b9 100644 --- a/grammars/silver/driver/CompileInterface.sv +++ b/grammars/silver/driver/CompileInterface.sv @@ -26,12 +26,17 @@ IOVal> ::= grammarName::String silverHostGen::[String] grammar local pr :: IO = print("Found " ++ grammarName ++ "\n\t[" ++ file ++ "]\n", modTime.io); local text :: IOVal = readFile(file, pr); - local ir :: Either = deserialize("Silver.svi", text.iovalue); + local ir :: Either = deserialize("Silver.svi", text.iovalue); -- IO Step 4: Perhaps complain it failed to parse local pr2 :: IO = case ir of - | right(_) -> text.io + | right(i) -> + if !null(i.interfaceErrors) + then + print("\n\tErrors unpacking interface file:\n " ++ implode("\n ", i.interfaceErrors) ++ + "\n\tRecovering by parsing grammar....\n", text.io) + else text.io | left(msg) -> print("\n\tFailed to deserialize interface file!\n" ++ msg ++ "\n\tRecovering by parsing grammar....\n", text.io) @@ -46,7 +51,7 @@ IOVal> ::= grammarName::String silverHostGen::[String] grammar else if modTime.iovalue <= grammarTime then -- Interface file is too old, stop short, return nothing. ioval(modTime.io, nothing()) - else if ir.isLeft then + else if ir.isLeft || !null(ir.fromRight.interfaceErrors) then -- Deserialization failed, return nothing. ioval(pr2, nothing()) else ioval(pr2, just(rs)); diff --git a/grammars/silver/driver/util/RootSpec.sv b/grammars/silver/driver/util/RootSpec.sv index c3e1093a2..1f8abe9d0 100644 --- a/grammars/silver/driver/util/RootSpec.sv +++ b/grammars/silver/driver/util/RootSpec.sv @@ -94,26 +94,26 @@ top::RootSpec ::= g::Grammar grammarName::String grammarSource::String gramma - Create a RootSpec from an interface file, representing a grammar. -} abstract production interfaceRootSpec -top::RootSpec ::= p::GrammarProperties interfaceTime::Integer generateLocation::String +top::RootSpec ::= i::InterfaceItems interfaceTime::Integer generateLocation::String { - top.grammarSource = p.grammarSource; - top.grammarTime = p.grammarTime; + top.grammarSource = i.maybeGrammarSource.fromJust; + top.grammarTime = i.maybeGrammarTime.fromJust; top.interfaceTime = interfaceTime; top.generateLocation = generateLocation; local ood :: Boolean = isOutOfDate(interfaceTime, top.allGrammarDependencies, top.compiledGrammars); - top.recheckGrammars = if ood then [p.declaredName] else []; + top.recheckGrammars = if ood then [i.maybeDeclaredName.fromJust] else []; top.translateGrammars = []; - top.declaredName = p.declaredName; - top.moduleNames = p.moduleNames; - top.exportedGrammars = p.exportedGrammars; - top.optionalGrammars = p.optionalGrammars; - top.condBuild = p.condBuild; - top.allGrammarDependencies = p.allGrammarDependencies; + top.declaredName = i.maybeDeclaredName.fromJust; + top.moduleNames = i.maybeModuleNames.fromJust; + top.exportedGrammars = i.maybeExportedGrammars.fromJust; + top.optionalGrammars = i.maybeOptionalGrammars.fromJust; + top.condBuild = i.maybeCondBuild.fromJust; + top.allGrammarDependencies = i.maybeAllGrammarDependencies.fromJust; - top.defs = p.defs; - top.occursDefs = p.occursDefs; + top.defs = i.maybeDefs.fromJust; + top.occursDefs = i.maybeOccursDefs.fromJust; top.grammarErrors = []; -- TODO: consider getting grammarName and comparing against declaredName? top.parsingErrors = []; @@ -164,42 +164,7 @@ Pair ::= grammarSource::String e::ParseError end; } -{-- - - Representation of all properties of a grammar, to be serialized/deserialize to/from an interface - - file. - -} -nonterminal GrammarProperties with declaredName, grammarSource, grammarTime, moduleNames, exportedGrammars, optionalGrammars, condBuild, allGrammarDependencies, defs, occursDefs; - -abstract production consGrammarProperties -top::GrammarProperties ::= h::GrammarProperty t::GrammarProperties -{ - top.grammarSource = fromMaybe(t.grammarSource, h.maybeGrammarSource); - top.grammarTime = fromMaybe(t.grammarTime, h.maybeGrammarTime); - top.declaredName = fromMaybe(t.declaredName, h.maybeDeclaredName); - top.moduleNames = fromMaybe(t.moduleNames, h.maybeModuleNames); - top.exportedGrammars = fromMaybe(t.exportedGrammars, h.maybeExportedGrammars); - top.optionalGrammars = fromMaybe(t.optionalGrammars, h.maybeOptionalGrammars); - top.condBuild = fromMaybe(t.condBuild, h.maybeCondBuild); - top.allGrammarDependencies = fromMaybe(t.allGrammarDependencies, h.maybeAllGrammarDependencies); - top.defs = fromMaybe(t.defs, h.maybeDefs); - top.occursDefs = fromMaybe(t.occursDefs, h.maybeOccursDefs); -} - -abstract production nilGrammarProperties -top::GrammarProperties ::= -{ - top.grammarSource = error("Grammar property grammarSource missing from interface file"); - top.grammarTime = error("Grammar property grammarTime missing from interface file"); - top.declaredName = error("Grammar property declaredName missing from interface file"); - top.moduleNames = error("Grammar property moduleNames missing from interface file"); - top.exportedGrammars = error("Grammar property exportedGrammars missing from interface file"); - top.optionalGrammars = error("Grammar property optionalGrammars missing from interface file"); - top.condBuild = error("Grammar property condBuild missing from interface file"); - top.allGrammarDependencies = error("Grammar property allGrammarDependencies missing from interface file"); - top.defs = error("Grammar property defs missing from interface file"); - top.occursDefs = error("Grammar property occursDefs missing from interface file"); -} - +-- TODO: These should all be monoids synthesized attribute maybeGrammarSource::Maybe; synthesized attribute maybeGrammarTime::Maybe; synthesized attribute maybeDeclaredName::Maybe; @@ -211,10 +176,62 @@ synthesized attribute maybeAllGrammarDependencies::Maybe<[String]>; synthesized attribute maybeDefs::Maybe<[Def]>; synthesized attribute maybeOccursDefs::Maybe<[DclInfo]>; -closed nonterminal GrammarProperty with maybeGrammarSource, maybeGrammarTime, maybeDeclaredName, maybeModuleNames, maybeExportedGrammars, maybeOptionalGrammars, maybeCondBuild, maybeAllGrammarDependencies, maybeDefs, maybeOccursDefs; +synthesized attribute interfaceErrors::[String] with ++; + +{-- + - Representation of all properties of a grammar, to be serialized/deserialize to/from an interface + - file. + -} +nonterminal InterfaceItems with maybeGrammarSource, maybeGrammarTime, maybeDeclaredName, maybeModuleNames, maybeExportedGrammars, maybeOptionalGrammars, maybeCondBuild, maybeAllGrammarDependencies, maybeDefs, maybeOccursDefs, interfaceErrors; + +abstract production consInterfaceItem +top::InterfaceItems ::= h::InterfaceItem t::InterfaceItems +{ + top.maybeGrammarSource = orElse(t.maybeGrammarSource, h.maybeGrammarSource); + top.maybeGrammarTime = orElse(t.maybeGrammarTime, h.maybeGrammarTime); + top.maybeDeclaredName = orElse(t.maybeDeclaredName, h.maybeDeclaredName); + top.maybeModuleNames = orElse(t.maybeModuleNames, h.maybeModuleNames); + top.maybeExportedGrammars = orElse(t.maybeExportedGrammars, h.maybeExportedGrammars); + top.maybeOptionalGrammars = orElse(t.maybeOptionalGrammars, h.maybeOptionalGrammars); + top.maybeCondBuild = orElse(t.maybeCondBuild, h.maybeCondBuild); + top.maybeAllGrammarDependencies = orElse(t.maybeAllGrammarDependencies, h.maybeAllGrammarDependencies); + top.maybeDefs = orElse(t.maybeDefs, h.maybeDefs); + top.maybeOccursDefs = orElse(t.maybeOccursDefs, h.maybeOccursDefs); + + top.interfaceErrors := []; + top.interfaceErrors <- if !top.maybeGrammarSource.isJust then ["Missing item grammarSource"] else []; + top.interfaceErrors <- if !top.maybeGrammarTime.isJust then ["Missing item grammarTime"] else []; + top.interfaceErrors <- if !top.maybeDeclaredName.isJust then ["Missing item declaredName"] else []; + top.interfaceErrors <- if !top.maybeModuleNames.isJust then ["Missing item moduleNames"] else []; + top.interfaceErrors <- if !top.maybeExportedGrammars.isJust then ["Missing item exportedGrammars"] else []; + top.interfaceErrors <- if !top.maybeOptionalGrammars.isJust then ["Missing item optionalGrammars"] else []; + top.interfaceErrors <- if !top.maybeCondBuild.isJust then ["Missing item condBuild"] else []; + top.interfaceErrors <- if !top.maybeAllGrammarDependencies.isJust then ["Missing item allGrammarDependencies"] else []; + top.interfaceErrors <- if !top.maybeDefs.isJust then ["Missing item defs"] else []; + top.interfaceErrors <- if !top.maybeOccursDefs.isJust then ["Missing item occursDefs"] else []; +} + +abstract production nilInterfaceItem +top::InterfaceItems ::= +{ + top.maybeGrammarSource = nothing(); + top.maybeGrammarTime = nothing(); + top.maybeDeclaredName = nothing(); + top.maybeModuleNames = nothing(); + top.maybeExportedGrammars = nothing(); + top.maybeOptionalGrammars = nothing(); + top.maybeCondBuild = nothing(); + top.maybeAllGrammarDependencies = nothing(); + top.maybeDefs = nothing(); + top.maybeOccursDefs = nothing(); + + top.interfaceErrors := ["Missing all items"]; +} + +closed nonterminal InterfaceItem with maybeGrammarSource, maybeGrammarTime, maybeDeclaredName, maybeModuleNames, maybeExportedGrammars, maybeOptionalGrammars, maybeCondBuild, maybeAllGrammarDependencies, maybeDefs, maybeOccursDefs; aspect default production -top::GrammarProperty ::= +top::InterfaceItem ::= { top.maybeGrammarSource = nothing(); top.maybeGrammarTime = nothing(); @@ -228,62 +245,62 @@ top::GrammarProperty ::= top.maybeOccursDefs = nothing(); } -abstract production grammarSourceGrammarProperty -top::GrammarProperty ::= val::String +abstract production grammarSourceInterfaceItem +top::InterfaceItem ::= val::String { top.maybeGrammarSource = just(val); } -abstract production grammarTimeGrammarProperty -top::GrammarProperty ::= val::Integer +abstract production grammarTimeInterfaceItem +top::InterfaceItem ::= val::Integer { top.maybeGrammarTime = just(val); } -abstract production declaredNameGrammarProperty -top::GrammarProperty ::= val::String +abstract production declaredNameInterfaceItem +top::InterfaceItem ::= val::String { top.maybeDeclaredName = just(val); } -abstract production moduleNamesGrammarProperty -top::GrammarProperty ::= val::[String] +abstract production moduleNamesInterfaceItem +top::InterfaceItem ::= val::[String] { top.maybeModuleNames = just(val); } -abstract production exportedGrammarsGrammarProperty -top::GrammarProperty ::= val::[String] +abstract production exportedGrammarsInterfaceItem +top::InterfaceItem ::= val::[String] { top.maybeExportedGrammars = just(val); } -abstract production optionalGrammarsGrammarProperty -top::GrammarProperty ::= val::[String] +abstract production optionalGrammarsInterfaceItem +top::InterfaceItem ::= val::[String] { top.maybeOptionalGrammars = just(val); } -abstract production condBuildGrammarProperty -top::GrammarProperty ::= val::[[String]] +abstract production condBuildInterfaceItem +top::InterfaceItem ::= val::[[String]] { top.maybeCondBuild = just(val); } -abstract production allDepsGrammarProperty -top::GrammarProperty ::= val::[String] +abstract production allDepsInterfaceItem +top::InterfaceItem ::= val::[String] { top.maybeAllGrammarDependencies = just(val); } -abstract production defsGrammarProperty -top::GrammarProperty ::= val::[Def] +abstract production defsInterfaceItem +top::InterfaceItem ::= val::[Def] { top.maybeDefs = just(val); } -abstract production occursDefsGrammarProperty -top::GrammarProperty ::= val::[DclInfo] +abstract production occursDefsInterfaceItem +top::InterfaceItem ::= val::[DclInfo] { top.maybeOccursDefs = just(val); } @@ -296,23 +313,23 @@ top::GrammarProperty ::= val::[DclInfo] function unparseRootSpec String ::= r::Decorated RootSpec { - production attribute grammarProperties :: [GrammarProperty] with ++; - grammarProperties := [ - grammarSourceGrammarProperty(r.grammarSource), - grammarTimeGrammarProperty(r.grammarTime), - declaredNameGrammarProperty(r.declaredName), - moduleNamesGrammarProperty(r.moduleNames), - exportedGrammarsGrammarProperty(r.exportedGrammars), - optionalGrammarsGrammarProperty(r.optionalGrammars), - condBuildGrammarProperty(r.condBuild), - allDepsGrammarProperty(r.allGrammarDependencies), - defsGrammarProperty(r.defs), - occursDefsGrammarProperty(r.occursDefs) + production attribute interfaceItems :: [InterfaceItem] with ++; + interfaceItems := [ + grammarSourceInterfaceItem(r.grammarSource), + grammarTimeInterfaceItem(r.grammarTime), + declaredNameInterfaceItem(r.declaredName), + moduleNamesInterfaceItem(r.moduleNames), + exportedGrammarsInterfaceItem(r.exportedGrammars), + optionalGrammarsInterfaceItem(r.optionalGrammars), + condBuildInterfaceItem(r.condBuild), + allDepsInterfaceItem(r.allGrammarDependencies), + defsInterfaceItem(r.defs), + occursDefsInterfaceItem(r.occursDefs) ]; return - case serialize(foldr(consGrammarProperties, nilGrammarProperties(), grammarProperties)) of - | left(msg) -> error("Fatal internal error generating interface file: \n" ++ show(80, reflect(foldr(consGrammarProperties, nilGrammarProperties(), grammarProperties)).pp) ++ "\n" ++ msg) + case serialize(foldr(consInterfaceItem, nilInterfaceItem(), interfaceItems)) of + | left(msg) -> error("Fatal internal error generating interface file: \n" ++ show(80, reflect(foldr(consInterfaceItem, nilInterfaceItem(), interfaceItems)).pp) ++ "\n" ++ msg) | right(txt) -> txt end; } From 34c18d2bd659422a52eff777474c95cf20723069 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 6 Mar 2020 14:10:04 -0600 Subject: [PATCH 15/57] Add missing import --- grammars/silver/composed/idetest/Main.sv | 1 + 1 file changed, 1 insertion(+) diff --git a/grammars/silver/composed/idetest/Main.sv b/grammars/silver/composed/idetest/Main.sv index fabf6aa0c..d8357fc05 100644 --- a/grammars/silver/composed/idetest/Main.sv +++ b/grammars/silver/composed/idetest/Main.sv @@ -1,5 +1,6 @@ grammar silver:composed:idetest; +import silver:definition:env; import silver:host; -- NOTE: this is needed for the correct generation of IDE, From d96d5ae3a5ea2b41439631592d6fb1a95fc17c37 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 6 Mar 2020 15:27:00 -0600 Subject: [PATCH 16/57] Fix some flow errors --- grammars/silver/composed/idetest/Main.sv | 8 ++++++++ grammars/silver/definition/core/AGDcl.sv | 2 +- grammars/silver/metatranslation/Translation.sv | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/grammars/silver/composed/idetest/Main.sv b/grammars/silver/composed/idetest/Main.sv index d8357fc05..57fddaa96 100644 --- a/grammars/silver/composed/idetest/Main.sv +++ b/grammars/silver/composed/idetest/Main.sv @@ -2,6 +2,8 @@ grammar silver:composed:idetest; import silver:definition:env; import silver:host; +import silver:util:cmdargs; +import silver:util:raw:treemap as tm; -- NOTE: this is needed for the correct generation of IDE, -- even if we just use an empty IDE declaration block. @@ -89,7 +91,13 @@ IOVal<[Message]> ::= project::IdeProject args::[IdeProperty] i::IO function fold [Location] ::= cst::Root { + -- Dummy values + cst.config = decorate errorCmdArgs("") with {}; + cst.compiledGrammars = tm:empty(compareString); + cst.grammarName = ""; cst.env = emptyEnv(); + cst.globalImports = emptyEnv(); + cst.grammarDependencies = []; return cst.foldableRanges; -- see ./Folding.sv } diff --git a/grammars/silver/definition/core/AGDcl.sv b/grammars/silver/definition/core/AGDcl.sv index 56d630a9f..f655af5f8 100644 --- a/grammars/silver/definition/core/AGDcl.sv +++ b/grammars/silver/definition/core/AGDcl.sv @@ -6,7 +6,7 @@ grammar silver:definition:core; nonterminal AGDcls with config, grammarName, env, location, unparse, errors, defs, occursDefs, moduleNames, compiledGrammars, grammarDependencies, jarName; nonterminal AGDcl with config, grammarName, env, location, unparse, errors, defs, occursDefs, moduleNames, compiledGrammars, grammarDependencies, jarName; -flowtype forward {grammarName, env} on AGDcl; +flowtype forward {grammarName, env} on AGDcls, AGDcl; concrete production nilAGDcls top::AGDcls ::= diff --git a/grammars/silver/metatranslation/Translation.sv b/grammars/silver/metatranslation/Translation.sv index 6b9550056..353ffbefe 100644 --- a/grammars/silver/metatranslation/Translation.sv +++ b/grammars/silver/metatranslation/Translation.sv @@ -29,6 +29,10 @@ synthesized attribute patternTranslation::a; synthesized attribute foundLocation::Maybe; autocopy attribute givenLocation::Location; +flowtype translation {givenLocation} on AST, ASTs, NamedASTs, NamedAST; +flowtype patternTranslation {givenLocation} on AST, ASTs; +flowtype foundLocation {} on ASTs, NamedASTs, NamedAST; + attribute givenLocation, translation, patternTranslation occurs on AST; aspect production nonterminalAST From 48c662d5cf7e4a17ef80d9feece73451e8850e1f Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 6 Mar 2020 20:22:34 -0600 Subject: [PATCH 17/57] Fix flow analysis bug introduced by occursDefs env refactor --- grammars/silver/driver/util/FlowTypes.sv | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grammars/silver/driver/util/FlowTypes.sv b/grammars/silver/driver/util/FlowTypes.sv index 3253c75f9..a2e4be5a2 100644 --- a/grammars/silver/driver/util/FlowTypes.sv +++ b/grammars/silver/driver/util/FlowTypes.sv @@ -21,7 +21,8 @@ top::Compilation ::= g::Grammars r::Grammars buildGrammar::String benv::Build -- We need to know about all attributes and occurences on nonterminals. -- It's possible (likely) we could do better than using the overall env here. local allRealDefs :: [Def] = flatMap((.defs), g.grammarList); - local allRealEnv :: Decorated Env = toEnv(allRealDefs); + local allRealOccursDefs :: [DclInfo] = flatMap((.occursDefs), g.grammarList); + local allRealEnv :: Decorated Env = occursEnv(allRealOccursDefs, toEnv(allRealDefs)); -- List of all productions local allProds :: [DclInfo] = foldr(consDefs, nilDefs(), allRealDefs).prodDclList; From 36dfb5c7eac71a7abe23ca3099d7dd5d0672cec0 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Sat, 7 Mar 2020 14:04:11 -0600 Subject: [PATCH 18/57] Fixing flow errors --- grammars/silver/definition/core/ProductionBody.sv | 5 +++++ grammars/silver/extension/autoattr/Propagate.sv | 2 ++ grammars/silver/modification/copper/ActionCode.sv | 1 + grammars/silver/modification/copper/Env.sv | 6 ++++++ grammars/silver/modification/copper/ProductionStmt.sv | 1 + 5 files changed, 15 insertions(+) diff --git a/grammars/silver/definition/core/ProductionBody.sv b/grammars/silver/definition/core/ProductionBody.sv index b5dccb9a9..5fd32638b 100644 --- a/grammars/silver/definition/core/ProductionBody.sv +++ b/grammars/silver/definition/core/ProductionBody.sv @@ -10,6 +10,11 @@ nonterminal ProductionStmt with config, grammarName, env, location, unparse, errors, defs, frame, compiledGrammars, productionAttributes, uniqueSignificantExpression; +flowtype decorate {frame, grammarName, compiledGrammars, config, env, flowEnv, downSubst} + on ProductionBody, ProductionStmts; +flowtype decorate {frame, grammarName, compiledGrammars, config, env, flowEnv, downSubst, finalSubst} + on ProductionStmt; + nonterminal DefLHS with config, grammarName, env, location, unparse, errors, frame, compiledGrammars, name, typerep, defLHSattr, found; diff --git a/grammars/silver/extension/autoattr/Propagate.sv b/grammars/silver/extension/autoattr/Propagate.sv index 11d94f9f3..41bef2f85 100644 --- a/grammars/silver/extension/autoattr/Propagate.sv +++ b/grammars/silver/extension/autoattr/Propagate.sv @@ -21,6 +21,8 @@ top::ProductionStmt ::= 'propagate' ns::NameList ';' abstract production propagateOneAttr top::ProductionStmt ::= attr::QName { + top.unparse = s"propagate ${attr.unparse};"; + -- Ugh, workaround for circular dependency top.defs = []; top.productionAttributes = []; diff --git a/grammars/silver/modification/copper/ActionCode.sv b/grammars/silver/modification/copper/ActionCode.sv index 2bc0805ce..a49b0d47d 100644 --- a/grammars/silver/modification/copper/ActionCode.sv +++ b/grammars/silver/modification/copper/ActionCode.sv @@ -59,6 +59,7 @@ top::ActionCode_c ::= '{' stmts::ProductionStmts '}' -- contained in the snoc-list (so this statement or before) are a pluck. Handles -- raising errors if there are statements after a pluck. synthesized attribute containsPluck :: Boolean occurs on ProductionStmts, ProductionStmt; +flowtype containsPluck {decorate} on ProductionStmts, ProductionStmt; aspect production productionStmtsSnoc top::ProductionStmts ::= h::ProductionStmts t::ProductionStmt diff --git a/grammars/silver/modification/copper/Env.sv b/grammars/silver/modification/copper/Env.sv index a3da8d605..bf4fa9b86 100644 --- a/grammars/silver/modification/copper/Env.sv +++ b/grammars/silver/modification/copper/Env.sv @@ -121,6 +121,12 @@ top::QName ::= id::Name ':' qn::QName top.lookupLexerClass = decorate customLookup("lexer class", getLexerClassDcl(top.name, top.env), top.name, top.location) with {}; } +aspect production qNameError +top::QName ::= msg::[Message] +{ + top.lookupLexerClass = decorate errorLookup(msg) with {}; +} + -------------------------------------------------------------------------------- diff --git a/grammars/silver/modification/copper/ProductionStmt.sv b/grammars/silver/modification/copper/ProductionStmt.sv index 210338738..f5e372931 100644 --- a/grammars/silver/modification/copper/ProductionStmt.sv +++ b/grammars/silver/modification/copper/ProductionStmt.sv @@ -30,6 +30,7 @@ top::ProductionStmt ::= 'pluck' e::Expr ';' local tyCk :: TypeCheck = check(e.typerep, terminalIdType()); tyCk.downSubst = e.upSubst; + tyCk.finalSubst = top.finalSubst; top.errors <- if tyCk.typeerror then [err(top.location, "'pluck' expects one of the terminals it is disambiguating between. Instead it received "++tyCk.leftpp)] From 65b667d30f7249670c51b8d0ee60497594b47834 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Sat, 7 Mar 2020 15:54:47 -0600 Subject: [PATCH 19/57] Implement propagate ... on ...; global decl to propagate on all known non-forwarding productions --- .../analysis/typechecking/core/AspectDcl.sv | 4 +- grammars/silver/definition/core/DclInfo.sv | 2 +- .../silver/definition/core/ProductionDcl.sv | 2 +- grammars/silver/definition/env/DclInfo.sv | 12 ++-- grammars/silver/definition/env/Defs.sv | 4 +- grammars/silver/definition/env/Env.sv | 2 + .../silver/extension/autoattr/Propagate.sv | 68 +++++++++++++++++++ .../extension/patternmatching/PatternTypes.sv | 2 +- .../modification/collection/Collection.sv | 4 +- .../primitivepattern/VarBinders.sv | 2 +- test/silver_features/Functor.sv | 60 ++++++++++++---- 11 files changed, 136 insertions(+), 26 deletions(-) diff --git a/grammars/silver/analysis/typechecking/core/AspectDcl.sv b/grammars/silver/analysis/typechecking/core/AspectDcl.sv index f1d6c0319..7f164c4c7 100644 --- a/grammars/silver/analysis/typechecking/core/AspectDcl.sv +++ b/grammars/silver/analysis/typechecking/core/AspectDcl.sv @@ -16,7 +16,7 @@ top::AGDcl ::= 'aspect' 'production' id::QName ns::AspectProductionSignature bod -- dcl is potentially not found, accessing it can crash. -- so check on dcls for this. case id.lookupValue.dcls of - | prodDcl (_, _, _) :: _ -> [] + | prodDcl (_, _, _, _) :: _ -> [] | funDcl (_, _, _) :: _ -> [err(top.location, "Production aspect for '" ++ id.name ++ "' should be a 'function' aspect instead.")] | _ -> [err(id.location, id.name ++ " is not a production.")] end; @@ -43,7 +43,7 @@ top::AGDcl ::= 'aspect' 'function' id::QName ns::AspectFunctionSignature body::P -- must be on dcls because lookup may have failed. case id.lookupValue.dcls of | funDcl (_, _, _) :: _ -> [] - | prodDcl (_, _, _) :: _ -> [err(top.location, "Function aspect for '" ++ id.name ++ "' should be a 'production' aspect instead.")] + | prodDcl (_, _, _, _) :: _ -> [err(top.location, "Function aspect for '" ++ id.name ++ "' should be a 'production' aspect instead.")] | _ -> [err(id.location, id.name ++ " is not a function.")] end; diff --git a/grammars/silver/definition/core/DclInfo.sv b/grammars/silver/definition/core/DclInfo.sv index 6a828a20e..5de08513c 100644 --- a/grammars/silver/definition/core/DclInfo.sv +++ b/grammars/silver/definition/core/DclInfo.sv @@ -79,7 +79,7 @@ top::DclInfo ::= sg::String sl::Location fn::String ty::Type -- -- interface values aspect production prodDcl -top::DclInfo ::= sg::String sl::Location ns::NamedSignature +top::DclInfo ::= sg::String sl::Location ns::NamedSignature hasForward::Boolean { top.refDispatcher = productionReference(_, location=_); -- Note that we still need production references, even though bug #16 removes the production type. diff --git a/grammars/silver/definition/core/ProductionDcl.sv b/grammars/silver/definition/core/ProductionDcl.sv index 8cacdabdc..7a6def1a6 100644 --- a/grammars/silver/definition/core/ProductionDcl.sv +++ b/grammars/silver/definition/core/ProductionDcl.sv @@ -26,7 +26,7 @@ top::AGDcl ::= 'abstract' 'production' id::Name ns::ProductionSignature body::Pr production fName :: String = top.grammarName ++ ":" ++ id.name; production namedSig :: NamedSignature = ns.namedSignature; - top.defs = prodDef(top.grammarName, id.location, namedSig) :: + top.defs = prodDef(top.grammarName, id.location, namedSig, length(body.uniqueSignificantExpression) > 0) :: if null(body.productionAttributes) then [] else [prodOccursDef(top.grammarName, id.location, namedSig, body.productionAttributes)]; diff --git a/grammars/silver/definition/env/DclInfo.sv b/grammars/silver/definition/env/DclInfo.sv index 2f06e97e7..b13e381ee 100644 --- a/grammars/silver/definition/env/DclInfo.sv +++ b/grammars/silver/definition/env/DclInfo.sv @@ -14,6 +14,7 @@ synthesized attribute dclBoundVars :: [TyVar]; -- values synthesized attribute namedSignature :: NamedSignature; +synthesized attribute hasForward :: Boolean; -- occurs synthesized attribute attrOccurring :: String; @@ -45,7 +46,7 @@ inherited attribute givenSubstitution :: Substitution; -} closed nonterminal DclInfo with sourceGrammar, sourceLocation, fullName, -- everyone typerep, givenNonterminalType, -- types (gNT for occurs) - namedSignature, -- values that are fun/prod + namedSignature, hasForward, -- values that are fun/prod attrOccurring, isAnnotation, -- occurs isInherited, isSynthesized, -- attrs prodDefs, -- production attributes @@ -81,6 +82,7 @@ top::DclInfo ::= -- Values that are not fun/prod have this valid default. top.namedSignature = bogusNamedSignature(); + top.hasForward = false; -- On Occurs declarations and attrs top.isAnnotation = false; @@ -136,7 +138,7 @@ top::DclInfo ::= sg::String sl::Location ty::Type -- ValueDclInfos that DO appear in interface files: abstract production prodDcl -top::DclInfo ::= sg::String sl::Location ns::NamedSignature +top::DclInfo ::= sg::String sl::Location ns::NamedSignature hasForward::Boolean { top.sourceGrammar = sg; top.sourceLocation = sl; @@ -144,8 +146,9 @@ top::DclInfo ::= sg::String sl::Location ns::NamedSignature local boundvars :: [TyVar] = top.typerep.freeVariables; - top.namedSignature = ns; + top.namedSignature = ns; top.typerep = ns.typerep; + top.hasForward = hasForward; } abstract production funDcl top::DclInfo ::= sg::String sl::Location ns::NamedSignature @@ -156,8 +159,9 @@ top::DclInfo ::= sg::String sl::Location ns::NamedSignature local boundvars :: [TyVar] = top.typerep.freeVariables; - top.namedSignature = ns; + top.namedSignature = ns; top.typerep = ns.typerep; + top.hasForward = false; } abstract production globalValueDcl top::DclInfo ::= sg::String sl::Location fn::String ty::Type diff --git a/grammars/silver/definition/env/Defs.sv b/grammars/silver/definition/env/Defs.sv index 15acfcf45..3a5427971 100644 --- a/grammars/silver/definition/env/Defs.sv +++ b/grammars/silver/definition/env/Defs.sv @@ -133,9 +133,9 @@ Def ::= sg::String sl::Location fn::String ty::Type return valueDef(defaultEnvItem(localDcl(sg,sl,fn,ty))); } function prodDef -Def ::= sg::String sl::Location ns::NamedSignature +Def ::= sg::String sl::Location ns::NamedSignature hasForward::Boolean { - return prodDclDef(defaultEnvItem(prodDcl(sg,sl,ns))); + return prodDclDef(defaultEnvItem(prodDcl(sg,sl,ns,hasForward))); } function funDef Def ::= sg::String sl::Location ns::NamedSignature diff --git a/grammars/silver/definition/env/Env.sv b/grammars/silver/definition/env/Env.sv index 15b6e90d9..142b47849 100644 --- a/grammars/silver/definition/env/Env.sv +++ b/grammars/silver/definition/env/Env.sv @@ -223,6 +223,8 @@ function getProdAttrs - 2. MWDA checking known forwarding productions on attribute occurrence declaration. - - We need to be able to look from forwarding to occurs, and from - occurs to forwarding to cover all cases. + - 3. For the automatic attributes extension + - - to implement propagate on all the known non-forwarding productions of a nonterminal. - You should probably have a good reason for using this, and document it here if you do. -} function getKnownProds diff --git a/grammars/silver/extension/autoattr/Propagate.sv b/grammars/silver/extension/autoattr/Propagate.sv index 41bef2f85..501dae179 100644 --- a/grammars/silver/extension/autoattr/Propagate.sv +++ b/grammars/silver/extension/autoattr/Propagate.sv @@ -1,5 +1,73 @@ grammar silver:extension:autoattr; +concrete production propagateOnNTListDcl +top::AGDcl ::= 'propagate' attrs::NameList 'on' nts::NameList ';' +{ + top.unparse = s"propagate ${attrs.unparse} on ${nts.unparse};"; + + forwards to + case nts of + | nameListOne(n) -> propagateOnOneNTDcl(attrs, n, location=n.location) + | nameListCons(n, _, rest) -> + appendAGDcl( + propagateOnOneNTDcl(attrs, n, location=n.location), + propagateOnNTListDcl($1, attrs, $3, rest, $5, location=top.location), + location=top.location) + end; +} + +-- Note that this only propagates on all *known* non-forwarding productions. +-- Usually all non-forwarding productions are exported by the NT, but that isn't +-- always the case (see options and closed nonterminals.) +-- For such productions the attribute must still be explicitly propagated. +abstract production propagateOnOneNTDcl +top::AGDcl ::= attrs::NameList nt::QName +{ + top.unparse = s"propagate ${attrs.unparse} on ${nt.unparse};"; + + -- Ugh, workaround for circular dependency + top.defs = []; + top.occursDefs = []; + top.moduleNames = []; + + local nonForwardingProds::[DclInfo] = + filter(\ d::DclInfo -> !d.hasForward, getKnownProds(nt.lookupType.fullName, top.env)); + forwards to + foldr( + appendAGDcl(_, _, location=top.location), emptyAGDcl(location=top.location), + map( + \ d::DclInfo -> + aspectProductionDcl( + 'aspect', 'production', qName(top.location, d.fullName), + aspectProductionSignature( + aspectProductionLHSFull( + name(d.namedSignature.outputElement.elementName, top.location), + d.namedSignature.outputElement.typerep, + location=top.location), + '::=', + foldr( + aspectRHSElemCons(_, _, location=top.location), + aspectRHSElemNil(location=top.location), + map( + \ ie::NamedSignatureElement -> + aspectRHSElemFull( + name(ie.elementName, top.location), + ie.typerep, + location=top.location), + d.namedSignature.inputElements)), + location=top.location), + productionBody( + '{', + productionStmtsSnoc( + productionStmtsNil(location=top.location), + propagateAttrList('propagate', attrs, ';', location=top.location), + location=top.location), + '}', + location=top.location), + location=top.location), + nonForwardingProds)); +} + concrete production propagateAttrList top::ProductionStmt ::= 'propagate' ns::NameList ';' { diff --git a/grammars/silver/extension/patternmatching/PatternTypes.sv b/grammars/silver/extension/patternmatching/PatternTypes.sv index 034a79110..a6f663e2b 100644 --- a/grammars/silver/extension/patternmatching/PatternTypes.sv +++ b/grammars/silver/extension/patternmatching/PatternTypes.sv @@ -118,7 +118,7 @@ top::Pattern ::= v::Name else []; top.errors <- case getValueDcl(v.name, top.env) of - | prodDcl(_,_,_) :: _ -> + | prodDcl(_,_,_,_) :: _ -> [err(v.location, "Pattern variables should not share the name of a production. (Potential confusion between '" ++ v.name ++ "' and '" ++ v.name ++ "()')")] | _ -> [] end; diff --git a/grammars/silver/modification/collection/Collection.sv b/grammars/silver/modification/collection/Collection.sv index 24cef9f8f..1ea04ca20 100644 --- a/grammars/silver/modification/collection/Collection.sv +++ b/grammars/silver/modification/collection/Collection.sv @@ -19,7 +19,7 @@ top::NameOrBOperator ::= q::QName top.operation = case q.lookupValue.dcl of | funDcl(_,_,_) -> functionOperation(q.lookupValue.fullName) - | prodDcl(_,_,_) -> productionOperation(q.lookupValue.fullName) + | prodDcl(_,_,_,_) -> productionOperation(q.lookupValue.fullName) | _ -> error("INTERNAL ERROR: operation attribute demanded for non-function or production.") end; @@ -39,7 +39,7 @@ top::NameOrBOperator ::= q::QName top.errors <- if !q.lookupValue.found then [] else case q.lookupValue.dcl of | funDcl(_,_,_) -> operationErrors - | prodDcl(_,_,_) -> operationErrors + | prodDcl(_,_,_,_) -> operationErrors | _ -> [err(top.location, q.name ++ " is not a valid operator for collections.")] end; } diff --git a/grammars/silver/modification/primitivepattern/VarBinders.sv b/grammars/silver/modification/primitivepattern/VarBinders.sv index 7f4fb7542..4d4f1e10e 100644 --- a/grammars/silver/modification/primitivepattern/VarBinders.sv +++ b/grammars/silver/modification/primitivepattern/VarBinders.sv @@ -168,7 +168,7 @@ top::VarBinder ::= n::Name -- this would allow us to match 'left' and 'right' on a Pair, for example, but error on Either top.errors <- case getValueDcl(n.name, top.env) of - | prodDcl(_,_,_) :: _ -> [err(top.location, "Pattern variables cannot have the same name as productions (to avoid confusion)")] + | prodDcl(_,_,_,_) :: _ -> [err(top.location, "Pattern variables cannot have the same name as productions (to avoid confusion)")] | _ -> [] end; } diff --git a/test/silver_features/Functor.sv b/test/silver_features/Functor.sv index c8474f4f5..1e2b3b92f 100644 --- a/test/silver_features/Functor.sv +++ b/test/silver_features/Functor.sv @@ -1,37 +1,49 @@ +import silver:reflect; +import silver:langutil; +import silver:langutil:pp; + functor attribute functorSyn; -synthesized attribute functorTestAnnoSum :: Integer; annotation functorTestAnno::Integer; -nonterminal FunctorTestNT with functorSyn, functorTestAnnoSum, functorTestAnno; -nonterminal FunctorTestNT2 with functorSyn, functorTestAnnoSum, functorTestAnno; +functor attribute functorSyn2 occurs on FunctorTestNT, FunctorTestNT2; +propagate functorSyn2 on FunctorTestNT, FunctorTestNT2; + +nonterminal FunctorTestNT with functorSyn, functorTestAnno; +nonterminal FunctorTestNT2 with functorSyn, functorTestAnno; abstract production consFTNT top::FunctorTestNT ::= h::FunctorTestNT t::FunctorTestNT { propagate functorSyn; - top.functorTestAnnoSum = h.functorTestAnnoSum + t.functorTestAnnoSum + top.functorTestAnno; } abstract production consFTNT2 top::FunctorTestNT ::= h::FunctorTestNT2 t::FunctorTestNT { propagate functorSyn; - top.functorTestAnnoSum = h.functorTestAnnoSum + t.functorTestAnnoSum + top.functorTestAnno; } abstract production nilFTNT top::FunctorTestNT ::= i::Integer { top.functorSyn = nilFTNT(10, functorTestAnno=123); -- test non-propagate - top.functorTestAnnoSum = top.functorTestAnno; +} + +abstract production forwardingFTNT +top::FunctorTestNT ::= h::FunctorTestNT2 +{ + forwards to + consFTNT2( + h, + nilFTNT(42, functorTestAnno=top.functorTestAnno), + functorTestAnno=top.functorTestAnno); } abstract production nilFTNT2 top::FunctorTestNT2 ::= s::String { propagate functorSyn; - top.functorTestAnnoSum = top.functorTestAnno; } global functorValue :: FunctorTestNT = @@ -45,7 +57,7 @@ global functorValue :: FunctorTestNT = nilFTNT(2, functorTestAnno=5), functorTestAnno=6), functorTestAnno=7); - + global functorValueRes :: FunctorTestNT = consFTNT( consFTNT2( @@ -58,10 +70,34 @@ global functorValueRes :: FunctorTestNT = functorTestAnno=6), functorTestAnno=7); --- Test to ensure it reaches all nils: -equalityTest(hackUnparse(functorValueRes), hackUnparse(functorValue.functorSyn), String, silver_tests); --- Test to ensure annotations are copied correctly -equalityTest(functorValueRes.functorTestAnnoSum, functorValue.functorSyn.functorTestAnnoSum, Integer, silver_tests); +-- Test to ensure it reaches all nils and copies annos correctly +equalityTest(show(80, reflect(functorValueRes).pp), show(80, reflect(functorValue.functorSyn).pp), String, silver_tests); + +global functorValue2 :: FunctorTestNT = + consFTNT( + consFTNT2( + nilFTNT2("a", functorTestAnno=1), + nilFTNT(1, functorTestAnno=2), + functorTestAnno=3), + forwardingFTNT( + nilFTNT2("b", functorTestAnno=4), + functorTestAnno=5), + functorTestAnno=6); + +global functorValueRes2 :: FunctorTestNT = + consFTNT( + consFTNT2( + nilFTNT2("a", functorTestAnno=1), + nilFTNT(1, functorTestAnno=2), + functorTestAnno=3), + consFTNT2( + nilFTNT2("b", functorTestAnno=4), + nilFTNT(42, functorTestAnno=5), + functorTestAnno=5), + functorTestAnno=6); + +-- Test global propagation +equalityTest(show(80, reflect(functorValueRes2).pp), show(80, reflect(functorValue2.functorSyn2).pp), String, silver_tests); nonterminal FunctorTestNT3 with functorSyn; From 170ed8a8c9296241fef0762e81456e7c664f52a1 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Sat, 7 Mar 2020 16:54:34 -0600 Subject: [PATCH 20/57] Use global propagate in silver where useful --- grammars/silver/extension/rewriting/Expr.sv | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/grammars/silver/extension/rewriting/Expr.sv b/grammars/silver/extension/rewriting/Expr.sv index a8b4a10bb..a119d6998 100644 --- a/grammars/silver/extension/rewriting/Expr.sv +++ b/grammars/silver/extension/rewriting/Expr.sv @@ -253,13 +253,13 @@ top::Expr ::= 'decorate' e::Expr 'with' '{' inh::ExprInhs '}' attribute transform occurs on ExprInhs; synthesized attribute lambdaParams::ProductionRHS occurs on ExprInhs; functor attribute bodyExprInhTransform occurs on ExprInhs, ExprInh; +propagate bodyExprInhTransform on ExprInhs; aspect production exprInhsEmpty top::ExprInhs ::= { top.transform = nilASTExpr(); top.lambdaParams = productionRHSNil(location=builtin); - propagate bodyExprInhTransform; } aspect production exprInhsOne @@ -268,7 +268,6 @@ top::ExprInhs ::= lhs::ExprInh top.transform = consASTExpr(lhs.transform, nilASTExpr()); top.lambdaParams = productionRHSCons(lhs.lambdaParam, productionRHSNil(location=builtin), location=builtin); - propagate bodyExprInhTransform; } aspect production exprInhsCons @@ -276,7 +275,6 @@ top::ExprInhs ::= lhs::ExprInh inh::ExprInhs { top.transform = consASTExpr(lhs.transform, inh.transform); top.lambdaParams = productionRHSCons(lhs.lambdaParam, inh.lambdaParams, location=builtin); - propagate bodyExprInhTransform; } attribute transform occurs on ExprInh; From 1343b59554a793b5131ad55e03b0ef579eb26425 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Thu, 12 Mar 2020 15:51:03 -0500 Subject: [PATCH 21/57] Removed unneeded forwards --- grammars/silver/modification/collection/DclInfo.sv | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/grammars/silver/modification/collection/DclInfo.sv b/grammars/silver/modification/collection/DclInfo.sv index e16c87c4c..bd5c783ed 100644 --- a/grammars/silver/modification/collection/DclInfo.sv +++ b/grammars/silver/modification/collection/DclInfo.sv @@ -34,6 +34,7 @@ top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type o::O top.typerep = ty; top.dclBoundVars = bound; + top.isSynthesized = true; top.decoratedAccessHandler = synDecoratedAccessHandler(_, _, location=_); top.undecoratedAccessHandler = accessBounceDecorate(synDecoratedAccessHandler(_, _, location=_), _, _, _); @@ -43,8 +44,6 @@ top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type o::O top.attrBaseDefDispatcher = synBaseColAttributeDef(_, _, _, location=_); top.attrAppendDefDispatcher = synAppendColAttributeDef(_, _, _, location=_); - - forwards to synDcl(sg,sl,fn,bound,ty); } abstract production inhCollectionDcl top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type o::Operation @@ -55,6 +54,7 @@ top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type o::O top.typerep = ty; top.dclBoundVars = bound; + top.isInherited = true; top.decoratedAccessHandler = inhDecoratedAccessHandler(_, _, location=_); top.undecoratedAccessHandler = accessBounceDecorate(inhDecoratedAccessHandler(_, _, location=_), _, _, _); -- TODO: above should probably be an error handler! @@ -64,8 +64,6 @@ top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type o::O top.attrBaseDefDispatcher = inhBaseColAttributeDef(_, _, _, location=_); top.attrAppendDefDispatcher = inhAppendColAttributeDef(_, _, _, location=_); - - forwards to inhDcl(sg,sl,fn,bound,ty); } abstract production localCollectionDcl @@ -83,8 +81,6 @@ top::DclInfo ::= sg::String sl::Location fn::String ty::Type o::Operation top.baseDefDispatcher = baseCollectionValueDef(_, _, location=_); top.appendDefDispatcher = appendCollectionValueDef(_, _, location=_); - - forwards to localDcl(sg,sl,fn,ty); top.substitutedDclInfo = localCollectionDcl(sg,sl,fn, performRenaming(ty, top.givenSubstitution), o); } From 2916e53ba05c755d836e43a75b55c36f2cd0e5e0 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Thu, 12 Mar 2020 16:07:23 -0500 Subject: [PATCH 22/57] Fix some interfering equations for collection modification --- grammars/silver/definition/core/AGDcl.sv | 2 +- .../modification/collection/Collection.sv | 30 ++++++++++--------- .../silver/modification/collection/DclInfo.sv | 6 ++++ 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/grammars/silver/definition/core/AGDcl.sv b/grammars/silver/definition/core/AGDcl.sv index f655af5f8..8d5eb3807 100644 --- a/grammars/silver/definition/core/AGDcl.sv +++ b/grammars/silver/definition/core/AGDcl.sv @@ -57,7 +57,7 @@ top::AGDcl ::= e::[Message] abstract production defsAGDcl top::AGDcl ::= d::[Def] { - top.unparse = s"{- Defs -}"; + top.unparse = s"{- Defs:\n${hackUnparse(d)} -}"; top.errors := []; top.defs = d; } diff --git a/grammars/silver/modification/collection/Collection.sv b/grammars/silver/modification/collection/Collection.sv index 1ea04ca20..ffa0ad2a8 100644 --- a/grammars/silver/modification/collection/Collection.sv +++ b/grammars/silver/modification/collection/Collection.sv @@ -118,22 +118,23 @@ top::AGDcl ::= 'synthesized' 'attribute' a::Name tl::BracketedOptTypeExprs '::' production attribute fName :: String; fName = top.grammarName ++ ":" ++ a.name; - top.defs = [synColDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep, q.operation)]; - tl.initialEnv = top.env; tl.env = tl.envBindingTyVars; te.env = tl.envBindingTyVars; + + q.operatorForType = te.typerep; - top.errors := te.errors ++ q.errors ++ tl.errors ++ tl.errorsTyVars; + top.errors <- te.errors ++ q.errors ++ tl.errors ++ tl.errorsTyVars; top.errors <- if length(getAttrDclAll(fName, top.env)) > 1 then [err(a.location, "Attribute '" ++ fName ++ "' is already bound.")] - else []; - - q.operatorForType = te.typerep; + else []; - forwards to attributeDclSyn($1, $2, a, tl, $5, te, $9, location=top.location); + forwards to + defsAGDcl( + [synColDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep, q.operation)], + location=top.location); } concrete production collectionAttributeDclInh @@ -144,22 +145,23 @@ top::AGDcl ::= 'inherited' 'attribute' a::Name tl::BracketedOptTypeExprs '::' te production attribute fName :: String; fName = top.grammarName ++ ":" ++ a.name; - top.defs = [inhColDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep, q.operation)]; - tl.initialEnv = top.env; tl.env = tl.envBindingTyVars; te.env = tl.envBindingTyVars; + + q.operatorForType = te.typerep; - top.errors := te.errors ++ q.errors ++ tl.errors ++ tl.errorsTyVars; + top.errors <- te.errors ++ q.errors ++ tl.errors ++ tl.errorsTyVars; top.errors <- if length(getAttrDclAll(fName, top.env)) > 1 then [err(a.location, "Attribute '" ++ fName ++ "' is already bound.")] - else []; - - q.operatorForType = te.typerep; + else []; - forwards to attributeDclInh($1, $2, a, tl, $5, te, $9, location=top.location); + forwards to + defsAGDcl( + [inhColDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep, q.operation)], + location=top.location); } diff --git a/grammars/silver/modification/collection/DclInfo.sv b/grammars/silver/modification/collection/DclInfo.sv index bd5c783ed..50256df03 100644 --- a/grammars/silver/modification/collection/DclInfo.sv +++ b/grammars/silver/modification/collection/DclInfo.sv @@ -41,6 +41,7 @@ top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type o::O top.attrDefDispatcher = \ dl::Decorated DefLHS attr::Decorated QNameAttrOccur e::Expr l::Location -> errorAttributeDef([err(l, attr.name ++ " is a collection attribute, and you must use ':=' or '<-', not '='.")], dl, attr, e, location=l); + top.attributionDispatcher = defaultAttributionDcl(_, _, _, _, location=_); top.attrBaseDefDispatcher = synBaseColAttributeDef(_, _, _, location=_); top.attrAppendDefDispatcher = synAppendColAttributeDef(_, _, _, location=_); @@ -61,6 +62,7 @@ top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type o::O top.attrDefDispatcher = \ dl::Decorated DefLHS attr::Decorated QNameAttrOccur e::Expr l::Location -> errorAttributeDef([err(l, attr.name ++ " is a collection attribute, and you must use ':=' or '<-', not '='.")], dl, attr, e, location=l); + top.attributionDispatcher = defaultAttributionDcl(_, _, _, _, location=_); top.attrBaseDefDispatcher = inhBaseColAttributeDef(_, _, _, location=_); top.attrAppendDefDispatcher = inhAppendColAttributeDef(_, _, _, location=_); @@ -83,6 +85,10 @@ top::DclInfo ::= sg::String sl::Location fn::String ty::Type o::Operation top.appendDefDispatcher = appendCollectionValueDef(_, _, location=_); top.substitutedDclInfo = localCollectionDcl(sg,sl,fn, performRenaming(ty, top.givenSubstitution), o); + + -- TODO: attrOccursIndex + -- We shouldn't be forwarding here + forwards to localDcl(sg,sl,fn,ty); } From 8e9ff99783f51141002976a940cf2785d6ee361b Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Thu, 12 Mar 2020 18:55:17 -0500 Subject: [PATCH 23/57] Actually these productions shouldn't forward --- .../modification/collection/Collection.sv | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/grammars/silver/modification/collection/Collection.sv b/grammars/silver/modification/collection/Collection.sv index ffa0ad2a8..0b5f3380c 100644 --- a/grammars/silver/modification/collection/Collection.sv +++ b/grammars/silver/modification/collection/Collection.sv @@ -123,18 +123,15 @@ top::AGDcl ::= 'synthesized' 'attribute' a::Name tl::BracketedOptTypeExprs '::' te.env = tl.envBindingTyVars; q.operatorForType = te.typerep; - - top.errors <- te.errors ++ q.errors ++ tl.errors ++ tl.errorsTyVars; + + top.defs = [synColDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep, q.operation)]; + + top.errors := te.errors ++ q.errors ++ tl.errors ++ tl.errorsTyVars; top.errors <- if length(getAttrDclAll(fName, top.env)) > 1 then [err(a.location, "Attribute '" ++ fName ++ "' is already bound.")] else []; - - forwards to - defsAGDcl( - [synColDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep, q.operation)], - location=top.location); } concrete production collectionAttributeDclInh @@ -151,17 +148,14 @@ top::AGDcl ::= 'inherited' 'attribute' a::Name tl::BracketedOptTypeExprs '::' te q.operatorForType = te.typerep; - top.errors <- te.errors ++ q.errors ++ tl.errors ++ tl.errorsTyVars; + top.defs = [inhColDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep, q.operation)]; + + top.errors := te.errors ++ q.errors ++ tl.errors ++ tl.errorsTyVars; top.errors <- if length(getAttrDclAll(fName, top.env)) > 1 then [err(a.location, "Attribute '" ++ fName ++ "' is already bound.")] else []; - - forwards to - defsAGDcl( - [inhColDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep, q.operation)], - location=top.location); } From 1192968b69d0053000adeeffd43d5f942b0a7b79 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Thu, 12 Mar 2020 19:05:55 -0500 Subject: [PATCH 24/57] Implement monoid attributes --- grammars/silver/extension/autoattr/Env.sv | 27 ++++ grammars/silver/extension/autoattr/Functor.sv | 8 +- grammars/silver/extension/autoattr/Monoid.sv | 125 ++++++++++++++++++ grammars/silver/extension/autoattr/Project.sv | 1 + .../silver/extension/autoattr/Propagate.sv | 2 +- .../silver/modification/collection/DclInfo.sv | 10 +- test/silver_features/Monoid.sv | 40 ++++++ 7 files changed, 202 insertions(+), 11 deletions(-) create mode 100644 grammars/silver/extension/autoattr/Monoid.sv create mode 100644 test/silver_features/Monoid.sv diff --git a/grammars/silver/extension/autoattr/Env.sv b/grammars/silver/extension/autoattr/Env.sv index 7d6306108..b60d4d545 100644 --- a/grammars/silver/extension/autoattr/Env.sv +++ b/grammars/silver/extension/autoattr/Env.sv @@ -2,10 +2,13 @@ grammar silver:extension:autoattr; synthesized attribute propagateDispatcher :: (ProductionStmt ::= Decorated QName Location) occurs on DclInfo; +synthesized attribute emptyVal::Expr occurs on DclInfo; + aspect default production top::DclInfo ::= { top.propagateDispatcher = propagateError(_, location=_); + top.emptyVal = error("Internal compiler error: must be defined for all monoid attribute declarations"); } abstract production functorDcl @@ -25,3 +28,27 @@ top::DclInfo ::= sg::String sl::Location fn::String tyVar::TyVar top.attributionDispatcher = functorAttributionDcl(_, _, _, _, location=_); top.propagateDispatcher = propagateFunctor(_, location=_); } + +abstract production monoidDcl +top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type empty::Expr append::Operation +{ + top.sourceGrammar = sg; + top.sourceLocation = sl; + top.fullName = fn; + + top.typerep = ty; + top.dclBoundVars = bound; + top.isSynthesized = true; + top.emptyVal = empty; + top.operation = append; + + top.decoratedAccessHandler = synDecoratedAccessHandler(_, _, location=_); + top.undecoratedAccessHandler = accessBounceDecorate(synDecoratedAccessHandler(_, _, location=_), _, _, _); + top.attrDefDispatcher = + \ dl::Decorated DefLHS attr::Decorated QNameAttrOccur e::Expr l::Location -> + errorAttributeDef([err(l, attr.name ++ " is a monoid collection attribute, and you must use ':=' or '<-', not '='.")], dl, attr, e, location=l); + top.attrBaseDefDispatcher = synBaseColAttributeDef(_, _, _, location=_); + top.attrAppendDefDispatcher = synAppendColAttributeDef(_, _, _, location=_); + top.attributionDispatcher = defaultAttributionDcl(_, _, _, _, location=_); + top.propagateDispatcher = propagateMonoid(_, location=_); +} diff --git a/grammars/silver/extension/autoattr/Functor.sv b/grammars/silver/extension/autoattr/Functor.sv index 8f6f189c3..adba5da28 100644 --- a/grammars/silver/extension/autoattr/Functor.sv +++ b/grammars/silver/extension/autoattr/Functor.sv @@ -91,12 +91,8 @@ Expr ::= loc::Location env::Decorated Env attrName::Decorated QName input::Named at.env = env; -- Check if the attribute occurs on the first child - local attrOccursOnHead :: Boolean = - !null( - -- The occurs dcls on this nonterminal for - flatMap(getOccursDcl(_, input.typerep.typeName, env), - -- the full names of each candidate - map((.fullName), attrName.lookupAttribute.dcls))); + local attrOccursOnHead :: Boolean = + !null(getOccursDcl(attrName.lookupAttribute.dcl.fullName, input.typerep.typeName, env)); local validTypeHead :: Boolean = input.typerep.isDecorable; return diff --git a/grammars/silver/extension/autoattr/Monoid.sv b/grammars/silver/extension/autoattr/Monoid.sv new file mode 100644 index 000000000..59e53d17c --- /dev/null +++ b/grammars/silver/extension/autoattr/Monoid.sv @@ -0,0 +1,125 @@ +grammar silver:extension:autoattr; + +concrete production monoidAttributeDcl +top::AGDcl ::= 'monoid' 'attribute' a::Name tl::BracketedOptTypeExprs '::' te::TypeExpr 'with' e::Expr ',' q::NameOrBOperator ';' +{ + top.unparse = "monoid attribute " ++ a.unparse ++ ";"; + + production attribute fName :: String; + fName = top.grammarName ++ ":" ++ a.name; + + tl.initialEnv = top.env; + tl.env = tl.envBindingTyVars; + te.env = tl.envBindingTyVars; + + q.operatorForType = te.typerep; + + -- TODO: We want to define our own defs here but can't forward to defsAGDcl because collections define different translation. + -- Not sure about the best way to refactor this. + top.defs = + [attrDef(defaultEnvItem(monoidDcl(top.grammarName, a.location, fName, tl.freeVariables, te.typerep, e, q.operation)))]; + + top.errors <- e.errors; + + top.errors <- + if length(getAttrDclAll(fName, top.env)) > 1 + then [err(a.location, "Attribute '" ++ fName ++ "' is already bound.")] + else []; + + local errCheck1 :: TypeCheck = check(e.typerep, te.typerep); + top.errors <- + if errCheck1.typeerror + then [err(e.location, "Monoid attribute " ++ fName ++ " of type " ++ errCheck1.rightpp ++ " has empty value specified with type " ++ errCheck1.leftpp)] + else []; + + e.downSubst = emptySubst(); + errCheck1.downSubst = e.upSubst; + + errCheck1.finalSubst = errCheck1.upSubst; + e.finalSubst = errCheck1.upSubst; + + forwards to + collectionAttributeDclSyn( + 'synthesized', 'attribute', a, tl, '::', te, 'with', q, ';', + location=top.location); +} + +synthesized attribute appendProd :: (Expr ::= Expr Expr Location) occurs on Operation; + +aspect production functionOperation +top::Operation ::= s::String +{ + top.appendProd = \ e1::Expr e2::Expr l::Location -> mkStrFunctionInvocation(l, s, [e1, e2]); +} +aspect production productionOperation +top::Operation ::= s::String +{ + top.appendProd = \ e1::Expr e2::Expr l::Location -> mkStrFunctionInvocation(l, s, [e1, e2]); +} +aspect production plusPlusOperationString +top::Operation ::= +{ + top.appendProd = plusPlus(_, '++', _, location=_); +} +aspect production plusPlusOperationList +top::Operation ::= +{ + top.appendProd = plusPlus(_, '++', _, location=_); +} +aspect production borOperation +top::Operation ::= +{ + top.appendProd = or(_, '||', _, location=_); +} +aspect production bandOperation +top::Operation ::= +{ + top.appendProd = and(_, '&&', _, location=_); +} + +{-- + - Propagate a monoid attribute on the enclosing production + - @param attr The name of the attribute to propagate + -} +abstract production propagateMonoid +top::ProductionStmt ::= attr::Decorated QName +{ + -- No explicit errors, for now. The only conceivable issue is the attribute not + -- occuring on the LHS but this should be caught by the forward errors. + + local attrFullName::String = attr.lookupAttribute.dcl.fullName; + local inputsWithAttr::[NamedSignatureElement] = + filter( + \ input::NamedSignatureElement -> + !null(getOccursDcl(attrFullName, input.typerep.typeName, top.env)), + top.frame.signature.inputElements); + + local topName::QName = qName(top.location, top.frame.signature.outputElement.elementName); + local prodName::QName = qName(top.location, top.frame.fullName); + prodName.grammarName = top.grammarName; + prodName.config = top.config; + prodName.env = top.env; + + local res :: Expr = + if null(inputsWithAttr) + then attr.lookupAttribute.dcl.emptyVal + else + foldr1( + attr.lookupAttribute.dcl.operation.appendProd(_, _, top.location), + map( + \ i::NamedSignatureElement -> + access( + baseExpr(qName(top.location, i.elementName), location=top.location), + '.', + qNameAttrOccur(new(attr), location=top.location), + location=top.location), + inputsWithAttr)); + + -- Construct an attribute def and call with the generated arguments + forwards to + attrContainsBase( + concreteDefLHS(topName, location=top.location), + '.', + qNameAttrOccur(new(attr), location=top.location), + ':=', res, ';', location=top.location); +} diff --git a/grammars/silver/extension/autoattr/Project.sv b/grammars/silver/extension/autoattr/Project.sv index 49653b891..70624d0a8 100644 --- a/grammars/silver/extension/autoattr/Project.sv +++ b/grammars/silver/extension/autoattr/Project.sv @@ -4,5 +4,6 @@ imports silver:definition:core; imports silver:definition:env; imports silver:definition:type; imports silver:definition:type:syntax; +imports silver:modification:collection; exports silver:extension:autoattr:convenience; diff --git a/grammars/silver/extension/autoattr/Propagate.sv b/grammars/silver/extension/autoattr/Propagate.sv index 501dae179..159841a2e 100644 --- a/grammars/silver/extension/autoattr/Propagate.sv +++ b/grammars/silver/extension/autoattr/Propagate.sv @@ -95,7 +95,7 @@ top::ProductionStmt ::= attr::QName top.defs = []; top.productionAttributes = []; forwards to - if !attr.lookupAttribute.found + if !null(attr.lookupAttribute.errors) then errorProductionStmt(attr.lookupAttribute.errors, location=top.location) else attr.lookupAttribute.dcl.propagateDispatcher(attr, top.location); } diff --git a/grammars/silver/modification/collection/DclInfo.sv b/grammars/silver/modification/collection/DclInfo.sv index 50256df03..cadc0a511 100644 --- a/grammars/silver/modification/collection/DclInfo.sv +++ b/grammars/silver/modification/collection/DclInfo.sv @@ -1,6 +1,6 @@ grammar silver:modification:collection; -attribute attrBaseDefDispatcher, attrAppendDefDispatcher, baseDefDispatcher, appendDefDispatcher occurs on DclInfo; +attribute operation, attrBaseDefDispatcher, attrAppendDefDispatcher, baseDefDispatcher, appendDefDispatcher occurs on DclInfo; synthesized attribute attrBaseDefDispatcher :: (ProductionStmt ::= Decorated DefLHS Decorated QNameAttrOccur Expr Location); synthesized attribute attrAppendDefDispatcher :: (ProductionStmt ::= Decorated DefLHS Decorated QNameAttrOccur Expr Location); @@ -8,12 +8,11 @@ synthesized attribute attrAppendDefDispatcher :: (ProductionStmt ::= Decorated D synthesized attribute baseDefDispatcher :: (ProductionStmt ::= Decorated QName Expr Location); synthesized attribute appendDefDispatcher :: (ProductionStmt ::= Decorated QName Expr Location); --- TODO: the 'operation' value on these declarations is never used. --- Please take a moment to think about whether it should even exist or not. - aspect default production top::DclInfo ::= { + top.operation = error("Internal compiler error: must be defined for all collection attribute declarations"); + top.attrBaseDefDispatcher = \ dl::Decorated DefLHS attr::Decorated QNameAttrOccur e::Expr l::Location -> errorAttributeDef([err(l, "The ':=' operator can only be used for collections. " ++ attr.name ++ " is not a collection.")], dl, attr, e, location=l); @@ -35,6 +34,7 @@ top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type o::O top.typerep = ty; top.dclBoundVars = bound; top.isSynthesized = true; + top.operation = o; top.decoratedAccessHandler = synDecoratedAccessHandler(_, _, location=_); top.undecoratedAccessHandler = accessBounceDecorate(synDecoratedAccessHandler(_, _, location=_), _, _, _); @@ -56,6 +56,7 @@ top::DclInfo ::= sg::String sl::Location fn::String bound::[TyVar] ty::Type o::O top.typerep = ty; top.dclBoundVars = bound; top.isInherited = true; + top.operation = o; top.decoratedAccessHandler = inhDecoratedAccessHandler(_, _, location=_); top.undecoratedAccessHandler = accessBounceDecorate(inhDecoratedAccessHandler(_, _, location=_), _, _, _); -- TODO: above should probably be an error handler! @@ -76,6 +77,7 @@ top::DclInfo ::= sg::String sl::Location fn::String ty::Type o::Operation top.fullName = fn; top.typerep = ty; + top.operation = o; top.refDispatcher = localReference(_, location=_); top.defDispatcher = errorColNormalValueDef(_, _, location=_); diff --git a/test/silver_features/Monoid.sv b/test/silver_features/Monoid.sv new file mode 100644 index 000000000..a455995c2 --- /dev/null +++ b/test/silver_features/Monoid.sv @@ -0,0 +1,40 @@ + +monoid attribute defs::[String] with [], ++; +monoid attribute freeVars::[String] with [], ++; + +propagate defs on MStmt; +propagate freeVars on MExpr; + +nonterminal MStmt with defs, freeVars; +nonterminal MExpr with freeVars; + +abstract production seqMStmt +top::MStmt ::= s1::MStmt s2::MStmt +{ + top.freeVars := s1.freeVars ++ removeAllBy(stringEq, s1.defs, s2.freeVars); +} + +abstract production assignMStmt +top::MStmt ::= a::String e::MExpr +{ + propagate freeVars; + top.defs <- [a]; +} + +abstract production addMExpr +top::MExpr ::= e1::MExpr e2::MExpr +{} + +abstract production varMExpr +top::MExpr ::= a::String +{ + top.freeVars <- [a]; +} + +global testMStmt::MStmt = + seqMStmt( + assignMStmt("a", addMExpr(varMExpr("b"), varMExpr("c"))), + assignMStmt("d", varMExpr("a"))); + +equalityTest(testMStmt.defs, ["a", "d"], [String], silver_tests); +equalityTest(testMStmt.freeVars, ["b", "c"], [String], silver_tests); From fd811d3dbf1e713df607f872e2aa7d3bbf76b6c3 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Thu, 12 Mar 2020 19:07:31 -0500 Subject: [PATCH 25/57] Rename grammars/silver/extension/autoattr/Env.sv -> grammars/silver/extension/autoattr/DclInfo.sv --- grammars/silver/extension/autoattr/{Env.sv => DclInfo.sv} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename grammars/silver/extension/autoattr/{Env.sv => DclInfo.sv} (100%) diff --git a/grammars/silver/extension/autoattr/Env.sv b/grammars/silver/extension/autoattr/DclInfo.sv similarity index 100% rename from grammars/silver/extension/autoattr/Env.sv rename to grammars/silver/extension/autoattr/DclInfo.sv From 9892d37e07c1b735c0166281cd1cc351d6cde7b7 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 13 Mar 2020 13:36:56 -0500 Subject: [PATCH 26/57] Fix to interaction of IMP ide fonts and lexer super-class relations --- .../silver/modification/impide/cstast/LexerClassModifiers.sv | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/grammars/silver/modification/impide/cstast/LexerClassModifiers.sv b/grammars/silver/modification/impide/cstast/LexerClassModifiers.sv index 9f96dcfcf..71f48a120 100644 --- a/grammars/silver/modification/impide/cstast/LexerClassModifiers.sv +++ b/grammars/silver/modification/impide/cstast/LexerClassModifiers.sv @@ -35,3 +35,8 @@ top::SyntaxLexerClassModifier ::= fontName::String top.fontAttr = makeCopperName(fontName); } +aspect production lexerClassExtends +top::SyntaxLexerClassModifier ::= super::[String] +{ + top.fontAttr = dumbExtractFont(superRefs); +} \ No newline at end of file From 3aa02f504807c494d5e6f3bc1730434c9f7985bd Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 13 Mar 2020 19:25:50 -0500 Subject: [PATCH 27/57] Only include non-decorated children in monoid propagage by default --- grammars/silver/extension/autoattr/Monoid.sv | 1 + 1 file changed, 1 insertion(+) diff --git a/grammars/silver/extension/autoattr/Monoid.sv b/grammars/silver/extension/autoattr/Monoid.sv index 59e53d17c..21c359ce3 100644 --- a/grammars/silver/extension/autoattr/Monoid.sv +++ b/grammars/silver/extension/autoattr/Monoid.sv @@ -91,6 +91,7 @@ top::ProductionStmt ::= attr::Decorated QName local inputsWithAttr::[NamedSignatureElement] = filter( \ input::NamedSignatureElement -> + input.typerep.isDecorable && !null(getOccursDcl(attrFullName, input.typerep.typeName, top.env)), top.frame.signature.inputElements); From 131ade796ae736d76478733a3d0a5e9bde937469 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 13 Mar 2020 21:39:00 -0500 Subject: [PATCH 28/57] Add missing error check for nt name lookup --- grammars/silver/extension/autoattr/Propagate.sv | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/grammars/silver/extension/autoattr/Propagate.sv b/grammars/silver/extension/autoattr/Propagate.sv index 159841a2e..5cac91b21 100644 --- a/grammars/silver/extension/autoattr/Propagate.sv +++ b/grammars/silver/extension/autoattr/Propagate.sv @@ -32,7 +32,7 @@ top::AGDcl ::= attrs::NameList nt::QName local nonForwardingProds::[DclInfo] = filter(\ d::DclInfo -> !d.hasForward, getKnownProds(nt.lookupType.fullName, top.env)); - forwards to + local dcl::AGDcl = foldr( appendAGDcl(_, _, location=top.location), emptyAGDcl(location=top.location), map( @@ -66,6 +66,11 @@ top::AGDcl ::= attrs::NameList nt::QName location=top.location), location=top.location), nonForwardingProds)); + + forwards to + if !null(nt.lookupType.errors) + then errorAGDcl(nt.lookupType.errors, location=top.location) + else dcl; } concrete production propagateAttrList From 5579977ab6fe5c23ad08c8164951fe285afffb22 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Mon, 16 Mar 2020 14:07:28 -0500 Subject: [PATCH 29/57] Use monoid attributes as appropriate in the Silver compiler --- .../concrete_syntax/NonTerminalDcl.sv | 28 +- .../definition/concrete_syntax/ParserSpec.sv | 4 +- .../concrete_syntax/ProductionDcl.sv | 46 +-- .../silver/definition/concrete_syntax/Root.sv | 33 +- .../definition/concrete_syntax/RootSpec.sv | 52 +-- .../definition/concrete_syntax/TerminalDcl.sv | 33 +- .../ast/LexerClassModifiers.sv | 40 +-- .../ast/NonterminalModifiers.sv | 18 +- .../ast/ProductionModifiers.sv | 40 +-- .../definition/concrete_syntax/ast/Syntax.sv | 154 +++----- .../concrete_syntax/ast/TerminalModifiers.sv | 119 +++---- grammars/silver/definition/core/AGDcl.sv | 42 +-- grammars/silver/definition/core/Annotation.sv | 4 +- grammars/silver/definition/core/AspectDcl.sv | 34 +- .../silver/definition/core/AttributeDcl.sv | 8 +- grammars/silver/definition/core/Attributes.sv | 2 +- .../definition/core/BuiltInFunctions.sv | 13 +- grammars/silver/definition/core/Expr.sv | 143 +++----- .../silver/definition/core/FunctionDcl.sv | 13 +- grammars/silver/definition/core/GlobalDcl.sv | 3 +- .../silver/definition/core/GrammarParts.sv | 31 +- .../silver/definition/core/ModuleStmts.sv | 160 +++------ .../silver/definition/core/NonTerminalDcl.sv | 14 +- grammars/silver/definition/core/OccursDcl.sv | 14 +- .../silver/definition/core/ProductionBody.sv | 96 ++--- .../silver/definition/core/ProductionDcl.sv | 28 +- grammars/silver/definition/core/Root.sv | 26 +- grammars/silver/definition/env/Attributes.sv | 14 +- grammars/silver/definition/flow/env/Expr.sv | 334 ++++++------------ .../silver/definition/flow/env/FlowEnv.sv | 2 +- .../silver/definition/flow/env/FunctionDcl.sv | 4 - .../definition/flow/env/NonterminalDcl.sv | 2 +- grammars/silver/definition/flow/env/Occurs.sv | 2 +- .../definition/flow/env/ProductionBody.sv | 146 +------- .../definition/flow/env/ProductionDcl.sv | 14 +- grammars/silver/definition/flow/env/Root.sv | 26 +- .../silver/definition/flow/env/RootSpec.sv | 37 +- .../silver/definition/flow/syntax/FlowSpec.sv | 40 +-- grammars/silver/driver/util/Compilation.sv | 12 +- grammars/silver/driver/util/RootSpec.sv | 146 ++++---- grammars/silver/extension/autoattr/Monoid.sv | 4 +- .../silver/extension/autoattr/Propagate.sv | 10 +- .../extension/convenience/Productions.sv | 2 +- .../silver/extension/testing/WrongCode.sv | 2 +- grammars/silver/extension/treegen/Eq.sv | 2 +- grammars/silver/extension/treegen/TestFor.sv | 6 +- grammars/silver/langutil/Attributes.sv | 2 +- .../modification/autocopyattr/AutoCopy.sv | 2 +- .../modification/collection/Collection.sv | 34 +- .../silver/modification/copper/ActionCode.sv | 6 +- .../modification/copper/CustomLayout.sv | 28 +- .../copper/DisambiguationGroup.sv | 2 +- .../silver/modification/copper/LexerClass.sv | 30 +- .../modification/copper/ParserAttributes.sv | 8 +- .../silver/modification/copper/ParserDcl.sv | 49 ++- grammars/silver/modification/copper/Prefix.sv | 20 +- .../modification/copper/ProductionStmt.sv | 66 ++-- .../silver/modification/copper/TermList.sv | 19 +- .../silver/modification/copper/TerminalDcl.sv | 81 ++--- .../modification/copper_mda/Analysis.sv | 4 +- .../modification/defaultattr/DefaultAttr.sv | 4 +- grammars/silver/modification/ffi/TypeDcl.sv | 5 +- .../silver/modification/impide/FontDecl.sv | 33 +- .../modification/impide/FontModifiers.sv | 5 +- .../silver/modification/impide/IdeDecl.sv | 2 +- .../modification/impide/cstast/CstAst.sv | 7 +- .../modification/impide/cstast/Syntax.sv | 66 +--- .../silver/modification/lambda_fn/Lambda.sv | 26 +- grammars/silver/modification/let_fix/Let.sv | 10 +- .../primitivepattern/PrimitiveMatch.sv | 22 +- .../primitivepattern/VarBinders.sv | 14 +- .../silver/modification/typedecl/TypeDecl.sv | 5 +- 72 files changed, 832 insertions(+), 1721 deletions(-) diff --git a/grammars/silver/definition/concrete_syntax/NonTerminalDcl.sv b/grammars/silver/definition/concrete_syntax/NonTerminalDcl.sv index 233611c48..dafbafcf4 100644 --- a/grammars/silver/definition/concrete_syntax/NonTerminalDcl.sv +++ b/grammars/silver/definition/concrete_syntax/NonTerminalDcl.sv @@ -21,33 +21,13 @@ top::AGDcl ::= cl::ClosedOrNot 'nonterminal' id::Name tl::BracketedOptTypeExprs local exportedLayoutTerms::[String] = map((.fullName), syntax.allIgnoreTerminals); local exportedProds::[String] = map((.fullName), syntax.allProductions); - top.syntaxAst = + top.syntaxAst := [syntaxNonterminal( nonterminalType(fName, tl.types), nilSyntax(), exportedProds, exportedLayoutTerms, foldr(consNonterminalMod, nilNonterminalMod(), nm.nonterminalModifiers))]; } -synthesized attribute nonterminalModifiers :: [SyntaxNonterminalModifier] occurs on NonterminalModifiers, NonterminalModifierList, NonterminalModifier; - -aspect production nonterminalModifiersNone -top::NonterminalModifiers ::= -{ - top.nonterminalModifiers = []; -} -aspect production nonterminalModifierSome -top::NonterminalModifiers ::= nm::NonterminalModifierList -{ - top.nonterminalModifiers = nm.nonterminalModifiers; -} - -aspect production nonterminalModifierSingle -top::NonterminalModifierList ::= nm::NonterminalModifier -{ - top.nonterminalModifiers = nm.nonterminalModifiers; -} -aspect production nonterminalModifiersCons -top::NonterminalModifierList ::= h::NonterminalModifier ',' t::NonterminalModifierList -{ - top.nonterminalModifiers = h.nonterminalModifiers ++ t.nonterminalModifiers; -} \ No newline at end of file +monoid attribute nonterminalModifiers :: [SyntaxNonterminalModifier] with [], ++; +attribute nonterminalModifiers occurs on NonterminalModifiers, NonterminalModifierList, NonterminalModifier; +propagate nonterminalModifiers on NonterminalModifiers, NonterminalModifierList; diff --git a/grammars/silver/definition/concrete_syntax/ParserSpec.sv b/grammars/silver/definition/concrete_syntax/ParserSpec.sv index 3ac9ff463..613d2eaa9 100644 --- a/grammars/silver/definition/concrete_syntax/ParserSpec.sv +++ b/grammars/silver/definition/concrete_syntax/ParserSpec.sv @@ -23,7 +23,7 @@ synthesized attribute startNT :: String; {-- - Prefixes to inject onto marking terminals in the composed parser. -} -synthesized attribute terminalPrefixes :: [Pair]; +monoid attribute terminalPrefixes :: [Pair] with [], ++; abstract production parserSpec @@ -33,7 +33,7 @@ top::ParserSpec ::= sl::Location sg::String fn::String snt::String grams::[S top.sourceGrammar = sg; top.fullName = fn; top.startNT = snt; - top.moduleNames = grams; + top.moduleNames := grams; -- We've decided we're using only the grammars in this parser to compute dependencies, as opposed -- to all grammars imported in the env. diff --git a/grammars/silver/definition/concrete_syntax/ProductionDcl.sv b/grammars/silver/definition/concrete_syntax/ProductionDcl.sv index 6b651767f..2b7825c43 100644 --- a/grammars/silver/definition/concrete_syntax/ProductionDcl.sv +++ b/grammars/silver/definition/concrete_syntax/ProductionDcl.sv @@ -18,7 +18,7 @@ top::AGDcl ::= 'concrete' 'production' id::Name ns::ProductionSignature pm::Prod top.errors <- ns.concreteSyntaxTypeErrors; -- TODO: we should CHANGE syntaxProduction so it just plain takes a NamedSignature! - top.syntaxAst = [ + top.syntaxAst := [ syntaxProduction(namedSig, foldr(consProductionMod, nilProductionMod(), pm.productionModifiers))]; @@ -29,40 +29,31 @@ nonterminal ProductionModifiers with config, location, unparse, productionModifi nonterminal ProductionModifierList with config, location, unparse, productionModifiers, errors, env, productionName; -- 1 or more closed nonterminal ProductionModifier with config, location, unparse, productionModifiers, errors, env, productionName; -- 1 -synthesized attribute productionModifiers :: [SyntaxProductionModifier]; +monoid attribute productionModifiers :: [SyntaxProductionModifier] with [], ++; + +propagate productionModifiers on ProductionModifiers, ProductionModifierList; +propagate errors on ProductionModifiers, ProductionModifierList, ProductionModifier; concrete production productionModifiersNone top::ProductionModifiers ::= { top.unparse = ""; - - top.productionModifiers = []; - top.errors := []; } concrete production productionModifierSome top::ProductionModifiers ::= pm::ProductionModifierList { top.unparse = pm.unparse; - - top.productionModifiers = pm.productionModifiers; - top.errors := pm.errors; } concrete production productionModifierSingle top::ProductionModifierList ::= pm::ProductionModifier { top.unparse = pm.unparse; - - top.productionModifiers = pm.productionModifiers; - top.errors := pm.errors; } concrete production productionModifiersCons top::ProductionModifierList ::= h::ProductionModifier ',' t::ProductionModifierList { top.unparse = h.unparse ++ ", " ++ t.unparse; - - top.productionModifiers = h.productionModifiers ++ t.productionModifiers; - top.errors := h.errors ++ t.errors; } @@ -71,8 +62,7 @@ top::ProductionModifier ::= 'precedence' '=' i::Int_t { top.unparse = "precedence = " ++ i.lexeme; - top.productionModifiers = [prodPrecedence(toInteger(i.lexeme))]; - top.errors := []; + top.productionModifiers := [prodPrecedence(toInteger(i.lexeme))]; } terminal Operator_kwd /operator/ lexer classes {KEYWORD,RESERVED}; @@ -82,9 +72,9 @@ top::ProductionModifier ::= 'operator' '=' n::QName { top.unparse = "operator = " ++ n.unparse; - top.productionModifiers = [prodOperator(n.lookupType.fullName)]; + top.productionModifiers := [prodOperator(n.lookupType.fullName)]; - top.errors := n.lookupType.errors ++ + top.errors <- n.lookupType.errors ++ if !n.lookupType.typerep.isTerminal then [err(n.location, n.unparse ++ " is not a terminal.")] else []; @@ -93,15 +83,13 @@ top::ProductionModifier ::= 'operator' '=' n::QName -------------------------------------------------------------------------------- -- Type sanity checking on concrete productions -synthesized attribute concreteSyntaxTypeErrors :: [Message] with ++; +monoid attribute concreteSyntaxTypeErrors :: [Message] with [], ++; attribute concreteSyntaxTypeErrors occurs on ProductionSignature, ProductionRHS, ProductionRHSElem; +propagate concreteSyntaxTypeErrors on ProductionSignature, ProductionRHS, ProductionRHSElem; aspect production productionSignature top::ProductionSignature ::= lhs::ProductionLHS '::=' rhs::ProductionRHS { - -- lhs is safe - top.concreteSyntaxTypeErrors := rhs.concreteSyntaxTypeErrors; - local fstType :: Type = head(top.namedSignature.inputElements).typerep; local lstType :: Type = last(top.namedSignature.inputElements).typerep; @@ -131,22 +119,10 @@ top::ProductionSignature ::= lhs::ProductionLHS '::=' rhs::ProductionRHS [err(top.location, "Annotations on this production are not handlable by the parser generator.")]; } -aspect production productionRHSNil -top::ProductionRHS ::= -{ - top.concreteSyntaxTypeErrors := []; -} - -aspect production productionRHSCons -top::ProductionRHS ::= h::ProductionRHSElem t::ProductionRHS -{ - top.concreteSyntaxTypeErrors := h.concreteSyntaxTypeErrors ++ t.concreteSyntaxTypeErrors; -} - aspect production productionRHSElem top::ProductionRHSElem ::= id::Name '::' t::TypeExpr { - top.concreteSyntaxTypeErrors := + top.concreteSyntaxTypeErrors <- if t.typerep.permittedInConcreteSyntax then [] else [err(t.location, t.unparse ++ " is not permitted on concrete productions. Only terminals and nonterminals (without type variables) can appear here")]; } diff --git a/grammars/silver/definition/concrete_syntax/Root.sv b/grammars/silver/definition/concrete_syntax/Root.sv index 3d7281181..03bbdf5ec 100644 --- a/grammars/silver/definition/concrete_syntax/Root.sv +++ b/grammars/silver/definition/concrete_syntax/Root.sv @@ -1,40 +1,19 @@ grammar silver:definition:concrete_syntax; -synthesized attribute syntaxAst :: [SyntaxDcl]; -synthesized attribute parserSpecs :: [ParserSpec]; +monoid attribute syntaxAst :: [SyntaxDcl] with [], ++; +monoid attribute parserSpecs :: [ParserSpec] with [], ++; attribute syntaxAst, parserSpecs occurs on Root, AGDcls, AGDcl; - -aspect production root -top::Root ::= gdcl::GrammarDcl ms::ModuleStmts ims::ImportStmts ags::AGDcls -{ - top.syntaxAst = ags.syntaxAst; - top.parserSpecs = ags.parserSpecs; -} - -aspect production nilAGDcls -top::AGDcls ::= -{ - top.syntaxAst = []; - top.parserSpecs = []; -} -aspect production consAGDcls -top::AGDcls ::= h::AGDcl t::AGDcls -{ - top.syntaxAst = h.syntaxAst ++ t.syntaxAst; - top.parserSpecs = h.parserSpecs ++ t.parserSpecs; -} +propagate syntaxAst, parserSpecs on Root, AGDcls; aspect default production top::AGDcl ::= { - top.syntaxAst = []; - top.parserSpecs = []; + propagate syntaxAst, parserSpecs; } + aspect production appendAGDcl top::AGDcl ::= ag1::AGDcl ag2::AGDcl { - top.syntaxAst = ag1.syntaxAst ++ ag2.syntaxAst; - top.parserSpecs = ag1.parserSpecs ++ ag2.parserSpecs; + propagate syntaxAst, parserSpecs; } - diff --git a/grammars/silver/definition/concrete_syntax/RootSpec.sv b/grammars/silver/definition/concrete_syntax/RootSpec.sv index e321ac2d6..8ef5b68f9 100644 --- a/grammars/silver/definition/concrete_syntax/RootSpec.sv +++ b/grammars/silver/definition/concrete_syntax/RootSpec.sv @@ -3,43 +3,37 @@ grammar silver:definition:concrete_syntax; import silver:driver:util; attribute syntaxAst, parserSpecs occurs on RootSpec, ModuleExportedDefs, Grammar; +propagate syntaxAst, parserSpecs on Grammar; -synthesized attribute maybeSyntaxAst::Maybe<[SyntaxDcl]> occurs on InterfaceItems, InterfaceItem; -synthesized attribute maybeParserSpecs::Maybe<[ParserSpec]> occurs on InterfaceItems, InterfaceItem; +monoid attribute maybeSyntaxAst::Maybe<[SyntaxDcl]> with nothing(), orElse; +monoid attribute maybeParserSpecs::Maybe<[ParserSpec]> with nothing(), orElse; +attribute maybeSyntaxAst, maybeParserSpecs occurs on InterfaceItems, InterfaceItem; +propagate maybeSyntaxAst, maybeParserSpecs on InterfaceItems; aspect production consInterfaceItem top::InterfaceItems ::= h::InterfaceItem t::InterfaceItems { - top.maybeSyntaxAst = orElse(t.maybeSyntaxAst, h.maybeSyntaxAst); - top.maybeParserSpecs = orElse(t.maybeParserSpecs, h.maybeParserSpecs); top.interfaceErrors <- if !top.maybeSyntaxAst.isJust then ["Missing item syntaxAst"] else []; top.interfaceErrors <- if !top.maybeParserSpecs.isJust then ["Missing item parserSpecs"] else []; } -aspect production nilInterfaceItem -top::InterfaceItems ::= -{ - top.maybeSyntaxAst = nothing(); - top.maybeParserSpecs = nothing(); -} - aspect default production top::InterfaceItem ::= { - top.maybeSyntaxAst = nothing(); - top.maybeParserSpecs = nothing(); + top.maybeSyntaxAst := nothing(); + top.maybeParserSpecs := nothing(); } abstract production syntaxAstInterfaceItem top::InterfaceItem ::= val::[SyntaxDcl] { - top.maybeSyntaxAst = just(val); + top.maybeSyntaxAst := just(val); } abstract production parserSpecsInterfaceItem top::InterfaceItem ::= val::[ParserSpec] { - top.maybeParserSpecs = just(val); + top.maybeParserSpecs := just(val); } aspect function unparseRootSpec @@ -52,42 +46,26 @@ String ::= r::Decorated RootSpec aspect production errorRootSpec top::RootSpec ::= _ _ _ _ _ { - top.syntaxAst = []; - top.parserSpecs = []; + propagate syntaxAst, parserSpecs; } aspect production grammarRootSpec top::RootSpec ::= c1::Grammar _ _ _ _ { - top.syntaxAst = c1.syntaxAst; - top.parserSpecs = c1.parserSpecs; + propagate syntaxAst, parserSpecs; } aspect production interfaceRootSpec top::RootSpec ::= i::InterfaceItems interfaceTime::Integer _ { - top.syntaxAst = i.maybeSyntaxAst.fromJust; - top.parserSpecs = i.maybeParserSpecs.fromJust; -} - -aspect production nilGrammar -top::Grammar ::= -{ - top.syntaxAst = []; - top.parserSpecs = []; -} - -aspect production consGrammar -top::Grammar ::= c1::Root c2::Grammar -{ - top.syntaxAst = c1.syntaxAst ++ c2.syntaxAst; - top.parserSpecs = c1.parserSpecs ++ c2.parserSpecs; + top.syntaxAst := i.maybeSyntaxAst.fromJust; + top.parserSpecs := i.maybeParserSpecs.fromJust; } aspect production moduleExportedDefs top::ModuleExportedDefs ::= l::Location compiled::EnvTree grammarDependencies::[String] need::[String] seen::[String] { - top.syntaxAst = if null(need) || null(rs) then [] else (head(rs).syntaxAst ++ recurse.syntaxAst); - top.parserSpecs = if null(need) || null(rs) then [] else (head(rs).parserSpecs ++ recurse.parserSpecs); + top.syntaxAst := if null(need) || null(rs) then [] else (head(rs).syntaxAst ++ recurse.syntaxAst); + top.parserSpecs := if null(need) || null(rs) then [] else (head(rs).parserSpecs ++ recurse.parserSpecs); } diff --git a/grammars/silver/definition/concrete_syntax/TerminalDcl.sv b/grammars/silver/definition/concrete_syntax/TerminalDcl.sv index 7c7011d14..65f546885 100644 --- a/grammars/silver/definition/concrete_syntax/TerminalDcl.sv +++ b/grammars/silver/definition/concrete_syntax/TerminalDcl.sv @@ -20,7 +20,7 @@ top::AGDcl ::= t::TerminalKeywordModifier id::Name r::RegExpr tm::TerminalModifi production attribute fName :: String; fName = top.grammarName ++ ":" ++ id.name; - top.defs = [termDef(top.grammarName, id.location, fName, r.terminalRegExprSpec)]; + top.defs := [termDef(top.grammarName, id.location, fName, r.terminalRegExprSpec)]; top.errors <- if length(getTypeDclAll(fName, top.env)) > 1 @@ -38,9 +38,9 @@ top::AGDcl ::= t::TerminalKeywordModifier id::Name r::RegExpr tm::TerminalModifi then [wrn(r.location, "Regex contains '\\n' but not '\\r'. This is your reminder about '\\r\\n' newlines.")] else []; - top.errors := tm.errors; + propagate errors; - top.syntaxAst = [ + top.syntaxAst := [ syntaxTerminal(fName, r.terminalRegExprSpec, foldr(consTerminalMod, nilTerminalMod(), t.terminalModifiers ++ tm.terminalModifiers))]; } @@ -81,7 +81,7 @@ top::TerminalKeywordModifier ::= 'ignore' { top.unparse = "ignore "; - top.terminalModifiers = [termIgnore()]; + top.terminalModifiers := [termIgnore()]; } concrete production terminalKeywordModifierMarking @@ -89,7 +89,7 @@ top::TerminalKeywordModifier ::= 'marking' { top.unparse = "marking "; - top.terminalModifiers = [termMarking()]; + top.terminalModifiers := [termMarking()]; } concrete production terminalKeywordModifierNone @@ -97,38 +97,31 @@ top::TerminalKeywordModifier ::= { top.unparse = ""; - top.terminalModifiers = []; + top.terminalModifiers := []; } nonterminal TerminalModifiers with config, location, unparse, terminalModifiers, errors, env, grammarName, compiledGrammars, flowEnv; closed nonterminal TerminalModifier with config, location, unparse, terminalModifiers, errors, env, grammarName, compiledGrammars, flowEnv; -synthesized attribute terminalModifiers :: [SyntaxTerminalModifier]; +monoid attribute terminalModifiers :: [SyntaxTerminalModifier] with [], ++; + +propagate terminalModifiers, errors on TerminalModifiers; abstract production terminalModifiersNone top::TerminalModifiers ::= { top.unparse = ""; - - top.terminalModifiers = []; - top.errors := []; } concrete production terminalModifierSingle top::TerminalModifiers ::= tm::TerminalModifier { top.unparse = tm.unparse; - - top.terminalModifiers = tm.terminalModifiers; - top.errors := tm.errors; } concrete production terminalModifiersCons top::TerminalModifiers ::= h::TerminalModifier ',' t::TerminalModifiers { top.unparse = h.unparse ++ ", " ++ t.unparse; - - top.terminalModifiers = h.terminalModifiers ++ t.terminalModifiers; - top.errors := h.errors ++ t.errors; } concrete production terminalModifierLeft @@ -136,7 +129,7 @@ top::TerminalModifier ::= 'association' '=' 'left' { top.unparse = "association = left"; - top.terminalModifiers = [termAssociation("left")]; + top.terminalModifiers := [termAssociation("left")]; top.errors := []; } concrete production terminalModifierRight @@ -144,7 +137,7 @@ top::TerminalModifier ::= 'association' '=' 'right' { top.unparse = "association = right"; - top.terminalModifiers = [termAssociation("right")]; + top.terminalModifiers := [termAssociation("right")]; top.errors := []; } @@ -153,7 +146,7 @@ top::TerminalModifier ::= 'precedence' '=' i::Int_t { top.unparse = "precedence = " ++ i.lexeme; - top.terminalModifiers = [termPrecedence(toInteger(i.lexeme))]; + top.terminalModifiers := [termPrecedence(toInteger(i.lexeme))]; top.errors := []; } @@ -162,6 +155,6 @@ top::TerminalModifier ::= 'named' name::String_t { top.unparse = "named " ++ name.lexeme; - top.terminalModifiers = [termPrettyName(substring(1, length(name.lexeme) - 1, name.lexeme))]; + top.terminalModifiers := [termPrettyName(substring(1, length(name.lexeme) - 1, name.lexeme))]; top.errors := []; } diff --git a/grammars/silver/definition/concrete_syntax/ast/LexerClassModifiers.sv b/grammars/silver/definition/concrete_syntax/ast/LexerClassModifiers.sv index fab1f6ce3..c6a221ee5 100644 --- a/grammars/silver/definition/concrete_syntax/ast/LexerClassModifiers.sv +++ b/grammars/silver/definition/concrete_syntax/ast/LexerClassModifiers.sv @@ -12,16 +12,12 @@ autocopy attribute className :: String; -} nonterminal SyntaxLexerClassModifiers with cstEnv, cstErrors, className, classTerminals, superClasses, subClasses, superClassContribs, disambiguationClasses, dominatesXML, submitsXML, prefixSeperator, containingGrammar; +propagate cstErrors, superClassContribs, disambiguationClasses, dominatesXML, submitsXML, prefixSeperator + on SyntaxLexerClassModifiers; + abstract production consLexerClassMod top::SyntaxLexerClassModifiers ::= h::SyntaxLexerClassModifier t::SyntaxLexerClassModifiers { - top.cstErrors := h.cstErrors ++ t.cstErrors; - top.superClassContribs = h.superClassContribs ++ t.superClassContribs; - top.disambiguationClasses = h.disambiguationClasses ++ t.disambiguationClasses; - top.dominatesXML = h.dominatesXML ++ t.dominatesXML; - top.submitsXML = h.submitsXML ++ t.submitsXML; - top.prefixSeperator = orElse(h.prefixSeperator, t.prefixSeperator); - top.cstErrors <- if h.prefixSeperator.isJust && t.prefixSeperator.isJust then ["Multiple prefix separators for class " ++ top.className] @@ -30,14 +26,7 @@ top::SyntaxLexerClassModifiers ::= h::SyntaxLexerClassModifier t::SyntaxLexerCl abstract production nilLexerClassMod top::SyntaxLexerClassModifiers ::= -{ - top.cstErrors := []; - top.superClassContribs = []; - top.disambiguationClasses = []; - top.dominatesXML = ""; - top.submitsXML = ""; - top.prefixSeperator = nothing(); -} +{} @@ -50,12 +39,8 @@ closed nonterminal SyntaxLexerClassModifier with cstEnv, cstErrors, className, c aspect default production top::SyntaxLexerClassModifier ::= { - --top.cstErrors := []; - top.superClassContribs = []; - top.disambiguationClasses = []; - top.dominatesXML = ""; - top.submitsXML = ""; - top.prefixSeperator = nothing(); + -- Empty values as defaults + propagate cstErrors, superClassContribs, disambiguationClasses, dominatesXML, submitsXML, prefixSeperator; } {-- @@ -72,7 +57,7 @@ top::SyntaxLexerClassModifier ::= super::[String] else ["Lexer Class " ++ a.fst ++ " was referenced but " ++ "this grammar was not included in this parser. (Referenced from extends clause for lexer class)"], zipWith(pair, super, superRefsL)); - top.superClassContribs = map(pair(top.className, _), super); + top.superClassContribs := map(pair(top.className, _), super); } {-- @@ -89,7 +74,7 @@ top::SyntaxLexerClassModifier ::= sub::[String] else ["Terminal / Lexer Class " ++ a.fst ++ " was referenced but " ++ "this grammar was not included in this parser. (Referenced from submit clause for lexer class)"], --TODO: come up with a way to reference a given lexer class (line numbers would be great) zipWith(pair, sub, subRefs)); - top.submitsXML = implode("", map(xmlCopperRef, map(head, subRefs))); + top.submitsXML := implode("", map(xmlCopperRef, map(head, subRefs))); } {-- - The dominates list for the lexer class. Either lexer classes or terminals. @@ -105,7 +90,7 @@ top::SyntaxLexerClassModifier ::= dom::[String] else ["Terminal / Lexer Class " ++ a.fst ++ " was referenced but " ++ "this grammar was not included in this parser. (Referenced from dominates clause for lexer class)"], zipWith(pair, dom, domRefs)); - top.dominatesXML = implode("", map(xmlCopperRef, map(head, domRefs))); + top.dominatesXML := implode("", map(xmlCopperRef, map(head, domRefs))); } {-- @@ -130,8 +115,9 @@ ${acode} syntaxDcl.cstEnv = top.cstEnv; syntaxDcl.containingGrammar = top.containingGrammar; - top.cstErrors := []; -- TODO: Check for duplicate disambiguation for a lexer class - top.disambiguationClasses = [syntaxDcl]; + -- TODO: Check for duplicate disambiguation for a lexer class + + top.disambiguationClasses := [syntaxDcl]; } {-- @@ -141,5 +127,5 @@ abstract production lexerClassPrefixSeperator top::SyntaxLexerClassModifier ::= sep::String { top.cstErrors := []; - top.prefixSeperator = just(sep); + top.prefixSeperator := just(sep); } diff --git a/grammars/silver/definition/concrete_syntax/ast/NonterminalModifiers.sv b/grammars/silver/definition/concrete_syntax/ast/NonterminalModifiers.sv index 03c3d4d67..a509d74e1 100644 --- a/grammars/silver/definition/concrete_syntax/ast/NonterminalModifiers.sv +++ b/grammars/silver/definition/concrete_syntax/ast/NonterminalModifiers.sv @@ -7,19 +7,15 @@ imports silver:definition:core only nonterminalName; -} nonterminal SyntaxNonterminalModifiers with cstEnv, cstErrors, customLayout, nonterminalName; +propagate cstErrors, customLayout on SyntaxNonterminalModifiers; + abstract production consNonterminalMod top::SyntaxNonterminalModifiers ::= h::SyntaxNonterminalModifier t::SyntaxNonterminalModifiers -{ - top.cstErrors := h.cstErrors ++ t.cstErrors; - top.customLayout = orElse(h.customLayout, t.customLayout); -} +{} abstract production nilNonterminalMod top::SyntaxNonterminalModifiers ::= -{ - top.cstErrors := []; - top.customLayout = nothing(); -} +{} {-- @@ -30,8 +26,8 @@ nonterminal SyntaxNonterminalModifier with cstEnv, cstErrors, customLayout, nont aspect default production top::SyntaxNonterminalModifier ::= { - top.cstErrors := []; - top.customLayout = nothing(); + -- Empty values as defaults + propagate cstErrors, customLayout; } {-- @@ -48,5 +44,5 @@ top::SyntaxNonterminalModifier ::= terms::[String] "this grammar was not included in this parser. (Referenced from layout clause on nonterminal " ++ top.nonterminalName ++ ")"], zipWith(pair, terms, termRefs)); - top.customLayout = just(terms); + top.customLayout := just(terms); } diff --git a/grammars/silver/definition/concrete_syntax/ast/ProductionModifiers.sv b/grammars/silver/definition/concrete_syntax/ast/ProductionModifiers.sv index 0147b5210..9ecfdebc2 100644 --- a/grammars/silver/definition/concrete_syntax/ast/ProductionModifiers.sv +++ b/grammars/silver/definition/concrete_syntax/ast/ProductionModifiers.sv @@ -2,35 +2,26 @@ grammar silver:definition:concrete_syntax:ast; imports silver:definition:concrete_syntax only productionName; -synthesized attribute productionPrecedence :: Maybe; +monoid attribute productionPrecedence :: Maybe with nothing(), orElse; -- acode from terminal modifiers -synthesized attribute customLayout :: Maybe<[String]>; -synthesized attribute productionOperator :: Maybe; +monoid attribute customLayout :: Maybe<[String]> with nothing(), orElse; +monoid attribute productionOperator :: Maybe with nothing(), orElse; {-- - Modifiers for productions. -} nonterminal SyntaxProductionModifiers with cstEnv, cstErrors, acode, productionPrecedence, customLayout, productionOperator, productionName; +propagate cstErrors, acode, productionPrecedence, customLayout, productionOperator + on SyntaxProductionModifiers; + abstract production consProductionMod top::SyntaxProductionModifiers ::= h::SyntaxProductionModifier t::SyntaxProductionModifiers -{ - top.cstErrors := h.cstErrors ++ t.cstErrors; - top.acode = h.acode ++ t.acode; - top.customLayout = orElse(h.customLayout, t.customLayout); - top.productionOperator = orElse(h.productionOperator, t.productionOperator); - top.productionPrecedence = orElse(h.productionPrecedence, t.productionPrecedence); -} +{} abstract production nilProductionMod top::SyntaxProductionModifiers ::= -{ - top.cstErrors := []; - top.acode = ""; - top.customLayout = nothing(); - top.productionOperator = nothing(); - top.productionPrecedence = nothing(); -} +{} {-- @@ -41,11 +32,8 @@ nonterminal SyntaxProductionModifier with cstEnv, cstErrors, acode, productionPr aspect default production top::SyntaxProductionModifier ::= { - top.cstErrors := []; - top.acode = ""; - top.customLayout = nothing(); - top.productionOperator = nothing(); - top.productionPrecedence = nothing(); + -- Empty values as defaults + propagate cstErrors, acode, productionPrecedence, customLayout, productionOperator; } {-- @@ -54,7 +42,7 @@ top::SyntaxProductionModifier ::= abstract production prodPrecedence top::SyntaxProductionModifier ::= lvl::Integer { - top.productionPrecedence = just(lvl); + top.productionPrecedence := just(lvl); } {-- - The terminal this production uses for shift/reduce conflict resolution. @@ -68,7 +56,7 @@ top::SyntaxProductionModifier ::= term::String top.cstErrors := if !null(termRef) then [] else ["Terminal " ++ term ++ " was referenced but " ++ "this grammar was not included in this parser. (Referenced from operator clause on production " ++ top.productionName ++ ")"]; - top.productionOperator = just(xmlCopperRef(head(termRef))); + top.productionOperator := just(xmlCopperRef(head(termRef))); } {-- - The action to perform when this production is REDUCEd. @@ -76,7 +64,7 @@ top::SyntaxProductionModifier ::= term::String abstract production prodAction top::SyntaxProductionModifier ::= acode::String { - top.acode = acode; + top.acode := acode; } {-- - The layout for this production. @@ -92,5 +80,5 @@ top::SyntaxProductionModifier ::= terms::[String] "this grammar was not included in this parser. (Referenced from layout clause on production " ++ top.productionName ++ ")"], zipWith(pair, terms, termRefs)); - top.customLayout = just(terms); + top.customLayout := just(terms); } diff --git a/grammars/silver/definition/concrete_syntax/ast/Syntax.sv b/grammars/silver/definition/concrete_syntax/ast/Syntax.sv index 393172040..69f5d37a1 100644 --- a/grammars/silver/definition/concrete_syntax/ast/Syntax.sv +++ b/grammars/silver/definition/concrete_syntax/ast/Syntax.sv @@ -3,39 +3,39 @@ grammar silver:definition:concrete_syntax:ast; imports silver:translation:java:core only makeTerminalName; -- For looking syntax elements up by name. -synthesized attribute cstDcls :: [Pair]; +monoid attribute cstDcls :: [Pair] with [], ++; autocopy attribute cstEnv :: EnvTree; -synthesized attribute cstErrors :: [String] with ++; +monoid attribute cstErrors :: [String] with [], ++; -- Transformation that moves productions underneath their respective nonterminals. -synthesized attribute cstProds :: [Pair]; +monoid attribute cstProds :: [Pair] with [], ++; autocopy attribute cstNTProds :: EnvTree; -synthesized attribute cstNormalize :: [SyntaxDcl]; +monoid attribute cstNormalize :: [SyntaxDcl] with [], ++; -- Compute and allow lookup of all terminals in a lexer class -synthesized attribute classTerminalContribs::[Pair]; +monoid attribute classTerminalContribs::[Pair] with [], ++; autocopy attribute classTerminals::EnvTree; -synthesized attribute superClassContribs::[Pair]; +monoid attribute superClassContribs::[Pair] with [], ++; autocopy attribute superClasses::EnvTree; autocopy attribute subClasses::EnvTree; -- Parser attribute action code aspects -synthesized attribute parserAttributeAspectContribs::[Pair]; +monoid attribute parserAttributeAspectContribs::[Pair] with [], ++; autocopy attribute parserAttributeAspects::EnvTree; -synthesized attribute allTerminals :: [Decorated SyntaxDcl]; -synthesized attribute allIgnoreTerminals :: [Decorated SyntaxDcl]; -synthesized attribute allMarkingTerminals :: [Decorated SyntaxDcl]; -synthesized attribute allProductions :: [Decorated SyntaxDcl]; -synthesized attribute allNonterminals :: [Decorated SyntaxDcl]; -synthesized attribute disambiguationClasses :: [Decorated SyntaxDcl]; +monoid attribute allTerminals :: [Decorated SyntaxDcl] with [], ++; +monoid attribute allIgnoreTerminals :: [Decorated SyntaxDcl] with [], ++; +monoid attribute allMarkingTerminals :: [Decorated SyntaxDcl] with [], ++; +monoid attribute allProductions :: [Decorated SyntaxDcl] with [], ++; +monoid attribute allNonterminals :: [Decorated SyntaxDcl] with [], ++; +monoid attribute disambiguationClasses :: [Decorated SyntaxDcl] with [], ++; synthesized attribute classDomContribs :: String; synthesized attribute classSubContribs :: String; autocopy attribute containingGrammar :: String; -synthesized attribute lexerClassRefDcls :: String; +monoid attribute lexerClassRefDcls :: String with "", ++; synthesized attribute exportedProds :: [String]; synthesized attribute hasCustomLayout :: Boolean; -synthesized attribute layoutContribs :: [Pair]; -- prod/nt name, prod/nt/term name +monoid attribute layoutContribs :: [Pair] with [], ++; -- prod/nt name, prod/nt/term name autocopy attribute layoutTerms::EnvTree; autocopy attribute prefixesForTerminals :: EnvTree; @@ -46,44 +46,18 @@ autocopy attribute prefixesForTerminals :: EnvTree; -} nonterminal Syntax with cstDcls, cstEnv, cstErrors, cstProds, cstNTProds, cstNormalize, allTerminals, allIgnoreTerminals, allMarkingTerminals, allProductions, allNonterminals, disambiguationClasses, classTerminalContribs, classTerminals, superClassContribs, superClasses, subClasses, parserAttributeAspectContribs, parserAttributeAspects, lexerClassRefDcls, layoutContribs, layoutTerms, xmlCopper, containingGrammar, prefixesForTerminals; +propagate cstDcls, cstErrors, cstProds, cstNormalize, allTerminals, allIgnoreTerminals, allMarkingTerminals, allProductions, allNonterminals, disambiguationClasses, classTerminalContribs, superClassContribs, parserAttributeAspectContribs, lexerClassRefDcls, layoutContribs + on Syntax; + abstract production nilSyntax top::Syntax ::= { - top.cstDcls = []; - top.cstErrors := []; - top.cstProds = []; - top.cstNormalize = []; - top.allTerminals = []; - top.allIgnoreTerminals = []; - top.allMarkingTerminals = []; - top.allProductions = []; - top.allNonterminals = []; - top.disambiguationClasses = []; - top.classTerminalContribs = []; - top.superClassContribs = []; - top.parserAttributeAspectContribs = []; - top.lexerClassRefDcls = ""; - top.layoutContribs = []; top.xmlCopper = ""; } + abstract production consSyntax top::Syntax ::= s1::SyntaxDcl s2::Syntax { - top.cstDcls = s1.cstDcls ++ s2.cstDcls; - top.cstErrors := s1.cstErrors ++ s2.cstErrors; - top.cstProds = s1.cstProds ++ s2.cstProds; - top.cstNormalize = s1.cstNormalize ++ s2.cstNormalize; - top.allTerminals = s1.allTerminals ++ s2.allTerminals; - top.allIgnoreTerminals = s1.allIgnoreTerminals ++ s2.allIgnoreTerminals; - top.allMarkingTerminals = s1.allMarkingTerminals ++ s2.allMarkingTerminals; - top.allProductions = s1.allProductions ++ s2.allProductions; - top.allNonterminals = s1.allNonterminals ++ s2.allNonterminals; - top.disambiguationClasses = s1.disambiguationClasses ++ s2.disambiguationClasses; - top.classTerminalContribs = s1.classTerminalContribs ++ s2.classTerminalContribs; - top.superClassContribs = s1.superClassContribs ++ s2.superClassContribs; - top.parserAttributeAspectContribs = s1.parserAttributeAspectContribs ++ s2.parserAttributeAspectContribs; - top.lexerClassRefDcls = s1.lexerClassRefDcls ++ s2.lexerClassRefDcls; - top.layoutContribs = s1.layoutContribs ++ s2.layoutContribs; top.xmlCopper = s1.xmlCopper ++ s2.xmlCopper; } @@ -94,26 +68,17 @@ nonterminal SyntaxDcl with cstDcls, cstEnv, cstErrors, cstProds, cstNTProds, cst synthesized attribute sortKey :: String; +propagate cstErrors, prefixSeperator on SyntaxDcl; + aspect default production top::SyntaxDcl ::= { - top.cstProds = []; - top.allTerminals = []; - top.allIgnoreTerminals = []; - top.allMarkingTerminals = []; - top.allProductions = []; - top.allNonterminals = []; - top.disambiguationClasses = []; - top.classTerminalContribs = []; - top.superClassContribs = []; - top.parserAttributeAspectContribs = []; + -- Empty values as defaults + propagate cstProds, allTerminals, allIgnoreTerminals, allMarkingTerminals, allProductions, allNonterminals, disambiguationClasses, classTerminalContribs, superClassContribs, parserAttributeAspectContribs, lexerClassRefDcls, layoutContribs; top.classDomContribs = error("Internal compiler error: should only ever be demanded of lexer classes"); top.classSubContribs = error("Internal compiler error: should only ever be demanded of lexer classes"); - top.lexerClassRefDcls = ""; top.exportedProds = error("Internal compiler error: should only ever be demanded of nonterminals"); top.hasCustomLayout = false; - top.layoutContribs = []; - top.prefixSeperator = nothing(); } @@ -127,14 +92,13 @@ top::SyntaxDcl ::= t::Type subdcls::Syntax exportedProds::[String] exportedLayou { top.fullName = t.typeName; top.sortKey = "EEE" ++ t.typeName; - top.cstDcls = [pair(t.typeName, top)] ++ subdcls.cstDcls; - top.allNonterminals = [top]; + top.cstDcls := [pair(t.typeName, top)] ++ subdcls.cstDcls; + top.allNonterminals := [top]; - top.cstErrors := if length(searchEnvTree(t.typeName, top.cstEnv)) == 1 then [] + top.cstErrors <- if length(searchEnvTree(t.typeName, top.cstEnv)) == 1 then [] else ["Name conflict with nonterminal " ++ t.typeName]; - top.cstErrors <- subdcls.cstErrors; - top.cstProds = subdcls.cstProds; - top.cstNormalize = + top.cstProds := subdcls.cstProds; + top.cstNormalize := let myProds :: [SyntaxDcl] = searchEnvTree(t.typeName, top.cstNTProds) in if null(myProds) then [] -- Eliminate "Useless nonterminals" as these are expected in Silver code (non-syntax) else [syntaxNonterminal(t, foldr(consSyntax, nilSyntax(), myProds), exportedProds, exportedLayoutTerms, modifiers)] @@ -142,7 +106,7 @@ top::SyntaxDcl ::= t::Type subdcls::Syntax exportedProds::[String] exportedLayou top.exportedProds = exportedProds; top.hasCustomLayout = modifiers.customLayout.isJust; - top.layoutContribs = map(pair(t.typeName, _), fromMaybe(exportedLayoutTerms, modifiers.customLayout)); + top.layoutContribs := map(pair(t.typeName, _), fromMaybe(exportedLayoutTerms, modifiers.customLayout)); top.xmlCopper = "\n \n" ++ @@ -162,18 +126,17 @@ top::SyntaxDcl ::= n::String regex::Regex modifiers::SyntaxTerminalModifiers { top.fullName = n; top.sortKey = "CCC" ++ n; - top.cstDcls = [pair(n, top)]; - top.cstErrors := modifiers.cstErrors; + top.cstDcls := [pair(n, top)]; top.cstErrors <- if length(searchEnvTree(n, top.cstEnv)) == 1 then [] else ["Name conflict with terminal " ++ n]; modifiers.terminalName = n; - top.allTerminals = [top]; - top.allIgnoreTerminals = if modifiers.ignored then [top] else []; - top.allMarkingTerminals = if modifiers.marking then [top] else []; - top.classTerminalContribs = modifiers.classTerminalContribs; + top.allTerminals := [top]; + top.allIgnoreTerminals := if modifiers.ignored then [top] else []; + top.allMarkingTerminals := if modifiers.marking then [top] else []; + top.classTerminalContribs := modifiers.classTerminalContribs; -- left(terminal name) or right(string prefix) production pfx::[String] = searchEnvTree(n, top.prefixesForTerminals); @@ -181,9 +144,7 @@ top::SyntaxDcl ::= n::String regex::Regex modifiers::SyntaxTerminalModifiers if length(pfx) <= 1 then [] else ["Multiple prefixes for terminal " ++ n]; - top.prefixSeperator = modifiers.prefixSeperator; - - top.cstNormalize = + top.cstNormalize := case modifiers.prefixSeperatorToApply of | just(sep) -> [syntaxTerminal(n, regexConcatenate(regex, regexLiteral(sep)), modifiers)] | nothing() -> [top] @@ -235,8 +196,8 @@ top::SyntaxDcl ::= ns::NamedSignature modifiers::SyntaxProductionModifiers { top.fullName = ns.fullName; top.sortKey = "FFF" ++ ns.fullName; - top.cstDcls = [pair(ns.fullName, top)]; - top.allProductions = [top]; + top.cstDcls := [pair(ns.fullName, top)]; + top.allProductions := [top]; modifiers.productionName = ns.fullName; @@ -245,7 +206,6 @@ top::SyntaxDcl ::= ns::NamedSignature modifiers::SyntaxProductionModifiers production rhsRefs :: [[Decorated SyntaxDcl]] = lookupStrings(map((.typeName), map((.typerep), ns.inputElements)), top.cstEnv); - top.cstErrors := modifiers.cstErrors; top.cstErrors <- if length(searchEnvTree(ns.fullName, top.cstEnv)) == 1 then [] else ["Name conflict with production " ++ ns.fullName]; @@ -258,11 +218,11 @@ top::SyntaxDcl ::= ns::NamedSignature modifiers::SyntaxProductionModifiers top.cstErrors <- checkRHS(ns.fullName, map((.typerep), ns.inputElements), rhsRefs); - top.cstProds = [pair(ns.outputElement.typerep.typeName, top)]; - top.cstNormalize = []; + top.cstProds := [pair(ns.outputElement.typerep.typeName, top)]; + top.cstNormalize := []; top.hasCustomLayout = modifiers.customLayout.isJust; - top.layoutContribs = + top.layoutContribs := map(pair(ns.fullName, _), fromMaybe([], modifiers.customLayout)) ++ -- The production inherits its LHS nonterminal's layout, unless overridden. (if top.hasCustomLayout then [] else [pair(ns.fullName, head(lhsRef).fullName)]) ++ @@ -357,8 +317,8 @@ top::SyntaxDcl ::= n::String modifiers::SyntaxLexerClassModifiers { top.fullName = n; top.sortKey = "AAA" ++ n; - top.cstDcls = [pair(n, top)]; - top.cstErrors := modifiers.cstErrors ++ + top.cstDcls := [pair(n, top)]; + top.cstErrors <- if length(searchEnvTree(n, top.cstEnv)) == 1 then [] else ["Name conflict with lexer class " ++ n]; modifiers.className = n; @@ -368,9 +328,9 @@ top::SyntaxDcl ::= n::String modifiers::SyntaxLexerClassModifiers top.classDomContribs = modifiers.dominatesXML; top.classSubContribs = modifiers.submitsXML; - top.cstNormalize = [top]; - top.superClassContribs = modifiers.superClassContribs; - top.disambiguationClasses = modifiers.disambiguationClasses; + top.cstNormalize := [top]; + top.superClassContribs := modifiers.superClassContribs; + top.disambiguationClasses := modifiers.disambiguationClasses; production terms :: [String] = searchEnvTree(n, top.classTerminals); local termsInit::String = @@ -378,13 +338,11 @@ top::SyntaxDcl ::= n::String modifiers::SyntaxLexerClassModifiers \ term::String rest::String -> s"new common.ConsCell(Terminals.${makeCopperName(term)}.num(), ${rest})", "common.ConsCell.nil", terms); - top.lexerClassRefDcls = + top.lexerClassRefDcls := s" protected common.ConsCell ${makeCopperName(n)} = ${termsInit};\n"; top.xmlCopper = " \n"; - - top.prefixSeperator = modifiers.prefixSeperator; } {-- @@ -395,11 +353,11 @@ top::SyntaxDcl ::= n::String ty::Type acode::String { top.fullName = n; top.sortKey = "BBB" ++ n; - top.cstDcls = [pair(n, top)]; - top.cstErrors := if length(searchEnvTree(n, top.cstEnv)) == 1 then [] + top.cstDcls := [pair(n, top)]; + top.cstErrors <- if length(searchEnvTree(n, top.cstEnv)) == 1 then [] else ["Name conflict with parser attribute " ++ n]; - top.cstNormalize = [top]; + top.cstNormalize := [top]; top.xmlCopper = " \n" ++ @@ -423,14 +381,14 @@ top::SyntaxDcl ::= n::String acode::String { top.fullName = n; top.sortKey = "BBB" ++ n; - top.cstDcls = []; - top.cstErrors := + top.cstDcls := []; + top.cstErrors <- if !null(searchEnvTree(n, top.cstEnv)) then [] else ["Parser attribute " ++ n ++ " was referenced but this grammar was not included in this parser."]; - top.cstNormalize = [top]; + top.cstNormalize := [top]; - top.parserAttributeAspectContribs = [pair(n, acode)]; + top.parserAttributeAspectContribs := [pair(n, acode)]; top.xmlCopper = ""; } @@ -443,19 +401,19 @@ top::SyntaxDcl ::= n::String terms::[String] applicableToSubsets::Boolean acode: { top.fullName = n; top.sortKey = "DDD" ++ n; - top.cstDcls = []; + top.cstDcls := []; local trefs::[[Decorated SyntaxDcl]] = lookupStrings(terms, top.cstEnv); -- this 'n' here appears to actually hold the line number of the -- disambiguation, and the grammar. But we arent supposed to know this? - top.cstErrors := flatMap(\p ::Pair -> + top.cstErrors <- flatMap(\p ::Pair -> if !null(p.snd) then [] else ["Terminal " ++ p.fst ++ " was referenced but " ++ "this grammar was not included in this parser. (Referenced from disambiguation group " ++ n ++ ")"], zipWith(pair, terms, trefs)); - top.cstNormalize = [top]; + top.cstNormalize := [top]; top.xmlCopper = " \n" ++ diff --git a/grammars/silver/definition/concrete_syntax/ast/TerminalModifiers.sv b/grammars/silver/definition/concrete_syntax/ast/TerminalModifiers.sv index 4d9666c28..a9df7dbd6 100644 --- a/grammars/silver/definition/concrete_syntax/ast/TerminalModifiers.sv +++ b/grammars/silver/definition/concrete_syntax/ast/TerminalModifiers.sv @@ -1,16 +1,16 @@ grammar silver:definition:concrete_syntax:ast; -synthesized attribute dominatesXML :: String; -synthesized attribute submitsXML :: String; -synthesized attribute lexerclassesXML :: String; -synthesized attribute ignored :: Boolean; -synthesized attribute marking :: Boolean; -synthesized attribute acode :: String; -synthesized attribute opPrecedence :: Maybe; -synthesized attribute opAssociation :: Maybe; -- TODO type? -synthesized attribute prefixSeperator :: Maybe; -synthesized attribute prefixSeperatorToApply :: Maybe; -synthesized attribute prettyName :: Maybe; +monoid attribute dominatesXML :: String with "", ++; +monoid attribute submitsXML :: String with "", ++; +monoid attribute lexerclassesXML :: String with "", ++; +monoid attribute ignored :: Boolean with false, ||; +monoid attribute marking :: Boolean with false, ||; +monoid attribute acode :: String with "", ++; +monoid attribute opPrecedence :: Maybe with nothing(), orElse; +monoid attribute opAssociation :: Maybe with nothing(), orElse; -- TODO type? +monoid attribute prefixSeperator :: Maybe with nothing(), orElse; +monoid attribute prefixSeperatorToApply :: Maybe with nothing(), orElse; +monoid attribute prettyName :: Maybe with nothing(), orElse; autocopy attribute terminalName :: String; {-- @@ -20,23 +20,14 @@ nonterminal SyntaxTerminalModifiers with cstEnv, cstErrors, classTerminalContrib submitsXML, ignored, acode, lexerclassesXML, opPrecedence, opAssociation, prefixSeperator, prefixSeperatorToApply, marking, terminalName, prettyName; +propagate cstErrors, classTerminalContribs, dominatesXML, + submitsXML, ignored, acode, lexerclassesXML, opPrecedence, opAssociation, prefixSeperator, prefixSeperatorToApply, + marking, prettyName + on SyntaxTerminalModifiers; + abstract production consTerminalMod top::SyntaxTerminalModifiers ::= h::SyntaxTerminalModifier t::SyntaxTerminalModifiers -{ - top.cstErrors := h.cstErrors ++ t.cstErrors; - top.classTerminalContribs = h.classTerminalContribs ++ t.classTerminalContribs; - top.dominatesXML = h.dominatesXML ++ t.dominatesXML; - top.submitsXML = h.submitsXML ++ t.submitsXML; - top.lexerclassesXML = h.lexerclassesXML ++ t.lexerclassesXML; - top.ignored = h.ignored || t.ignored; - top.marking = h.marking || t.marking; - top.acode = h.acode ++ t.acode; - top.opPrecedence = orElse(h.opPrecedence, t.opPrecedence); - top.opAssociation = orElse(h.opAssociation, t.opAssociation); - top.prefixSeperator = orElse(h.prefixSeperator, t.prefixSeperator); - top.prefixSeperatorToApply = orElse(h.prefixSeperatorToApply, t.prefixSeperatorToApply); - top.prettyName = orElse(h.prettyName, t.prettyName); - +{ top.cstErrors <- if h.prefixSeperator.isJust && t.prefixSeperator.isJust then ["Multiple prefix separators for terminal " ++ top.terminalName] @@ -45,21 +36,7 @@ top::SyntaxTerminalModifiers ::= h::SyntaxTerminalModifier t::SyntaxTerminalMod abstract production nilTerminalMod top::SyntaxTerminalModifiers ::= -{ - top.cstErrors := []; - top.classTerminalContribs = []; - top.dominatesXML = ""; - top.submitsXML = ""; - top.lexerclassesXML = ""; - top.ignored = false; - top.marking = false; - top.acode = ""; - top.opPrecedence = nothing(); - top.opAssociation = nothing(); - top.prefixSeperator = nothing(); - top.prefixSeperatorToApply = nothing(); - top.prettyName = nothing(); -} +{} @@ -74,19 +51,10 @@ closed nonterminal SyntaxTerminalModifier with cstEnv, cstErrors, classTerminalC aspect default production top::SyntaxTerminalModifier ::= { - top.cstErrors := []; - top.classTerminalContribs = []; - top.dominatesXML = ""; - top.submitsXML = ""; - top.lexerclassesXML = ""; - top.ignored = false; - top.marking = false; - top.acode = ""; - top.opPrecedence = nothing(); - top.opAssociation = nothing(); - top.prefixSeperator = nothing(); - top.prefixSeperatorToApply = nothing(); - top.prettyName = nothing(); + -- Empty values as defaults + propagate cstErrors, classTerminalContribs, dominatesXML, + submitsXML, ignored, acode, lexerclassesXML, opPrecedence, opAssociation, prefixSeperator, prefixSeperatorToApply, + marking, prettyName; } {-- @@ -96,7 +64,7 @@ top::SyntaxTerminalModifier ::= abstract production termIgnore top::SyntaxTerminalModifier ::= { - top.ignored = true; + top.ignored := true; } {-- - If present, this is a Marking terminal. In the default translation, @@ -105,7 +73,7 @@ top::SyntaxTerminalModifier ::= abstract production termMarking top::SyntaxTerminalModifier ::= { - top.marking = true; + top.marking := true; } {-- - The terminal's precedence. (Resolves shift/reduce conflicts) @@ -113,7 +81,7 @@ top::SyntaxTerminalModifier ::= abstract production termPrecedence top::SyntaxTerminalModifier ::= lvl::Integer { - top.opPrecedence = just(lvl); + top.opPrecedence := just(lvl); } {-- - The terminal's association. Either left, right, or nonassoc. TODO: a type? @@ -121,7 +89,7 @@ top::SyntaxTerminalModifier ::= lvl::Integer abstract production termAssociation top::SyntaxTerminalModifier ::= direction::String { - top.opAssociation = just(direction); + top.opAssociation := just(direction); } {-- - The terminal's "pretty name". Used for error messages. @@ -129,7 +97,7 @@ top::SyntaxTerminalModifier ::= direction::String abstract production termPrettyName top::SyntaxTerminalModifier ::= prettyName::String { - top.prettyName = just(prettyName); + top.prettyName := just(prettyName); } {-- - The terminal's lexer classes. @@ -147,14 +115,14 @@ top::SyntaxTerminalModifier ::= cls::[String] else ["Lexer Class " ++ a.fst ++ " was referenced but " ++ "this grammar was not included in this parser. (Referenced from lexer class on terminal " ++ top.terminalName ++ ")"], zipWith(pair, allCls, allClsRefsL)); - top.classTerminalContribs = map(pair(_, top.terminalName), allCls); + top.classTerminalContribs := map(pair(_, top.terminalName), allCls); -- We "translate away" lexer classes dom/sub, by moving that info to the terminals (here) - top.dominatesXML = implode("", map((.classDomContribs), allClsRefs)); - top.submitsXML = implode("", map((.classSubContribs), allClsRefs)); - top.lexerclassesXML = implode("", map(xmlCopperRef, allClsRefs)); + top.dominatesXML := implode("", map((.classDomContribs), allClsRefs)); + top.submitsXML := implode("", map((.classSubContribs), allClsRefs)); + top.lexerclassesXML := implode("", map(xmlCopperRef, allClsRefs)); local termSeps :: [Maybe] = map((.prefixSeperator), allClsRefs); - top.prefixSeperator = foldr(orElse, nothing(), termSeps); + top.prefixSeperator := foldr(orElse, nothing(), termSeps); top.cstErrors <- if length(catMaybes(termSeps)) > 1 then ["Multiple prefix separators for terminal " ++ top.terminalName] @@ -174,7 +142,7 @@ top::SyntaxTerminalModifier ::= sub::[String] else ["Terminal / Lexer Class " ++ a.fst ++ " was referenced but " ++ "this grammar was not included in this parser. (Referenced from submit clause on terminal " ++ top.terminalName ++ ")"], zipWith(pair, sub, subRefs)); - top.submitsXML = implode("", map(xmlCopperRef, map(head, subRefs))); + top.submitsXML := implode("", map(xmlCopperRef, map(head, subRefs))); } {-- - The dominates list for the terminal. Either lexer classes or terminals. @@ -190,7 +158,7 @@ top::SyntaxTerminalModifier ::= dom::[String] else ["Terminal / Lexer Class " ++ a.fst ++ " was referenced but " ++ "this grammar was not included in this parser. (Referenced from dominates clause on terminal " ++ top.terminalName ++ ")"], zipWith(pair, dom, domRefs)); - top.dominatesXML = implode("", map(xmlCopperRef, map(head, domRefs))); + top.dominatesXML := implode("", map(xmlCopperRef, map(head, domRefs))); } {-- - The action to take whenever this terminal is SHIFTed. @@ -198,7 +166,7 @@ top::SyntaxTerminalModifier ::= dom::[String] abstract production termAction top::SyntaxTerminalModifier ::= acode::String { - top.acode = acode; + top.acode := acode; } {-- - The prefix separator to use for the terminal. @@ -207,7 +175,7 @@ top::SyntaxTerminalModifier ::= acode::String abstract production termPrefixSeperator top::SyntaxTerminalModifier ::= sep::String { - top.prefixSeperator = just(sep); + top.prefixSeperator := just(sep); } {-- - The terminals prefixed by this terminal, for which to use their separator. @@ -215,9 +183,14 @@ top::SyntaxTerminalModifier ::= sep::String abstract production termUsePrefixSeperatorFor top::SyntaxTerminalModifier ::= terms::[String] { - production termRefs :: [Decorated SyntaxDcl] = map(head, lookupStrings(terms, top.cstEnv)); - top.cstErrors := []; - top.prefixSeperatorToApply = head(termRefs).prefixSeperator; + production termRefs :: [[Decorated SyntaxDcl]] = lookupStrings(terms, top.cstEnv); + top.prefixSeperatorToApply := head(head(termRefs)).prefixSeperator; + + top.cstErrors := flatMap(\ a::Pair -> + if !null(a.snd) then [] + else ["Terminal " ++ a.fst ++ " was referenced but " ++ + "this grammar was not included in this parser. (Referenced from use prefix seperator for clause for terminal)"], + zipWith(pair, terms, termRefs)); top.cstErrors <- flatMap( @@ -225,7 +198,7 @@ top::SyntaxTerminalModifier ::= terms::[String] if !s.prefixSeperator.isJust then ["Terminal " ++ s.fullName ++ " does not define a prefix separator, and must use an explicit terminal to define a prefix."] else [], - termRefs); + map(head, termRefs)); local distinctSepTermRefs :: [Decorated SyntaxDcl] = nubBy( @@ -234,7 +207,7 @@ top::SyntaxTerminalModifier ::= terms::[String] | just(ps1), just(ps2) -> ps1 == ps2 | _, _ -> false end, - termRefs); + map(head, termRefs)); top.cstErrors <- if length(distinctSepTermRefs) > 1 then ["Terminals " ++ implode(", ", map((.fullName), distinctSepTermRefs)) ++ diff --git a/grammars/silver/definition/core/AGDcl.sv b/grammars/silver/definition/core/AGDcl.sv index 8d5eb3807..119195b3d 100644 --- a/grammars/silver/definition/core/AGDcl.sv +++ b/grammars/silver/definition/core/AGDcl.sv @@ -8,16 +8,13 @@ nonterminal AGDcl with config, grammarName, env, location, unparse, errors, def flowtype forward {grammarName, env} on AGDcls, AGDcl; +propagate errors, moduleNames, jarName on AGDcls, AGDcl; +propagate defs, occursDefs on AGDcls; + concrete production nilAGDcls top::AGDcls ::= { top.unparse = ""; - - top.defs = []; - top.occursDefs = []; - top.errors := []; - top.moduleNames = []; - top.jarName = nothing(); } concrete production consAGDcls @@ -25,11 +22,7 @@ top::AGDcls ::= h::AGDcl t::AGDcls { top.unparse = h.unparse ++ "\n" ++ t.unparse; - top.defs = h.defs ++ t.defs; - top.occursDefs = h.occursDefs ++ t.occursDefs; - top.errors := h.errors ++ t.errors ++ warnIfMultJarName(h.jarName, t.jarName, top.location); - top.moduleNames = h.moduleNames ++ t.moduleNames; - top.jarName = orElse(h.jarName, t.jarName); + top.errors <- warnIfMultJarName(h.jarName, t.jarName, top.location); } -------- @@ -43,23 +36,20 @@ abstract production emptyAGDcl top::AGDcl ::= { top.unparse = ""; - - top.errors := []; } abstract production errorAGDcl top::AGDcl ::= e::[Message] { top.unparse = s"{- Errors:\n${messagesToString(e)} -}"; - top.errors := e; + top.errors <- e; } abstract production defsAGDcl top::AGDcl ::= d::[Def] { top.unparse = s"{- Defs:\n${hackUnparse(d)} -}"; - top.errors := []; - top.defs = d; + top.defs := d; } {-- @@ -69,34 +59,22 @@ abstract production appendAGDcl top::AGDcl ::= h::AGDcl t::AGDcl { top.unparse = h.unparse ++ "\n" ++ t.unparse; + propagate defs, occursDefs; - top.defs = h.defs ++ t.defs; - top.occursDefs = h.occursDefs ++ t.occursDefs; - top.errors := h.errors ++ t.errors ++ warnIfMultJarName(h.jarName, t.jarName, top.location); - top.moduleNames = h.moduleNames ++ t.moduleNames; - top.jarName = orElse(h.jarName, t.jarName); + top.errors <- warnIfMultJarName(h.jarName, t.jarName, top.location); } abstract production jarNameDcl top::AGDcl ::= n::Name { top.unparse = "jarName " ++ n.unparse; - top.errors := []; - top.moduleNames = []; - top.defs = []; - top.occursDefs = []; - top.jarName = just(n.name); + top.jarName <- just(n.name); } aspect default production top::AGDcl ::= { - -- can't provide unparse or location! - top.moduleNames = []; - top.defs = []; - top.occursDefs = []; - top.jarName = nothing(); - --top.errors := []; -- should never be omitted, really. + propagate moduleNames, defs, occursDefs, jarName; } function warnIfMultJarName diff --git a/grammars/silver/definition/core/Annotation.sv b/grammars/silver/definition/core/Annotation.sv index 68880ae1a..1a45b4545 100644 --- a/grammars/silver/definition/core/Annotation.sv +++ b/grammars/silver/definition/core/Annotation.sv @@ -9,7 +9,7 @@ top::AGDcl ::= 'annotation' a::QName tl::BracketedOptTypeExprs '::' te::TypeExpr production fName :: String = top.grammarName ++ ":" ++ a.name; - top.defs = [annoDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep)]; + top.defs := [annoDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep)]; tl.initialEnv = top.env; tl.env = tl.envBindingTyVars; @@ -23,7 +23,7 @@ top::AGDcl ::= 'annotation' a::QName tl::BracketedOptTypeExprs '::' te::TypeExpr if indexOf(":", a.name) == -1 then [] else [err(a.location, "The name '" ++ a.name ++ "' must not be qualified.")]; - top.errors := te.errors ++ tl.errors ++ tl.errorsTyVars; + top.errors <- tl.errorsTyVars; } diff --git a/grammars/silver/definition/core/AspectDcl.sv b/grammars/silver/definition/core/AspectDcl.sv index bbf1c3791..6d2d15106 100644 --- a/grammars/silver/definition/core/AspectDcl.sv +++ b/grammars/silver/definition/core/AspectDcl.sv @@ -17,13 +17,14 @@ flowtype forward {deterministicCount, realSignature, env} on AspectRHSElem; -} autocopy attribute realSignature :: [NamedSignatureElement]; +propagate errors on AspectProductionSignature, AspectProductionLHS, AspectFunctionSignature, AspectFunctionLHS, AspectRHS, AspectRHSElem; concrete production aspectProductionDcl top::AGDcl ::= 'aspect' 'production' id::QName ns::AspectProductionSignature body::ProductionBody { top.unparse = "aspect production " ++ id.unparse ++ "\n" ++ ns.unparse ++ "\n" ++ body.unparse; - top.defs = + top.defs := if null(body.productionAttributes) then [] else [prodOccursDef(top.grammarName, id.location, namedSig, body.productionAttributes)]; @@ -36,7 +37,7 @@ top::AGDcl ::= 'aspect' 'production' id::QName ns::AspectProductionSignature bod -- Making sure we're aspecting a production is taken care of by type checking. - top.errors := id.lookupValue.errors ++ ns.errors ++ body.errors; + top.errors <- id.lookupValue.errors; production attribute sigDefs :: [Def] with ++; sigDefs := ns.defs; @@ -59,7 +60,7 @@ top::AGDcl ::= 'aspect' 'function' id::QName ns::AspectFunctionSignature body::P { top.unparse = "aspect function " ++ id.unparse ++ "\n" ++ ns.unparse ++ "\n" ++ body.unparse; - top.defs = + top.defs := if null(body.productionAttributes) then [] else [prodOccursDef(top.grammarName, id.location, namedSig, body.productionAttributes)]; @@ -72,7 +73,7 @@ top::AGDcl ::= 'aspect' 'function' id::QName ns::AspectFunctionSignature body::P -- Making sure we're aspecting a function is taken care of by type checking. - top.errors := id.lookupValue.errors ++ ns.errors ++ body.errors; + top.errors <- id.lookupValue.errors; production attribute sigDefs :: [Def] with ++; sigDefs := ns.defs; @@ -95,8 +96,7 @@ top::AspectProductionSignature ::= lhs::AspectProductionLHS '::=' rhs::AspectRHS { top.unparse = lhs.unparse ++ " ::= " ++ rhs.unparse; - top.defs = lhs.defs ++ rhs.defs; - top.errors := lhs.errors ++ rhs.errors; + propagate defs; top.namedSignature = namedSignature(top.signatureName, rhs.inputElements, lhs.outputElement, annotationsForNonterminal(lhs.outputElement.typerep, top.env)); @@ -144,9 +144,9 @@ top::AspectProductionLHS ::= id::Name t::Type top.outputElement = namedSignatureElement(id.name, t); - top.defs = [aliasedLhsDef(top.grammarName, id.location, fName, t, id.name)]; + top.defs := [aliasedLhsDef(top.grammarName, id.location, fName, t, id.name)]; - top.errors := if length(getValueDclInScope(id.name, top.env)) > 1 + top.errors <- if length(getValueDclInScope(id.name, top.env)) > 1 then [err(id.location, "Value '" ++ fName ++ "' is already bound.")] else []; } @@ -156,8 +156,7 @@ top::AspectRHS ::= { top.unparse = ""; - top.defs = []; - top.errors := []; + propagate defs; top.inputElements = []; } @@ -166,8 +165,7 @@ top::AspectRHS ::= h::AspectRHSElem t::AspectRHS { top.unparse = h.unparse ++ " " ++ t.unparse; - top.defs = h.defs ++ t.defs; - top.errors := h.errors ++ t.errors; + propagate defs; top.inputElements = h.inputElements ++ t.inputElements; @@ -225,9 +223,9 @@ top::AspectRHSElem ::= id::Name t::Type top.inputElements = [namedSignatureElement(id.name, t)]; - top.defs = [aliasedChildDef(top.grammarName, id.location, fName, t, id.name)]; + top.defs := [aliasedChildDef(top.grammarName, id.location, fName, t, id.name)]; - top.errors := if length(getValueDclInScope(id.name, top.env)) > 1 + top.errors <- if length(getValueDclInScope(id.name, top.env)) > 1 then [err(id.location, "Value '" ++ id.name ++ "' is already bound.")] else []; } @@ -237,8 +235,7 @@ top::AspectFunctionSignature ::= lhs::AspectFunctionLHS '::=' rhs::AspectRHS { top.unparse = lhs.unparse ++ " ::= " ++ rhs.unparse; - top.defs = lhs.defs ++ rhs.defs; - top.errors := lhs.errors ++ rhs.errors; + propagate defs; -- For the moment, functions do not have named parameters (hence, []) top.namedSignature = namedSignature(top.signatureName, rhs.inputElements, lhs.outputElement, []); @@ -260,8 +257,5 @@ top::AspectFunctionLHS ::= t::TypeExpr top.outputElement = namedSignatureElement(fName, t.typerep); -- TODO: this needs thinking. is it broken? maybe __return? or wait, it's doing that automatically isnt it... - top.defs = [aliasedLhsDef(top.grammarName, t.location, fName, t.typerep, fName)]; - - top.errors := []; + top.defs := [aliasedLhsDef(top.grammarName, t.location, fName, t.typerep, fName)]; } - diff --git a/grammars/silver/definition/core/AttributeDcl.sv b/grammars/silver/definition/core/AttributeDcl.sv index d1a6d09ca..19bcf1346 100644 --- a/grammars/silver/definition/core/AttributeDcl.sv +++ b/grammars/silver/definition/core/AttributeDcl.sv @@ -8,7 +8,7 @@ top::AGDcl ::= 'inherited' 'attribute' a::Name tl::BracketedOptTypeExprs '::' te production attribute fName :: String; fName = top.grammarName ++ ":" ++ a.name; - top.defs = [inhDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep)]; + top.defs := [inhDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep)]; tl.initialEnv = top.env; tl.env = tl.envBindingTyVars; @@ -19,7 +19,7 @@ top::AGDcl ::= 'inherited' 'attribute' a::Name tl::BracketedOptTypeExprs '::' te then [err(a.location, "Attribute '" ++ fName ++ "' is already bound.")] else []; - top.errors := te.errors ++ tl.errors ++ tl.errorsTyVars; + top.errors <- tl.errorsTyVars; } concrete production attributeDclSyn @@ -30,7 +30,7 @@ top::AGDcl ::= 'synthesized' 'attribute' a::Name tl::BracketedOptTypeExprs '::' production attribute fName :: String; fName = top.grammarName ++ ":" ++ a.name; - top.defs = [synDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep)]; + top.defs := [synDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep)]; tl.initialEnv = top.env; tl.env = tl.envBindingTyVars; @@ -41,6 +41,6 @@ top::AGDcl ::= 'synthesized' 'attribute' a::Name tl::BracketedOptTypeExprs '::' then [err(a.location, "Attribute '" ++ fName ++ "' is already bound.")] else []; - top.errors := te.errors ++ tl.errors ++ tl.errorsTyVars; + top.errors <- tl.errorsTyVars; } diff --git a/grammars/silver/definition/core/Attributes.sv b/grammars/silver/definition/core/Attributes.sv index df52b1761..906c7931c 100644 --- a/grammars/silver/definition/core/Attributes.sv +++ b/grammars/silver/definition/core/Attributes.sv @@ -8,5 +8,5 @@ autocopy attribute grammarName :: String; {-- - The name to use for the generated .jar if not overridden by -o command-line option. -} -synthesized attribute jarName :: Maybe; +monoid attribute jarName :: Maybe with nothing(), orElse; diff --git a/grammars/silver/definition/core/BuiltInFunctions.sv b/grammars/silver/definition/core/BuiltInFunctions.sv index 6ba3d29e9..73244864e 100644 --- a/grammars/silver/definition/core/BuiltInFunctions.sv +++ b/grammars/silver/definition/core/BuiltInFunctions.sv @@ -20,8 +20,8 @@ top::Expr ::= e::Decorated Expr local resolved :: Type = performSubstitution(e.typerep, top.finalSubst); - top.errors := - e.errors ++ + top.errors <- e.errors; + top.errors <- if resolved.isError then [] -- suppress additional error message else [err(e.location, "Operand to length is not compatible. It is of type " ++ prettyType(resolved))]; } @@ -33,7 +33,7 @@ top::Expr ::= e::Decorated Expr top.typerep = intType(); - top.errors := e.errors; + top.errors <- e.errors; } concrete production toIntegerFunction @@ -41,7 +41,6 @@ top::Expr ::= 'toInteger' '(' e::Expr ')' { top.unparse = "toInteger(" ++ e.unparse ++ ")"; - top.errors := e.errors; top.typerep = intType(); } @@ -50,7 +49,6 @@ top::Expr ::= 'toBoolean' '(' e::Expr ')' { top.unparse = "toBoolean(" ++ e.unparse ++ ")"; - top.errors := e.errors; top.typerep = boolType(); } @@ -59,7 +57,6 @@ top::Expr ::= 'toFloat' '(' e::Expr ')' { top.unparse = "toFloat(" ++ e.unparse ++ ")"; - top.errors := e.errors; top.typerep = floatType(); } @@ -68,7 +65,6 @@ top::Expr ::= 'toString' '(' e::Expr ')' { top.unparse = "toString(" ++ e.unparse ++ ")"; - top.errors := e.errors; top.typerep = stringType(); } @@ -77,7 +73,6 @@ top::Expr ::= 'reify' { top.unparse = "reify"; - top.errors := []; top.typerep = functionType(nonterminalType("core:Either", [stringType(), varType(freshTyVar())]), [nonterminalType("core:reflect:AST", [])], []); } @@ -87,7 +82,6 @@ top::Expr ::= 'new' '(' e::Expr ')' { top.unparse = "new(" ++ e.unparse ++ ")"; - top.errors := e.errors; top.typerep = performSubstitution(e.typerep, top.upSubst).decoratedType; } @@ -101,7 +95,6 @@ top::Expr ::= 'terminal' '(' t::TypeExpr ',' es::Expr ',' el::Expr ')' { top.unparse = "terminal(" ++ t.unparse ++ ", " ++ es.unparse ++ ", " ++ el.unparse ++ ")"; - top.errors := t.errors ++ es.errors ++ el.errors; top.typerep = t.typerep; } diff --git a/grammars/silver/definition/core/Expr.sv b/grammars/silver/definition/core/Expr.sv index 94c66f10c..5d8805879 100644 --- a/grammars/silver/definition/core/Expr.sv +++ b/grammars/silver/definition/core/Expr.sv @@ -14,6 +14,8 @@ nonterminal ExprInh with nonterminal ExprLHSExpr with config, grammarName, env, location, unparse, errors, name, typerep, decoratingnt, suppliedInhs; +propagate errors on Expr, Exprs, ExprInhs, ExprInh, ExprLHSExpr; + {-- - The nonterminal being decorated. (Used for 'decorate with {}') -} @@ -25,18 +27,18 @@ synthesized attribute suppliedInhs :: [String]; {-- - A list of decorated expressions from an Exprs. -} -synthesized attribute exprs :: [Decorated Expr]; +monoid attribute exprs :: [Decorated Expr] with [], ++; {-- - Get each individual Expr, without decorating them. -} -synthesized attribute rawExprs :: [Expr]; +monoid attribute rawExprs :: [Expr] with [], ++; abstract production errorExpr top::Expr ::= e::[Message] { top.unparse = s"{- Errors:\n${messagesToString(e)} -}"; - top.errors := e; + top.errors <- e; top.typerep = errorType(); } @@ -63,7 +65,7 @@ top::Expr ::= msg::[Message] q::Decorated QName { top.unparse = q.unparse; - top.errors := msg; + top.errors <- msg; top.typerep = errorType(); } @@ -73,7 +75,6 @@ top::Expr ::= q::Decorated QName { top.unparse = q.unparse; - top.errors := []; top.typerep = if q.lookupValue.typerep.isDecorable then ntOrDecType(q.lookupValue.typerep, freshType()) else q.lookupValue.typerep; @@ -84,7 +85,6 @@ top::Expr ::= q::Decorated QName { top.unparse = q.unparse; - top.errors := []; -- An LHS is *always* a decorable (nonterminal) type. top.typerep = ntOrDecType(q.lookupValue.typerep, freshType()); } @@ -94,7 +94,6 @@ top::Expr ::= q::Decorated QName { top.unparse = q.unparse; - top.errors := []; top.typerep = if q.lookupValue.typerep.isDecorable then ntOrDecType(q.lookupValue.typerep, freshType()) else q.lookupValue.typerep; @@ -105,7 +104,6 @@ top::Expr ::= q::Decorated QName { top.unparse = q.unparse; - top.errors := []; -- An LHS (and thus, forward) is *always* a decorable (nonterminal) type. top.typerep = ntOrDecType(q.lookupValue.typerep, freshType()); } @@ -118,8 +116,6 @@ top::Expr ::= q::Decorated QName { top.unparse = q.unparse; - top.errors := []; - -- TODO: the freshening should probably be the responsibility of the thing in the environment, not here? top.typerep = freshenCompletely(q.lookupValue.typerep); } @@ -129,8 +125,6 @@ top::Expr ::= q::Decorated QName { top.unparse = q.unparse; - top.errors := []; - top.typerep = freshenCompletely(q.lookupValue.typerep); -- TODO see above } @@ -139,8 +133,6 @@ top::Expr ::= q::Decorated QName { top.unparse = q.unparse; - top.errors := []; - top.typerep = freshenCompletely(q.lookupValue.typerep); -- TODO see above } @@ -186,11 +178,11 @@ top::Expr ::= e::Decorated Expr es::AppExprs anns::AnnoAppExprs { top.unparse = e.unparse ++ "(" ++ es.unparse ++ "," ++ anns.unparse ++ ")"; - top.errors := e.errors ++ - (if e.typerep.isError then [] else - [err(top.location, e.unparse ++ " has type " ++ prettyType(performSubstitution(e.typerep, e.upSubst)) ++ - " and cannot be invoked as a function.")]) ++ - es.errors ++ anns.errors; + top.errors <- e.errors; + top.errors <- + if e.typerep.isError then [] else + [err(top.location, e.unparse ++ " has type " ++ prettyType(performSubstitution(e.typerep, e.upSubst)) ++ + " and cannot be invoked as a function.")]; -- TODO This error message is cumbersomely generated... top.typerep = errorType(); @@ -234,7 +226,7 @@ top::Expr ::= e::Decorated Expr es::Decorated AppExprs anns::Decorated AnnoAppEx { top.unparse = e.unparse ++ "(" ++ es.unparse ++ "," ++ anns.unparse ++ ")"; - top.errors := e.errors ++ es.errors ++ anns.errors; + top.errors <- e.errors ++ es.errors ++ anns.errors; local ety :: Type = performSubstitution(e.typerep, e.upSubst); @@ -246,7 +238,7 @@ top::Expr ::= e::Decorated Expr es::Decorated AppExprs anns::Decorated AnnoAppEx { top.unparse = e.unparse ++ "(" ++ es.unparse ++ "," ++ anns.unparse ++ ")"; - top.errors := e.errors ++ es.errors ++ anns.errors; + top.errors <- e.errors ++ es.errors ++ anns.errors; local ety :: Type = performSubstitution(e.typerep, e.upSubst); @@ -265,7 +257,7 @@ top::Expr ::= '(' '.' q::QName ')' local rawInputType :: Type = freshType(); top.typerep = functionType(freshenCompletely(q.lookupAttribute.typerep), [rawInputType], []); - top.errors := q.lookupAttribute.errors; + top.errors <- q.lookupAttribute.errors; top.errors <- if null(q.lookupAttribute.dclBoundVars) then [] else [err(q.location, "Attribute " ++ q.name ++ " is parameterized, and attribute sections currently do not work with parameterized attributes, yet.")]; -- TODO The type inference system is too weak, currently. @@ -292,7 +284,6 @@ concrete production forwardAccess top::Expr ::= e::Expr '.' 'forward' { top.unparse = e.unparse ++ ".forward"; - top.errors := e.errors; top.typerep = e.typerep; } @@ -323,9 +314,9 @@ top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur top.unparse = e.unparse ++ "." ++ q.unparse; top.typerep = errorType(); - top.errors := accessError ++ q.errors; + top.errors <- q.errors; - local accessError :: [Message] = + top.errors <- if e.typerep.isError then [] else let ref :: String = if length(e.unparse) < 12 then "'" ++ e.unparse ++ "' has" else "LHS of '.' is" @@ -343,7 +334,7 @@ top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur top.typerep = q.typerep; - top.errors := q.errors; + top.errors <- q.errors; } abstract production terminalAccessHandler @@ -353,7 +344,7 @@ top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur -- NO use of q.errors, as that become nonsensical here. - top.errors := + top.errors <- if q.name == "lexeme" || q.name == "location" || q.name == "filename" || q.name == "line" || q.name == "column" then [] @@ -434,7 +425,6 @@ top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur top.unparse = e.unparse ++ "." ++ q.unparse; top.typerep = q.typerep; - top.errors := []; -- already included? } abstract production inhDecoratedAccessHandler @@ -443,7 +433,6 @@ top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur top.unparse = e.unparse ++ "." ++ q.unparse; top.typerep = q.typerep; - top.errors := []; -- already included? } -- TODO: change name. really "unknownDclAccessHandler" @@ -452,8 +441,6 @@ top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur { top.unparse = e.unparse ++ "." ++ q.unparse; - top.errors := []; -- empty because we only ever get here if lookup failed. see above. - top.typerep = errorType(); } @@ -472,7 +459,6 @@ top::Expr ::= 'decorate' e::Expr 'with' '{' inh::ExprInhs '}' top.unparse = "decorate " ++ e.unparse ++ " with {" ++ inh.unparse ++ "}"; top.typerep = decoratedType(performSubstitution(e.typerep, e.upSubst)); -- .decoratedForm? - top.errors := e.errors ++ inh.errors; inh.decoratingnt = performSubstitution(e.typerep, e.upSubst); } @@ -482,7 +468,6 @@ top::ExprInhs ::= { top.unparse = ""; - top.errors := []; top.suppliedInhs = []; } @@ -491,7 +476,6 @@ top::ExprInhs ::= lhs::ExprInh { top.unparse = lhs.unparse; - top.errors := lhs.errors; top.suppliedInhs = lhs.suppliedInhs; } @@ -500,7 +484,6 @@ top::ExprInhs ::= lhs::ExprInh inh::ExprInhs { top.unparse = lhs.unparse ++ " " ++ inh.unparse; - top.errors := lhs.errors ++ inh.errors; top.suppliedInhs = lhs.suppliedInhs ++ inh.suppliedInhs; } @@ -509,7 +492,6 @@ top::ExprInh ::= lhs::ExprLHSExpr '=' e::Expr ';' { top.unparse = lhs.unparse ++ " = " ++ e.unparse ++ ";"; - top.errors := lhs.errors ++ e.errors; top.suppliedInhs = lhs.suppliedInhs; } @@ -519,7 +501,6 @@ top::ExprLHSExpr ::= q::QNameAttrOccur top.name = q.name; top.unparse = q.unparse; - top.errors := q.errors; top.typerep = q.typerep; top.suppliedInhs = [q.dcl.attrOccurring]; @@ -531,7 +512,6 @@ top::Expr ::= 'true' { top.unparse = "true"; - top.errors := []; top.typerep = boolType(); } @@ -540,7 +520,6 @@ top::Expr ::= 'false' { top.unparse = "false"; - top.errors := []; top.typerep = boolType(); } @@ -549,7 +528,6 @@ top::Expr ::= e1::Expr '&&' e2::Expr { top.unparse = e1.unparse ++ " && " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors; top.typerep = boolType(); } @@ -558,7 +536,6 @@ top::Expr ::= e1::Expr '||' e2::Expr { top.unparse = e1.unparse ++ " || " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors; top.typerep = boolType(); } @@ -568,7 +545,6 @@ top::Expr ::= '!' e::Expr top.unparse = "! " ++ e.unparse; top.typerep = boolType(); - top.errors := e.errors; } concrete production gt @@ -576,7 +552,6 @@ top::Expr ::= e1::Expr '>' e2::Expr { top.unparse = e1.unparse ++ " > " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors; top.typerep = boolType(); } @@ -585,7 +560,6 @@ top::Expr ::= e1::Expr '<' e2::Expr { top.unparse = e1.unparse ++ " < " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors; top.typerep = boolType(); } @@ -594,7 +568,6 @@ top::Expr ::= e1::Expr '>=' e2::Expr { top.unparse = e1.unparse ++ " >= " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors; top.typerep = boolType(); } @@ -603,7 +576,6 @@ top::Expr ::= e1::Expr '<=' e2::Expr { top.unparse = e1.unparse ++ " <= " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors; top.typerep = boolType(); } @@ -612,7 +584,6 @@ top::Expr ::= e1::Expr '==' e2::Expr { top.unparse = e1.unparse ++ " == " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors; top.typerep = boolType(); } @@ -621,7 +592,6 @@ top::Expr ::= e1::Expr '!=' e2::Expr { top.unparse = e1.unparse ++ " != " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors; top.typerep = boolType(); } @@ -631,7 +601,6 @@ precedence = 0 { top.unparse = "if " ++ e1.unparse ++ " then " ++ e2.unparse ++ " else " ++ e3.unparse; - top.errors := e1.errors ++ e2.errors ++ e3.errors; top.typerep = e2.typerep; } @@ -640,7 +609,6 @@ top::Expr ::= i::Int_t { top.unparse = i.lexeme; - top.errors := []; top.typerep = intType(); } @@ -649,7 +617,6 @@ top::Expr ::= f::Float_t { top.unparse = f.lexeme; - top.errors := []; top.typerep = floatType(); } @@ -658,7 +625,6 @@ top::Expr ::= e1::Expr '+' e2::Expr { top.unparse = e1.unparse ++ " + " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors; top.typerep = e1.typerep; } @@ -667,7 +633,6 @@ top::Expr ::= e1::Expr '-' e2::Expr { top.unparse = e1.unparse ++ " - " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors; top.typerep = e1.typerep; } @@ -676,7 +641,6 @@ top::Expr ::= e1::Expr '*' e2::Expr { top.unparse = e1.unparse ++ " * " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors; top.typerep = e1.typerep; } @@ -685,7 +649,6 @@ top::Expr ::= e1::Expr '/' e2::Expr { top.unparse = e1.unparse ++ " / " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors; top.typerep = e1.typerep; } @@ -694,7 +657,6 @@ top::Expr ::= e1::Expr '%' e2::Expr { top.unparse = e1.unparse ++ " % " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors; top.typerep = e1.typerep; } @@ -704,7 +666,6 @@ precedence = 13 { top.unparse = "- " ++ e.unparse; - top.errors := e.errors; top.typerep = e.typerep; } @@ -713,7 +674,6 @@ top::Expr ::= s::String_t { top.unparse = s.lexeme; - top.errors := []; top.typerep = stringType(); } @@ -722,7 +682,8 @@ top::Expr ::= e1::Expr '++' e2::Expr { top.unparse = e1.unparse ++ " ++ " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors ++ forward.errors; + propagate errors; + top.errors <- forward.errors; top.typerep = if errCheck1.typeerror then errorType() else result_type; local result_type :: Type = performSubstitution(e1.typerep, errCheck1.upSubst); @@ -750,7 +711,6 @@ top::Expr ::= e1::Decorated Expr e2::Decorated Expr { top.unparse = e1.unparse ++ " ++ " ++ e2.unparse; - top.errors := []; top.typerep = stringType(); } @@ -761,7 +721,7 @@ top::Expr ::= e1::Decorated Expr e2::Decorated Expr local result_type :: Type = performSubstitution(e1.typerep, top.downSubst); - top.errors := + top.errors <- if result_type.isError then [] else [err(e1.location, prettyType(result_type) ++ " is not a concatenable type.")]; top.typerep = errorType(); @@ -775,27 +735,24 @@ top::Exprs ::= { top.unparse = ""; - top.errors := []; - top.exprs = []; - top.rawExprs = []; + top.exprs := []; + top.rawExprs := []; } concrete production exprsSingle top::Exprs ::= e::Expr { top.unparse = e.unparse; - top.errors := e.errors; - top.exprs = [e]; - top.rawExprs = [e]; + top.exprs := [e]; + top.rawExprs := [e]; } concrete production exprsCons top::Exprs ::= e1::Expr ',' e2::Exprs { top.unparse = e1.unparse ++ ", " ++ e2.unparse; - top.errors := e1.errors ++ e2.errors; - top.exprs = [e1] ++ e2.exprs; - top.rawExprs = [e1] ++ e2.rawExprs; + top.exprs := [e1] ++ e2.exprs; + top.rawExprs := [e1] ++ e2.rawExprs; } @@ -811,6 +768,9 @@ nonterminal AppExpr with config, grammarName, env, location, unparse, errors, frame, compiledGrammars, exprs, rawExprs, isPartial, missingTypereps, appExprIndicies, appExprIndex, appExprTyperep, appExprApplied; +propagate errors on AppExprs, AppExpr; +propagate exprs, rawExprs on AppExprs; + synthesized attribute isPartial :: Boolean; synthesized attribute missingTypereps :: [Type]; synthesized attribute appExprIndicies :: [Integer]; @@ -829,11 +789,9 @@ top::AppExpr ::= '_' top.isPartial = true; top.missingTypereps = [top.appExprTyperep]; - top.rawExprs = []; - top.exprs = []; + top.rawExprs := []; + top.exprs := []; top.appExprIndicies = []; - - top.errors := []; } concrete production presentAppExpr top::AppExpr ::= e::Expr @@ -843,11 +801,9 @@ top::AppExpr ::= e::Expr top.isPartial = false; top.missingTypereps = []; - top.rawExprs = [e]; - top.exprs = [e]; + top.rawExprs := [e]; + top.exprs := [e]; top.appExprIndicies = [top.appExprIndex]; - - top.errors := e.errors; } concrete production snocAppExprs @@ -858,11 +814,8 @@ top::AppExprs ::= es::AppExprs ',' e::AppExpr top.isPartial = es.isPartial || e.isPartial; top.missingTypereps = es.missingTypereps ++ e.missingTypereps; - top.rawExprs = es.rawExprs ++ e.rawExprs; - top.exprs = es.exprs ++ e.exprs; top.appExprIndicies = es.appExprIndicies ++ e.appExprIndicies; - top.errors := es.errors ++ e.errors; top.appExprSize = es.appExprSize + 1; e.appExprIndex = es.appExprSize; @@ -880,16 +833,13 @@ top::AppExprs ::= e::AppExpr top.isPartial = e.isPartial; top.missingTypereps = e.missingTypereps; - top.rawExprs = e.rawExprs; - top.exprs = e.exprs; top.appExprIndicies = e.appExprIndicies; - top.errors := if null(top.appExprTypereps) + top.errors <- if null(top.appExprTypereps) then [err(top.location, "Too many arguments provided to function '" ++ top.appExprApplied ++ "'")] else if length(top.appExprTypereps) > 1 then [err(top.location, "Too few arguments provided to function '" ++ top.appExprApplied ++ "'")] else []; - top.errors <- e.errors; top.appExprSize = 1; e.appExprIndex = 0; @@ -905,14 +855,12 @@ top::AppExprs ::= top.isPartial = false; top.missingTypereps = []; - top.rawExprs = []; - top.exprs = []; top.appExprIndicies = []; top.appExprSize = 0; -- Assumption: We only get here when we're looking at () -- i.e. we can't ever have 'too many' provided error - top.errors := if null(top.appExprTypereps) then [] + top.errors <- if null(top.appExprTypereps) then [] else [err(top.location, "Too few arguments provided to function '" ++ top.appExprApplied ++ "'")]; } @@ -927,6 +875,8 @@ nonterminal AnnoExpr with isPartial, appExprApplied, exprs, remainingFuncAnnotations, funcAnnotations, missingAnnotations, partialAnnoTypereps, annoIndexConverted, annoIndexSupplied; + +propagate errors, exprs on AnnoAppExprs, AnnoExpr; {-- - Annotations that have not yet been supplied @@ -964,12 +914,10 @@ top::AnnoExpr ::= qn::QName '=' e::AppExpr top.missingAnnotations = fq.snd; -- minus qn, if it was there top.partialAnnoTypereps = e.missingTypereps; - top.errors := - (if fq.fst.isJust then [] - else [err(qn.location, "Named parameter '" ++ qn.name ++ "' is not appropriate for '" ++ top.appExprApplied ++ "'")]) ++ - e.errors; + top.errors <- + if fq.fst.isJust then [] + else [err(qn.location, "Named parameter '" ++ qn.name ++ "' is not appropriate for '" ++ top.appExprApplied ++ "'")]; top.isPartial = e.isPartial; - top.exprs = e.exprs; top.annoIndexConverted = if e.isPartial then [e.appExprIndex] else []; top.annoIndexSupplied = @@ -982,7 +930,6 @@ top::AnnoAppExprs ::= es::AnnoAppExprs ',' e::AnnoExpr top.unparse = es.unparse ++ ", " ++ e.unparse; top.isPartial = es.isPartial || e.isPartial; - top.errors := es.errors ++ e.errors; e.remainingFuncAnnotations = top.remainingFuncAnnotations; es.remainingFuncAnnotations = e.missingAnnotations; @@ -991,7 +938,6 @@ top::AnnoAppExprs ::= es::AnnoAppExprs ',' e::AnnoExpr top.partialAnnoTypereps = es.partialAnnoTypereps ++ e.partialAnnoTypereps; top.annoIndexConverted = es.annoIndexConverted ++ e.annoIndexConverted; top.annoIndexSupplied = es.annoIndexSupplied ++ e.annoIndexSupplied; - top.exprs = es.exprs ++ e.exprs; } concrete production oneAnnoAppExprs @@ -1000,7 +946,7 @@ top::AnnoAppExprs ::= e::AnnoExpr top.unparse = e.unparse; top.isPartial = e.isPartial; - top.errors := + top.errors <- if null(top.missingAnnotations) then [] else [err(top.location, "Missing named parameters for function '" ++ top.appExprApplied ++ "': " ++ implode(", ", map((.argName), top.missingAnnotations)))]; @@ -1013,7 +959,6 @@ top::AnnoAppExprs ::= e::AnnoExpr top.partialAnnoTypereps = e.partialAnnoTypereps; top.annoIndexConverted = e.annoIndexConverted; top.annoIndexSupplied = e.annoIndexSupplied; - top.exprs = e.exprs; } abstract production emptyAnnoAppExprs @@ -1022,7 +967,7 @@ top::AnnoAppExprs ::= top.unparse = ""; top.isPartial = false; - top.errors := + top.errors <- if null(top.missingAnnotations) then [] else [err(top.location, "Missing named parameters for function '" ++ top.appExprApplied ++ "': " ++ implode(", ", map((.argName), top.missingAnnotations)))]; @@ -1032,7 +977,6 @@ top::AnnoAppExprs ::= top.partialAnnoTypereps = []; top.annoIndexConverted = []; top.annoIndexSupplied = []; - top.exprs = []; } function reorderedAnnoAppExprs @@ -1126,7 +1070,6 @@ top::Expr ::= e::Decorated Expr top.unparse = e.unparse; -- See the major restriction. This should have been checked for error already! - top.errors := []; top.typerep = e.typerep; -- TODO: one of the little things we might want is to make this transparent to diff --git a/grammars/silver/definition/core/FunctionDcl.sv b/grammars/silver/definition/core/FunctionDcl.sv index cb10bf856..e628adc87 100644 --- a/grammars/silver/definition/core/FunctionDcl.sv +++ b/grammars/silver/definition/core/FunctionDcl.sv @@ -3,6 +3,8 @@ grammar silver:definition:core; nonterminal FunctionSignature with config, grammarName, env, location, unparse, errors, defs, namedSignature, signatureName; nonterminal FunctionLHS with config, grammarName, env, location, unparse, errors, defs, outputElement; +propagate errors on FunctionSignature, FunctionLHS; + concrete production functionDcl top::AGDcl ::= 'function' id::Name ns::FunctionSignature body::ProductionBody { @@ -11,7 +13,7 @@ top::AGDcl ::= 'function' id::Name ns::FunctionSignature body::ProductionBody production fName :: String = top.grammarName ++ ":" ++ id.name; production namedSig :: NamedSignature = ns.namedSignature; - top.defs = funDef(top.grammarName, id.location, namedSig) :: + top.defs := funDef(top.grammarName, id.location, namedSig) :: if null(body.productionAttributes) then [] else [prodOccursDef(top.grammarName, id.location, namedSig, body.productionAttributes)]; @@ -27,8 +29,6 @@ top::AGDcl ::= 'function' id::Name ns::FunctionSignature body::ProductionBody then [err(top.location, "Function '" ++ id.name ++ "' has more than one declared return value.")] else []; - top.errors := ns.errors ++ body.errors; - production attribute sigDefs :: [Def] with ++; sigDefs := ns.defs; @@ -47,8 +47,7 @@ top::FunctionSignature ::= lhs::FunctionLHS '::=' rhs::ProductionRHS { top.unparse = lhs.unparse ++ " ::= " ++ rhs.unparse; - top.defs = lhs.defs ++ rhs.defs; - top.errors := lhs.errors ++ rhs.errors; + propagate defs; -- For the moment, functions do not have named parameters (hence, []) top.namedSignature = namedSignature(top.signatureName, rhs.inputElements, lhs.outputElement, []); @@ -65,8 +64,6 @@ top::FunctionLHS ::= t::TypeExpr top.outputElement = namedSignatureElement(fName, t.typerep); -- TODO: think about this. lhs doesn't really have an fName. - top.defs = [lhsDef(top.grammarName, t.location, fName, t.typerep)]; - - top.errors := t.errors; + top.defs := [lhsDef(top.grammarName, t.location, fName, t.typerep)]; } diff --git a/grammars/silver/definition/core/GlobalDcl.sv b/grammars/silver/definition/core/GlobalDcl.sv index eb6767ef3..fc1758b64 100644 --- a/grammars/silver/definition/core/GlobalDcl.sv +++ b/grammars/silver/definition/core/GlobalDcl.sv @@ -6,12 +6,11 @@ concrete production globalValueDclConcrete top::AGDcl ::= 'global' id::Name '::' t::TypeExpr '=' e::Expr ';' { top.unparse = "global " ++ id.unparse ++ " :: " ++ t.unparse ++ " = " ++ e.unparse ++ "\n"; - top.errors := t.errors ++ e.errors; production attribute fName :: String; fName = top.grammarName ++ ":" ++ id.name; - top.defs = [globalDef(top.grammarName, id.location, fName, t.typerep)]; + top.defs := [globalDef(top.grammarName, id.location, fName, t.typerep)]; top.errors <- if length(getValueDclAll(fName, top.env)) > 1 diff --git a/grammars/silver/definition/core/GrammarParts.sv b/grammars/silver/definition/core/GrammarParts.sv index 48ea3cd41..970010231 100644 --- a/grammars/silver/definition/core/GrammarParts.sv +++ b/grammars/silver/definition/core/GrammarParts.sv @@ -25,51 +25,34 @@ autocopy attribute globalImports :: Decorated Env; - The definitions resulting from grammar-wide imports definitions. - At the top of a grammar, these are echoed down as globalImports -} -synthesized attribute importedDefs :: [Def]; -synthesized attribute importedOccursDefs :: [DclInfo]; +monoid attribute importedDefs :: [Def] with [], ++; +monoid attribute importedOccursDefs :: [DclInfo] with [], ++; {-- - An overall listing of error messages for a grammar -} synthesized attribute grammarErrors :: [Pair]; +propagate + moduleNames, exportedGrammars, optionalGrammars, condBuild, defs, + occursDefs, importedDefs, importedOccursDefs, jarName + on Grammar; + abstract production nilGrammar top::Grammar ::= { -- A value here is actually used. Grammars without any .sv files -- turn into this, and this "aren't found". TODO verify this is true? top.declaredName = ":null"; - top.moduleNames = []; - top.exportedGrammars = []; - top.optionalGrammars = []; - top.condBuild = []; - - top.importedDefs = []; - top.importedOccursDefs = []; - top.defs = []; - top.occursDefs = []; top.grammarErrors = []; - - top.jarName = nothing(); } abstract production consGrammar top::Grammar ::= h::Root t::Grammar { top.declaredName = if h.declaredName == t.declaredName then h.declaredName else top.grammarName; - top.moduleNames = h.moduleNames ++ t.moduleNames; - top.exportedGrammars = h.exportedGrammars ++ t.exportedGrammars; - top.optionalGrammars = h.optionalGrammars ++ t.optionalGrammars; - top.condBuild = h.condBuild ++ t.condBuild; - - top.defs = h.defs ++ t.defs; - top.occursDefs = h.occursDefs ++ t.occursDefs; - top.importedDefs = h.importedDefs ++ t.importedDefs; - top.importedOccursDefs = h.importedOccursDefs ++ t.importedOccursDefs; top.grammarErrors = if null(h.errors ++ jarNameErrors) then t.grammarErrors else pair(h.location.filename, h.errors ++ jarNameErrors) :: t.grammarErrors; local jarNameErrors :: [Message] = warnIfMultJarName(h.jarName, t.jarName, h.location); - - top.jarName = orElse(h.jarName, t.jarName); } diff --git a/grammars/silver/definition/core/ModuleStmts.sv b/grammars/silver/definition/core/ModuleStmts.sv index 51cc39e7a..1a802d6a5 100644 --- a/grammars/silver/definition/core/ModuleStmts.sv +++ b/grammars/silver/definition/core/ModuleStmts.sv @@ -16,6 +16,9 @@ nonterminal NameList with config, grammarName, location, unparse, names; nonterminal WithElems with config, grammarName, location, unparse, envMaps; nonterminal WithElem with config, grammarName, location, unparse, envMaps; +propagate errors, moduleNames, defs, occursDefs on ModuleStmts, ModuleStmt, ImportStmt, ImportStmts; +propagate exportedGrammars, optionalGrammars, condBuild on ModuleStmts; + {-- - A list of QName strings. Used for 'only' and 'hiding'. -} @@ -60,8 +63,8 @@ top::Module ::= l::Location if asPrepend == "" then defs_after_renames else map(mapDefOnEnvItem(envItemPrepend(_, asPrepend ++ ":"), _), defs_after_renames); - top.defs = defs_after_prepend; - top.occursDefs = med.occursDefs; + top.defs := defs_after_prepend; + top.occursDefs := med.occursDefs; top.errors := med.errors; } @@ -97,10 +100,10 @@ top::ModuleExportedDefs ::= l::Location compiledGrammars::EnvTree 1 @@ -163,8 +134,8 @@ top::ProductionStmt ::= 'production' 'attribute' a::Name '::' te::TypeExpr ';' -- TODO: we should unparse the production keyword, not local here!! --top.unparse = "\tproduction attribute " ++ a.unparse ++ "::" ++ te.unparse ++ ";"; - top.productionAttributes = forward.defs; - top.defs = []; + top.productionAttributes := forward.defs; + top.defs := []; top.errors <- if !top.frame.permitProductionAttributes then [err(top.location, "Production attributes are not valid in this context.")] @@ -178,10 +149,8 @@ top::ProductionStmt ::= 'forwards' 'to' e::Expr ';' { top.unparse = "\tforwards to " ++ e.unparse; - top.productionAttributes = [forwardDef(top.grammarName, top.location, top.frame.signature.outputElement.typerep)]; - top.uniqueSignificantExpression = [e]; - - top.errors := e.errors; + top.productionAttributes := [forwardDef(top.grammarName, top.location, top.frame.signature.outputElement.typerep)]; + top.uniqueSignificantExpression := [e]; top.errors <- if !top.frame.permitForward then [err(top.location, "Forwarding is not permitted in this context. (Only permitted in non-aspect productions.)")] @@ -206,8 +175,6 @@ top::ProductionStmt ::= 'forwarding' 'with' '{' inh::ForwardInhs '}' ';' production attribute fwdDcls :: [DclInfo]; fwdDcls = getValueDcl("forward", top.env); - - top.errors := inh.errors; top.errors <- if null(fwdDcls) then [err(top.location, "'forwarding with' clause for a production that does not forward!")] @@ -219,22 +186,18 @@ concrete production forwardInh top::ForwardInh ::= lhs::ForwardLHSExpr '=' e::Expr ';' { top.unparse = lhs.unparse ++ " = " ++ e.unparse ++ ";"; - - top.errors := lhs.errors ++ e.errors; } concrete production forwardInhsOne top::ForwardInhs ::= lhs::ForwardInh { top.unparse = lhs.unparse; - top.errors := lhs.errors; } concrete production forwardInhsCons top::ForwardInhs ::= lhs::ForwardInh rhs::ForwardInhs { top.unparse = lhs.unparse ++ " " ++ rhs.unparse; - top.errors := lhs.errors ++ rhs.errors; } concrete production forwardLhsExpr @@ -243,7 +206,6 @@ top::ForwardLHSExpr ::= q::QNameAttrOccur top.name = q.name; top.unparse = q.unparse; - top.errors := q.errors; top.typerep = q.typerep; q.attrFor = top.frame.signature.outputElement.typerep; @@ -255,8 +217,8 @@ top::ProductionStmt ::= dl::DefLHS '.' attr::QNameAttrOccur '=' e::Expr ';' top.unparse = "\t" ++ dl.unparse ++ "." ++ attr.unparse ++ " = " ++ e.unparse ++ ";"; -- defs must stay here explicitly, because we dispatch on types in the forward here! - top.productionAttributes = []; - top.defs = []; + top.productionAttributes := []; + top.defs := []; dl.defLHSattr = attr; attr.attrFor = dl.typerep; @@ -290,16 +252,12 @@ abstract production synthesizedAttributeDef top::ProductionStmt ::= dl::Decorated DefLHS attr::Decorated QNameAttrOccur e::Expr { top.unparse = "\t" ++ dl.unparse ++ "." ++ attr.unparse ++ " = " ++ e.unparse ++ ";"; - - top.errors := e.errors; } abstract production inheritedAttributeDef top::ProductionStmt ::= dl::Decorated DefLHS attr::Decorated QNameAttrOccur e::Expr { top.unparse = "\t" ++ dl.unparse ++ "." ++ attr.unparse ++ " = " ++ e.unparse ++ ";"; - - top.errors := e.errors; } concrete production concreteDefLHS @@ -322,7 +280,7 @@ top::DefLHS ::= q::Decorated QName top.unparse = q.unparse; top.found = false; - top.errors := + top.errors <- if top.typerep.isError then [] else [err(q.location, "Cannot define attributes on " ++ q.name)]; top.typerep = q.lookupValue.typerep; } @@ -342,7 +300,7 @@ top::DefLHS ::= q::Decorated QName local existingProblems :: Boolean = !top.defLHSattr.found || top.typerep.isError; - top.errors := + top.errors <- if existingProblems || top.found then [] else [err(q.location, "Cannot define synthesized attribute '" ++ top.defLHSattr.name ++ "' on child '" ++ q.name ++ "'")]; @@ -358,7 +316,7 @@ top::DefLHS ::= q::Decorated QName local existingProblems :: Boolean = !top.defLHSattr.found || top.typerep.isError; - top.errors := + top.errors <- if existingProblems || top.found then [] else [err(q.location, "Cannot define inherited attribute '" ++ top.defLHSattr.name ++ "' on the lhs '" ++ q.name ++ "'")]; @@ -374,7 +332,7 @@ top::DefLHS ::= q::Decorated QName local existingProblems :: Boolean = !top.defLHSattr.found || top.typerep.isError; - top.errors := + top.errors <- if existingProblems || top.found then [] else [err(q.location, "Cannot define synthesized attribute '" ++ top.defLHSattr.name ++ "' on local '" ++ q.name ++ "'")]; @@ -390,7 +348,7 @@ top::DefLHS ::= q::Decorated QName local existingProblems :: Boolean = !top.defLHSattr.found || top.typerep.isError; - top.errors := + top.errors <- if existingProblems || top.found then [] else [err(q.location, "Cannot define synthesized attribute '" ++ top.defLHSattr.name ++ "' on forward")]; @@ -407,8 +365,8 @@ top::ProductionStmt ::= val::QName '=' e::Expr ';' top.errors <- val.lookupValue.errors; -- defs must stay here explicitly, because we dispatch on types in the forward here! - top.productionAttributes = []; - top.defs = []; + top.productionAttributes := []; + top.defs := []; forwards to if null(val.lookupValue.dcls) then errorValueDef(val, e, location=top.location) @@ -419,13 +377,10 @@ abstract production errorValueDef top::ProductionStmt ::= val::Decorated QName e::Expr { top.unparse = "\t" ++ val.unparse ++ " = " ++ e.unparse ++ ";"; - - top.errors := assignError ++ e.errors; - local assignError :: [Message] = + top.errors <- if val.lookupValue.typerep.isError then [] else [err(val.location, val.name ++ " cannot be assigned to.")]; - } abstract production localValueDef @@ -434,7 +389,6 @@ top::ProductionStmt ::= val::Decorated QName e::Expr top.unparse = "\t" ++ val.unparse ++ " = " ++ e.unparse ++ ";"; -- val is already valid here - top.errors := e.errors; -- TODO: missing redefinition check } diff --git a/grammars/silver/definition/core/ProductionDcl.sv b/grammars/silver/definition/core/ProductionDcl.sv index 7a6def1a6..93110ee7f 100644 --- a/grammars/silver/definition/core/ProductionDcl.sv +++ b/grammars/silver/definition/core/ProductionDcl.sv @@ -8,6 +8,9 @@ nonterminal ProductionRHSElem with config, grammarName, env, location, unparse, flowtype forward {env} on ProductionSignature, ProductionLHS, ProductionRHS; flowtype forward {deterministicCount, env} on ProductionRHSElem; +propagate errors on ProductionSignature, ProductionLHS, ProductionRHS, ProductionRHSElem; +propagate defs on ProductionSignature, ProductionRHS; + {-- - Used to help give names to children, when names are omitted. -} @@ -26,7 +29,7 @@ top::AGDcl ::= 'abstract' 'production' id::Name ns::ProductionSignature body::Pr production fName :: String = top.grammarName ++ ":" ++ id.name; production namedSig :: NamedSignature = ns.namedSignature; - top.defs = prodDef(top.grammarName, id.location, namedSig, length(body.uniqueSignificantExpression) > 0) :: + top.defs := prodDef(top.grammarName, id.location, namedSig, length(body.uniqueSignificantExpression) > 0) :: if null(body.productionAttributes) then [] else [prodOccursDef(top.grammarName, id.location, namedSig, body.productionAttributes)]; @@ -48,8 +51,6 @@ top::AGDcl ::= 'abstract' 'production' id::Name ns::ProductionSignature body::Pr if isLower(substring(0,1,id.name)) then [] else [wrn(id.location, s"(future) ${id.name}: productions may be required to begin with a lower-case letter.")]; - top.errors := ns.errors ++ body.errors; - production attribute sigDefs :: [Def] with ++; sigDefs := ns.defs; @@ -68,9 +69,6 @@ top::ProductionSignature ::= lhs::ProductionLHS '::=' rhs::ProductionRHS { top.unparse = lhs.unparse ++ " ::= " ++ rhs.unparse; - top.defs = lhs.defs ++ rhs.defs; - top.errors := lhs.errors ++ rhs.errors; - top.namedSignature = namedSignature(top.signatureName, rhs.inputElements, lhs.outputElement, annotationsForNonterminal(lhs.outputElement.typerep, top.env)); } @@ -81,14 +79,12 @@ top::ProductionLHS ::= id::Name '::' t::TypeExpr top.outputElement = namedSignatureElement(id.name, t.typerep); - top.defs = [lhsDef(top.grammarName, t.location, id.name, t.typerep)]; + top.defs := [lhsDef(top.grammarName, t.location, id.name, t.typerep)]; top.errors <- if length(getValueDclInScope(id.name, top.env)) > 1 then [err(id.location, "Value '" ++ id.name ++ "' is already bound.")] - else []; - - top.errors := t.errors; + else []; } concrete production productionRHSNil @@ -96,9 +92,6 @@ top::ProductionRHS ::= { top.unparse = ""; - top.defs = []; - top.errors := []; - top.inputElements = []; } @@ -107,9 +100,6 @@ top::ProductionRHS ::= h::ProductionRHSElem t::ProductionRHS { top.unparse = h.unparse ++ " " ++ t.unparse; - top.defs = h.defs ++ t.defs; - top.errors := h.errors ++ t.errors; - top.inputElements = h.inputElements ++ t.inputElements; h.deterministicCount = length(t.inputElements); } @@ -121,14 +111,12 @@ top::ProductionRHSElem ::= id::Name '::' t::TypeExpr top.inputElements = [namedSignatureElement(id.name, t.typerep)]; - top.defs = [childDef(top.grammarName, t.location, id.name, t.typerep)]; + top.defs := [childDef(top.grammarName, t.location, id.name, t.typerep)]; top.errors <- if length(getValueDclInScope(id.name, top.env)) > 1 then [err(id.location, "Value '" ++ id.name ++ "' is already bound.")] - else []; - - top.errors := t.errors; + else []; } concrete production productionRHSElemType diff --git a/grammars/silver/definition/core/Root.sv b/grammars/silver/definition/core/Root.sv index 18fbcce10..f79eb51d6 100644 --- a/grammars/silver/definition/core/Root.sv +++ b/grammars/silver/definition/core/Root.sv @@ -16,6 +16,9 @@ nonterminal Root with nonterminal GrammarDcl with declaredName, grammarName, location, unparse, errors; +propagate errors on Root, GrammarDcl; +propagate moduleNames on Root; + concrete production root top::Root ::= gdcl::GrammarDcl ms::ModuleStmts ims::ImportStmts ags::AGDcls { @@ -27,19 +30,15 @@ top::Root ::= gdcl::GrammarDcl ms::ModuleStmts ims::ImportStmts ags::AGDcls top.unparse = gdcl.unparse ++ "\n\n" ++ ms.unparse ++ "\n\n" ++ ims.unparse ++ "\n\n" ++ ags.unparse; top.declaredName = gdcl.declaredName; - top.moduleNames = ims.moduleNames ++ ms.moduleNames ++ ags.moduleNames; - - top.defs = ags.defs; - top.occursDefs = ags.occursDefs; - - top.importedDefs = ms.defs; - top.importedOccursDefs = ms.occursDefs; - top.exportedGrammars = ms.exportedGrammars; - top.optionalGrammars = ms.optionalGrammars; - top.condBuild = ms.condBuild; - top.jarName = ags.jarName; + top.defs := ags.defs; + top.occursDefs := ags.occursDefs; - top.errors := gdcl.errors ++ ms.errors ++ ims.errors ++ ags.errors; + top.importedDefs := ms.defs; + top.importedOccursDefs := ms.occursDefs; + top.exportedGrammars := ms.exportedGrammars; + top.optionalGrammars := ms.optionalGrammars; + top.condBuild := ms.condBuild; + top.jarName := ags.jarName; -- We have an mismatch in how the environment gets put together: -- Outermost, we have grammar-wide imports in one sope. That's top.globalImports here. @@ -54,7 +53,6 @@ top::GrammarDcl ::= { top.unparse = ""; top.declaredName = top.grammarName; - top.errors := []; } concrete production grammarDcl_c @@ -63,7 +61,7 @@ top::GrammarDcl ::= 'grammar' qn::QName ';' top.unparse = "grammar " ++ qn.unparse ++ ";"; top.declaredName = qn.name; - top.errors := + top.errors <- if qn.name == top.grammarName then [] else [err(top.location, "Grammar declaration is incorrect: " ++ qn.name)]; } diff --git a/grammars/silver/definition/env/Attributes.sv b/grammars/silver/definition/env/Attributes.sv index 391bb9207..886421eb2 100644 --- a/grammars/silver/definition/env/Attributes.sv +++ b/grammars/silver/definition/env/Attributes.sv @@ -29,30 +29,30 @@ synthesized attribute declaredName :: String; - i.e. imports, exports, parser components, etc. - NOT options, or triggers, or transitive dependencies. -} -synthesized attribute moduleNames :: [String]; +monoid attribute moduleNames :: [String] with [], ++; {-- - Grammars DIRECTLY exported by this grammar. -} -synthesized attribute exportedGrammars :: [String]; +monoid attribute exportedGrammars :: [String] with [], ++; {-- - Grammars this grammar specifies as optional modifications. - (i.e. grammars that introduce more productions that do not forward) -} -synthesized attribute optionalGrammars :: [String]; +monoid attribute optionalGrammars :: [String] with [], ++; {-- - A list of triggered builds. Format is actually [ [build x, with gram], ... ] -} -synthesized attribute condBuild :: [[String]]; +monoid attribute condBuild :: [[String]] with [], ++; {-- - A list of TRUE dependencies of this grammar. - Closes over moduleNames using exports & triggers. -} -synthesized attribute allGrammarDependencies :: [String]; +monoid attribute allGrammarDependencies :: [String] with [], ++; {-- - A list of attribute occurences that are exported by this particular grammar. - Seperate from defs as a workaround for circular dependency issues. -} -synthesized attribute occursDefs :: [DclInfo]; +monoid attribute occursDefs :: [DclInfo] with [], ++; -- @@ -62,7 +62,7 @@ synthesized attribute occursDefs :: [DclInfo]; {-- - A list of definitions exported by this particular grammar. -} -synthesized attribute defs :: [Def]; +monoid attribute defs :: [Def] with [], ++; {-- - The environment. Dun dun dunnn. -} diff --git a/grammars/silver/definition/flow/env/Expr.sv b/grammars/silver/definition/flow/env/Expr.sv index b63bd9915..bacd880d9 100644 --- a/grammars/silver/definition/flow/env/Expr.sv +++ b/grammars/silver/definition/flow/env/Expr.sv @@ -10,7 +10,7 @@ import silver:modification:let_fix; {-- - Direct (potential) dependencies this expression has on nodes in the production flow graph. -} -synthesized attribute flowDeps :: [FlowVertex]; +monoid attribute flowDeps :: [FlowVertex] with [], ++; {-- - Determines whether this expression corresponds to a node in the flow graph, and how - to treat it specially if so. @@ -21,6 +21,7 @@ synthesized attribute flowVertexInfo :: ExprVertexInfo; attribute flowDeps, flowDefs, flowEnv occurs on Expr, ExprInhs, ExprInh, Exprs, AppExprs, AppExpr, AnnoAppExprs, AnnoExpr; attribute flowVertexInfo occurs on Expr; +propagate flowDefs on Expr, ExprInhs, ExprInh, Exprs, AppExprs, AppExpr, AnnoAppExprs, AnnoExpr; function inhsForTakingRef [String] ::= nt::String flowEnv::Decorated FlowEnv @@ -49,22 +50,21 @@ top::Expr ::= aspect production errorExpr top::Expr ::= e::[Message] { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production errorReference top::Expr ::= msg::[Message] q::Decorated QName { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } + aspect production childReference top::Expr ::= q::Decorated QName { -- Note that q should find the actual type written in the signature, and so -- isDecorable on that indeed tells us whether it's something autodecorated. - top.flowDeps = + top.flowDeps := if q.lookupValue.typerep.isDecorable && !performSubstitution(top.typerep, top.finalSubst).isDecorable then depsForTakingRef(rhsVertexType(q.lookupValue.fullName), q.lookupValue.typerep.typeName, top.flowEnv) else []; @@ -72,13 +72,12 @@ top::Expr ::= q::Decorated QName if q.lookupValue.typerep.isDecorable && !performSubstitution(top.typerep, top.finalSubst).isDecorable then hasVertex(rhsVertexType(q.lookupValue.fullName)) else noVertex(); - top.flowDefs = []; } aspect production lhsReference top::Expr ::= q::Decorated QName { -- Always a decorable type, so just check how it's being used: - top.flowDeps = + top.flowDeps := if !performSubstitution(top.typerep, top.finalSubst).isDecorable then depsForTakingRef(lhsVertexType, q.lookupValue.typerep.typeName, top.flowEnv) else []; @@ -86,13 +85,12 @@ top::Expr ::= q::Decorated QName if !performSubstitution(top.typerep, top.finalSubst).isDecorable then hasVertex(lhsVertexType) else noVertex(); - top.flowDefs = []; } aspect production localReference top::Expr ::= q::Decorated QName { -- Again, q give the actual type written. - top.flowDeps = [localEqVertex(q.lookupValue.fullName)] ++ + top.flowDeps := [localEqVertex(q.lookupValue.fullName)] ++ if q.lookupValue.typerep.isDecorable && !performSubstitution(top.typerep, top.finalSubst).isDecorable then depsForTakingRef(localVertexType(q.lookupValue.fullName), q.lookupValue.typerep.typeName, top.flowEnv) else []; @@ -101,13 +99,12 @@ top::Expr ::= q::Decorated QName if q.lookupValue.typerep.isDecorable && !performSubstitution(top.typerep, top.finalSubst).isDecorable then hasVertex(localVertexType(q.lookupValue.fullName)) else noVertex(); - top.flowDefs = []; } aspect production forwardReference top::Expr ::= q::Decorated QName { -- Again, always a decorable type. - top.flowDeps = [forwardEqVertex()]++ + top.flowDeps := [forwardEqVertex()]++ if !performSubstitution(top.typerep, top.finalSubst).isDecorable then depsForTakingRef(forwardVertexType, q.lookupValue.typerep.typeName, top.flowEnv) else []; @@ -116,111 +113,106 @@ top::Expr ::= q::Decorated QName if !performSubstitution(top.typerep, top.finalSubst).isDecorable then hasVertex(forwardVertexType) else noVertex(); - top.flowDefs = []; } aspect production productionReference top::Expr ::= q::Decorated QName { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production functionReference top::Expr ::= q::Decorated QName { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production globalValueReference top::Expr ::= q::Decorated QName { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } +-- Still need these equations since propagate ignores decorated references aspect production functionInvocation top::Expr ::= e::Decorated Expr es::Decorated AppExprs annos::Decorated AnnoAppExprs { - top.flowDeps = e.flowDeps ++ es.flowDeps ++ annos.flowDeps; - top.flowDefs = e.flowDefs ++ es.flowDefs ++ annos.flowDefs; + top.flowDeps := e.flowDeps ++ es.flowDeps ++ annos.flowDeps; + top.flowDefs <- e.flowDefs ++ es.flowDefs ++ annos.flowDefs; } aspect production partialApplication top::Expr ::= e::Decorated Expr es::Decorated AppExprs annos::Decorated AnnoAppExprs { - top.flowDeps = e.flowDeps ++ es.flowDeps ++ annos.flowDeps; - top.flowDefs = e.flowDefs ++ es.flowDefs ++ annos.flowDefs; + top.flowDeps := e.flowDeps ++ es.flowDeps ++ annos.flowDeps; + top.flowDefs <- e.flowDefs ++ es.flowDefs ++ annos.flowDefs; } aspect production errorApplication top::Expr ::= e::Decorated Expr es::AppExprs annos::AnnoAppExprs { - top.flowDeps = []; - top.flowDefs = []; + top.flowDeps := []; } - aspect production attributeSection top::Expr ::= '(' '.' q::QName ')' { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } + + aspect production forwardAccess top::Expr ::= e::Expr '.' 'forward' { - top.flowDeps = + top.flowDeps := case e.flowVertexInfo of | hasVertex(vertex) -> vertex.fwdVertex :: vertex.eqVertex | noVertex() -> e.flowDeps end; - top.flowDefs = e.flowDefs; } aspect production errorAccessHandler top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur { - top.flowDeps = []; - top.flowDefs = e.flowDefs; + propagate flowDeps; + top.flowDefs <- e.flowDefs; } -- Note that below we IGNORE the flow deps of the lhs if we know what it is -- this is because by default the lhs will have 'taking ref' flow deps (see above) aspect production synDecoratedAccessHandler top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur { - top.flowDeps = + top.flowDeps := case e.flowVertexInfo of | hasVertex(vertex) -> vertex.synVertex(q.attrDcl.fullName) :: vertex.eqVertex | noVertex() -> e.flowDeps end; - top.flowDefs = e.flowDefs; + top.flowDefs <- e.flowDefs; } aspect production inhDecoratedAccessHandler top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur { - top.flowDeps = + top.flowDeps := case e.flowVertexInfo of | hasVertex(vertex) -> vertex.inhVertex(q.attrDcl.fullName) :: vertex.eqVertex | noVertex() -> e.flowDeps end; - top.flowDefs = e.flowDefs; + top.flowDefs <- e.flowDefs; } aspect production errorDecoratedAccessHandler top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur { - top.flowDeps = []; -- errors, who cares? - top.flowDefs = e.flowDefs; + top.flowDeps := []; -- errors, who cares? + top.flowDefs <- e.flowDefs; } aspect production terminalAccessHandler top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur { - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; + top.flowDeps := e.flowDeps; + top.flowDefs <- e.flowDefs; } aspect production annoAccessHandler top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur { - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; + top.flowDeps := e.flowDeps; + top.flowDefs <- e.flowDefs; } @@ -243,7 +235,7 @@ top::Expr ::= 'decorate' e::Expr 'with' '{' inh::ExprInhs '}' -- Next, emit the "local equation" for this anonymous flow vertex. -- This means only the deps in 'e', see above conceptual transformation to see why. -- N.B. 'inh.flowDefs' will emit 'localInhEq's for this anonymous flow vertex. - top.flowDefs = e.flowDefs ++ inh.flowDefs ++ + top.flowDefs <- [anonEq(top.frame.fullName, inh.decorationVertex, performSubstitution(e.typerep, top.finalSubst).typeName, top.location, e.flowDeps)]; -- Now, we represent ourselves to anything that might use us specially @@ -252,7 +244,7 @@ top::Expr ::= 'decorate' e::Expr 'with' '{' inh::ExprInhs '}' -- Finally, our standard flow deps mimic those of a local: "taking a reference" -- This are of course ignored when treated specially. - top.flowDeps = [anonEqVertex(inh.decorationVertex)] ++ + top.flowDeps := [anonEqVertex(inh.decorationVertex)] ++ depsForTakingRef(anonVertexType(inh.decorationVertex), performSubstitution(e.typerep, top.finalSubst).typeName, top.flowEnv); } @@ -261,8 +253,8 @@ autocopy attribute decorationVertex :: String occurs on ExprInhs, ExprInh; aspect production exprInh top::ExprInh ::= lhs::ExprLHSExpr '=' e1::Expr ';' { - top.flowDeps = e1.flowDeps; - top.flowDefs = e1.flowDefs ++ + propagate flowDeps; + top.flowDefs <- if !null(lhs.errors) then [] else case lhs of | exprLhsExpr(q) -> [anonInhEq(top.frame.fullName, top.decorationVertex, q.attrDcl.fullName, e1.flowDeps)] @@ -272,237 +264,201 @@ top::ExprInh ::= lhs::ExprLHSExpr '=' e1::Expr ';' aspect production exprInhsEmpty top::ExprInhs ::= { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production exprInhsOne top::ExprInhs ::= h::ExprInh { - top.flowDeps = h.flowDeps; - top.flowDefs = h.flowDefs; + propagate flowDeps; } aspect production exprInhsCons top::ExprInhs ::= h::ExprInh t::ExprInhs { - top.flowDeps = h.flowDeps ++ t.flowDeps; - top.flowDefs = h.flowDefs ++ t.flowDefs; + propagate flowDeps; } aspect production trueConst top::Expr ::= 'true' { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production falseConst top::Expr ::= 'false' { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production and top::Expr ::= e1::Expr '&&' e2::Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + propagate flowDeps; } aspect production or top::Expr ::= e1::Expr '||' e2::Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + propagate flowDeps; } aspect production not top::Expr ::= '!' e1::Expr { - top.flowDeps = e1.flowDeps; - top.flowDefs = e1.flowDefs; + propagate flowDeps; } aspect production gt top::Expr ::= e1::Expr '>' e2::Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + propagate flowDeps; } aspect production lt top::Expr ::= e1::Expr '<' e2::Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + propagate flowDeps; } aspect production gteq top::Expr ::= e1::Expr '>=' e2::Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + propagate flowDeps; } aspect production lteq top::Expr ::= e1::Expr '<=' e2::Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + propagate flowDeps; } aspect production eqeq top::Expr ::= e1::Expr '==' e2::Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + propagate flowDeps; } aspect production neq top::Expr ::= e1::Expr '!=' e2::Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + propagate flowDeps; } aspect production ifThenElse top::Expr ::= 'if' e1::Expr 'then' e2::Expr 'else' e3::Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps ++ e3.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs ++ e3.flowDefs; + propagate flowDeps; } aspect production intConst top::Expr ::= i::Int_t { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production floatConst top::Expr ::= f::Float_t { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production plus top::Expr ::= e1::Expr '+' e2::Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + propagate flowDeps; } aspect production minus top::Expr ::= e1::Expr '-' e2::Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + propagate flowDeps; } aspect production multiply top::Expr ::= e1::Expr '*' e2::Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + propagate flowDeps; } aspect production divide top::Expr ::= e1::Expr '/' e2::Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + propagate flowDeps; } aspect production modulus top::Expr ::= e1::Expr '%' e2::Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + propagate flowDeps; } aspect production neg top::Expr ::= '-' e1::Expr { - top.flowDeps = e1.flowDeps; - top.flowDefs = e1.flowDefs; + propagate flowDeps; } aspect production stringConst top::Expr ::= s::String_t { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production errorPlusPlus top::Expr ::= e1::Decorated Expr e2::Decorated Expr { - top.flowDeps = []; -- error, so who cares? - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + top.flowDeps := []; -- error, so who cares? + top.flowDefs <- e1.flowDefs ++ e2.flowDefs; } aspect production stringPlusPlus top::Expr ::= e1::Decorated Expr e2::Decorated Expr { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + top.flowDeps := e1.flowDeps ++ e2.flowDeps; + top.flowDefs <- e1.flowDefs ++ e2.flowDefs; } aspect production exprsEmpty top::Exprs ::= { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production exprsSingle top::Exprs ::= e::Expr { - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; + propagate flowDeps; } aspect production exprsCons top::Exprs ::= e1::Expr ',' e2::Exprs { - top.flowDeps = e1.flowDeps ++ e2.flowDeps; - top.flowDefs = e1.flowDefs ++ e2.flowDefs; + propagate flowDeps; } aspect production missingAppExpr top::AppExpr ::= '_' { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production presentAppExpr top::AppExpr ::= e::Expr { - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; + propagate flowDeps; } aspect production snocAppExprs top::AppExprs ::= es::AppExprs ',' e::AppExpr { - top.flowDeps = es.flowDeps ++ e.flowDeps; - top.flowDefs = es.flowDefs ++ e.flowDefs; + propagate flowDeps; } aspect production oneAppExprs top::AppExprs ::= e::AppExpr { - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; + propagate flowDeps; } aspect production emptyAppExprs top::AppExprs ::= { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production annoExpr top::AnnoExpr ::= qn::QName '=' e::AppExpr { - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; + propagate flowDeps; } aspect production snocAnnoAppExprs top::AnnoAppExprs ::= es::AnnoAppExprs ',' e::AnnoExpr { - top.flowDeps = es.flowDeps ++ e.flowDeps; - top.flowDefs = es.flowDefs ++ e.flowDefs; + propagate flowDeps; } aspect production oneAnnoAppExprs top::AnnoAppExprs ::= e::AnnoExpr { - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; + propagate flowDeps; } aspect production emptyAnnoAppExprs top::AnnoAppExprs ::= { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } @@ -517,9 +473,9 @@ top::Expr ::= e::Decorated Expr -- So definitely don't consider making this []! - top.flowDeps = e.flowDeps; + top.flowDeps := e.flowDeps; top.flowVertexInfo = e.flowVertexInfo; - top.flowDefs = e.flowDefs; -- I guess? I haven't thought about this exactly. + top.flowDefs <- e.flowDefs; -- I guess? I haven't thought about this exactly. -- i.e. whether this has already been included. shouldn't hurt to do so though. } @@ -529,68 +485,61 @@ top::Expr ::= e::Decorated Expr aspect production stringLength top::Expr ::= e::Decorated Expr { - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; + top.flowDeps := e.flowDeps; + top.flowDefs <- e.flowDefs; } aspect production errorLength top::Expr ::= e::Decorated Expr { - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; + top.flowDeps := e.flowDeps; + top.flowDefs <- e.flowDefs; } aspect production toBooleanFunction top::Expr ::= 'toBoolean' '(' e1::Expr ')' { - top.flowDeps = e1.flowDeps; - top.flowDefs = e1.flowDefs; + propagate flowDeps; } aspect production toIntegerFunction top::Expr ::= 'toInteger' '(' e1::Expr ')' { - top.flowDeps = e1.flowDeps; - top.flowDefs = e1.flowDefs; + propagate flowDeps; } aspect production toFloatFunction top::Expr ::= 'toFloat' '(' e1::Expr ')' { - top.flowDeps = e1.flowDeps; - top.flowDefs = e1.flowDefs; + propagate flowDeps; } aspect production toStringFunction top::Expr ::= 'toString' '(' e1::Expr ')' { - top.flowDeps = e1.flowDeps; - top.flowDefs = e1.flowDefs; + propagate flowDeps; } aspect production reifyFunctionLiteral top::Expr ::= 'reify' { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production newFunction top::Expr ::= 'new' '(' e1::Expr ')' { -- Emit nothing except the keepDeps, for a vertex node - top.flowDeps = + top.flowDeps := case e1.flowVertexInfo of | hasVertex(vertex) -> vertex.eqVertex | noVertex() -> e1.flowDeps end; - top.flowDefs = e1.flowDefs; } aspect production terminalConstructor top::Expr ::= 'terminal' '(' t::TypeExpr ',' es::Expr ',' el::Expr ')' { - top.flowDeps = es.flowDeps ++ el.flowDeps; - top.flowDefs = es.flowDefs ++ el.flowDefs; + propagate flowDeps; } @@ -603,73 +552,54 @@ top::Expr ::= 'terminal' '(' t::TypeExpr ',' es::Expr ',' el::Expr ')' aspect production failureTerminalIdExpr top::Expr ::= 'disambiguationFailure' { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production actionChildReference top::Expr ::= q::Decorated QName { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production pluckTerminalReference top::Expr ::= q::Decorated QName { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production terminalIdReference top::Expr ::= q::Decorated QName { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production lexerClassReference top::Expr ::= q::Decorated QName { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production parserAttributeReference top::Expr ::= q::Decorated QName { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } aspect production termAttrValueReference top::Expr ::= q::Decorated QName { - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps; } -- FROM LET TODO attribute flowDefs, flowEnv occurs on AssignExpr; +propagate flowDefs on AssignExpr; aspect production letp top::Expr ::= la::AssignExpr e::Expr { - top.flowDeps = e.flowDeps; - top.flowDefs = la.flowDefs ++ e.flowDefs; -} - -aspect production appendAssignExpr -top::AssignExpr ::= a1::AssignExpr a2::AssignExpr -{ - top.flowDefs = a1.flowDefs ++ a2.flowDefs; -} - -aspect production assignExpr -top::AssignExpr ::= id::Name '::' t::TypeExpr '=' e::Expr -{ - top.flowDefs = e.flowDefs; + top.flowDeps := e.flowDeps; } aspect production lexicalLocalReference @@ -684,7 +614,7 @@ top::Expr ::= q::Decorated QName fi::ExprVertexInfo fd::[FlowVertex] -- 3. Used as undecorated type -- Then: Suppress `fd` and report just `fi.eq` - top.flowDeps = + top.flowDeps := case fi of | hasVertex(vertex) -> if performSubstitution(q.lookupValue.typerep, top.finalSubst).isDecorated && @@ -693,13 +623,13 @@ top::Expr ::= q::Decorated QName fi::ExprVertexInfo fd::[FlowVertex] else fd -- we're passing along our vertex-ness to the outer expression | noVertex() -> fd -- we're actually being used as a ref-set-taking decorated var end; - top.flowDefs = []; top.flowVertexInfo = fi; } -- FROM PATTERN TODO attribute flowDeps, flowDefs, flowEnv, scrutineeVertexType occurs on PrimPatterns, PrimPattern; +propagate flowDeps, flowDefs on PrimPatterns, PrimPattern; autocopy attribute scrutineeVertexType :: VertexType; @@ -726,10 +656,10 @@ top::Expr ::= e::Expr t::TypeExpr pr::PrimPatterns f::Expr -- Let's make sure for decorated types, we only demand what's necessary for forward -- evaluation. - top.flowDeps = pr.flowDeps ++ f.flowDeps ++ + top.flowDeps := pr.flowDeps ++ f.flowDeps ++ (pr.scrutineeVertexType.fwdVertex :: pr.scrutineeVertexType.eqVertex); - top.flowDefs = e.flowDefs ++ pr.flowDefs ++ f.flowDefs ++ + top.flowDefs <- case e.flowVertexInfo of | hasVertex(vertex) -> [] | noVertex() -> [anonEq(top.frame.fullName, anonName, performSubstitution(e.typerep, top.finalSubst).typeName, top.location, e.flowDeps)] @@ -737,67 +667,15 @@ top::Expr ::= e::Expr t::TypeExpr pr::PrimPatterns f::Expr -- We want to use anonEq here because that introduces the nonterminal stitch point for our vertex. } -aspect production onePattern -top::PrimPatterns ::= p::PrimPattern -{ - top.flowDeps = p.flowDeps; - top.flowDefs = p.flowDefs; -} -aspect production consPattern -top::PrimPatterns ::= p::PrimPattern '|' ps::PrimPatterns -{ - top.flowDeps = p.flowDeps ++ ps.flowDeps; - top.flowDefs = p.flowDefs ++ ps.flowDefs; -} - aspect production prodPatternNormal top::PrimPattern ::= qn::Decorated QName ns::VarBinders e::Expr { - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs ++ + top.flowDefs <- [patternRuleEq(top.frame.fullName, qn.lookupValue.fullName, top.scrutineeVertexType, ns.flowProjections)]; } aspect production prodPatternGadt top::PrimPattern ::= qn::Decorated QName ns::VarBinders e::Expr { - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs ++ + top.flowDefs <- [patternRuleEq(top.frame.fullName, qn.lookupValue.fullName, top.scrutineeVertexType, ns.flowProjections)]; } -aspect production integerPattern -top::PrimPattern ::= i::Int_t '->' e::Expr -{ - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; -} -aspect production floatPattern -top::PrimPattern ::= f::Float_t '->' e::Expr -{ - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; -} -aspect production stringPattern -top::PrimPattern ::= i::String_t '->' e::Expr -{ - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; -} -aspect production booleanPattern -top::PrimPattern ::= i::String '->' e::Expr -{ - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; -} -aspect production nilPattern -top::PrimPattern ::= e::Expr -{ - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; -} -aspect production conslstPattern -top::PrimPattern ::= h::Name t::Name e::Expr -{ - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; -} - diff --git a/grammars/silver/definition/flow/env/FlowEnv.sv b/grammars/silver/definition/flow/env/FlowEnv.sv index dcc84edb8..42e5540c6 100644 --- a/grammars/silver/definition/flow/env/FlowEnv.sv +++ b/grammars/silver/definition/flow/env/FlowEnv.sv @@ -6,7 +6,7 @@ imports silver:definition:core; autocopy attribute flowEnv :: Decorated FlowEnv; -synthesized attribute flowDefs :: [FlowDef]; +monoid attribute flowDefs :: [FlowDef] with [], ++; nonterminal FlowEnv with synTree, inhTree, defTree, fwdTree, prodTree, fwdInhTree, refTree, localInhTree, localTree, nonSuspectTree, hostSynTree, specTree, prodGraphTree; diff --git a/grammars/silver/definition/flow/env/FunctionDcl.sv b/grammars/silver/definition/flow/env/FunctionDcl.sv index cb74f87cd..c358315ff 100644 --- a/grammars/silver/definition/flow/env/FunctionDcl.sv +++ b/grammars/silver/definition/flow/env/FunctionDcl.sv @@ -13,8 +13,6 @@ top::AGDcl ::= 'function' id::Name ns::FunctionSignature body::ProductionBody {-- Used by core to send down with .frame -} production myFlowGraph :: ProductionGraph = constructFunctionGraph(namedSig, top.flowEnv, top.env, myProds, myFlow); - - top.flowDefs = body.flowDefs; } aspect production aspectFunctionDcl @@ -27,7 +25,5 @@ top::AGDcl ::= 'aspect' 'function' id::QName ns::AspectFunctionSignature body::P {-- Used by core to send down with .frame -} production myFlowGraph :: ProductionGraph = constructFunctionGraph(namedSig, top.flowEnv, top.env, myProds, myFlow); - - top.flowDefs = body.flowDefs; } diff --git a/grammars/silver/definition/flow/env/NonterminalDcl.sv b/grammars/silver/definition/flow/env/NonterminalDcl.sv index efff37245..585a1c44a 100644 --- a/grammars/silver/definition/flow/env/NonterminalDcl.sv +++ b/grammars/silver/definition/flow/env/NonterminalDcl.sv @@ -20,7 +20,7 @@ top::AGDcl ::= cl::ClosedOrNot 'nonterminal' id::Name tl::BracketedOptTypeExprs -- Notice the circularity: flowDefs uses flowEnv. Works fine because only -- the (lazy) parameter of ntRefFlowDef isn't computable until later. - top.flowDefs = [ntRefFlowDef(fName, fromMaybe(inferredInhs, specInhs))]; + top.flowDefs <- [ntRefFlowDef(fName, fromMaybe(inferredInhs, specInhs))]; } -- If it is inherited and exported by this grammar (according to authority) diff --git a/grammars/silver/definition/flow/env/Occurs.sv b/grammars/silver/definition/flow/env/Occurs.sv index 0384efd02..fab7ae615 100644 --- a/grammars/silver/definition/flow/env/Occurs.sv +++ b/grammars/silver/definition/flow/env/Occurs.sv @@ -11,7 +11,7 @@ top::AGDcl ::= 'attribute' at::QName attl::BracketedOptTypeExprs 'occurs' 'on' n local isSyn :: Boolean = at.lookupAttribute.dcl.isSynthesized; -- We must be able to identify host-language synthesized attributes from the flow environment - top.flowDefs = + top.flowDefs <- if !at.lookupAttribute.found || !nt.lookupType.found || !isHost || !isSyn then [] else diff --git a/grammars/silver/definition/flow/env/ProductionBody.sv b/grammars/silver/definition/flow/env/ProductionBody.sv index f987a51a2..87943ad94 100644 --- a/grammars/silver/definition/flow/env/ProductionBody.sv +++ b/grammars/silver/definition/flow/env/ProductionBody.sv @@ -10,6 +10,8 @@ import silver:driver:util only isExportedBy, RootSpec; attribute flowDefs, flowEnv occurs on ProductionBody, ProductionStmts, ProductionStmt, ForwardInhs, ForwardInh; attribute flowEnv occurs on DefLHS; +propagate flowDefs on ProductionBody, ProductionStmts, ProductionStmt, ForwardInhs, ForwardInh; + {- A short note on how flowDefs are generated: - We ALWAYS produce the flowDef itself. This is necessary to catch missing or duplicate equations. @@ -17,50 +19,6 @@ attribute flowEnv occurs on DefLHS; This is to allow us to just compute flow types once, globally. -} -aspect production productionBody -top::ProductionBody ::= '{' stmts::ProductionStmts '}' -{ - top.flowDefs = stmts.flowDefs; -} - ----- - -aspect production productionStmtsNil -top::ProductionStmts ::= -{ - top.flowDefs = []; -} - -aspect production productionStmtsSnoc -top::ProductionStmts ::= h::ProductionStmts t::ProductionStmt -{ - top.flowDefs = h.flowDefs ++ t.flowDefs; -} - ----- - -aspect production productionStmtAppend -top::ProductionStmt ::= h::ProductionStmt t::ProductionStmt -{ - top.flowDefs = h.flowDefs ++ t.flowDefs; -} - -aspect production errorProductionStmt -top::ProductionStmt ::= e::[Message] -{ - top.flowDefs = []; -} - -{- -aspect default production -top::ProductionStmt ::= -{ - top.flowDefs = []; -} --} - ----- - {-- - An occurs dcl info 's flow type can be affected here -} @@ -78,7 +36,7 @@ top::ProductionStmt ::= 'forwards' 'to' e::Expr ';' local mayAffectFlowType :: Boolean = isExportedBy(top.grammarName, [ntDefGram], top.compiledGrammars); - top.flowDefs = e.flowDefs ++ [ + top.flowDefs <- [ fwdEq(top.frame.fullName, e.flowDeps, mayAffectFlowType), -- These are attributes that we know, here, occurs on this nonterminal. -- The point is, these are the implicit equations we KNOW get generated, so @@ -89,51 +47,17 @@ top::ProductionStmt ::= 'forwards' 'to' e::Expr ';' filter(isAffectable(top.grammarName, ntDefGram, top.compiledGrammars, _), getAttrsOn(top.frame.lhsNtName, top.env))))]; } -aspect production forwardingWith -top::ProductionStmt ::= 'forwarding' 'with' '{' inh::ForwardInhs '}' ';' -{ - top.flowDefs = inh.flowDefs; -} - -aspect production forwardInhsOne -top::ForwardInhs ::= lhs::ForwardInh -{ - top.flowDefs = lhs.flowDefs; -} -aspect production forwardInhsCons -top::ForwardInhs ::= lhs::ForwardInh rhs::ForwardInhs -{ - top.flowDefs = lhs.flowDefs ++ rhs.flowDefs; -} aspect production forwardInh top::ForwardInh ::= lhs::ForwardLHSExpr '=' e::Expr ';' { -- TODO: we need to figure out how to introduce any new lhsinh deps to the -- forward flow type automatically. - top.flowDefs = e.flowDefs ++ + top.flowDefs <- case lhs of | forwardLhsExpr(q) -> [fwdInhEq(top.frame.fullName, q.attrDcl.fullName, e.flowDeps)] end; } -aspect production localAttributeDcl -top::ProductionStmt ::= 'local' 'attribute' a::Name '::' te::TypeExpr ';' -{ - top.flowDefs = []; - -- This is basically taken care of by the definition equation, rather than here. -} -aspect production returnDef -top::ProductionStmt ::= 'return' e::Expr ';' -{ - top.flowDefs = e.flowDefs; -} - -aspect production errorAttributeDef -top::ProductionStmt ::= msg::[Message] dl::Decorated DefLHS attr::Decorated QNameAttrOccur e::Expr -{ - top.flowDefs = e.flowDefs; -} - aspect production synthesizedAttributeDef top::ProductionStmt ::= dl::Decorated DefLHS attr::Decorated QNameAttrOccur e::Expr { @@ -144,7 +68,7 @@ top::ProductionStmt ::= dl::Decorated DefLHS attr::Decorated QNameAttrOccur e: local mayAffectFlowType :: Boolean = isExportedBy(top.grammarName, srcGrams, top.compiledGrammars); - top.flowDefs = e.flowDefs ++ + top.flowDefs <- if top.frame.hasPartialSignature then [synEq(top.frame.fullName, attr.attrDcl.fullName, e.flowDeps, mayAffectFlowType)] else @@ -153,7 +77,7 @@ top::ProductionStmt ::= dl::Decorated DefLHS attr::Decorated QNameAttrOccur e: aspect production inheritedAttributeDef top::ProductionStmt ::= dl::Decorated DefLHS attr::Decorated QNameAttrOccur e::Expr { - top.flowDefs = e.flowDefs ++ + top.flowDefs <- case dl of | childDefLHS(q) -> [inhEq(top.frame.fullName, q.lookupValue.fullName, attr.attrDcl.fullName, e.flowDeps)] | localDefLHS(q) -> [localInhEq(top.frame.fullName, q.lookupValue.fullName, attr.attrDcl.fullName, e.flowDeps)] @@ -168,14 +92,9 @@ top::ProductionStmt ::= val::Decorated QName e::Expr -- TODO: So, I'm just going to assume for the moment that we're always allowed to define the eq for a local... -- technically, it's possible to break this if you declare it in one grammar, but define it in another, but -- I think we should forbid that syntactically, later on... - top.flowDefs = e.flowDefs ++ + top.flowDefs <- [localEq(top.frame.fullName, val.lookupValue.fullName, val.lookupValue.typerep.typeName, e.flowDeps)]; } -aspect production errorValueDef -top::ProductionStmt ::= val::Decorated QName e::Expr -{ - top.flowDefs = e.flowDefs; -} -- FROM COLLECTIONS TODO @@ -187,7 +106,7 @@ top::ProductionStmt ::= dl::Decorated DefLHS attr::Decorated QNameAttrOccur {- local mayAffectFlowType :: Boolean = isExportedBy(top.grammarName, [ntDefGram, hackGramFromDcl(attr)], top.compiledGrammars); - top.flowDefs = e.flowDefs ++ + top.flowDefs <- [extraEq(top.frame.fullName, lhsSynVertex(attr.attrDcl.fullName), e.flowDeps, mayAffectFlowType)]; } @@ -201,7 +120,7 @@ top::ProductionStmt ::= dl::Decorated DefLHS attr::Decorated QNameAttrOccur {- | forwardDefLHS(q) -> forwardVertex(attr.attrDcl.fullName) | _ -> localEqVertex("bogus:value:from:inhcontrib:flow") end; - top.flowDefs = e.flowDefs ++ + top.flowDefs <- [extraEq(top.frame.fullName, vertex, e.flowDeps, true)]; } aspect production synBaseColAttributeDef @@ -214,7 +133,7 @@ top::ProductionStmt ::= dl::Decorated DefLHS attr::Decorated QNameAttrOccur e: local mayAffectFlowType :: Boolean = isExportedBy(top.grammarName, srcGrams, top.compiledGrammars); - top.flowDefs = e.flowDefs ++ + top.flowDefs <- if top.frame.hasPartialSignature then [synEq(top.frame.fullName, attr.attrDcl.fullName, e.flowDeps, mayAffectFlowType)] else @@ -223,7 +142,7 @@ top::ProductionStmt ::= dl::Decorated DefLHS attr::Decorated QNameAttrOccur e: aspect production inhBaseColAttributeDef top::ProductionStmt ::= dl::Decorated DefLHS attr::Decorated QNameAttrOccur e::Expr { - top.flowDefs = e.flowDefs ++ + top.flowDefs <- case dl of | childDefLHS(q) -> [inhEq(top.frame.fullName, q.lookupValue.fullName, attr.attrDcl.fullName, e.flowDeps)] | localDefLHS(q) -> [localInhEq(top.frame.fullName, q.lookupValue.fullName, attr.attrDcl.fullName, e.flowDeps)] @@ -249,52 +168,13 @@ top::ProductionStmt ::= val::Decorated QName e::Expr -- If we do, we'll have to come back here to add 'location' info anyway, -- so if we do that, uhhh... fix this! Because you're here! Reading this! - top.flowDefs = e.flowDefs ++ + top.flowDefs <- if mayAffectFlowType then [extraEq(top.frame.fullName, localEqVertex(val.lookupValue.fullName), e.flowDeps, true)] else []; } ------- FROM COPPER TODO - -aspect production pluckDef -top::ProductionStmt ::= 'pluck' e::Expr ';' -{ - top.flowDefs = e.flowDefs; -} - -aspect production printStmt -top::ProductionStmt ::= 'print' e::Expr ';' -{ - top.flowDefs = e.flowDefs; -} - -aspect production parserAttributeValueDef -top::ProductionStmt ::= val::Decorated QName e::Expr -{ - top.flowDefs = e.flowDefs; -} - -aspect production termAttrValueValueDef -top::ProductionStmt ::= val::Decorated QName e::Expr -{ - top.flowDefs = e.flowDefs; -} -aspect production blockStmt -top::ProductionStmt ::= '{' stmts::ProductionStmts '}' -{ - top.flowDefs = stmts.flowDefs; -} -aspect production ifElseStmt -top::ProductionStmt ::= 'if' '(' condition::Expr ')' th::ProductionStmt 'else' el::ProductionStmt -{ - top.flowDefs = condition.flowDefs ++ th.flowDefs ++ el.flowDefs; -} -aspect production pushTokenStmt -top::ProductionStmt ::= 'pushToken' '(' val::QName ',' lexeme::Expr ')' ';' -{ - top.flowDefs = lexeme.flowDefs; -} +-- TODO: Copper ProductuionStmts -- We're in the unfortunate position of HAVING to compute values for 'flowDefs' -- even if there are errors in the larger grammar, as remote errors in binding diff --git a/grammars/silver/definition/flow/env/ProductionDcl.sv b/grammars/silver/definition/flow/env/ProductionDcl.sv index ba93568d0..ae47a3f9c 100644 --- a/grammars/silver/definition/flow/env/ProductionDcl.sv +++ b/grammars/silver/definition/flow/env/ProductionDcl.sv @@ -14,7 +14,7 @@ top::AGDcl ::= 'abstract' 'production' id::Name ns::ProductionSignature body::Pr production myFlowGraph :: ProductionGraph = findProductionGraph(fName, myGraphs); - top.flowDefs = body.flowDefs ++ + top.flowDefs <- if null(body.uniqueSignificantExpression) then [prodFlowDef(namedSig.outputElement.typerep.typeName, fName)] else []; @@ -29,16 +29,4 @@ top::AGDcl ::= 'aspect' 'production' id::QName ns::AspectProductionSignature bod {-- Used by core to send down with .frame -} production myFlowGraph :: ProductionGraph = findProductionGraph(id.lookupValue.fullName, myGraphs); - - top.flowDefs = body.flowDefs; -} - -------- Default attrs hack sorta - -aspect production aspectDefaultProduction -top::AGDcl ::= 'aspect' 'default' 'production' - lhs::Name '::' _ '::=' body::ProductionBody -{ - top.flowDefs = body.flowDefs; } - diff --git a/grammars/silver/definition/flow/env/Root.sv b/grammars/silver/definition/flow/env/Root.sv index 25126f82e..86fd7e85b 100644 --- a/grammars/silver/definition/flow/env/Root.sv +++ b/grammars/silver/definition/flow/env/Root.sv @@ -1,32 +1,10 @@ grammar silver:definition:flow:env; attribute flowDefs, flowEnv occurs on Root, AGDcls, AGDcl, Grammar; - -aspect production root -top::Root ::= gdcl::GrammarDcl ms::ModuleStmts ims::ImportStmts ags::AGDcls -{ - top.flowDefs = ags.flowDefs; -} - -aspect production nilAGDcls -top::AGDcls ::= -{ - top.flowDefs = []; -} -aspect production consAGDcls -top::AGDcls ::= h::AGDcl t::AGDcls -{ - top.flowDefs = h.flowDefs ++ t.flowDefs; -} +propagate flowDefs on Root, AGDcls, AGDcl, Grammar; aspect default production top::AGDcl ::= { - top.flowDefs = []; + top.flowDefs := []; } -aspect production appendAGDcl -top::AGDcl ::= ag1::AGDcl ag2::AGDcl -{ - top.flowDefs = ag1.flowDefs ++ ag2.flowDefs; -} - diff --git a/grammars/silver/definition/flow/env/RootSpec.sv b/grammars/silver/definition/flow/env/RootSpec.sv index 633c5308a..c45a65caf 100644 --- a/grammars/silver/definition/flow/env/RootSpec.sv +++ b/grammars/silver/definition/flow/env/RootSpec.sv @@ -2,31 +2,26 @@ grammar silver:definition:flow:env; import silver:driver:util; -synthesized attribute maybeFlowDefs::Maybe<[FlowDef]> occurs on InterfaceItems, InterfaceItem; +monoid attribute maybeFlowDefs::Maybe<[FlowDef]> with nothing(), orElse; +attribute maybeFlowDefs occurs on InterfaceItems, InterfaceItem; +propagate maybeFlowDefs on InterfaceItems; aspect production consInterfaceItem top::InterfaceItems ::= h::InterfaceItem t::InterfaceItems { - top.maybeFlowDefs = orElse(t.maybeFlowDefs, h.maybeFlowDefs); top.interfaceErrors <- if !top.maybeFlowDefs.isJust then ["Missing item flowDefs"] else []; } -aspect production nilInterfaceItem -top::InterfaceItems ::= -{ - top.maybeFlowDefs = nothing(); -} - aspect default production top::InterfaceItem ::= { - top.maybeFlowDefs = nothing(); + propagate maybeFlowDefs; } abstract production flowDefsInterfaceItem top::InterfaceItem ::= val::[FlowDef] { - top.maybeFlowDefs = just(val); + top.maybeFlowDefs := just(val); } aspect function unparseRootSpec @@ -35,35 +30,23 @@ String ::= r::Decorated RootSpec interfaceItems <- [flowDefsInterfaceItem(r.flowDefs)]; } +attribute flowDefs occurs on RootSpec; + aspect production errorRootSpec top::RootSpec ::= _ _ _ _ _ { - top.flowDefs = []; + top.flowDefs := []; } aspect production grammarRootSpec top::RootSpec ::= g::Grammar _ _ _ _ { - top.flowDefs = g.flowDefs; + top.flowDefs := g.flowDefs; } -attribute flowDefs occurs on RootSpec; - aspect production interfaceRootSpec top::RootSpec ::= i::InterfaceItems interfaceTime::Integer _ { - top.flowDefs = i.maybeFlowDefs.fromJust; -} - -aspect production nilGrammar -top::Grammar ::= -{ - top.flowDefs = []; -} - -aspect production consGrammar -top::Grammar ::= h::Root t::Grammar -{ - top.flowDefs = h.flowDefs ++ t.flowDefs; + top.flowDefs := i.maybeFlowDefs.fromJust; } diff --git a/grammars/silver/definition/flow/syntax/FlowSpec.sv b/grammars/silver/definition/flow/syntax/FlowSpec.sv index 247e0dab9..bdd147a8d 100644 --- a/grammars/silver/definition/flow/syntax/FlowSpec.sv +++ b/grammars/silver/definition/flow/syntax/FlowSpec.sv @@ -22,7 +22,7 @@ top::AGDcl ::= 'flowtype' nt::QName '=' specs::FlowSpecs ';' if nt.lookupType.found then specs.errors else nt.lookupType.errors; - top.flowDefs = + top.flowDefs := if nt.lookupType.found then specs.flowDefs else []; @@ -36,7 +36,7 @@ top::AGDcl ::= 'flowtype' attr::FlowSpec 'on' nts::NtList ';' { top.unparse = "flowtype " ++ attr.unparse ++ " on " ++ nts.unparse ++ ";"; top.errors := nts.errors; - top.flowDefs = nts.flowDefs; + top.flowDefs := nts.flowDefs; nts.flowSpecSpec = attr; } @@ -44,30 +44,29 @@ top::AGDcl ::= 'flowtype' attr::FlowSpec 'on' nts::NtList ';' nonterminal FlowSpecs with config, location, grammarName, errors, env, unparse, onNt, flowDefs, compiledGrammars, flowEnv; +propagate errors, flowDefs on FlowSpecs; + concrete production oneFlowSpec top::FlowSpecs ::= h::FlowSpec { top.unparse = h.unparse; - top.errors := h.errors; - top.flowDefs = h.flowDefs; } concrete production snocFlowSpec top::FlowSpecs ::= h::FlowSpecs ',' t::FlowSpec { top.unparse = h.unparse ++ ", " ++ t.unparse; - top.errors := h.errors ++ t.errors; - top.flowDefs = h.flowDefs ++ t.flowDefs; } nonterminal FlowSpec with config, location, grammarName, errors, env, unparse, onNt, flowDefs, compiledGrammars, flowEnv; autocopy attribute onNt :: Type; +propagate errors on FlowSpec; + concrete production flowSpecDcl top::FlowSpec ::= attr::FlowSpecId '{' inhs::FlowSpecInhs '}' { top.unparse = attr.unparse ++ " {" ++ inhs.unparse ++ "}"; - top.errors := attr.errors ++ inhs.errors; top.errors <- if !attr.found || @@ -96,7 +95,7 @@ top::FlowSpec ::= attr::FlowSpecId '{' inhs::FlowSpecInhs '}' -- We want to put the spec in even if there are errors in 'inhs' so that -- we can look up specs from inhs. - top.flowDefs = + top.flowDefs := if !attr.found then [] else [specificationFlowDef(top.onNt.typeName, attr.synName, inhs.inhList)]; } @@ -106,12 +105,13 @@ nonterminal FlowSpecId with config, location, grammarName, errors, env, unparse, synthesized attribute synName :: String; synthesized attribute authorityGrammar :: String; +propagate errors on FlowSpecId; + concrete production qnameSpecId top::FlowSpecId ::= syn::QNameAttrOccur { top.name = syn.name; top.unparse = syn.unparse; - top.errors := syn.errors; top.synName = syn.attrDcl.fullName; top.authorityGrammar = syn.dcl.sourceGrammar; top.found = syn.found && syn.attrDcl.isSynthesized; @@ -128,7 +128,6 @@ top::FlowSpecId ::= 'forward' { top.name = "forward"; top.unparse = top.name; - top.errors := []; top.synName = "forward"; top.authorityGrammar = hackGramFromFName(top.onNt.typeName); top.found = true; @@ -139,7 +138,6 @@ top::FlowSpecId ::= 'decorate' { top.name = "decorate"; top.unparse = top.name; - top.errors := []; top.synName = "decorate"; top.authorityGrammar = hackGramFromFName(top.onNt.typeName); top.found = true; @@ -148,25 +146,24 @@ top::FlowSpecId ::= 'decorate' nonterminal FlowSpecInhs with config, location, grammarName, errors, env, unparse, onNt, inhList, flowEnv; +propagate errors on FlowSpecInhs; + concrete production nilFlowSpecInhs top::FlowSpecInhs ::= { top.unparse = ""; - top.errors := []; top.inhList = []; } concrete production oneFlowSpecInhs top::FlowSpecInhs ::= h::FlowSpecInh { top.unparse = h.unparse; - top.errors := h.errors; top.inhList = h.inhList; } concrete production consFlowSpecInhs top::FlowSpecInhs ::= h::FlowSpecInh ',' t::FlowSpecInhs { top.unparse = h.unparse ++ ", " ++ t.unparse; - top.errors := h.errors ++ t.errors; top.inhList = h.inhList ++ t.inhList; } @@ -174,11 +171,12 @@ nonterminal FlowSpecInh with config, location, grammarName, errors, env, unparse synthesized attribute inhList :: [String]; +propagate errors on FlowSpecInh; + concrete production flowSpecInh top::FlowSpecInh ::= inh::QNameAttrOccur { top.unparse = inh.unparse; - top.errors := inh.errors; top.inhList = if inh.found then [inh.attrDcl.fullName] else []; inh.attrFor = top.onNt; @@ -211,7 +209,7 @@ top::FlowSpecInh ::= 'decorate' local specs :: [Pair] = getFlowTypeSpecFor(top.onNt.typeName, top.flowEnv); local decSpec :: Maybe<[String]> = lookupBy(stringEq, "decorate", specs); - top.errors := + top.errors <- if decSpec.isJust then [] else [err(top.location, s"to use 'decorate' in a flow type for nonterminal ${top.onNt.typeName}, 'decorate' must also have an explicit flow type")]; @@ -221,26 +219,22 @@ top::FlowSpecInh ::= 'decorate' nonterminal NtList with config, location, grammarName, errors, env, unparse, flowSpecSpec, flowDefs, compiledGrammars, flowEnv; +propagate errors, flowDefs on NtList; + concrete production nilNtList top::NtList ::= { top.unparse = ""; - top.errors := []; - top.flowDefs = []; } concrete production oneNtList top::NtList ::= h::NtName { top.unparse = h.unparse; - top.errors := h.errors; - top.flowDefs = h.flowDefs; } concrete production consNtList top::NtList ::= h::NtName ',' t::NtList { top.unparse = h.unparse ++ ", " ++ t.unparse; - top.errors := h.errors ++ t.errors; - top.flowDefs = h.flowDefs ++ t.flowDefs; } nonterminal NtName with config, location, grammarName, errors, env, unparse, flowSpecSpec, flowDefs, compiledGrammars, flowEnv; @@ -256,7 +250,7 @@ top::NtName ::= nt::QName then myCopy.errors else nt.lookupType.errors; - top.flowDefs = + top.flowDefs := if nt.lookupType.found then myCopy.flowDefs else []; diff --git a/grammars/silver/driver/util/Compilation.sv b/grammars/silver/driver/util/Compilation.sv index 00c1f7e61..ef6078440 100644 --- a/grammars/silver/driver/util/Compilation.sv +++ b/grammars/silver/driver/util/Compilation.sv @@ -8,7 +8,7 @@ flowtype postOps {config} on Compilation; synthesized attribute postOps :: [DriverAction] with ++; synthesized attribute grammarList :: [Decorated RootSpec]; -synthesized attribute recheckGrammars :: [String]; +monoid attribute recheckGrammars :: [String] with [], ++; -- This is used on the outside, e.g. the ide functions. synthesized attribute allGrammars :: [Decorated RootSpec]; @@ -30,7 +30,7 @@ top::Compilation ::= g::Grammars r::Grammars buildGrammar::String benv::Build -- the list of rootspecs coming out of g top.grammarList = g.grammarList; -- the list of grammars that should be re-checked - top.recheckGrammars = g.recheckGrammars; + top.recheckGrammars := g.recheckGrammars; g.compiledGrammars = directBuildTree(map(grammarPairing, g.grammarList)); -- However, we are then forced to use the interface files that we are going to @@ -60,22 +60,18 @@ top::Compilation ::= g::Grammars r::Grammars buildGrammar::String benv::Build nonterminal Grammars with config, compiledGrammars, productionFlowGraphs, grammarFlowTypes, grammarList, recheckGrammars, translateGrammars, jarName; +propagate translateGrammars, recheckGrammars, jarName on Grammars; + abstract production consGrammars top::Grammars ::= h::RootSpec t::Grammars { top.grammarList = h :: t.grammarList; - top.recheckGrammars = h.recheckGrammars ++ t.recheckGrammars; - top.translateGrammars = h.translateGrammars ++ t.translateGrammars; - top.jarName = orElse(h.jarName, t.jarName); } abstract production nilGrammars top::Grammars ::= { top.grammarList = []; - top.recheckGrammars = []; - top.translateGrammars = []; - top.jarName = nothing(); } {-- diff --git a/grammars/silver/driver/util/RootSpec.sv b/grammars/silver/driver/util/RootSpec.sv index 1f8abe9d0..80aa1f600 100644 --- a/grammars/silver/driver/util/RootSpec.sv +++ b/grammars/silver/driver/util/RootSpec.sv @@ -25,7 +25,7 @@ nonterminal RootSpec with {-- - Grammars that were read from source. -} -synthesized attribute translateGrammars :: [Decorated RootSpec]; +monoid attribute translateGrammars :: [Decorated RootSpec] with [], ++; {-- - Parse errors present in this grammar (only for errorRootSpec!) @@ -72,22 +72,22 @@ top::RootSpec ::= g::Grammar grammarName::String grammarSource::String gramma top.grammarTime = grammarTime; top.interfaceTime = grammarTime; top.generateLocation = generateLocation; - top.recheckGrammars = []; - top.translateGrammars = [top]; + top.recheckGrammars := []; + top.translateGrammars := [top]; top.declaredName = g.declaredName; - top.moduleNames = makeSet(g.moduleNames ++ ["core"]); -- Ensure the prelude is in the deps, always - top.exportedGrammars = g.exportedGrammars; - top.optionalGrammars = g.optionalGrammars; - top.condBuild = g.condBuild; - top.allGrammarDependencies = actualDependencies; + top.moduleNames := makeSet(g.moduleNames ++ ["core"]); -- Ensure the prelude is in the deps, always + top.exportedGrammars := g.exportedGrammars; + top.optionalGrammars := g.optionalGrammars; + top.condBuild := g.condBuild; + top.allGrammarDependencies := actualDependencies; - top.defs = g.defs; - top.occursDefs = g.occursDefs; + top.defs := g.defs; + top.occursDefs := g.occursDefs; top.grammarErrors = g.grammarErrors; top.parsingErrors = []; - top.jarName = g.jarName; + top.jarName := g.jarName; } {-- @@ -102,22 +102,22 @@ top::RootSpec ::= i::InterfaceItems interfaceTime::Integer generateLocation::S top.generateLocation = generateLocation; local ood :: Boolean = isOutOfDate(interfaceTime, top.allGrammarDependencies, top.compiledGrammars); - top.recheckGrammars = if ood then [i.maybeDeclaredName.fromJust] else []; - top.translateGrammars = []; + top.recheckGrammars := if ood then [i.maybeDeclaredName.fromJust] else []; + top.translateGrammars := []; top.declaredName = i.maybeDeclaredName.fromJust; - top.moduleNames = i.maybeModuleNames.fromJust; - top.exportedGrammars = i.maybeExportedGrammars.fromJust; - top.optionalGrammars = i.maybeOptionalGrammars.fromJust; - top.condBuild = i.maybeCondBuild.fromJust; - top.allGrammarDependencies = i.maybeAllGrammarDependencies.fromJust; - - top.defs = i.maybeDefs.fromJust; - top.occursDefs = i.maybeOccursDefs.fromJust; + top.moduleNames := i.maybeModuleNames.fromJust; + top.exportedGrammars := i.maybeExportedGrammars.fromJust; + top.optionalGrammars := i.maybeOptionalGrammars.fromJust; + top.condBuild := i.maybeCondBuild.fromJust; + top.allGrammarDependencies := i.maybeAllGrammarDependencies.fromJust; + + top.defs := i.maybeDefs.fromJust; + top.occursDefs := i.maybeOccursDefs.fromJust; top.grammarErrors = []; -- TODO: consider getting grammarName and comparing against declaredName? top.parsingErrors = []; - top.jarName = nothing(); + top.jarName := nothing(); } {-- @@ -131,22 +131,22 @@ top::RootSpec ::= e::[ParseError] grammarName::String grammarSource::String g top.interfaceTime = grammarTime; top.generateLocation = generateLocation; - top.recheckGrammars = []; - top.translateGrammars = []; + top.recheckGrammars := []; + top.translateGrammars := []; top.declaredName = grammarName; - top.moduleNames = []; - top.exportedGrammars = []; - top.optionalGrammars = []; - top.condBuild = []; - top.allGrammarDependencies = []; - - top.defs = []; - top.occursDefs = []; + top.moduleNames := []; + top.exportedGrammars := []; + top.optionalGrammars := []; + top.condBuild := []; + top.allGrammarDependencies := []; + + top.defs := []; + top.occursDefs := []; top.grammarErrors = []; top.parsingErrors = map(parseErrorToMessage(grammarSource, _), e); - top.jarName = nothing(); + top.jarName := nothing(); } function parseErrorToMessage @@ -164,19 +164,18 @@ Pair ::= grammarSource::String e::ParseError end; } --- TODO: These should all be monoids -synthesized attribute maybeGrammarSource::Maybe; -synthesized attribute maybeGrammarTime::Maybe; -synthesized attribute maybeDeclaredName::Maybe; -synthesized attribute maybeModuleNames::Maybe<[String]>; -synthesized attribute maybeExportedGrammars::Maybe<[String]>; -synthesized attribute maybeOptionalGrammars::Maybe<[String]>; -synthesized attribute maybeCondBuild::Maybe<[[String]]>; -synthesized attribute maybeAllGrammarDependencies::Maybe<[String]>; -synthesized attribute maybeDefs::Maybe<[Def]>; -synthesized attribute maybeOccursDefs::Maybe<[DclInfo]>; +monoid attribute maybeGrammarSource::Maybe with nothing(), orElse; +monoid attribute maybeGrammarTime::Maybe with nothing(), orElse; +monoid attribute maybeDeclaredName::Maybe with nothing(), orElse; +monoid attribute maybeModuleNames::Maybe<[String]> with nothing(), orElse; +monoid attribute maybeExportedGrammars::Maybe<[String]> with nothing(), orElse; +monoid attribute maybeOptionalGrammars::Maybe<[String]> with nothing(), orElse; +monoid attribute maybeCondBuild::Maybe<[[String]]> with nothing(), orElse; +monoid attribute maybeAllGrammarDependencies::Maybe<[String]> with nothing(), orElse; +monoid attribute maybeDefs::Maybe<[Def]> with nothing(), orElse; +monoid attribute maybeOccursDefs::Maybe<[DclInfo]> with nothing(), orElse; -synthesized attribute interfaceErrors::[String] with ++; +monoid attribute interfaceErrors::[String] with [], ++; {-- - Representation of all properties of a grammar, to be serialized/deserialize to/from an interface @@ -184,20 +183,12 @@ synthesized attribute interfaceErrors::[String] with ++; -} nonterminal InterfaceItems with maybeGrammarSource, maybeGrammarTime, maybeDeclaredName, maybeModuleNames, maybeExportedGrammars, maybeOptionalGrammars, maybeCondBuild, maybeAllGrammarDependencies, maybeDefs, maybeOccursDefs, interfaceErrors; +propagate maybeGrammarSource, maybeGrammarTime, maybeDeclaredName, maybeModuleNames, maybeExportedGrammars, maybeOptionalGrammars, maybeCondBuild, maybeAllGrammarDependencies, maybeDefs, maybeOccursDefs + on InterfaceItems; + abstract production consInterfaceItem top::InterfaceItems ::= h::InterfaceItem t::InterfaceItems { - top.maybeGrammarSource = orElse(t.maybeGrammarSource, h.maybeGrammarSource); - top.maybeGrammarTime = orElse(t.maybeGrammarTime, h.maybeGrammarTime); - top.maybeDeclaredName = orElse(t.maybeDeclaredName, h.maybeDeclaredName); - top.maybeModuleNames = orElse(t.maybeModuleNames, h.maybeModuleNames); - top.maybeExportedGrammars = orElse(t.maybeExportedGrammars, h.maybeExportedGrammars); - top.maybeOptionalGrammars = orElse(t.maybeOptionalGrammars, h.maybeOptionalGrammars); - top.maybeCondBuild = orElse(t.maybeCondBuild, h.maybeCondBuild); - top.maybeAllGrammarDependencies = orElse(t.maybeAllGrammarDependencies, h.maybeAllGrammarDependencies); - top.maybeDefs = orElse(t.maybeDefs, h.maybeDefs); - top.maybeOccursDefs = orElse(t.maybeOccursDefs, h.maybeOccursDefs); - top.interfaceErrors := []; top.interfaceErrors <- if !top.maybeGrammarSource.isJust then ["Missing item grammarSource"] else []; top.interfaceErrors <- if !top.maybeGrammarTime.isJust then ["Missing item grammarTime"] else []; @@ -214,17 +205,6 @@ top::InterfaceItems ::= h::InterfaceItem t::InterfaceItems abstract production nilInterfaceItem top::InterfaceItems ::= { - top.maybeGrammarSource = nothing(); - top.maybeGrammarTime = nothing(); - top.maybeDeclaredName = nothing(); - top.maybeModuleNames = nothing(); - top.maybeExportedGrammars = nothing(); - top.maybeOptionalGrammars = nothing(); - top.maybeCondBuild = nothing(); - top.maybeAllGrammarDependencies = nothing(); - top.maybeDefs = nothing(); - top.maybeOccursDefs = nothing(); - top.interfaceErrors := ["Missing all items"]; } @@ -233,76 +213,68 @@ closed nonterminal InterfaceItem with maybeGrammarSource, maybeGrammarTime, mayb aspect default production top::InterfaceItem ::= { - top.maybeGrammarSource = nothing(); - top.maybeGrammarTime = nothing(); - top.maybeDeclaredName = nothing(); - top.maybeModuleNames = nothing(); - top.maybeExportedGrammars = nothing(); - top.maybeOptionalGrammars = nothing(); - top.maybeCondBuild = nothing(); - top.maybeAllGrammarDependencies = nothing(); - top.maybeDefs = nothing(); - top.maybeOccursDefs = nothing(); + -- Empty values as defaults + propagate maybeGrammarSource, maybeGrammarTime, maybeDeclaredName, maybeModuleNames, maybeExportedGrammars, maybeOptionalGrammars, maybeCondBuild, maybeAllGrammarDependencies, maybeDefs, maybeOccursDefs; } abstract production grammarSourceInterfaceItem top::InterfaceItem ::= val::String { - top.maybeGrammarSource = just(val); + top.maybeGrammarSource := just(val); } abstract production grammarTimeInterfaceItem top::InterfaceItem ::= val::Integer { - top.maybeGrammarTime = just(val); + top.maybeGrammarTime := just(val); } abstract production declaredNameInterfaceItem top::InterfaceItem ::= val::String { - top.maybeDeclaredName = just(val); + top.maybeDeclaredName := just(val); } abstract production moduleNamesInterfaceItem top::InterfaceItem ::= val::[String] { - top.maybeModuleNames = just(val); + top.maybeModuleNames := just(val); } abstract production exportedGrammarsInterfaceItem top::InterfaceItem ::= val::[String] { - top.maybeExportedGrammars = just(val); + top.maybeExportedGrammars := just(val); } abstract production optionalGrammarsInterfaceItem top::InterfaceItem ::= val::[String] { - top.maybeOptionalGrammars = just(val); + top.maybeOptionalGrammars := just(val); } abstract production condBuildInterfaceItem top::InterfaceItem ::= val::[[String]] { - top.maybeCondBuild = just(val); + top.maybeCondBuild := just(val); } abstract production allDepsInterfaceItem top::InterfaceItem ::= val::[String] { - top.maybeAllGrammarDependencies = just(val); + top.maybeAllGrammarDependencies := just(val); } abstract production defsInterfaceItem top::InterfaceItem ::= val::[Def] { - top.maybeDefs = just(val); + top.maybeDefs := just(val); } abstract production occursDefsInterfaceItem top::InterfaceItem ::= val::[DclInfo] { - top.maybeOccursDefs = just(val); + top.maybeOccursDefs := just(val); } {-- diff --git a/grammars/silver/extension/autoattr/Monoid.sv b/grammars/silver/extension/autoattr/Monoid.sv index 21c359ce3..16781a633 100644 --- a/grammars/silver/extension/autoattr/Monoid.sv +++ b/grammars/silver/extension/autoattr/Monoid.sv @@ -16,7 +16,7 @@ top::AGDcl ::= 'monoid' 'attribute' a::Name tl::BracketedOptTypeExprs '::' te::T -- TODO: We want to define our own defs here but can't forward to defsAGDcl because collections define different translation. -- Not sure about the best way to refactor this. - top.defs = + top.defs := [attrDef(defaultEnvItem(monoidDcl(top.grammarName, a.location, fName, tl.freeVariables, te.typerep, e, q.operation)))]; top.errors <- e.errors; @@ -117,7 +117,7 @@ top::ProductionStmt ::= attr::Decorated QName inputsWithAttr)); -- Construct an attribute def and call with the generated arguments - forwards to + forwards to attrContainsBase( concreteDefLHS(topName, location=top.location), '.', diff --git a/grammars/silver/extension/autoattr/Propagate.sv b/grammars/silver/extension/autoattr/Propagate.sv index 5cac91b21..8ec49b515 100644 --- a/grammars/silver/extension/autoattr/Propagate.sv +++ b/grammars/silver/extension/autoattr/Propagate.sv @@ -26,9 +26,9 @@ top::AGDcl ::= attrs::NameList nt::QName top.unparse = s"propagate ${attrs.unparse} on ${nt.unparse};"; -- Ugh, workaround for circular dependency - top.defs = []; - top.occursDefs = []; - top.moduleNames = []; + top.defs := []; + top.occursDefs := []; + top.moduleNames := []; local nonForwardingProds::[DclInfo] = filter(\ d::DclInfo -> !d.hasForward, getKnownProds(nt.lookupType.fullName, top.env)); @@ -97,8 +97,8 @@ top::ProductionStmt ::= attr::QName top.unparse = s"propagate ${attr.unparse};"; -- Ugh, workaround for circular dependency - top.defs = []; - top.productionAttributes = []; + top.defs := []; + top.productionAttributes := []; forwards to if !null(attr.lookupAttribute.errors) then errorProductionStmt(attr.lookupAttribute.errors, location=top.location) diff --git a/grammars/silver/extension/convenience/Productions.sv b/grammars/silver/extension/convenience/Productions.sv index d17ca2b6d..ff52288ef 100644 --- a/grammars/silver/extension/convenience/Productions.sv +++ b/grammars/silver/extension/convenience/Productions.sv @@ -15,7 +15,7 @@ concrete production productionDclC top::AGDcl ::= 'concrete' 'productions' lhs::ProductionLHS stmts::ProductionDclStmts { top.unparse = "concrete productions " ++ lhs.unparse ++ stmts.unparse; - top.moduleNames = []; + propagate moduleNames, jarName; -- Avoid dependency on forward stmts.lhsdcl = lhs; diff --git a/grammars/silver/extension/testing/WrongCode.sv b/grammars/silver/extension/testing/WrongCode.sv index 19e7be9ab..73116e58e 100644 --- a/grammars/silver/extension/testing/WrongCode.sv +++ b/grammars/silver/extension/testing/WrongCode.sv @@ -36,7 +36,7 @@ top::AGDcl ::= 'wrongFlowCode' s::String_t '{' ags::AGDcls '}' ags.env = occursEnv(ags.occursDefs, newScopeEnv(ags.defs, top.env)); -- let's ALSO propagate up flow info, so these kinds of errors are checked/caught - top.flowDefs = ags.flowDefs; + top.flowDefs := ags.flowDefs; forwards to emptyAGDcl(location=top.location); } diff --git a/grammars/silver/extension/treegen/Eq.sv b/grammars/silver/extension/treegen/Eq.sv index 2c4b11bb1..08d3e7ce5 100644 --- a/grammars/silver/extension/treegen/Eq.sv +++ b/grammars/silver/extension/treegen/Eq.sv @@ -11,7 +11,7 @@ concrete production deriveEqagdcl top::AGDcl ::= 'derive' 'Eq' 'on' names::QNames ';' { -- bug: stupid hack. Find some other way to fix this, maybe? - top.flowDefs = []; + top.flowDefs := []; forwards to foldr( diff --git a/grammars/silver/extension/treegen/TestFor.sv b/grammars/silver/extension/treegen/TestFor.sv index 057bfe767..ea6ba7606 100644 --- a/grammars/silver/extension/treegen/TestFor.sv +++ b/grammars/silver/extension/treegen/TestFor.sv @@ -7,9 +7,9 @@ terminal TestFor_T 'testFor'; concrete production testforagdcl top::AGDcl ::= 'testFor' testSuite::Name ':' n::Name '::' id::QName ',' e::Expr ';' { - top.defs = []; - top.moduleNames = []; - top.flowDefs = []; + top.defs := []; + top.moduleNames := []; + top.flowDefs := []; forward.env = newScopeEnv(forward.defs, top.env); diff --git a/grammars/silver/langutil/Attributes.sv b/grammars/silver/langutil/Attributes.sv index a28f19b31..efbbbd621 100644 --- a/grammars/silver/langutil/Attributes.sv +++ b/grammars/silver/langutil/Attributes.sv @@ -38,5 +38,5 @@ synthesized attribute ast :: a; {-- - For accumulating error/warning messages over a syntax tree -} -synthesized attribute errors :: [Message] with ++; +monoid attribute errors :: [Message] with [], ++; diff --git a/grammars/silver/modification/autocopyattr/AutoCopy.sv b/grammars/silver/modification/autocopyattr/AutoCopy.sv index 3ea3979f4..8261f7d99 100644 --- a/grammars/silver/modification/autocopyattr/AutoCopy.sv +++ b/grammars/silver/modification/autocopyattr/AutoCopy.sv @@ -12,7 +12,7 @@ top::AGDcl ::= 'autocopy' 'attribute' a::Name tl::BracketedOptTypeExprs '::' te: production attribute fName :: String; fName = top.grammarName ++ ":" ++ a.name; - top.defs = [autocopyDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep)]; + top.defs := [autocopyDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep)]; tl.initialEnv = top.env; tl.env = tl.envBindingTyVars; diff --git a/grammars/silver/modification/collection/Collection.sv b/grammars/silver/modification/collection/Collection.sv index 0b5f3380c..f6c09c7d0 100644 --- a/grammars/silver/modification/collection/Collection.sv +++ b/grammars/silver/modification/collection/Collection.sv @@ -124,9 +124,11 @@ top::AGDcl ::= 'synthesized' 'attribute' a::Name tl::BracketedOptTypeExprs '::' q.operatorForType = te.typerep; - top.defs = [synColDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep, q.operation)]; + top.defs := [synColDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep, q.operation)]; - top.errors := te.errors ++ q.errors ++ tl.errors ++ tl.errorsTyVars; + propagate errors, flowDefs; + + top.errors <- tl.errorsTyVars; top.errors <- if length(getAttrDclAll(fName, top.env)) > 1 @@ -148,9 +150,11 @@ top::AGDcl ::= 'inherited' 'attribute' a::Name tl::BracketedOptTypeExprs '::' te q.operatorForType = te.typerep; - top.defs = [inhColDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep, q.operation)]; + top.defs := [inhColDef(top.grammarName, a.location, fName, tl.freeVariables, te.typerep, q.operation)]; - top.errors := te.errors ++ q.errors ++ tl.errors ++ tl.errorsTyVars; + propagate errors, flowDefs; + + top.errors <- tl.errorsTyVars; top.errors <- if length(getAttrDclAll(fName, top.env)) > 1 @@ -164,14 +168,14 @@ top::ProductionStmt ::= 'production' 'attribute' a::Name '::' te::TypeExpr 'with { top.unparse = "production attribute " ++ a.name ++ " :: " ++ te.unparse ++ " with " ++ q.unparse ++ " ;" ; - top.productionAttributes = [localColDef(top.grammarName, a.location, fName, te.typerep, q.operation)]; + top.productionAttributes := [localColDef(top.grammarName, a.location, fName, te.typerep, q.operation)]; production attribute fName :: String; fName = top.frame.fullName ++ ":local:" ++ a.name; - top.defs = []; + top.defs := []; - top.errors := te.errors ++ q.errors; + propagate errors; top.errors <- if length(getValueDclAll(fName, top.env)) > 1 @@ -325,8 +329,8 @@ top::ProductionStmt ::= dl::DefLHS '.' attr::QNameAttrOccur '<-' e::Expr ';' top.unparse = "\t" ++ dl.unparse ++ "." ++ attr.unparse ++ " <- " ++ e.unparse ++ ";"; -- defs must stay here explicitly, because we dispatch on types in the forward here! - top.productionAttributes = []; - top.defs = []; + top.productionAttributes := []; + top.defs := []; dl.defLHSattr = attr; attr.attrFor = dl.typerep; @@ -343,8 +347,8 @@ top::ProductionStmt ::= dl::DefLHS '.' attr::QNameAttrOccur ':=' e::Expr ';' top.unparse = "\t" ++ dl.unparse ++ "." ++ attr.unparse ++ " := " ++ e.unparse ++ ";"; -- defs must stay here explicitly, because we dispatch on types in the forward here! - top.productionAttributes = []; - top.defs = []; + top.productionAttributes := []; + top.defs := []; dl.defLHSattr = attr; attr.attrFor = dl.typerep; @@ -362,8 +366,8 @@ top::ProductionStmt ::= val::QName '<-' e::Expr ';' top.errors <- val.lookupValue.errors; - top.productionAttributes = []; - top.defs = []; + top.productionAttributes := []; + top.defs := []; forwards to if null(val.lookupValue.dcls) then errorValueDef(val, e, location=top.location) @@ -377,8 +381,8 @@ top::ProductionStmt ::= val::QName ':=' e::Expr ';' top.errors <- val.lookupValue.errors; - top.productionAttributes = []; - top.defs = []; + top.productionAttributes := []; + top.defs := []; forwards to if null(val.lookupValue.dcls) then errorValueDef(val, e, location=top.location) diff --git a/grammars/silver/modification/copper/ActionCode.sv b/grammars/silver/modification/copper/ActionCode.sv index a49b0d47d..99d1adbe0 100644 --- a/grammars/silver/modification/copper/ActionCode.sv +++ b/grammars/silver/modification/copper/ActionCode.sv @@ -9,7 +9,7 @@ top::AGDcl ::= 'concrete' 'production' id::Name ns::ProductionSignature pm::Prod production fName :: String = top.grammarName ++ ":" ++ id.name; - top.syntaxAst = [ + top.syntaxAst := [ syntaxProduction(ns.namedSignature, foldr(consProductionMod, nilProductionMod(), prodAction(acode.actionCode) :: pm.productionModifiers))]; @@ -42,8 +42,8 @@ concrete production actionCode_c top::ActionCode_c ::= '{' stmts::ProductionStmts '}' { top.unparse = "{\n" ++ stmts.unparse ++ "}\n"; - top.defs = flatMap(hackTransformLocals, stmts.defs); - top.flowDefs = stmts.flowDefs; + top.defs := flatMap(hackTransformLocals, stmts.defs); + propagate flowDefs; top.actionCode = sflatMap(hacklocaldeclarations, stmts.defs) ++ stmts.translation; diff --git a/grammars/silver/modification/copper/CustomLayout.sv b/grammars/silver/modification/copper/CustomLayout.sv index 13f04aa9f..cd5923c2f 100644 --- a/grammars/silver/modification/copper/CustomLayout.sv +++ b/grammars/silver/modification/copper/CustomLayout.sv @@ -8,7 +8,7 @@ top::ProductionModifier ::= 'layout' '{' terms::TermList '}' { top.unparse = "layout {" ++ terms.unparse ++ "}"; - top.productionModifiers = [prodLayout(terms.termList)]; + top.productionModifiers := [prodLayout(terms.termList)]; top.errors := terms.errors; } @@ -17,7 +17,7 @@ top::ProductionModifier ::= 'layout' '{' '}' { top.unparse = "layout {}"; - top.productionModifiers = [prodLayout([])]; + top.productionModifiers := [prodLayout([])]; top.errors := []; } @@ -26,7 +26,7 @@ top::NonterminalModifier ::= 'layout' '{' terms::TermList '}' { top.unparse = "layout {" ++ terms.unparse ++ "}"; - top.nonterminalModifiers = [ntLayout(terms.termList)]; + top.nonterminalModifiers := [ntLayout(terms.termList)]; top.errors := terms.errors; } @@ -35,43 +35,31 @@ top::NonterminalModifier ::= 'layout' '{' '}' { top.unparse = "layout {}"; - top.nonterminalModifiers = [ntLayout([])]; + top.nonterminalModifiers := [ntLayout([])]; top.errors := []; } attribute customLayout occurs on ParserComponents, ParserComponent; -aspect production nilParserComponent -top::ParserComponents ::= -{ - top.customLayout = nothing(); -} - -aspect production consParserComponent -top::ParserComponents ::= c1::ParserComponent c2::ParserComponents -{ - top.customLayout = orElse(c1.customLayout, c2.customLayout); -} +propagate customLayout on ParserComponents, ParserComponent; aspect default production top::ParserComponent ::= { - top.customLayout = nothing(); + propagate customLayout; } concrete production parserComponentLayout top::ParserComponent ::= 'layout' '{' terms::TermList '}' ';' { top.unparse = "layout {" ++ terms.unparse ++ "};"; - top.errors := terms.errors; - top.customLayout = just(terms.termList); + top.customLayout <- just(terms.termList); } concrete production parserComponentLayoutNone top::ParserComponent ::= 'layout' '{' '}' ';' { top.unparse = "layout {};"; - top.errors := []; - top.customLayout = just([]); + top.customLayout <- just([]); } diff --git a/grammars/silver/modification/copper/DisambiguationGroup.sv b/grammars/silver/modification/copper/DisambiguationGroup.sv index f214ff145..a612bdf86 100644 --- a/grammars/silver/modification/copper/DisambiguationGroup.sv +++ b/grammars/silver/modification/copper/DisambiguationGroup.sv @@ -23,6 +23,6 @@ top::AGDcl ::= 'disambiguate' terms::TermList acode::ActionCode_c acode.frame = disambiguationContext(myFlowGraph); - top.syntaxAst = [syntaxDisambiguationGroup(fName, terms.termList, false, acode.actionCode)]; + top.syntaxAst := [syntaxDisambiguationGroup(fName, terms.termList, false, acode.actionCode)]; } diff --git a/grammars/silver/modification/copper/LexerClass.sv b/grammars/silver/modification/copper/LexerClass.sv index 699f5ace3..7a7bc1474 100644 --- a/grammars/silver/modification/copper/LexerClass.sv +++ b/grammars/silver/modification/copper/LexerClass.sv @@ -18,7 +18,7 @@ top::AGDcl ::= 'lexer' 'class' id::Name modifiers::LexerClassModifiers ';' production attribute fName :: String; fName = top.grammarName ++ ":" ++ id.name; - top.defs = [lexerClassDef(top.grammarName, id.location, fName)]; + top.defs := [lexerClassDef(top.grammarName, id.location, fName)]; top.errors <- if length(getLexerClassDcl(fName, top.env)) > 1 then [err(id.location, "Lexer class '" ++ fName ++ "' is already bound.")] @@ -26,38 +26,32 @@ top::AGDcl ::= 'lexer' 'class' id::Name modifiers::LexerClassModifiers ';' top.errors := modifiers.errors; - top.syntaxAst = [syntaxLexerClass(fName, + top.syntaxAst := [syntaxLexerClass(fName, foldr(consLexerClassMod, nilLexerClassMod(), modifiers.lexerClassModifiers))]; } nonterminal LexerClassModifiers with config, location, unparse, lexerClassModifiers, errors, env, grammarName, compiledGrammars, flowEnv; closed nonterminal LexerClassModifier with config, location, unparse, lexerClassModifiers, errors, env, grammarName, compiledGrammars, flowEnv; -synthesized attribute lexerClassModifiers :: [SyntaxLexerClassModifier]; +monoid attribute lexerClassModifiers :: [SyntaxLexerClassModifier] with [], ++; + +propagate errors on LexerClassModifiers, LexerClassModifier; +propagate lexerClassModifiers on LexerClassModifiers; abstract production lexerClassModifiersNone top::LexerClassModifiers ::= { top.unparse = ""; - - top.lexerClassModifiers = []; - top.errors := []; } concrete production lexerClassModifierSingle top::LexerClassModifiers ::= tm::LexerClassModifier { top.unparse = tm.unparse; - - top.lexerClassModifiers = tm.lexerClassModifiers; - top.errors := tm.errors; } concrete production lexerClassModifiersCons top::LexerClassModifiers ::= h::LexerClassModifier ',' t::LexerClassModifiers { top.unparse = h.unparse ++ " " ++ t.unparse; - - top.lexerClassModifiers = h.lexerClassModifiers ++ t.lexerClassModifiers; - top.errors := h.errors ++ t.errors; } concrete production lexerClassModifierExtends @@ -65,8 +59,7 @@ top::LexerClassModifier ::= 'extends' cls::LexerClasses { top.unparse = "extends " ++ cls.unparse; - top.lexerClassModifiers = [lexerClassExtends(cls.lexerClasses)]; - top.errors := cls.errors; + top.lexerClassModifiers := [lexerClassExtends(cls.lexerClasses)]; } concrete production lexerClassModifierDominates @@ -74,8 +67,7 @@ top::LexerClassModifier ::= 'dominates' terms::TermPrecs { top.unparse = "dominates " ++ terms.unparse; - top.lexerClassModifiers = [lexerClassDominates(terms.precTermList)]; - top.errors := terms.errors; + top.lexerClassModifiers := [lexerClassDominates(terms.precTermList)]; } concrete production lexerClassModifierSubmitsTo @@ -83,8 +75,7 @@ top::LexerClassModifier ::= 'submits' 'to' terms::TermPrecs { top.unparse = "submits to " ++ terms.unparse; - top.lexerClassModifiers = [lexerClassSubmits(terms.precTermList)]; - top.errors := terms.errors; + top.lexerClassModifiers := [lexerClassSubmits(terms.precTermList)]; } concrete production lexerClassModifierDisambiguate @@ -92,8 +83,7 @@ top::LexerClassModifier ::= 'disambiguate' acode::ActionCode_c { top.unparse = "disambiguate " ++ acode.unparse; - top.lexerClassModifiers = [lexerClassDisambiguate(acode.actionCode)]; - top.errors := acode.errors; + top.lexerClassModifiers := [lexerClassDisambiguate(acode.actionCode)]; -- oh no again! local myFlow :: EnvTree = head(searchEnvTree(top.grammarName, top.compiledGrammars)).grammarFlowTypes; diff --git a/grammars/silver/modification/copper/ParserAttributes.sv b/grammars/silver/modification/copper/ParserAttributes.sv index a4f2636ea..5338f065c 100644 --- a/grammars/silver/modification/copper/ParserAttributes.sv +++ b/grammars/silver/modification/copper/ParserAttributes.sv @@ -8,7 +8,7 @@ top::AGDcl ::= 'parser' 'attribute' a::Name '::' te::TypeExpr 'action' acode::Ac production attribute fName :: String; fName = top.grammarName ++ ":" ++ a.name; - top.defs = [parserAttrDef(top.grammarName, a.location, fName, te.typerep)]; + top.defs := [parserAttrDef(top.grammarName, a.location, fName, te.typerep)]; top.errors <- if length(getValueDclAll(fName, top.env)) > 1 then [err(a.location, "Attribute '" ++ fName ++ "' is already bound.")] @@ -26,7 +26,7 @@ top::AGDcl ::= 'parser' 'attribute' a::Name '::' te::TypeExpr 'action' acode::Ac acode.frame = actionContext(myFlowGraph); acode.env = newScopeEnv(acode.defs, top.env); - top.syntaxAst = [syntaxParserAttribute(fName, te.typerep, acode.actionCode)]; + top.syntaxAst := [syntaxParserAttribute(fName, te.typerep, acode.actionCode)]; } concrete production attributeAspectParser @@ -37,7 +37,7 @@ top::AGDcl ::= 'aspect' 'parser' 'attribute' a::QName 'action' acode::ActionCode production attribute fName :: String; fName = a.lookupValue.dcl.fullName; - top.defs = []; + top.defs := []; top.errors <- if null(a.lookupValue.dcls) then [err(a.location, "Undefined attribute '" ++ a.name ++ "'.")] @@ -55,6 +55,6 @@ top::AGDcl ::= 'aspect' 'parser' 'attribute' a::QName 'action' acode::ActionCode acode.frame = actionContext(myFlowGraph); acode.env = newScopeEnv(acode.defs, top.env); - top.syntaxAst = [syntaxParserAttributeAspect(fName, acode.actionCode)]; + top.syntaxAst := [syntaxParserAttributeAspect(fName, acode.actionCode)]; } diff --git a/grammars/silver/modification/copper/ParserDcl.sv b/grammars/silver/modification/copper/ParserDcl.sv index 62ef22f66..3827eda6a 100644 --- a/grammars/silver/modification/copper/ParserDcl.sv +++ b/grammars/silver/modification/copper/ParserDcl.sv @@ -11,15 +11,16 @@ top::AGDcl ::= 'parser' n::Name '::' t::TypeExpr '{' m::ParserComponents '}' { top.unparse = "parser " ++ m.unparse ++ ";"; -- TODO? - top.moduleNames = m.moduleNames; + propagate errors, moduleNames; - top.errors := t.errors ++ m.errors ++ liftedAGDcls.errors; + top.errors <- liftedAGDcls.errors; -- Right now parsers masquerade as functions. This is probably fine. -- Only bug is that you can aspect it, but it's pointless to do so, you can't affect anything. - top.defs = [funDef(top.grammarName, n.location, namedSig)]; + top.defs := [funDef(top.grammarName, n.location, namedSig)]; -- TODO: These declarations should probably bubble up to the top level instead of being decorated here + -- TODO: Actually liftedAGDcls can probably just go away if we generate CST AST decls directly production liftedAGDcls :: AGDcl = m.liftedAGDcls; liftedAGDcls.config = top.config; liftedAGDcls.grammarName = top.grammarName; @@ -50,51 +51,46 @@ top::AGDcl ::= 'parser' n::Name '::' t::TypeExpr '{' m::ParserComponents '}' parserSpec(top.location, top.grammarName, fName, t.typerep.typeName, m.moduleNames, m.customLayout, m.terminalPrefixes, liftedAGDcls.syntaxAst); spec.compiledGrammars = top.compiledGrammars; - top.parserSpecs = [spec]; -- Note that this is undecorated. + top.parserSpecs := [spec]; -- Note that this is undecorated. } -synthesized attribute liftedAGDcls::AGDcl; +global nilAGDcl::AGDcl = emptyAGDcl(location=loc("", -1, -1, -1, -1, -1, -1)); +function appAGDcl +AGDcl ::= a::AGDcl b::AGDcl +{ return appendAGDcl(a, b, location=loc("", -1, -1, -1, -1, -1, -1)); } + +monoid attribute liftedAGDcls::AGDcl with nilAGDcl, appAGDcl; nonterminal ParserComponents with config, env, grammarName, location, unparse, errors, moduleNames, compiledGrammars, grammarDependencies, terminalPrefixes, liftedAGDcls; +propagate errors, moduleNames, terminalPrefixes, liftedAGDcls on ParserComponents; + concrete production nilParserComponent top::ParserComponents ::= { top.unparse = ""; - top.moduleNames = []; - top.errors := []; - top.terminalPrefixes = []; - top.liftedAGDcls = emptyAGDcl(location=top.location); } concrete production consParserComponent top::ParserComponents ::= c1::ParserComponent c2::ParserComponents { top.unparse = c1.unparse ++ ", " ++ c2.unparse; - top.moduleNames = c1.moduleNames ++ c2.moduleNames; - top.errors := c1.errors ++ c2.errors; - top.terminalPrefixes = c1.terminalPrefixes ++ c2.terminalPrefixes; - top.liftedAGDcls = appendAGDcl(c1.liftedAGDcls, c2.liftedAGDcls, location=top.location); } closed nonterminal ParserComponent with config, env, grammarName, location, unparse, errors, moduleNames, compiledGrammars, grammarDependencies, terminalPrefixes, liftedAGDcls; +propagate errors, moduleNames, terminalPrefixes, liftedAGDcls on ParserComponent; + aspect default production top::ParserComponent ::= { - top.moduleNames = []; - top.terminalPrefixes = []; - top.liftedAGDcls = emptyAGDcl(location=top.location); + propagate errors, moduleNames, terminalPrefixes, liftedAGDcls; } concrete production parserComponent top::ParserComponent ::= m::ModuleName mods::ParserComponentModifiers ';' { top.unparse = m.unparse; - top.moduleNames = m.moduleNames; - top.errors := m.errors ++ mods.errors; - top.terminalPrefixes = mods.terminalPrefixes; - top.liftedAGDcls = mods.liftedAGDcls; mods.componentGrammarName = head(m.moduleNames); } @@ -104,31 +100,28 @@ autocopy attribute componentGrammarName::String; {-- Have special env built from just this parser component and the global env -} nonterminal ParserComponentModifiers with config, env, grammarName, componentGrammarName, compiledGrammars, grammarDependencies, location, unparse, errors, terminalPrefixes, liftedAGDcls; +propagate errors, terminalPrefixes, liftedAGDcls on ParserComponentModifiers; + concrete production nilParserComponentModifier top::ParserComponentModifiers ::= { top.unparse = ""; - top.errors := []; - top.terminalPrefixes = []; - top.liftedAGDcls = emptyAGDcl(location=top.location); } concrete production consParserComponentModifier top::ParserComponentModifiers ::= h::ParserComponentModifier t::ParserComponentModifiers { top.unparse = h.unparse ++ t.unparse; - top.errors := h.errors ++ t.errors; - top.terminalPrefixes = h.terminalPrefixes ++ t.terminalPrefixes; - top.liftedAGDcls = appendAGDcl(h.liftedAGDcls, t.liftedAGDcls, location=top.location); } nonterminal ParserComponentModifier with config, env, grammarName, componentGrammarName, compiledGrammars, grammarDependencies, location, unparse, errors, terminalPrefixes, liftedAGDcls; +propagate errors, terminalPrefixes, liftedAGDcls on ParserComponentModifier; + aspect default production top::ParserComponentModifier ::= { - top.terminalPrefixes = []; - top.liftedAGDcls = emptyAGDcl(location=top.location); + propagate errors, terminalPrefixes, liftedAGDcls; } -- Separate bit translating the parser declaration. diff --git a/grammars/silver/modification/copper/Prefix.sv b/grammars/silver/modification/copper/Prefix.sv index da1f7abef..24c61231f 100644 --- a/grammars/silver/modification/copper/Prefix.sv +++ b/grammars/silver/modification/copper/Prefix.sv @@ -11,9 +11,7 @@ concrete production prefixParserComponentModifier top::ParserComponentModifier ::= 'prefix' ts::TerminalPrefixItems 'with' s::TerminalPrefix { top.unparse = "prefix " ++ ts.unparse ++ " with " ++ s.unparse; - top.errors := ts.errors ++ s.errors; - top.terminalPrefixes = map(pair(_, s.terminalPrefix), ts.prefixItemNames); - top.liftedAGDcls = s.liftedAGDcls; + top.terminalPrefixes <- map(pair(_, s.terminalPrefix), ts.prefixItemNames); s.prefixedTerminals = ts.prefixItemNames; } @@ -26,7 +24,7 @@ top::TerminalPrefix ::= s::QName { top.unparse = s.unparse; top.errors := s.lookupType.errors; - top.liftedAGDcls = emptyAGDcl(location=top.location); + propagate liftedAGDcls; top.terminalPrefix = makeCopperName(s.lookupType.fullName); } @@ -38,7 +36,7 @@ top::TerminalPrefix ::= r::RegExpr tm::TerminalModifiers -- Prefix terminal name isn't based off the prefix right now since that might not be alphanumeric -- TODO make the terminal name based off alphanumeric characters from the regex for easier debugging of parse conflicts local terminalName::String = "Prefix_" ++ toString(genInt()); - top.liftedAGDcls = + top.liftedAGDcls := terminalDclDefault( terminalKeywordModifierNone(location=top.location), name(terminalName, top.location), @@ -76,7 +74,7 @@ top::TerminalModifier ::= terms::[String] { top.unparse = s"use prefix separator for {${implode(", ", terms)}}"; - top.terminalModifiers = [termUsePrefixSeperatorFor(terms)]; + top.terminalModifiers := [termUsePrefixSeperatorFor(terms)]; top.errors := []; } @@ -160,8 +158,8 @@ concrete production disambiguateParserComponent top::ParserComponent ::= 'prefer' t::QName 'over' ts::TermList ';' { top.unparse = "prefer " ++ t.unparse ++ " over " ++ ts.unparse; - top.errors := t.lookupType.errors ++ ts.errors; - top.liftedAGDcls = + top.errors <- t.lookupType.errors; + top.liftedAGDcls <- -- Generate a disambiguation function for every combination of ts. -- TODO: we can't use Copper's subset disambiguation functions here unfourtunately, -- since we currently require those to be disjoint. @@ -200,8 +198,7 @@ top::LexerClassModifier ::= 'prefix' 'separator' s::String_t { top.unparse = s"prefix separator ${s.lexeme}"; - top.lexerClassModifiers = [lexerClassPrefixSeperator(substring(1, length(s.lexeme) - 1, s.lexeme))]; - top.errors := []; + top.lexerClassModifiers := [lexerClassPrefixSeperator(substring(1, length(s.lexeme) - 1, s.lexeme))]; } {- Not supported due to ambiguity with modifiers on prefix terminal defined @@ -211,7 +208,6 @@ top::TerminalModifier ::= 'prefix' 'separator' s::String_t { top.unparse = s"prefix separator ${s.lexeme}"; - top.terminalModifiers = [termPrefixSeperator(substring(1, length(s.lexeme) - 1, s.lexeme))]; - top.errors := []; + top.terminalModifiers := [termPrefixSeperator(substring(1, length(s.lexeme) - 1, s.lexeme))]; } -} diff --git a/grammars/silver/modification/copper/ProductionStmt.sv b/grammars/silver/modification/copper/ProductionStmt.sv index f5e372931..571444119 100644 --- a/grammars/silver/modification/copper/ProductionStmt.sv +++ b/grammars/silver/modification/copper/ProductionStmt.sv @@ -23,10 +23,11 @@ top::ProductionStmt ::= 'pluck' e::Expr ';' -- Perhaps this problem can be resolved by using a proper type in this situation. top.translation = "return (Integer)(" ++ e.translation ++ ");\n"; - top.errors := (if !top.frame.permitPluck - then [err(top.location, "'pluck' allowed only in disambiguation-group parser actions.")] - else []) - ++ e.errors; + propagate errors; + top.errors <- + if !top.frame.permitPluck + then [err(top.location, "'pluck' allowed only in disambiguation-group parser actions.")] + else []; local tyCk :: TypeCheck = check(e.typerep, terminalIdType()); tyCk.downSubst = e.upSubst; @@ -51,10 +52,11 @@ top::ProductionStmt ::= 'print' e::Expr ';' top.translation = "System.err.println(" ++ e.translation ++ ");\n"; - top.errors := (if !top.frame.permitActions - then [err(top.location, "'print' statement allowed only in parser action blocks. You may be looking for print(String,IO) :: IO.")] - else []) - ++ e.errors; + propagate errors; + top.errors <- + if !top.frame.permitActions + then [err(top.location, "'print' statement allowed only in parser action blocks. You may be looking for print(String,IO) :: IO.")] + else []; local attribute errCheck1 :: TypeCheck; errCheck1.finalSubst = top.finalSubst; @@ -80,10 +82,11 @@ top::ProductionStmt ::= val::Decorated QName e::Expr { top.unparse = "\t" ++ val.unparse ++ " = " ++ e.unparse ++ ";"; - top.errors := e.errors ++ - (if !top.frame.permitActions - then [err(top.location, "Assignment to parser attributes only permitted in parser action blocks")] - else []); + propagate errors; + top.errors <- + if !top.frame.permitActions + then [err(top.location, "Assignment to parser attributes only permitted in parser action blocks")] + else []; top.translation = makeCopperName(val.lookupValue.fullName) ++ " = " ++ e.translation ++ ";\n"; @@ -105,10 +108,11 @@ top::ProductionStmt ::= 'pushToken' '(' val::QName ',' lexeme::Expr ')' ';' { top.unparse = "\t" ++ "pushToken(" ++ val.unparse ++ ", " ++ lexeme.unparse ++ ");"; - top.errors := lexeme.errors ++ - (if !top.frame.permitActions - then [err(top.location, "Tokens may only be pushed in action blocks")] - else []); + propagate errors; + top.errors <- + if !top.frame.permitActions + then [err(top.location, "Tokens may only be pushed in action blocks")] + else []; top.translation = "pushToken(Terminals." ++ makeCopperName(val.lookupType.fullName) ++ ", (" ++ lexeme.translation ++ ").toString()" ++ ");"; @@ -129,10 +133,13 @@ concrete production blockStmt top::ProductionStmt ::= '{' stmts::ProductionStmts '}' { top.unparse = "\t{\n" ++ stmts.unparse ++ "\n\t}"; - top.errors := stmts.errors ++ - (if !top.frame.permitActions - then [err(top.location, "Block statement is only permitted in action blocks")] - else []); + + propagate errors; + top.errors <- + if !top.frame.permitActions + then [err(top.location, "Block statement is only permitted in action blocks")] + else []; + top.translation = stmts.translation; stmts.downSubst = top.downSubst; @@ -145,10 +152,11 @@ top::ProductionStmt ::= 'if' '(' condition::Expr ')' th::ProductionStmt 'else' e { top.unparse = "\t" ++ "if (" ++ condition.unparse ++ ") " ++ th.unparse ++ "\nelse " ++ el.unparse; - top.errors := condition.errors ++ th.errors ++ el.errors ++ - (if !top.frame.permitActions - then [err(top.location, "If statement is only permitted in action blocks")] - else []); + propagate errors; + top.errors <- + if !top.frame.permitActions + then [err(top.location, "If statement is only permitted in action blocks")] + else []; top.translation = s"if(${condition.translation}) {${th.translation}} else {${el.translation}}"; @@ -187,9 +195,11 @@ top::DefLHS ::= q::Decorated QName top.found = false; -- Note this is always erroring! - top.errors := if !top.frame.permitActions - then [err(q.location, "Parser attributes can only be used in action blocks")] - else [err(q.location, "Parser action blocks are imperative, not declarative. You cannot modify the attributes of " ++ q.name ++ ". If you are trying to set inherited attributes, you should use 'decorate ... with { ... }' when you create it.")]; + propagate errors; + top.errors <- + if !top.frame.permitActions + then [err(q.location, "Parser attributes can only be used in action blocks")] + else [err(q.location, "Parser action blocks are imperative, not declarative. You cannot modify the attributes of " ++ q.name ++ ". If you are trying to set inherited attributes, you should use 'decorate ... with { ... }' when you create it.")]; top.translation = error("Internal compiler error: translation not defined in the presence of errors"); @@ -202,7 +212,7 @@ top::ProductionStmt ::= val::Decorated QName e::Expr top.unparse = "\t" ++ val.unparse ++ " = " ++ e.unparse ++ ";"; -- these values should only ever be in scope when it's valid to use them - top.errors := e.errors; + propagate errors; top.errors <- if val.name != "lexeme" then [] else diff --git a/grammars/silver/modification/copper/TermList.sv b/grammars/silver/modification/copper/TermList.sv index 133145a01..82184e4de 100644 --- a/grammars/silver/modification/copper/TermList.sv +++ b/grammars/silver/modification/copper/TermList.sv @@ -8,18 +8,20 @@ grammar silver:modification:copper; synthesized attribute qnames :: [QName]; nonterminal TermList with config, grammarName, unparse, location, qnames, termList, defs, errors, env; -synthesized attribute termList :: [String]; +monoid attribute termList :: [String] with [], ++; + +propagate errors, termList on TermList; concrete production termListOne terms::TermList ::= t::QName { - forwards to termList(t,termListNull(location=t.location), location=t.location); + forwards to termList(t,termListNull(location=t.location), location=t.location); } concrete production termListCons terms::TermList ::= t::QName ',' terms_tail::TermList { - forwards to termList(t,terms_tail,location=terms.location); + forwards to termList(t,terms_tail,location=terms.location); } @@ -34,13 +36,12 @@ top::TermList ::= h::QName t::TermList production fName::String = h.lookupType.dcl.fullName; - top.termList = [fName] ++ t.termList ; + top.termList <- [fName]; -- Itd be nice if we didnt need this guard - top.defs = if null(h.lookupType.dcls) then t.defs - else pluckTermDef(top.grammarName, h.location, fName) :: t.defs; + top.defs := if null(h.lookupType.dcls) then t.defs + else pluckTermDef(top.grammarName, h.location, fName) :: t.defs; - top.errors := t.errors; -- Since were looking it up in two ways, do the errors ourselves -- Todo: Consider: should this report a different error if the element of the list -- exists but is not a terminal, i.e "Expected a terminal but got a _____"? @@ -56,7 +57,5 @@ top::TermList ::= { top.unparse = ""; top.qnames = []; - top.termList = []; - top.defs = []; - top.errors := []; + top.defs := []; } diff --git a/grammars/silver/modification/copper/TerminalDcl.sv b/grammars/silver/modification/copper/TerminalDcl.sv index f030c6b82..436631ccf 100644 --- a/grammars/silver/modification/copper/TerminalDcl.sv +++ b/grammars/silver/modification/copper/TerminalDcl.sv @@ -4,37 +4,17 @@ terminal Dominates_t 'dominates' lexer classes {KEYWORD}; terminal Submits_t 'submits' lexer classes {KEYWORD}; terminal Classes_kwd 'classes' lexer classes {KEYWORD}; -synthesized attribute lexerClasses :: [String] occurs on TerminalModifier, TerminalModifiers; - -aspect production terminalModifiersNone -top::TerminalModifiers ::= -{ - top.lexerClasses = []; -} -aspect production terminalModifierSingle -top::TerminalModifiers ::= tm::TerminalModifier -{ - top.lexerClasses = tm.lexerClasses; -} -aspect production terminalModifiersCons -top::TerminalModifiers ::= h::TerminalModifier ',' t::TerminalModifiers -{ - top.lexerClasses = h.lexerClasses ++ t.lexerClasses; -} - -aspect default production -top::TerminalModifier ::= -{ - top.lexerClasses = []; -} +monoid attribute lexerClasses :: [String] with [], ++; +attribute lexerClasses occurs on TerminalModifier, TerminalModifiers; +propagate lexerClasses on TerminalModifiers, TerminalModifier; concrete production terminalModifierDominates top::TerminalModifier ::= 'dominates' terms::TermPrecs { top.unparse = "dominates { " ++ terms.unparse ++ " } "; - top.terminalModifiers = [termDominates(terms.precTermList)]; - top.errors := terms.errors; + top.terminalModifiers := [termDominates(terms.precTermList)]; + propagate errors; } concrete production terminalModifierSubmitsTo @@ -42,8 +22,8 @@ top::TerminalModifier ::= 'submits' 'to' terms::TermPrecs { top.unparse = "submits to { " ++ terms.unparse ++ " } " ; - top.terminalModifiers = [termSubmits(terms.precTermList)]; - top.errors := terms.errors; + top.terminalModifiers := [termSubmits(terms.precTermList)]; + propagate errors; } concrete production terminalModifierClassSpec @@ -51,9 +31,8 @@ top::TerminalModifier ::= 'lexer' 'classes' cl::LexerClasses { top.unparse = "lexer classes { " ++ cl.unparse ++ " } " ; - top.terminalModifiers = [termClasses(cl.lexerClasses)]; - top.lexerClasses = cl.lexerClasses; - top.errors := cl.errors; + top.terminalModifiers := [termClasses(cl.lexerClasses)]; + propagate errors; } concrete production terminalModifierActionCode @@ -61,7 +40,7 @@ top::TerminalModifier ::= 'action' acode::ActionCode_c { top.unparse = "action " ++ acode.unparse; - top.terminalModifiers = [termAction(acode.actionCode)]; + top.terminalModifiers := [termAction(acode.actionCode)]; -- oh no again! local myFlow :: EnvTree = head(searchEnvTree(top.grammarName, top.compiledGrammars)).grammarFlowTypes; @@ -73,33 +52,35 @@ top::TerminalModifier ::= 'action' acode::ActionCode_c acode.frame = actionContext(myFlowGraph); acode.env = newScopeEnv(terminalActionVars ++ acode.defs, top.env); - top.errors := acode.errors; + propagate errors; } -synthesized attribute precTermList :: [String]; +monoid attribute precTermList :: [String] with [], ++; nonterminal TermPrecs with config, grammarName, unparse, location, precTermList, errors, env; +propagate errors, precTermList on TermPrecs; concrete production termPrecsOne top::TermPrecs ::= t::QName { - forwards to termPrecs(termPrecList(t,termPrecListNull(location=t.location), location=t.location), location=top.location); + forwards to termPrecs(termPrecList(t,termPrecListNull(location=t.location), location=t.location), location=top.location); } concrete production termPrecsList top::TermPrecs ::= '{' terms::TermPrecList '}' { - forwards to termPrecs(terms,location=top.location); + forwards to termPrecs(terms,location=top.location); } abstract production termPrecs top::TermPrecs ::= terms::TermPrecList { - top.unparse = s"{${terms.unparse}}"; - top.precTermList = terms.precTermList; - top.errors := terms.errors; + top.unparse = s"{${terms.unparse}}"; } +nonterminal TermPrecList with config, grammarName, unparse, location, precTermList, errors, env; +propagate errors, precTermList on TermPrecList; + abstract production termPrecList top::TermPrecList ::= h::QName t::TermPrecList { @@ -109,9 +90,7 @@ top::TermPrecList ::= h::QName t::TermPrecList production fName::String = if null(h.lookupType.dcls) then h.lookupLexerClass.dcl.fullName else h.lookupType.dcl.fullName; - top.precTermList = [fName] ++ t.precTermList ; - - top.errors := t.errors; + top.precTermList <- [fName]; -- Since we're looking it up in two ways, do the errors ourselves top.errors <- if null(h.lookupType.dcls) && null(h.lookupLexerClass.dcls) @@ -124,26 +103,23 @@ top::TermPrecList ::= h::QName t::TermPrecList abstract production termPrecListNull top::TermPrecList ::= { - top.precTermList = []; top.unparse = ""; - top.errors := []; } -nonterminal TermPrecList with config, grammarName, unparse, location, precTermList, errors, env; - concrete production termPrecListOne top::TermPrecList ::= t::QName { - forwards to termPrecList(t, termPrecListNull(location=top.location), location=top.location); + forwards to termPrecList(t, termPrecListNull(location=top.location), location=top.location); } concrete production termPrecListCons top::TermPrecList ::= t::QName ',' terms_tail::TermPrecList { - forwards to termPrecList(t, terms_tail,location=top.location); + forwards to termPrecList(t, terms_tail,location=top.location); } nonterminal LexerClasses with location, config, unparse, lexerClasses, errors, env; +propagate errors, lexerClasses on LexerClasses; concrete production lexerClassesOne top::LexerClasses ::= n::QName @@ -160,12 +136,11 @@ top::LexerClasses ::= '{' cls::LexerClassList '}' abstract production lexerClasses top::LexerClasses ::= cls::LexerClassList { - top.unparse = s"{${cls.unparse}}"; - top.lexerClasses = cls.lexerClasses; - top.errors := cls.errors; + top.unparse = s"{${cls.unparse}}"; } nonterminal LexerClassList with location, config, unparse, lexerClasses, errors, env; +propagate errors, lexerClasses on LexerClassList; concrete production lexerClassListOne top::LexerClassList ::= n::QName @@ -187,16 +162,14 @@ top::LexerClassList ::= n::QName t::LexerClassList then n.unparse else n.unparse ++ ", " ++ t.unparse; - top.errors := n.lookupLexerClass.errors ++ t.errors; + top.errors <- n.lookupLexerClass.errors; - top.lexerClasses = [n.lookupLexerClass.dcl.fullName] ++ t.lexerClasses; + top.lexerClasses <- [n.lookupLexerClass.dcl.fullName]; } abstract production lexerClassListNull cl::LexerClassList ::= { cl.unparse = ""; - cl.errors := []; - cl.lexerClasses = []; } diff --git a/grammars/silver/modification/copper_mda/Analysis.sv b/grammars/silver/modification/copper_mda/Analysis.sv index 27efa799a..2b54d05ab 100644 --- a/grammars/silver/modification/copper_mda/Analysis.sv +++ b/grammars/silver/modification/copper_mda/Analysis.sv @@ -16,9 +16,9 @@ top::AGDcl ::= 'copper_mda' testname::Name '(' orig::QName ')' '{' m::ParserComp { top.unparse = ""; - top.errors := orig.lookupValue.errors ++ m.errors; + propagate errors, moduleNames; - top.moduleNames = m.moduleNames; + top.errors <- orig.lookupValue.errors; local spec :: [ParserSpec] = if !orig.lookupValue.found then [] diff --git a/grammars/silver/modification/defaultattr/DefaultAttr.sv b/grammars/silver/modification/defaultattr/DefaultAttr.sv index 4b30403aa..00c7a011a 100644 --- a/grammars/silver/modification/defaultattr/DefaultAttr.sv +++ b/grammars/silver/modification/defaultattr/DefaultAttr.sv @@ -18,14 +18,14 @@ top::AGDcl ::= 'aspect' 'default' 'production' { top.unparse = "aspect default production\n" ++ lhs.unparse ++ "::" ++ te.unparse ++ " ::=\n" ++ body.unparse; - top.defs = []; + top.defs := []; production namedSig :: NamedSignature = namedSignature(top.grammarName ++ ":default" ++ te.typerep.typeName, [], namedSignatureElement(lhs.name, te.typerep), annotationsForNonterminal(te.typerep, top.env)); - top.errors := te.errors ++ body.errors; + propagate errors, flowDefs; local fakedDefs :: [Def] = [defaultLhsDef(top.grammarName, lhs.location, lhs.name, te.typerep)]; diff --git a/grammars/silver/modification/ffi/TypeDcl.sv b/grammars/silver/modification/ffi/TypeDcl.sv index 19137542c..72a1761ce 100644 --- a/grammars/silver/modification/ffi/TypeDcl.sv +++ b/grammars/silver/modification/ffi/TypeDcl.sv @@ -41,9 +41,10 @@ top::AGDcl ::= 'type' id::Name tl::BracketedOptTypeExprs 'foreign' '=' trans::St -- Strip quotes local transType :: String = substring(1, length(trans.lexeme) - 1, trans.lexeme); - top.defs = [typeAliasDef(top.grammarName, id.location, fName, tl.freeVariables, foreignType(fName, transType, tl.types))]; + top.defs := [typeAliasDef(top.grammarName, id.location, fName, tl.freeVariables, foreignType(fName, transType, tl.types))]; - top.errors := tl.errors ++ tl.errorsTyVars; + propagate errors, flowDefs; + top.errors <- tl.errorsTyVars; -- Put the variables listed on the rhs in the environment FOR TL ONLY, so they're all "declared" tl.initialEnv = top.env; diff --git a/grammars/silver/modification/impide/FontDecl.sv b/grammars/silver/modification/impide/FontDecl.sv index 003964c5b..6fce7835c 100644 --- a/grammars/silver/modification/impide/FontDecl.sv +++ b/grammars/silver/modification/impide/FontDecl.sv @@ -11,59 +11,58 @@ top::AGDcl ::= 'temp_imp_ide_font' id::Name 'color' '(' r::Int_t ',' g::Int_t ', top.unparse = "temp_imp_ide_font " ++ id.name ++ " color(" ++ r.lexeme ++ ", " ++ g.lexeme ++ ", " ++ b.lexeme ++ ")" ++ fontStyles.unparse ++ ";\n"; production fName :: String = top.grammarName ++ ":" ++ id.name; - - top.defs = [fontDef(top.grammarName, top.location, fName)]; top.errors := if length(getFontDcl(fName, top.env)) > 1 then [err(id.location, "Font style '" ++ fName ++ "' is already bound.")] else []; - top.syntaxAst = [syntaxFont( + -- TODO: Add a way to set this via forward + top.syntaxAst := [syntaxFont( fName, font(makeColor(toInteger(r.lexeme),toInteger(g.lexeme),toInteger(b.lexeme)), fontStyles.isBold, fontStyles.isItalic) )]; - -- TODO: this forward is bs - forwards to emptyAGDcl(location=top.location); + forwards to defsAGDcl([fontDef(top.grammarName, top.location, fName)], location=top.location); } -nonterminal FontStyles with isBold, isItalic, unparse; +monoid attribute isBold :: Boolean with false, ||; +monoid attribute isItalic :: Boolean with false, ||; -synthesized attribute isBold :: Boolean; -synthesized attribute isItalic :: Boolean; +nonterminal FontStyles with isBold, isItalic, unparse; +propagate isBold, isItalic on FontStyles, FontStyle; concrete production consFontStylesDcl top::FontStyles ::= h::FontStyle t::FontStyles { top.unparse = h.unparse ++ t.unparse; - top.isBold = h.isBold || t.isBold; - top.isItalic = h.isItalic || t.isItalic; } concrete production nilFontStylesDcl top::FontStyles ::= { top.unparse = ""; - top.isBold = false; - top.isItalic = false; } -nonterminal FontStyle with unparse, isBold, isItalic; +closed nonterminal FontStyle with unparse, isBold, isItalic; + +aspect default production +top::FontStyle ::= +{ + propagate isBold, isItalic; +} concrete production fontStyleBoldDcl top::FontStyle ::= 'bold' { top.unparse = " bold"; - top.isBold = true; - top.isItalic = false; + top.isBold <- true; } concrete production fontStyleItalicDcl top::FontStyle ::= 'italic' { top.unparse = " italic"; - top.isBold = false; - top.isItalic = true; + top.isItalic <- true; } -- temp_imp_ide_font KeywordFont color(255,0,0) bold; diff --git a/grammars/silver/modification/impide/FontModifiers.sv b/grammars/silver/modification/impide/FontModifiers.sv index 1cfb36517..54971177c 100644 --- a/grammars/silver/modification/impide/FontModifiers.sv +++ b/grammars/silver/modification/impide/FontModifiers.sv @@ -8,8 +8,9 @@ top::TerminalModifier ::= 'font' '=' id::QName { top.unparse = "font = " ++ id.name; - top.terminalModifiers = [termFont(id.lookupFont.fullName)]; + top.terminalModifiers := [termFont(id.lookupFont.fullName)]; top.errors := id.lookupFont.errors; + propagate silver:modification:copper:lexerClasses; } -- Allows fonts on lexer classes, too! @@ -18,7 +19,7 @@ top::LexerClassModifier ::= 'font' '=' id::QName { top.unparse = "font = " ++ id.name; - top.lexerClassModifiers = [lexerClassFont(id.lookupFont.fullName)]; + top.lexerClassModifiers := [lexerClassFont(id.lookupFont.fullName)]; top.errors := id.lookupFont.errors; } diff --git a/grammars/silver/modification/impide/IdeDecl.sv b/grammars/silver/modification/impide/IdeDecl.sv index 7a8033d39..d97721ab6 100644 --- a/grammars/silver/modification/impide/IdeDecl.sv +++ b/grammars/silver/modification/impide/IdeDecl.sv @@ -35,7 +35,7 @@ top::AGDcl ::= 'temp_imp_ide_dcl' parsername::QName fileextension::String_t stmt { top.unparse = "temp_imp_ide_dcl " ++ parsername.unparse ++ " " ++ fileextension.lexeme ++ "\n"; -- TODO not finished - top.defs = []; + top.defs := []; top.errors := parsername.lookupValue.errors; diff --git a/grammars/silver/modification/impide/cstast/CstAst.sv b/grammars/silver/modification/impide/cstast/CstAst.sv index 547efb529..97b2eefa5 100644 --- a/grammars/silver/modification/impide/cstast/CstAst.sv +++ b/grammars/silver/modification/impide/cstast/CstAst.sv @@ -10,14 +10,13 @@ imports silver:modification:impide:spec; aspect default production top::SyntaxRoot ::= { - top.fontList = error("This should only ever be demanded from cstRoot."); - top.classFontList = error("This should only ever be demanded from cstRoot."); + propagate fontList, classFontList; } aspect production cstRoot top::SyntaxRoot ::= parsername::String startnt::String s::Syntax customStartLayout::Maybe<[String]> terminalPrefixes::[Pair] { -- 1) font information - top.fontList = s2.fontList; - top.classFontList = s2.classFontList; + top.fontList := s2.fontList; + top.classFontList := s2.classFontList; } diff --git a/grammars/silver/modification/impide/cstast/Syntax.sv b/grammars/silver/modification/impide/cstast/Syntax.sv index 318413f8f..f981475dd 100644 --- a/grammars/silver/modification/impide/cstast/Syntax.sv +++ b/grammars/silver/modification/impide/cstast/Syntax.sv @@ -2,75 +2,31 @@ grammar silver:modification:impide:cstast; --import (see grammar-wide import in cstast.sv) -synthesized attribute fontList :: [Pair]; -attribute fontList occurs on Syntax, SyntaxDcl, SyntaxRoot; +monoid attribute fontList :: [Pair] with [], ++; +monoid attribute classFontList :: [Pair] with [], ++; -synthesized attribute classFontList :: [Pair]; -attribute classFontList occurs on Syntax, SyntaxDcl, SyntaxRoot; - -aspect production nilSyntax -top::Syntax ::= -{ - top.fontList = []; - top.classFontList = []; -} - -aspect production consSyntax -top::Syntax ::= s1::SyntaxDcl s2::Syntax -{ - top.fontList = s1.fontList ++ s2.fontList; - top.classFontList = s1.classFontList ++ s2.classFontList; -} - -aspect default production -top::SyntaxDcl ::= -{ - top.fontList = []; - top.classFontList = []; -} - -aspect production syntaxNonterminal -top::SyntaxDcl ::= t::Type subdcls::Syntax exportedProds::[String] exportedLayoutTerms::[String] modifiers::SyntaxNonterminalModifiers -{ -} - -aspect production syntaxTerminal -top::SyntaxDcl ::= n::String regex::Regex modifiers::SyntaxTerminalModifiers -{ -} - -aspect production syntaxProduction -top::SyntaxDcl ::= ns::NamedSignature modifiers::SyntaxProductionModifiers -{ -} +attribute fontList, classFontList occurs on Syntax, SyntaxDcl, SyntaxRoot; +propagate fontList, classFontList on Syntax, SyntaxDcl; aspect production syntaxLexerClass top::SyntaxDcl ::= n::String modifiers::SyntaxLexerClassModifiers { - top.classFontList = + top.classFontList <- if modifiers.fontAttr == "" then [] else [pair(n, modifiers.fontAttr)]; } -aspect production syntaxParserAttribute -top::SyntaxDcl ::= n::String ty::Type acode::String -{ -} - -aspect production syntaxDisambiguationGroup -top::SyntaxDcl ::= n::String terms::[String] applicableToSubsets::Boolean acode::String -{ -} - abstract production syntaxFont top::SyntaxDcl ::= fontName::String fnt::Font -- TODO: we probably? need to factor out this data structure somehow? { - top.fontList = [pair(makeCopperName(fontName), fnt)]; + top.fontList <- [pair(makeCopperName(fontName), fnt)]; + + propagate cstErrors, prefixSeperator; + top.fullName = fontName; top.sortKey = "111"; -- Doesn't really matter, it doesn't show up in the copper XML - top.cstDcls = [pair(fontName, top)]; - top.cstErrors := []; - top.cstNormalize = [top]; + top.cstDcls := [pair(fontName, top)]; + top.cstNormalize := [top]; top.xmlCopper = ""; } diff --git a/grammars/silver/modification/lambda_fn/Lambda.sv b/grammars/silver/modification/lambda_fn/Lambda.sv index ff920b5e0..66c027d22 100644 --- a/grammars/silver/modification/lambda_fn/Lambda.sv +++ b/grammars/silver/modification/lambda_fn/Lambda.sv @@ -26,51 +26,41 @@ top::Expr ::= params::ProductionRHS e::Expr { top.unparse = "\\ " ++ params.unparse ++ " -> " ++ e.unparse; - top.errors := params.errors ++ e.errors; + propagate errors; top.typerep = functionType(e.typerep, map((.typerep), params.inputElements), []); e.downSubst = top.downSubst; top.upSubst = e.upSubst; - top.flowDeps = e.flowDeps; - top.flowDefs = e.flowDefs; + propagate flowDeps, flowDefs; e.env = newScopeEnv(params.lambdaDefs, top.env); } -synthesized attribute lambdaDefs::[Def] occurs on ProductionRHS, ProductionRHSElem; +monoid attribute lambdaDefs::[Def] with [], ++; +attribute lambdaDefs occurs on ProductionRHS, ProductionRHSElem; -aspect production productionRHSCons -top::ProductionRHS ::= h::ProductionRHSElem t::ProductionRHS -{ - top.lambdaDefs = h.lambdaDefs ++ t.lambdaDefs; -} -aspect production productionRHSNil -top::ProductionRHS ::= -{ - top.lambdaDefs = []; -} +propagate lambdaDefs on ProductionRHS; aspect production productionRHSElem top::ProductionRHSElem ::= id::Name '::' t::TypeExpr { production fName :: String = toString(genInt()) ++ ":" ++ id.name; -- production transName :: String = "lambda_param" ++ id.name ++ toString(genInt()); - top.lambdaDefs = [lambdaParamDef(top.grammarName, t.location, fName, t.typerep)]; + top.lambdaDefs := [lambdaParamDef(top.grammarName, t.location, fName, t.typerep)]; } abstract production lambdaParamReference top::Expr ::= q::Decorated QName { top.unparse = q.unparse; - top.errors := []; -- TODO? + propagate errors; top.typerep = q.lookupValue.typerep; top.upSubst = top.downSubst; -- TODO? - top.flowDeps = []; - top.flowDefs = []; + propagate flowDeps, flowDefs; } diff --git a/grammars/silver/modification/let_fix/Let.sv b/grammars/silver/modification/let_fix/Let.sv index f1c0d6422..03bee5aa8 100644 --- a/grammars/silver/modification/let_fix/Let.sv +++ b/grammars/silver/modification/let_fix/Let.sv @@ -43,7 +43,7 @@ top::Expr ::= la::AssignExpr e::Expr { top.unparse = "let " ++ la.unparse ++ " in " ++ e.unparse ++ " end"; - top.errors := la.errors ++ e.errors; + propagate errors; top.typerep = e.typerep; @@ -60,12 +60,12 @@ nonterminal AssignExpr with location, config, grammarName, env, compiledGrammars unparse, defs, errors, upSubst, downSubst, finalSubst, frame; +propagate errors, defs on AssignExpr; + abstract production appendAssignExpr top::AssignExpr ::= a1::AssignExpr a2::AssignExpr { top.unparse = a1.unparse ++ ", " ++ a2.unparse; - top.defs = a1.defs ++ a2.defs; - top.errors := a1.errors ++ a2.errors; a1.downSubst = top.downSubst; a2.downSubst = a1.upSubst; @@ -78,8 +78,6 @@ top::AssignExpr ::= id::Name '::' t::TypeExpr '=' e::Expr { top.unparse = id.unparse ++ " :: " ++ t.unparse ++ " = " ++ e.unparse; - top.errors := t.errors ++ e.errors; - -- Right now some things (pattern matching) abuse us by giving type variables -- for `t`. So we want to do a little inference before we stuff this into -- our DclInfo in `defs` because we expect variables in the env to have @@ -93,7 +91,7 @@ top::AssignExpr ::= id::Name '::' t::TypeExpr '=' e::Expr -- auto-undecorate feature, so that's why we bother substituting. -- (er, except that we're starting with t, which is a Type... must be because we fake these -- in e.g. the pattern matching code, so type variables might appear there?) - top.defs = [lexicalLocalDef(top.grammarName, id.location, fName, semiTy, e.flowVertexInfo, e.flowDeps)]; + top.defs <- [lexicalLocalDef(top.grammarName, id.location, fName, semiTy, e.flowVertexInfo, e.flowDeps)]; -- TODO: At present, this isn't working properly, because the local scope is -- whatever scope encloses the real local scope... hrmm! diff --git a/grammars/silver/modification/primitivepattern/PrimitiveMatch.sv b/grammars/silver/modification/primitivepattern/PrimitiveMatch.sv index 323de33a2..eac176451 100644 --- a/grammars/silver/modification/primitivepattern/PrimitiveMatch.sv +++ b/grammars/silver/modification/primitivepattern/PrimitiveMatch.sv @@ -32,6 +32,7 @@ nonterminal PrimPattern with autocopy attribute scrutineeType :: Type; autocopy attribute returnType :: Type; +propagate errors on PrimPatterns, PrimPattern; concrete production matchPrimitiveConcrete top::Expr ::= 'match' e::Expr 'return' t::TypeExpr 'with' pr::PrimPatterns 'else' '->' f::Expr 'end' @@ -65,10 +66,9 @@ top::Expr ::= e::Expr t::TypeExpr pr::PrimPatterns f::Expr { top.unparse = "match " ++ e.unparse ++ " return " ++ t.unparse ++ " with " ++ pr.unparse ++ " else -> " ++ f.unparse ++ "end"; + propagate errors; top.typerep = t.typerep; - top.errors := e.errors ++ t.errors ++ pr.errors ++ f.errors; - {-- - Invariant: if we were given an undecorated expression, it should have been - decorated by matchPrimitive before we got here, so we should either @@ -129,7 +129,6 @@ top::PrimPatterns ::= p::PrimPattern { top.unparse = p.unparse; - top.errors := p.errors; top.translation = p.translation; p.downSubst = top.downSubst; @@ -140,7 +139,6 @@ top::PrimPatterns ::= p::PrimPattern '|' ps::PrimPatterns { top.unparse = p.unparse ++ " | " ++ ps.unparse; - top.errors := p.errors ++ ps.errors; top.translation = p.translation ++ "\nelse " ++ ps.translation; p.downSubst = top.downSubst; @@ -186,7 +184,7 @@ top::PrimPattern ::= qn::Decorated QName ns::VarBinders e::Expr if null(qn.lookupValue.dcls) || ns.varBinderCount == length(prod_type.inputTypes) then [] else [err(qn.location, qn.name ++ " has " ++ toString(length(prod_type.inputTypes)) ++ " parameters but " ++ toString(ns.varBinderCount) ++ " patterns were provided")]; - top.errors := qn.lookupValue.errors ++ ns.errors ++ chk ++ e.errors; + top.errors <- qn.lookupValue.errors; -- Turns the existential variables existential local prod_type :: Type = @@ -233,7 +231,7 @@ top::PrimPattern ::= qn::Decorated QName ns::VarBinders e::Expr if null(qn.lookupValue.dcls) || ns.varBinderCount == length(prod_type.inputTypes) then [] else [err(qn.location, qn.name ++ " has " ++ toString(length(prod_type.inputTypes)) ++ " parameters but " ++ toString(ns.varBinderCount) ++ " patterns were provided")]; - top.errors := qn.lookupValue.errors ++ ns.errors ++ chk ++ e.errors; + top.errors <- qn.lookupValue.errors; local prod_type :: Type = fullySkolemizeProductionType(qn.lookupValue.typerep); -- that says FULLY. See the comments on that function. @@ -284,8 +282,6 @@ top::PrimPattern ::= i::Int_t '->' e::Expr { top.unparse = i.lexeme ++ " -> " ++ e.unparse; - top.errors := e.errors; - local attribute errCheck1 :: TypeCheck; errCheck1.finalSubst = top.finalSubst; local attribute errCheck2 :: TypeCheck; errCheck2.finalSubst = top.finalSubst; @@ -312,8 +308,6 @@ top::PrimPattern ::= f::Float_t '->' e::Expr { top.unparse = f.lexeme ++ " -> " ++ e.unparse; - top.errors := e.errors; - local attribute errCheck1 :: TypeCheck; errCheck1.finalSubst = top.finalSubst; local attribute errCheck2 :: TypeCheck; errCheck2.finalSubst = top.finalSubst; @@ -340,8 +334,6 @@ top::PrimPattern ::= i::String_t '->' e::Expr { top.unparse = i.lexeme ++ " -> " ++ e.unparse; - top.errors := e.errors; - local attribute errCheck1 :: TypeCheck; errCheck1.finalSubst = top.finalSubst; local attribute errCheck2 :: TypeCheck; errCheck2.finalSubst = top.finalSubst; @@ -368,8 +360,6 @@ top::PrimPattern ::= i::String '->' e::Expr { top.unparse = i ++ " -> " ++ e.unparse; - top.errors := e.errors; - local attribute errCheck1 :: TypeCheck; errCheck1.finalSubst = top.finalSubst; local attribute errCheck2 :: TypeCheck; errCheck2.finalSubst = top.finalSubst; @@ -396,8 +386,6 @@ top::PrimPattern ::= e::Expr { top.unparse = "nil() -> " ++ e.unparse; - top.errors := e.errors; - local attribute errCheck1 :: TypeCheck; errCheck1.finalSubst = top.finalSubst; local attribute errCheck2 :: TypeCheck; errCheck2.finalSubst = top.finalSubst; @@ -423,8 +411,6 @@ abstract production conslstPattern top::PrimPattern ::= h::Name t::Name e::Expr { top.unparse = "cons(" ++ h.unparse ++ ", " ++ t.unparse ++ ") -> " ++ e.unparse; - - top.errors := e.errors; local h_fName :: String = toString(genInt()) ++ ":" ++ h.name; local t_fName :: String = toString(genInt()) ++ ":" ++ t.name; diff --git a/grammars/silver/modification/primitivepattern/VarBinders.sv b/grammars/silver/modification/primitivepattern/VarBinders.sv index 4d4f1e10e..828a1af1f 100644 --- a/grammars/silver/modification/primitivepattern/VarBinders.sv +++ b/grammars/silver/modification/primitivepattern/VarBinders.sv @@ -19,6 +19,8 @@ nonterminal VarBinder with bindingType, bindingIndex, translation, finalSubst, flowProjections, bindingName, flowEnv, matchingAgainst; +propagate errors, defs on VarBinders, VarBinder; + --- Types of each child inherited attribute bindingTypes :: [Type]; inherited attribute bindingType :: Type; @@ -40,8 +42,6 @@ concrete production oneVarBinder top::VarBinders ::= v::VarBinder { top.unparse = v.unparse; - top.defs = v.defs; - top.errors := v.errors; top.translation = v.translation; top.varBinderCount = 1; @@ -61,8 +61,6 @@ concrete production consVarBinder top::VarBinders ::= v::VarBinder ',' vs::VarBinders { top.unparse = v.unparse ++ ", " ++ vs.unparse; - top.defs = v.defs ++ vs.defs; - top.errors := v.errors ++ vs.errors; top.translation = v.translation ++ vs.translation; top.varBinderCount = 1 + vs.varBinderCount; @@ -92,8 +90,6 @@ concrete production nilVarBinder top::VarBinders ::= { top.unparse = ""; - top.defs = []; - top.errors := []; top.translation = ""; top.varBinderCount = 0; @@ -138,7 +134,7 @@ top::VarBinder ::= n::Name then depsForTakingRef(anonVertexType(fName), ty.typeName, top.flowEnv) else []; - top.defs = [lexicalLocalDef(top.grammarName, n.location, fName, ty, vt, deps)]; + top.defs <- [lexicalLocalDef(top.grammarName, n.location, fName, ty, vt, deps)]; -- finalSubst is not necessary, downSubst would work fine, but is not threaded through here. -- the point is that 'ty' for Pair would currently show Pair @@ -159,7 +155,7 @@ top::VarBinder ::= n::Name -- We prevent this to prevent newbies from thinking patterns are "typecase" -- (Types have to be upper case) - top.errors := + top.errors <- if !isUpper(substring(0,1,n.name)) then [] else [err(top.location, "Pattern variables must start with a lower case letter")]; @@ -176,8 +172,6 @@ concrete production ignoreVarBinder top::VarBinder ::= '_' { top.unparse = "_"; - top.defs = []; - top.errors := []; top.flowProjections = []; top.translation = ""; } diff --git a/grammars/silver/modification/typedecl/TypeDecl.sv b/grammars/silver/modification/typedecl/TypeDecl.sv index a9e700ffa..f82842ad9 100644 --- a/grammars/silver/modification/typedecl/TypeDecl.sv +++ b/grammars/silver/modification/typedecl/TypeDecl.sv @@ -15,9 +15,10 @@ top::AGDcl ::= 'type' id::Name tl::BracketedOptTypeExprs '=' te::TypeExpr ';' production attribute fName :: String; fName = top.grammarName ++ ":" ++ id.name; - top.defs = [typeAliasDef(top.grammarName, id.location, fName, tl.freeVariables, te.typerep)]; + top.defs := [typeAliasDef(top.grammarName, id.location, fName, tl.freeVariables, te.typerep)]; - top.errors := tl.errors ++ te.errors ++ tl.errorsTyVars; + propagate errors; + top.errors <- tl.errorsTyVars; tl.initialEnv = top.env; tl.env = tl.envBindingTyVars; From 5e74d149828b132e019f0e68676a7f3f9dae6ccd Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Thu, 19 Mar 2020 19:01:10 -0500 Subject: [PATCH 30/57] Better error messages for global propagate --- .../silver/extension/autoattr/Propagate.sv | 73 +++++++++++-------- test/silver_features/Monoid.sv | 18 +++++ 2 files changed, 59 insertions(+), 32 deletions(-) diff --git a/grammars/silver/extension/autoattr/Propagate.sv b/grammars/silver/extension/autoattr/Propagate.sv index 8ec49b515..bfdcdd424 100644 --- a/grammars/silver/extension/autoattr/Propagate.sv +++ b/grammars/silver/extension/autoattr/Propagate.sv @@ -35,37 +35,7 @@ top::AGDcl ::= attrs::NameList nt::QName local dcl::AGDcl = foldr( appendAGDcl(_, _, location=top.location), emptyAGDcl(location=top.location), - map( - \ d::DclInfo -> - aspectProductionDcl( - 'aspect', 'production', qName(top.location, d.fullName), - aspectProductionSignature( - aspectProductionLHSFull( - name(d.namedSignature.outputElement.elementName, top.location), - d.namedSignature.outputElement.typerep, - location=top.location), - '::=', - foldr( - aspectRHSElemCons(_, _, location=top.location), - aspectRHSElemNil(location=top.location), - map( - \ ie::NamedSignatureElement -> - aspectRHSElemFull( - name(ie.elementName, top.location), - ie.typerep, - location=top.location), - d.namedSignature.inputElements)), - location=top.location), - productionBody( - '{', - productionStmtsSnoc( - productionStmtsNil(location=top.location), - propagateAttrList('propagate', attrs, ';', location=top.location), - location=top.location), - '}', - location=top.location), - location=top.location), - nonForwardingProds)); + map(propagateAspectDcl(_, attrs, location=nt.location), nonForwardingProds)); forwards to if !null(nt.lookupType.errors) @@ -73,6 +43,45 @@ top::AGDcl ::= attrs::NameList nt::QName else dcl; } +abstract production propagateAspectDcl +top::AGDcl ::= d::DclInfo attrs::NameList +{ + top.errors := + if null(forward.errors) + then [] + else [nested(top.location, s"In propagating for production ${d.fullName}:", forward.errors)]; + + forwards to + aspectProductionDcl( + 'aspect', 'production', qName(top.location, d.fullName), + aspectProductionSignature( + aspectProductionLHSFull( + name(d.namedSignature.outputElement.elementName, top.location), + d.namedSignature.outputElement.typerep, + location=top.location), + '::=', + foldr( + aspectRHSElemCons(_, _, location=top.location), + aspectRHSElemNil(location=top.location), + map( + \ ie::NamedSignatureElement -> + aspectRHSElemFull( + name(ie.elementName, top.location), + ie.typerep, + location=top.location), + d.namedSignature.inputElements)), + location=top.location), + productionBody( + '{', + productionStmtsSnoc( + productionStmtsNil(location=top.location), + propagateAttrList('propagate', attrs, ';', location=top.location), + location=top.location), + '}', + location=top.location), + location=top.location); +} + concrete production propagateAttrList top::ProductionStmt ::= 'propagate' ns::NameList ';' { @@ -85,7 +94,7 @@ top::ProductionStmt ::= 'propagate' ns::NameList ';' | nameListOne(n) -> propagateOneAttr(n, location=top.location) | nameListCons(n, _, rest) -> productionStmtAppend( - propagateOneAttr(n, location=top.location), + propagateOneAttr(n, location=n.location), propagateAttrList($1, rest, $3, location=top.location), location=top.location) end; diff --git a/test/silver_features/Monoid.sv b/test/silver_features/Monoid.sv index a455995c2..8809e1cd8 100644 --- a/test/silver_features/Monoid.sv +++ b/test/silver_features/Monoid.sv @@ -38,3 +38,21 @@ global testMStmt::MStmt = equalityTest(testMStmt.defs, ["a", "d"], [String], silver_tests); equalityTest(testMStmt.freeVars, ["b", "c"], [String], silver_tests); + +-- Test errors in propagate +monoid attribute things::[a] with [], ++; + +nonterminal Thing1 with things; +nonterminal Thing2 with things; + +abstract production thing2Thing1 +top::Thing1 ::= Thing2 +{} + +-- Test for both parts of 2-part error message +wrongCode "In propagating on production silver_features:thing2Thing1" { + propagate things on Thing1; +} +wrongCode "things has type [Integer] but the expression being assigned to it has type [Float]" { + propagate things on Thing1; +} From 0dd06c7351f362cd948542579ba2d33e3bde841b Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Thu, 19 Mar 2020 19:09:25 -0500 Subject: [PATCH 31/57] Fix inconsistent error message --- grammars/silver/extension/autoattr/Propagate.sv | 2 +- test/silver_features/Monoid.sv | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/grammars/silver/extension/autoattr/Propagate.sv b/grammars/silver/extension/autoattr/Propagate.sv index bfdcdd424..9d3e568aa 100644 --- a/grammars/silver/extension/autoattr/Propagate.sv +++ b/grammars/silver/extension/autoattr/Propagate.sv @@ -49,7 +49,7 @@ top::AGDcl ::= d::DclInfo attrs::NameList top.errors := if null(forward.errors) then [] - else [nested(top.location, s"In propagating for production ${d.fullName}:", forward.errors)]; + else [nested(top.location, s"In propagate for production ${d.fullName}:", forward.errors)]; forwards to aspectProductionDcl( diff --git a/test/silver_features/Monoid.sv b/test/silver_features/Monoid.sv index 8809e1cd8..390fac9ab 100644 --- a/test/silver_features/Monoid.sv +++ b/test/silver_features/Monoid.sv @@ -50,7 +50,7 @@ top::Thing1 ::= Thing2 {} -- Test for both parts of 2-part error message -wrongCode "In propagating on production silver_features:thing2Thing1" { +wrongCode "In propagate for production silver_features:thing2Thing1" { propagate things on Thing1; } wrongCode "things has type [Integer] but the expression being assigned to it has type [Float]" { From d88663e50ba29e508813823506921949da0779c4 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Thu, 19 Mar 2020 20:17:46 -0500 Subject: [PATCH 32/57] Use monoid attributes in translation --- .../translation/java/core/ProductionBody.sv | 19 +--- grammars/silver/translation/java/core/Root.sv | 95 +++---------------- 2 files changed, 17 insertions(+), 97 deletions(-) diff --git a/grammars/silver/translation/java/core/ProductionBody.sv b/grammars/silver/translation/java/core/ProductionBody.sv index e9f351f0e..c71569aad 100644 --- a/grammars/silver/translation/java/core/ProductionBody.sv +++ b/grammars/silver/translation/java/core/ProductionBody.sv @@ -9,28 +9,24 @@ attribute attrName occurs on ForwardLHSExpr; attribute setupInh, translation, valueWeaving occurs on ProductionBody, ProductionStmts, ProductionStmt; attribute translation occurs on DefLHS, ForwardInhs, ForwardInh; +propagate setupInh, valueWeaving on ProductionBody, ProductionStmts; + aspect production productionBody top::ProductionBody ::= '{' stmts::ProductionStmts '}' { - top.setupInh := stmts.setupInh; top.translation = stmts.translation; - top.valueWeaving := stmts.valueWeaving; } aspect production productionStmtsNil top::ProductionStmts ::= { - top.setupInh := ""; top.translation = ""; - top.valueWeaving := ""; } aspect production productionStmtsSnoc top::ProductionStmts ::= h::ProductionStmts t::ProductionStmt { - top.setupInh := h.setupInh ++ t.setupInh; top.translation = h.translation ++ t.translation; - top.valueWeaving := h.valueWeaving ++ t.valueWeaving; } ------- @@ -38,17 +34,14 @@ top::ProductionStmts ::= h::ProductionStmts t::ProductionStmt aspect production productionStmtAppend top::ProductionStmt ::= h::ProductionStmt t::ProductionStmt { - top.setupInh := h.setupInh ++ t.setupInh; + propagate setupInh, valueWeaving; top.translation = h.translation ++ t.translation; - top.valueWeaving := h.valueWeaving ++ t.valueWeaving; } aspect production errorProductionStmt top::ProductionStmt ::= e::[Message] { - top.setupInh := ""; top.translation = ""; - top.valueWeaving := ""; } -------------------------------------------------------------------------------- @@ -56,9 +49,8 @@ top::ProductionStmt ::= e::[Message] aspect default production top::ProductionStmt ::= { - top.setupInh := ""; - -- require a translation. - top.valueWeaving := ""; + -- Always require translation + propagate setupInh, valueWeaving; } aspect production forwardsTo @@ -79,7 +71,6 @@ top::ForwardInh ::= lhs::ForwardLHSExpr '=' e::Expr ';' top.translation = s"\t\t//${top.unparse}\n" ++ s"\t\t${top.frame.className}.forwardInheritedAttributes[${lhs.attrName}] = ${wrapLazy(e)};\n"; - } aspect production forwardInhsOne diff --git a/grammars/silver/translation/java/core/Root.sv b/grammars/silver/translation/java/core/Root.sv index 7dc7f4283..6e3c23123 100644 --- a/grammars/silver/translation/java/core/Root.sv +++ b/grammars/silver/translation/java/core/Root.sv @@ -1,121 +1,50 @@ grammar silver:translation:java:core; -attribute genFiles,setupInh,initProd,initValues,postInit,initWeaving,valueWeaving occurs on Root, AGDcls, AGDcl, Grammar; - {-- - Java classes to generate. (filename, contents) -} -synthesized attribute genFiles :: [Pair] with ++; +monoid attribute genFiles :: [Pair] with [], ++; {-- - Early initializers: occurs.add, local's inh attr map creation, decorators.add, collection object creation -} -synthesized attribute setupInh :: String with ++; +monoid attribute setupInh :: String with "", ++; {-- - Initialize the attributes maps for each production. - note to be confused with "production attribute" dcls. -} -synthesized attribute initProd :: String with ++; +monoid attribute initProd :: String with "", ++; {-- - Global values. -} -synthesized attribute initValues :: String with ++; +monoid attribute initValues :: String with "", ++; {-- - Late initializers. Decorator application (late because we want all attribute equations to be posted first!!) -} -synthesized attribute postInit :: String with ++; +monoid attribute postInit :: String with "", ++; synthesized attribute translation :: String; {-- - Initial values for early weaving. e.g. counter for # attributes on NT -} -synthesized attribute initWeaving :: String with ++; +monoid attribute initWeaving :: String with "", ++; {-- - Values computed by early weaving. e.g. index of attribute in NT arrays -} -synthesized attribute valueWeaving :: String with ++; - +monoid attribute valueWeaving :: String with "", ++; -aspect production root -top::Root ::= gdcl::GrammarDcl ms::ModuleStmts ims::ImportStmts ags::AGDcls -{ - top.genFiles := ags.genFiles; - top.setupInh := ags.setupInh; - top.initProd := ags.initProd; - top.initValues := ags.initValues; - top.postInit := ags.postInit; - top.initWeaving := ags.initWeaving; - top.valueWeaving := ags.valueWeaving; -} - -aspect production nilAGDcls -top::AGDcls ::= -{ - top.genFiles := []; - top.setupInh := ""; - top.initProd := ""; - top.initValues := ""; - top.postInit := ""; - top.initWeaving := ""; - top.valueWeaving := ""; -} +attribute genFiles,setupInh,initProd,initValues,postInit,initWeaving,valueWeaving occurs on Root, AGDcls, AGDcl, Grammar; -aspect production consAGDcls -top::AGDcls ::= h::AGDcl t::AGDcls -{ - top.genFiles := h.genFiles ++ t.genFiles; - top.setupInh := h.setupInh ++ t.setupInh; - top.initProd := h.initProd ++ t.initProd; - top.initValues := h.initValues ++ t.initValues; - top.postInit := h.postInit ++ t.postInit; - top.initWeaving := h.initWeaving ++ t.initWeaving; - top.valueWeaving := h.valueWeaving ++ t.valueWeaving; -} +propagate genFiles,setupInh,initProd,initValues,postInit,initWeaving,valueWeaving on Root, AGDcls, Grammar; aspect default production top::AGDcl ::= { - top.genFiles := []; - top.setupInh := ""; - top.initProd := ""; - top.initValues := ""; - top.postInit := ""; - top.initWeaving := ""; - top.valueWeaving := ""; + -- Empty values as defaults + propagate genFiles,setupInh,initProd,initValues,postInit,initWeaving,valueWeaving; } aspect production appendAGDcl top::AGDcl ::= h::AGDcl t::AGDcl { - top.genFiles := h.genFiles ++ t.genFiles; - top.setupInh := h.setupInh ++ t.setupInh; - top.initProd := h.initProd ++ t.initProd; - top.initValues := h.initValues ++ t.initValues; - top.postInit := h.postInit ++ t.postInit; - top.initWeaving := h.initWeaving ++ t.initWeaving; - top.valueWeaving := h.valueWeaving ++ t.valueWeaving; -} - -aspect production nilGrammar -top::Grammar ::= -{ - top.genFiles := []; - top.setupInh := ""; - top.initProd := ""; - top.initValues := ""; - top.postInit := ""; - top.initWeaving := ""; - top.valueWeaving := ""; + propagate genFiles,setupInh,initProd,initValues,postInit,initWeaving,valueWeaving; } - -aspect production consGrammar -top::Grammar ::= c1::Root c2::Grammar -{ - top.genFiles := c1.genFiles ++ c2.genFiles; - top.setupInh := c1.setupInh ++ c2.setupInh; - top.initProd := c1.initProd ++ c2.initProd; - top.initValues := c1.initValues ++ c2.initValues; - top.postInit := c1.postInit ++ c2.postInit; - top.initWeaving := c1.initWeaving ++ c2.initWeaving; - top.valueWeaving := c1.valueWeaving ++ c2.valueWeaving; -} - From 93d320953769dcbf18332aea8a6f92b29e6e5f71 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 20 Mar 2020 14:12:00 -0500 Subject: [PATCH 33/57] Refactoring to prefix terminal/disambiguation function generation, generate syntaxAst directly instead of liftedAGDcls --- .../silver/modification/copper/ParserDcl.sv | 45 +++------- grammars/silver/modification/copper/Prefix.sv | 83 ++++++++++--------- .../silver/modification/copper/TermList.sv | 13 ++- .../translation/java/core/TerminalDcl.sv | 26 +++--- 4 files changed, 72 insertions(+), 95 deletions(-) diff --git a/grammars/silver/modification/copper/ParserDcl.sv b/grammars/silver/modification/copper/ParserDcl.sv index 3827eda6a..83fab3ea9 100644 --- a/grammars/silver/modification/copper/ParserDcl.sv +++ b/grammars/silver/modification/copper/ParserDcl.sv @@ -13,22 +13,10 @@ top::AGDcl ::= 'parser' n::Name '::' t::TypeExpr '{' m::ParserComponents '}' propagate errors, moduleNames; - top.errors <- liftedAGDcls.errors; - -- Right now parsers masquerade as functions. This is probably fine. -- Only bug is that you can aspect it, but it's pointless to do so, you can't affect anything. top.defs := [funDef(top.grammarName, n.location, namedSig)]; - -- TODO: These declarations should probably bubble up to the top level instead of being decorated here - -- TODO: Actually liftedAGDcls can probably just go away if we generate CST AST decls directly - production liftedAGDcls :: AGDcl = m.liftedAGDcls; - liftedAGDcls.config = top.config; - liftedAGDcls.grammarName = top.grammarName; - liftedAGDcls.env = m.env; - liftedAGDcls.compiledGrammars = top.compiledGrammars; - liftedAGDcls.grammarDependencies = top.grammarDependencies; - liftedAGDcls.flowEnv = top.flowEnv; - -- Parser spec grammarDependancies based off grammars included in the parser spec m.grammarDependencies = computeDependencies(m.moduleNames, top.compiledGrammars); @@ -36,7 +24,7 @@ top::AGDcl ::= 'parser' n::Name '::' t::TypeExpr '{' m::ParserComponents '}' production med :: ModuleExportedDefs = moduleExportedDefs(top.location, top.compiledGrammars, m.grammarDependencies, m.moduleNames, []); - m.env = appendEnv(toEnv(liftedAGDcls.defs ++ med.defs), top.env); + m.env = appendEnv(toEnv(med.defs), top.env); production fName :: String = top.grammarName ++ ":" ++ n.name; @@ -48,22 +36,15 @@ top::AGDcl ::= 'parser' n::Name '::' t::TypeExpr '{' m::ParserComponents '}' []); production spec :: ParserSpec = - parserSpec(top.location, top.grammarName, fName, t.typerep.typeName, m.moduleNames, m.customLayout, m.terminalPrefixes, liftedAGDcls.syntaxAst); + parserSpec(top.location, top.grammarName, fName, t.typerep.typeName, m.moduleNames, m.customLayout, m.terminalPrefixes, m.syntaxAst); spec.compiledGrammars = top.compiledGrammars; top.parserSpecs := [spec]; -- Note that this is undecorated. } -global nilAGDcl::AGDcl = emptyAGDcl(location=loc("", -1, -1, -1, -1, -1, -1)); -function appAGDcl -AGDcl ::= a::AGDcl b::AGDcl -{ return appendAGDcl(a, b, location=loc("", -1, -1, -1, -1, -1, -1)); } - -monoid attribute liftedAGDcls::AGDcl with nilAGDcl, appAGDcl; - -nonterminal ParserComponents with config, env, grammarName, location, unparse, errors, moduleNames, compiledGrammars, grammarDependencies, terminalPrefixes, liftedAGDcls; +nonterminal ParserComponents with config, env, flowEnv, grammarName, location, unparse, errors, moduleNames, compiledGrammars, grammarDependencies, terminalPrefixes, syntaxAst, genFiles; -propagate errors, moduleNames, terminalPrefixes, liftedAGDcls on ParserComponents; +propagate errors, moduleNames, terminalPrefixes, syntaxAst, genFiles on ParserComponents; concrete production nilParserComponent top::ParserComponents ::= @@ -77,14 +58,14 @@ top::ParserComponents ::= c1::ParserComponent c2::ParserComponents top.unparse = c1.unparse ++ ", " ++ c2.unparse; } -closed nonterminal ParserComponent with config, env, grammarName, location, unparse, errors, moduleNames, compiledGrammars, grammarDependencies, terminalPrefixes, liftedAGDcls; +closed nonterminal ParserComponent with config, env, flowEnv, grammarName, location, unparse, errors, moduleNames, compiledGrammars, grammarDependencies, terminalPrefixes, syntaxAst, genFiles; -propagate errors, moduleNames, terminalPrefixes, liftedAGDcls on ParserComponent; +propagate errors, moduleNames, terminalPrefixes, syntaxAst, genFiles on ParserComponent; aspect default production top::ParserComponent ::= { - propagate errors, moduleNames, terminalPrefixes, liftedAGDcls; + propagate errors, moduleNames, terminalPrefixes, syntaxAst, genFiles; } concrete production parserComponent @@ -98,9 +79,9 @@ top::ParserComponent ::= m::ModuleName mods::ParserComponentModifiers ';' autocopy attribute componentGrammarName::String; {-- Have special env built from just this parser component and the global env -} -nonterminal ParserComponentModifiers with config, env, grammarName, componentGrammarName, compiledGrammars, grammarDependencies, location, unparse, errors, terminalPrefixes, liftedAGDcls; +nonterminal ParserComponentModifiers with config, env, flowEnv, grammarName, componentGrammarName, compiledGrammars, grammarDependencies, location, unparse, errors, terminalPrefixes, syntaxAst, genFiles; -propagate errors, terminalPrefixes, liftedAGDcls on ParserComponentModifiers; +propagate errors, terminalPrefixes, syntaxAst, genFiles on ParserComponentModifiers; concrete production nilParserComponentModifier top::ParserComponentModifiers ::= @@ -114,14 +95,14 @@ top::ParserComponentModifiers ::= h::ParserComponentModifier t::ParserComponentM top.unparse = h.unparse ++ t.unparse; } -nonterminal ParserComponentModifier with config, env, grammarName, componentGrammarName, compiledGrammars, grammarDependencies, location, unparse, errors, terminalPrefixes, liftedAGDcls; +nonterminal ParserComponentModifier with config, env, flowEnv, grammarName, componentGrammarName, compiledGrammars, grammarDependencies, location, unparse, errors, terminalPrefixes, syntaxAst, genFiles; -propagate errors, terminalPrefixes, liftedAGDcls on ParserComponentModifier; +propagate errors, terminalPrefixes, syntaxAst, genFiles on ParserComponentModifier; aspect default production top::ParserComponentModifier ::= { - propagate errors, terminalPrefixes, liftedAGDcls; + propagate errors, terminalPrefixes, syntaxAst, genFiles; } -- Separate bit translating the parser declaration. @@ -144,7 +125,7 @@ top::AGDcl ::= 'parser' n::Name '::' t::TypeExpr '{' m::ParserComponents '}' -- TODO: As a hack, even though we don't propogates defs up to the top level, we -- do generate files for the lifted dcl. Needed to generate terminal class files. - top.genFiles := liftedAGDcls.genFiles ++ + top.genFiles := m.genFiles ++ [pair(className ++ ".java", generateFunctionClassString(top.grammarName, n.name, namedSig, parseResult))]; diff --git a/grammars/silver/modification/copper/Prefix.sv b/grammars/silver/modification/copper/Prefix.sv index 24c61231f..a84ce4aed 100644 --- a/grammars/silver/modification/copper/Prefix.sv +++ b/grammars/silver/modification/copper/Prefix.sv @@ -17,14 +17,15 @@ top::ParserComponentModifier ::= 'prefix' ts::TerminalPrefixItems 'with' s::Term autocopy attribute prefixedTerminals::[String]; synthesized attribute terminalPrefix::String; -nonterminal TerminalPrefix with config, env, grammarName, componentGrammarName, compiledGrammars, prefixedTerminals, location, unparse, errors, liftedAGDcls, terminalPrefix; +nonterminal TerminalPrefix with config, env, flowEnv, grammarName, componentGrammarName, compiledGrammars, prefixedTerminals, location, unparse, errors, syntaxAst, genFiles, terminalPrefix; + +propagate errors, syntaxAst, genFiles on TerminalPrefix; concrete production nameTerminalPrefix top::TerminalPrefix ::= s::QName { top.unparse = s.unparse; - top.errors := s.lookupType.errors; - propagate liftedAGDcls; + top.errors <- s.lookupType.errors; top.terminalPrefix = makeCopperName(s.lookupType.fullName); } @@ -32,17 +33,20 @@ concrete production newTermModifiersTerminalPrefix top::TerminalPrefix ::= r::RegExpr tm::TerminalModifiers { top.unparse = r.unparse ++ " " ++ tm.unparse; - top.errors := []; -- r and tm get checked when liftedAGDcls gets decorated - -- Prefix terminal name isn't based off the prefix right now since that might not be alphanumeric - -- TODO make the terminal name based off alphanumeric characters from the regex for easier debugging of parse conflicts - local terminalName::String = "Prefix_" ++ toString(genInt()); - top.liftedAGDcls := - terminalDclDefault( - terminalKeywordModifierNone(location=top.location), - name(terminalName, top.location), - r, tm, - location=top.location); - top.terminalPrefix = makeCopperName(top.grammarName ++ ":" ++ terminalName); + production regex::Regex = r.terminalRegExprSpec; + local terminalName::String = + "Prefix_" ++ toString(top.location.line) ++ + case regex.asLiteral of + | just(a) when isAlpha(a) -> "_" ++ a + | _ -> "" + end; + local terminalFullName::String = top.grammarName ++ ":" ++ terminalName; + top.syntaxAst <- + [syntaxTerminal( + terminalFullName, regex, + foldr(consTerminalMod, nilTerminalMod(), tm.terminalModifiers))]; + top.genFiles <- terminalTranslation(terminalName, top.grammarName, tm.lexerClasses); + top.terminalPrefix = makeCopperName(terminalFullName); } concrete production newTermTerminalPrefix @@ -81,11 +85,12 @@ top::TerminalModifier ::= terms::[String] synthesized attribute prefixItemNames::[String]; nonterminal TerminalPrefixItems with config, env, grammarName, componentGrammarName, compiledGrammars, grammarDependencies, location, unparse, errors, prefixItemNames; +propagate errors on TerminalPrefixItems; + concrete production consTerminalPrefixItem top::TerminalPrefixItems ::= t::TerminalPrefixItem ',' ts::TerminalPrefixItems { top.unparse = ts.unparse ++ ", " ++ t.unparse; - top.errors := ts.errors ++ t.errors; top.prefixItemNames = ts.prefixItemNames ++ t.prefixItemNames; } @@ -93,7 +98,6 @@ concrete production oneTerminalPrefixItem top::TerminalPrefixItems ::= t::TerminalPrefixItem { top.unparse = t.unparse; - top.errors := t.errors; top.prefixItemNames = t.prefixItemNames; } @@ -101,13 +105,14 @@ abstract production nilTerminalPrefixItem top::TerminalPrefixItems ::= { top.unparse = ""; - top.errors := []; top.prefixItemNames = []; } +-- Empty list = prefix all marking terminals concrete production allTerminalPrefixItems top::TerminalPrefixItems ::= { + -- TODO: Potentially missing marking terminals from conditionally exported grammars production med :: ModuleExportedDefs = moduleExportedDefs(top.location, top.compiledGrammars, top.grammarDependencies, [top.componentGrammarName], []); @@ -159,35 +164,31 @@ top::ParserComponent ::= 'prefer' t::QName 'over' ts::TermList ';' { top.unparse = "prefer " ++ t.unparse ++ " over " ++ ts.unparse; top.errors <- t.lookupType.errors; - top.liftedAGDcls <- + + local pluckTAction::ProductionStmt = Silver_ProductionStmt { pluck $QName{t}; }; + -- Most of these aren't actually needed since we just want the translation. + pluckTAction.config = top.config; + pluckTAction.env = top.env; + pluckTAction.flowEnv = top.flowEnv; + pluckTAction.grammarName = top.grammarName; + pluckTAction.compiledGrammars = top.compiledGrammars; + pluckTAction.frame = error("Not needed"); + pluckTAction.downSubst = emptySubst(); + pluckTAction.finalSubst = emptySubst(); + + local tName::String = t.lookupType.dcl.fullName; + top.syntaxAst <- -- Generate a disambiguation function for every combination of ts. -- TODO: we can't use Copper's subset disambiguation functions here unfourtunately, -- since we currently require those to be disjoint. -- Also a slight bug here, if any of ts are undefined we will report errors -- more than once. - foldr1( - appendAGDcl(_, _, location=top.location), - map( - \ ts::[QName] -> - disambiguationGroupDcl( - 'disambiguate', - foldr( - termList(_, _, location=top.location), - termListNull(location=top.location), - t :: ts), - actionCode_c( - '{', - productionStmtsSnoc( - productionStmtsNil(location=top.location), - pluckDef( - 'pluck', baseExpr(t, location=top.location), ';', - location=top.location), - location=top.location), - '}', - location=top.location), - -- HACK: disambiguation function names are based on line number. TODO fixme - location=loc("prefix", genInt() * 1234, -1, -1, -1, -1, -1)), - tail(powerSet(ts.qnames)))); + map( + \ tsNames::[String] -> + syntaxDisambiguationGroup( + s"Prefer_${toString(top.location.line)}_${tName}__${implode("__", tsNames)}", + tName :: tsNames, false, pluckTAction.translation), + tail(powerSet(ts.termList))); } -- Prefix separator diff --git a/grammars/silver/modification/copper/TermList.sv b/grammars/silver/modification/copper/TermList.sv index 82184e4de..192fab9f4 100644 --- a/grammars/silver/modification/copper/TermList.sv +++ b/grammars/silver/modification/copper/TermList.sv @@ -5,8 +5,7 @@ grammar silver:modification:copper; -- specifically with refernce how abstract / concrete is deliniated. -- if TermPrecList has its structure refactored, so should TermList. -synthesized attribute qnames :: [QName]; -nonterminal TermList with config, grammarName, unparse, location, qnames, termList, defs, errors, env; +nonterminal TermList with config, grammarName, unparse, location, termList, defs, errors, env; monoid attribute termList :: [String] with [], ++; @@ -28,11 +27,10 @@ terms::TermList ::= t::QName ',' terms_tail::TermList abstract production termList top::TermList ::= h::QName t::TermList { - top.unparse = if t.unparse == "" - then h.unparse - else h.unparse ++ ", " ++ t.unparse; - - top.qnames = h :: t.qnames; + top.unparse = + if t.unparse == "" + then h.unparse + else h.unparse ++ ", " ++ t.unparse; production fName::String = h.lookupType.dcl.fullName; @@ -56,6 +54,5 @@ abstract production termListNull top::TermList ::= { top.unparse = ""; - top.qnames = []; top.defs := []; } diff --git a/grammars/silver/translation/java/core/TerminalDcl.sv b/grammars/silver/translation/java/core/TerminalDcl.sv index 96f5eb802..2b2fcbdce 100644 --- a/grammars/silver/translation/java/core/TerminalDcl.sv +++ b/grammars/silver/translation/java/core/TerminalDcl.sv @@ -4,14 +4,20 @@ imports silver:definition:concrete_syntax; imports silver:modification:copper; aspect production terminalDclDefault -top::AGDcl ::= t::TerminalKeywordModifier id::Name r::RegExpr -tm::TerminalModifiers +top::AGDcl ::= t::TerminalKeywordModifier id::Name r::RegExpr tm::TerminalModifiers { - local className :: String = "T" ++ id.name; - local lexerClassesStr :: String = implode(", ", map(quote, tm.lexerClasses)); + top.genFiles := terminalTranslation(id.name, top.grammarName, tm.lexerClasses); +} + +function terminalTranslation +[Pair] ::= name::String grammarName::String lexerClasses::[String] +{ + local className :: String = "T" ++ name; + local fName :: String = grammarName ++ ":" ++ name; + local lexerClassesStr :: String = implode(", ", map(\ s::String -> s"\"${s}\"", lexerClasses)); - top.genFiles := [pair(className ++ ".java", s""" -package ${makeName(top.grammarName)}; + return [pair(className ++ ".java", s""" +package ${makeName(grammarName)}; import edu.umn.cs.melt.copper.runtime.engines.semantics.VirtualLocation; import core.NLocation; @@ -40,12 +46,4 @@ public class ${className} extends common.Terminal { } """)]; - } - -function quote -String ::= s::String -{ - return "\"" ++ s ++ "\""; -} - From 0f163bf9c866ba4ac470e43bc3db17993f94d602 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 20 Mar 2020 15:55:40 -0500 Subject: [PATCH 34/57] Handle nested messages in IDE --- grammars/silver/composed/idetest/Analyze.sv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/grammars/silver/composed/idetest/Analyze.sv b/grammars/silver/composed/idetest/Analyze.sv index 676280439..a3912c85d 100644 --- a/grammars/silver/composed/idetest/Analyze.sv +++ b/grammars/silver/composed/idetest/Analyze.sv @@ -106,6 +106,8 @@ Message ::= path::String m::Message | err(loc(file, a, b, c, d, e, f), g) -> err(loc(path ++ "/" ++ file, a, b, c, d, e, f), g) | wrn(loc(file, a, b, c, d, e, f), g) -> wrn(loc(path ++ "/" ++ file, a, b, c, d, e, f), g) | info(loc(file, a, b, c, d, e, f), g) -> info(loc(path ++ "/" ++ file, a, b, c, d, e, f), g) + | nested(loc(file, a, b, c, d, e, f), g, others) -> + nested(loc(path ++ "/" ++ file, a, b, c, d, e, f), g, map(rewriteMessage(path, _), others)) end; } From bf3ccae607f0ee7e24368241af3b2471263e864b Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 20 Mar 2020 17:04:53 -0500 Subject: [PATCH 35/57] Include wrapped Messages in message output for nested Message --- grammars/silver/langutil/Message.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grammars/silver/langutil/Message.sv b/grammars/silver/langutil/Message.sv index 96e062dc7..98e83a5e0 100644 --- a/grammars/silver/langutil/Message.sv +++ b/grammars/silver/langutil/Message.sv @@ -70,7 +70,7 @@ abstract production nested top::Message ::= l::Location m::String others::[Message] { top.where = l; - top.message = m; + top.message = s"${m}\n${messagesToString(others)}"; top.output = s"${l.unparse}: ${m}\n${messagesToString(others)}\n"; top.severity = foldr(max, 0, map((.severity), others)); } From 13fd42d80b7a728d923f778d53f87703ad8c6663 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Tue, 31 Mar 2020 11:39:30 -0500 Subject: [PATCH 36/57] Add convenience occurs on syntax for monoid and collection attributes --- grammars/silver/extension/autoattr/Monoid.sv | 2 +- .../autoattr/convenience/Convenience.sv | 12 +++++++++++ .../extension/convenience/Convenience.sv | 21 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/grammars/silver/extension/autoattr/Monoid.sv b/grammars/silver/extension/autoattr/Monoid.sv index 21c359ce3..cd73541ff 100644 --- a/grammars/silver/extension/autoattr/Monoid.sv +++ b/grammars/silver/extension/autoattr/Monoid.sv @@ -3,7 +3,7 @@ grammar silver:extension:autoattr; concrete production monoidAttributeDcl top::AGDcl ::= 'monoid' 'attribute' a::Name tl::BracketedOptTypeExprs '::' te::TypeExpr 'with' e::Expr ',' q::NameOrBOperator ';' { - top.unparse = "monoid attribute " ++ a.unparse ++ ";"; + top.unparse = "monoid attribute " ++ a.unparse ++ tl.unparse ++ " :: " ++ te.unparse ++ " with " ++ e.unparse ++ ", " ++ q.unparse ++ ";"; production attribute fName :: String; fName = top.grammarName ++ ":" ++ a.name; diff --git a/grammars/silver/extension/autoattr/convenience/Convenience.sv b/grammars/silver/extension/autoattr/convenience/Convenience.sv index 4c5a12d73..c62431a10 100644 --- a/grammars/silver/extension/autoattr/convenience/Convenience.sv +++ b/grammars/silver/extension/autoattr/convenience/Convenience.sv @@ -2,6 +2,7 @@ grammar silver:extension:autoattr:convenience; import silver:extension:autoattr; import silver:extension:convenience; +import silver:modification:collection; import silver:definition:core; import silver:definition:concrete_syntax; import silver:definition:type:syntax; @@ -18,3 +19,14 @@ top::AGDcl ::= 'functor' 'attribute' a::Name 'occurs' 'on' qs::QNames ';' makeOccursDclsHelp($1.location, qNameWithTL(qNameId(a, location=a.location), botlNone(location=top.location)), qs.qnames), location=top.location); } + +concrete production monoidAttributeDclMultiple +top::AGDcl ::= 'monoid' 'attribute' a::Name tl::BracketedOptTypeExprs '::' te::TypeExpr 'with' e::Expr ',' q::NameOrBOperator 'occurs' 'on' qs::QNames ';' +{ + top.unparse = "monoid attribute " ++ a.unparse ++ tl.unparse ++ " :: " ++ te.unparse ++ " with " ++ e.unparse ++ ", " ++ q.unparse ++ " occurs on " ++ qs.unparse ++ ";"; + forwards to + appendAGDcl( + monoidAttributeDcl($1, $2, a, tl, $5, te, $7, e, $9, q, $14, location=a.location), + makeOccursDclsHelp($1.location, qNameWithTL(qNameId(a, location=a.location), botlNone(location=top.location)), qs.qnames), + location=top.location); +} diff --git a/grammars/silver/extension/convenience/Convenience.sv b/grammars/silver/extension/convenience/Convenience.sv index 35a9ad1e0..3586cfa50 100644 --- a/grammars/silver/extension/convenience/Convenience.sv +++ b/grammars/silver/extension/convenience/Convenience.sv @@ -5,6 +5,7 @@ imports silver:definition:core; imports silver:definition:concrete_syntax; imports silver:definition:type; imports silver:definition:type:syntax; +import silver:modification:collection; -- Multiple attribute occurs on statements concrete production multipleAttributionDclsManyMany @@ -78,6 +79,26 @@ top::AGDcl ::= 'synthesized' 'attribute' a::Name tl::BracketedOptTypeExprs '::' location=top.location); } +concrete production collectionAttributeDclInhMultiple +top::AGDcl ::= 'inherited' 'attribute' a::Name tl::BracketedOptTypeExprs '::' te::TypeExpr 'with' q::NameOrBOperator 'occurs' 'on' qs::QNames ';' +{ + top.unparse = "inherited attribute " ++ a.name ++ tl.unparse ++ " :: " ++ te.unparse ++ " with " ++ q.unparse ++ " ;" ; + forwards to appendAGDcl( + collectionAttributeDclInh($1, $2, a, tl, $5, te, $7, q, $12, location=top.location), + makeOccursDclsHelp(top.location, qNameWithTL(qNameId(a, location=a.location), tl), qs.qnames), + location=top.location); +} + +concrete production collectionAttributeDclSynMultiple +top::AGDcl ::= 'synthesized' 'attribute' a::Name tl::BracketedOptTypeExprs '::' te::TypeExpr 'with' q::NameOrBOperator 'occurs' 'on' qs::QNames ';' +{ + top.unparse = "synthesized attribute " ++ a.name ++ tl.unparse ++ " :: " ++ te.unparse ++ " with " ++ q.unparse ++ " ;" ; + forwards to appendAGDcl( + collectionAttributeDclSyn($1, $2, a, tl, $5, te, $7, q, $12, location=top.location), + makeOccursDclsHelp(top.location, qNameWithTL(qNameId(a, location=a.location), tl), qs.qnames), + location=top.location); +} + From e20f376c72c57b4ca87924ad2fca99552ec3816a Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Tue, 31 Mar 2020 14:42:17 -0500 Subject: [PATCH 37/57] Add new keywords to editor modes for Silver --- support/emacs/silver-mode/silver-mode.el | 4 ++-- support/gedit/silver.lang | 4 ++++ support/vim/syntax/sv.vim | 6 +++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/support/emacs/silver-mode/silver-mode.el b/support/emacs/silver-mode/silver-mode.el index c6fe30240..512ba9852 100644 --- a/support/emacs/silver-mode/silver-mode.el +++ b/support/emacs/silver-mode/silver-mode.el @@ -16,13 +16,13 @@ For detail, see `comment-dwim'." '("[\/]\\(\\([\\\\].\\)\\|[^\/]\\)*[\/]". font-lock-string-face) '("\\<\\(production\\|productions\\|occurs\\|on\\|nonterminal\\|attribute\\|propagate\\|if\\|then\\|else\\|option\\|exports\\|close\\|closed\\)\\>" . font-lock-keyword-face) '("\\<\\(local\\|global\\|terminal\\|concrete\\|abstract\\|default\\|ignore\\|start\\|lexer\\|class\\|classes\\|dominates\\|submits\\|aspect\\|decorate\\|autocopy\\)\\>" . font-lock-keyword-face) - '("\\<\\(import\\|imports\\|grammar\\|association\\|precedence\\|synthesized\\|inherited\\|functor\\|with\\|as\\|include\\)\\>" . font-lock-keyword-face) + '("\\<\\(import\\|imports\\|grammar\\|association\\|precedence\\|synthesized\\|inherited\\|functor\\|monoid\\|with\\|as\\|include\\)\\>" . font-lock-keyword-face) '("\\<\\(only\\|hiding\\|using\\|forwards\\|to\\|use\\|syntax\\|forwarding\\|function\\|return\\)\\>" . font-lock-keyword-face) '("\\<\\(Integer*\\|Boolean\\|String\\|Float\\|Reference\\|Production\\|Decorated\\)\\>" . font-lock-type-face) '("\\<\\(reference\\|length\\|substring\\|indexof\\|parser\\|error\\|cast\\|toInt\\|toReal\\|toString\\|new\\)\\>" . font-lock-builtin-face) '("\\<\\(cons\\|null\\|head\\|tail\\|let\\)\\>" . font-lock-builtin-face) '("\\<\\(true\\|false\\|left\\|right\\|none\\)\\>" . font-lock-constant-face) - '("\\<\\(case\\|of\\|end\\)\\>" . font-lock-keyword-face) + '("\\<\\(case\\|rule\\|of\\|end\\)\\>" . font-lock-keyword-face) '("\\" 1 font-lock-function-name-face) '("\\" 1 font-lock-function-name-face) '("\\" 1 font-lock-function-name-face) diff --git a/support/gedit/silver.lang b/support/gedit/silver.lang index c87446baa..6872bb952 100644 --- a/support/gedit/silver.lang +++ b/support/gedit/silver.lang @@ -189,6 +189,7 @@ class default flowtype +propagate @@ -208,6 +209,8 @@ concrete inherited synthesized +functor +monoid autocopy ignore @@ -235,6 +238,7 @@ case +rule of let in diff --git a/support/vim/syntax/sv.vim b/support/vim/syntax/sv.vim index b603d735d..e135cf324 100644 --- a/support/vim/syntax/sv.vim +++ b/support/vim/syntax/sv.vim @@ -10,17 +10,17 @@ endif syn keyword svlangExternals grammar import imports exports build hiding as only option -syn keyword svlangDeclarations parser attribute annotation function local closed nonterminal type occurs on production terminal marking foreign layout disambiguate action global productions lexer class default +syn keyword svlangDeclarations parser attribute annotation function local closed nonterminal type occurs on production terminal marking foreign layout disambiguate action global productions lexer class default propagate syn keyword svlangPrimitiveTypes IO Boolean Decorated Float Function Integer Production String -syn keyword svlangStorageClass abstract aspect concrete inherited synthesized autocopy ignore +syn keyword svlangStorageClass abstract aspect concrete inherited synthesized autocopy functor monoid ignore syn keyword svlangScopeDeclarations association precedence operator dominates submits classes syn keyword svlangFlowOther forwarding forwards to return pluck -syn keyword svlangFlow case of let in end decorate with prefix else forward if new then +syn keyword svlangFlow case rule of let in end decorate with prefix else forward if new then syn keyword svlangFunction print toString toInt toFloat length reference substring indexOf error cast left right partitionEithers hackUnparse print readLineStdin exit mkdir system writeFile appendFile fileTime isFile isDirectory readFile cwd envVar listContents deleteFile deleteTree copyFile touchFile error unsafeIO genInt genRand unsafeTrace dirNameInFilePath fileNameInFilePath splitFileNameAndExtension map foldr foldl foldr1 foldl1 filter partition containsBy nubBy removeBy removeAllBy last drop take dropWhile takeWhile takeUntil positionOf positionOfHelper repeat zipWith reverse sortBy groupBy intersperse unionBy intersectBy unionsBy nil cons append null listLength head tail locationLte fromMaybe orElse consMaybe catMaybes fst snd lookupBy lookupAllBy unzipPairs parseTreeOrDieWithoutStackTrace implode explode indexOf lastIndexOf substring startsWith endsWith substitute replicate isDigit isAlpha isSpace isLower isUpper toIntSafe compareString stringConcat stringEq stringLte runIO evalIO unsafeEvalIO bindList returnList bindMaybe returnMaybe runState evalState ioval From b67b458a0ff698cb453a1caddedeabae1ea1b8ec Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Thu, 2 Apr 2020 14:33:11 -0500 Subject: [PATCH 38/57] Implement except clause on global propagate --- .../silver/extension/autoattr/Propagate.sv | 82 +++++++++++++++++-- .../silver/extension/autoattr/Terminals.sv | 1 + 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/grammars/silver/extension/autoattr/Propagate.sv b/grammars/silver/extension/autoattr/Propagate.sv index 9d3e568aa..3c643e590 100644 --- a/grammars/silver/extension/autoattr/Propagate.sv +++ b/grammars/silver/extension/autoattr/Propagate.sv @@ -1,17 +1,35 @@ grammar silver:extension:autoattr; -concrete production propagateOnNTListDcl +concrete production propagateOnNTListExceptDcl +top::AGDcl ::= 'propagate' attrs::NameList 'on' nts::NameList 'except' ps::ProdNameList ';' +{ + top.unparse = s"propagate ${attrs.unparse} on ${nts.unparse} except ${ps.unparse};"; + + top.errors <- ps.errors; + forwards to propagateOnNTListDcl(attrs, nts, ps, location=top.location); +} + +concrete production propagateOnNTListNoExceptDcl top::AGDcl ::= 'propagate' attrs::NameList 'on' nts::NameList ';' { top.unparse = s"propagate ${attrs.unparse} on ${nts.unparse};"; + forwards to + propagateOnNTListDcl(attrs, nts, prodNameListNil(location=top.location), location=top.location); +} + +abstract production propagateOnNTListDcl +top::AGDcl ::= attrs::NameList nts::NameList ps::ProdNameList +{ + top.unparse = s"propagate ${attrs.unparse} on ${nts.unparse} except ${ps.unparse};"; + forwards to case nts of - | nameListOne(n) -> propagateOnOneNTDcl(attrs, n, location=n.location) + | nameListOne(n) -> propagateOnOneNTDcl(attrs, n, ps, location=n.location) | nameListCons(n, _, rest) -> appendAGDcl( - propagateOnOneNTDcl(attrs, n, location=n.location), - propagateOnNTListDcl($1, attrs, $3, rest, $5, location=top.location), + propagateOnOneNTDcl(attrs, n, ps, location=n.location), + propagateOnNTListDcl(attrs, rest, ps, location=top.location), location=top.location) end; } @@ -21,21 +39,23 @@ top::AGDcl ::= 'propagate' attrs::NameList 'on' nts::NameList ';' -- always the case (see options and closed nonterminals.) -- For such productions the attribute must still be explicitly propagated. abstract production propagateOnOneNTDcl -top::AGDcl ::= attrs::NameList nt::QName +top::AGDcl ::= attrs::NameList nt::QName ps::ProdNameList { - top.unparse = s"propagate ${attrs.unparse} on ${nt.unparse};"; + top.unparse = s"propagate ${attrs.unparse} on ${nt.unparse} except ${ps.unparse};"; -- Ugh, workaround for circular dependency top.defs := []; top.occursDefs := []; top.moduleNames := []; - local nonForwardingProds::[DclInfo] = - filter(\ d::DclInfo -> !d.hasForward, getKnownProds(nt.lookupType.fullName, top.env)); + local includedProds::[DclInfo] = + filter( + \ d::DclInfo -> !d.hasForward && !containsBy(stringEq, d.fullName, ps.names), + getKnownProds(nt.lookupType.fullName, top.env)); local dcl::AGDcl = foldr( appendAGDcl(_, _, location=top.location), emptyAGDcl(location=top.location), - map(propagateAspectDcl(_, attrs, location=nt.location), nonForwardingProds)); + map(propagateAspectDcl(_, attrs, location=nt.location), includedProds)); forwards to if !null(nt.lookupType.errors) @@ -122,3 +142,47 @@ top::ProductionStmt ::= attr::Decorated QName [err(attr.location, s"Attribute ${attr.name} cannot be propagated")], location=top.location); } + + +-- Need a seperate nonterminal since this can be empty and needs env to check errors +nonterminal ProdNameList with config, grammarName, env, location, unparse, names, errors; +propagate errors on ProdNameList; + +abstract production prodNameListNil +top::ProdNameList ::= +{ + top.unparse = ""; + top.names = []; +} + +concrete production prodNameListOne +top::ProdNameList ::= n::QName +{ + top.unparse = n.unparse; + top.names = [n.lookupValue.fullName]; + top.errors <- n.lookupValue.errors; + top.errors <- + if n.lookupValue.found + then + case n.lookupValue.dcl of + | prodDcl(_, _, _, _) -> [] + | _ -> [err(n.location, n.name ++ " is not a production")] + end + else []; +} + +concrete production prodNameListCons +top::ProdNameList ::= h::QName ',' t::ProdNameList +{ + top.unparse = h.unparse ++ ", " ++ t.unparse; + top.names = [h.lookupValue.fullName] ++ t.names; + top.errors <- h.lookupValue.errors; + top.errors <- + if h.lookupValue.found + then + case h.lookupValue.dcl of + | prodDcl(_, _, _, _) -> [] + | _ -> [err(h.location, h.name ++ " is not a production")] + end + else []; +} diff --git a/grammars/silver/extension/autoattr/Terminals.sv b/grammars/silver/extension/autoattr/Terminals.sv index b24a8512c..56095c5fa 100644 --- a/grammars/silver/extension/autoattr/Terminals.sv +++ b/grammars/silver/extension/autoattr/Terminals.sv @@ -1,6 +1,7 @@ grammar silver:extension:autoattr; terminal Propagate_kwd 'propagate' lexer classes {KEYWORD,RESERVED}; +terminal Except_kwd 'except' lexer classes {KEYWORD}; terminal Functor_kwd 'functor' lexer classes {KEYWORD,RESERVED}; terminal Monoid_kwd 'monoid' lexer classes {KEYWORD,RESERVED}; From ae44a9a4365f8626cfd0976be54a171f458d6848 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Thu, 2 Apr 2020 14:33:29 -0500 Subject: [PATCH 39/57] Use except clause on global propagate --- grammars/silver/definition/flow/env/Expr.sv | 339 +------------------- 1 file changed, 14 insertions(+), 325 deletions(-) diff --git a/grammars/silver/definition/flow/env/Expr.sv b/grammars/silver/definition/flow/env/Expr.sv index bacd880d9..661a5f1fc 100644 --- a/grammars/silver/definition/flow/env/Expr.sv +++ b/grammars/silver/definition/flow/env/Expr.sv @@ -21,8 +21,12 @@ synthesized attribute flowVertexInfo :: ExprVertexInfo; attribute flowDeps, flowDefs, flowEnv occurs on Expr, ExprInhs, ExprInh, Exprs, AppExprs, AppExpr, AnnoAppExprs, AnnoExpr; attribute flowVertexInfo occurs on Expr; +propagate flowDeps on Expr, ExprInhs, ExprInh, Exprs, AppExprs, AppExpr, AnnoAppExprs, AnnoExpr + except childReference, lhsReference, localReference, forwardReference, forwardAccess, synDecoratedAccessHandler, inhDecoratedAccessHandler, + decorateExprWith, newFunction, letp, lexicalLocalReference, matchPrimitiveReal; propagate flowDefs on Expr, ExprInhs, ExprInh, Exprs, AppExprs, AppExpr, AnnoAppExprs, AnnoExpr; + function inhsForTakingRef [String] ::= nt::String flowEnv::Decorated FlowEnv { @@ -47,18 +51,6 @@ top::Expr ::= top.flowVertexInfo = noVertex(); } -aspect production errorExpr -top::Expr ::= e::[Message] -{ - propagate flowDeps; -} - -aspect production errorReference -top::Expr ::= msg::[Message] q::Decorated QName -{ - propagate flowDeps; -} - aspect production childReference top::Expr ::= q::Decorated QName { @@ -114,49 +106,20 @@ top::Expr ::= q::Decorated QName then hasVertex(forwardVertexType) else noVertex(); } -aspect production productionReference -top::Expr ::= q::Decorated QName -{ - propagate flowDeps; -} -aspect production functionReference -top::Expr ::= q::Decorated QName -{ - propagate flowDeps; -} -aspect production globalValueReference -top::Expr ::= q::Decorated QName -{ - propagate flowDeps; -} - -- Still need these equations since propagate ignores decorated references aspect production functionInvocation top::Expr ::= e::Decorated Expr es::Decorated AppExprs annos::Decorated AnnoAppExprs { - top.flowDeps := e.flowDeps ++ es.flowDeps ++ annos.flowDeps; + top.flowDeps <- e.flowDeps ++ es.flowDeps ++ annos.flowDeps; top.flowDefs <- e.flowDefs ++ es.flowDefs ++ annos.flowDefs; } aspect production partialApplication top::Expr ::= e::Decorated Expr es::Decorated AppExprs annos::Decorated AnnoAppExprs { - top.flowDeps := e.flowDeps ++ es.flowDeps ++ annos.flowDeps; + top.flowDeps <- e.flowDeps ++ es.flowDeps ++ annos.flowDeps; top.flowDefs <- e.flowDefs ++ es.flowDefs ++ annos.flowDefs; } -aspect production errorApplication -top::Expr ::= e::Decorated Expr es::AppExprs annos::AnnoAppExprs -{ - top.flowDeps := []; -} - -aspect production attributeSection -top::Expr ::= '(' '.' q::QName ')' -{ - propagate flowDeps; -} - - aspect production forwardAccess top::Expr ::= e::Expr '.' 'forward' @@ -171,7 +134,6 @@ top::Expr ::= e::Expr '.' 'forward' aspect production errorAccessHandler top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur { - propagate flowDeps; top.flowDefs <- e.flowDefs; } -- Note that below we IGNORE the flow deps of the lhs if we know what it is @@ -199,19 +161,19 @@ top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur aspect production errorDecoratedAccessHandler top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur { - top.flowDeps := []; -- errors, who cares? + top.flowDeps <- []; -- errors, who cares? top.flowDefs <- e.flowDefs; } aspect production terminalAccessHandler top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur { - top.flowDeps := e.flowDeps; + top.flowDeps <- e.flowDeps; top.flowDefs <- e.flowDefs; } aspect production annoAccessHandler top::Expr ::= e::Decorated Expr q::Decorated QNameAttrOccur { - top.flowDeps := e.flowDeps; + top.flowDeps <- e.flowDeps; top.flowDefs <- e.flowDefs; } @@ -253,7 +215,6 @@ autocopy attribute decorationVertex :: String occurs on ExprInhs, ExprInh; aspect production exprInh top::ExprInh ::= lhs::ExprLHSExpr '=' e1::Expr ';' { - propagate flowDeps; top.flowDefs <- if !null(lhs.errors) then [] else case lhs of @@ -261,207 +222,20 @@ top::ExprInh ::= lhs::ExprLHSExpr '=' e1::Expr ';' end; } -aspect production exprInhsEmpty -top::ExprInhs ::= -{ - propagate flowDeps; -} -aspect production exprInhsOne -top::ExprInhs ::= h::ExprInh -{ - propagate flowDeps; -} -aspect production exprInhsCons -top::ExprInhs ::= h::ExprInh t::ExprInhs -{ - propagate flowDeps; -} - -aspect production trueConst -top::Expr ::= 'true' -{ - propagate flowDeps; -} -aspect production falseConst -top::Expr ::= 'false' -{ - propagate flowDeps; -} -aspect production and -top::Expr ::= e1::Expr '&&' e2::Expr -{ - propagate flowDeps; -} -aspect production or -top::Expr ::= e1::Expr '||' e2::Expr -{ - propagate flowDeps; -} -aspect production not -top::Expr ::= '!' e1::Expr -{ - propagate flowDeps; -} -aspect production gt -top::Expr ::= e1::Expr '>' e2::Expr -{ - propagate flowDeps; -} -aspect production lt -top::Expr ::= e1::Expr '<' e2::Expr -{ - propagate flowDeps; -} -aspect production gteq -top::Expr ::= e1::Expr '>=' e2::Expr -{ - propagate flowDeps; -} -aspect production lteq -top::Expr ::= e1::Expr '<=' e2::Expr -{ - propagate flowDeps; -} -aspect production eqeq -top::Expr ::= e1::Expr '==' e2::Expr -{ - propagate flowDeps; -} -aspect production neq -top::Expr ::= e1::Expr '!=' e2::Expr -{ - propagate flowDeps; -} -aspect production ifThenElse -top::Expr ::= 'if' e1::Expr 'then' e2::Expr 'else' e3::Expr -{ - propagate flowDeps; -} -aspect production intConst -top::Expr ::= i::Int_t -{ - propagate flowDeps; -} -aspect production floatConst -top::Expr ::= f::Float_t -{ - propagate flowDeps; -} -aspect production plus -top::Expr ::= e1::Expr '+' e2::Expr -{ - propagate flowDeps; -} -aspect production minus -top::Expr ::= e1::Expr '-' e2::Expr -{ - propagate flowDeps; -} -aspect production multiply -top::Expr ::= e1::Expr '*' e2::Expr -{ - propagate flowDeps; -} -aspect production divide -top::Expr ::= e1::Expr '/' e2::Expr -{ - propagate flowDeps; -} -aspect production modulus -top::Expr ::= e1::Expr '%' e2::Expr -{ - propagate flowDeps; -} -aspect production neg -top::Expr ::= '-' e1::Expr -{ - propagate flowDeps; -} -aspect production stringConst -top::Expr ::= s::String_t -{ - propagate flowDeps; -} aspect production errorPlusPlus top::Expr ::= e1::Decorated Expr e2::Decorated Expr { - top.flowDeps := []; -- error, so who cares? + top.flowDeps <- []; -- error, so who cares? top.flowDefs <- e1.flowDefs ++ e2.flowDefs; } aspect production stringPlusPlus top::Expr ::= e1::Decorated Expr e2::Decorated Expr { - top.flowDeps := e1.flowDeps ++ e2.flowDeps; + top.flowDeps <- e1.flowDeps ++ e2.flowDeps; top.flowDefs <- e1.flowDefs ++ e2.flowDefs; } - -aspect production exprsEmpty -top::Exprs ::= -{ - propagate flowDeps; -} -aspect production exprsSingle -top::Exprs ::= e::Expr -{ - propagate flowDeps; -} -aspect production exprsCons -top::Exprs ::= e1::Expr ',' e2::Exprs -{ - propagate flowDeps; -} - - -aspect production missingAppExpr -top::AppExpr ::= '_' -{ - propagate flowDeps; -} -aspect production presentAppExpr -top::AppExpr ::= e::Expr -{ - propagate flowDeps; -} - -aspect production snocAppExprs -top::AppExprs ::= es::AppExprs ',' e::AppExpr -{ - propagate flowDeps; -} -aspect production oneAppExprs -top::AppExprs ::= e::AppExpr -{ - propagate flowDeps; -} -aspect production emptyAppExprs -top::AppExprs ::= -{ - propagate flowDeps; -} -aspect production annoExpr -top::AnnoExpr ::= qn::QName '=' e::AppExpr -{ - propagate flowDeps; -} -aspect production snocAnnoAppExprs -top::AnnoAppExprs ::= es::AnnoAppExprs ',' e::AnnoExpr -{ - propagate flowDeps; -} -aspect production oneAnnoAppExprs -top::AnnoAppExprs ::= e::AnnoExpr -{ - propagate flowDeps; -} -aspect production emptyAnnoAppExprs -top::AnnoAppExprs ::= -{ - propagate flowDeps; -} - - aspect production exprRef top::Expr ::= e::Decorated Expr { @@ -473,7 +247,7 @@ top::Expr ::= e::Decorated Expr -- So definitely don't consider making this []! - top.flowDeps := e.flowDeps; + top.flowDeps <- e.flowDeps; top.flowVertexInfo = e.flowVertexInfo; top.flowDefs <- e.flowDefs; -- I guess? I haven't thought about this exactly. -- i.e. whether this has already been included. shouldn't hurt to do so though. @@ -485,46 +259,16 @@ top::Expr ::= e::Decorated Expr aspect production stringLength top::Expr ::= e::Decorated Expr { - top.flowDeps := e.flowDeps; + top.flowDeps <- e.flowDeps; top.flowDefs <- e.flowDefs; } aspect production errorLength top::Expr ::= e::Decorated Expr { - top.flowDeps := e.flowDeps; + top.flowDeps <- e.flowDeps; top.flowDefs <- e.flowDefs; } -aspect production toBooleanFunction -top::Expr ::= 'toBoolean' '(' e1::Expr ')' -{ - propagate flowDeps; -} - -aspect production toIntegerFunction -top::Expr ::= 'toInteger' '(' e1::Expr ')' -{ - propagate flowDeps; -} - -aspect production toFloatFunction -top::Expr ::= 'toFloat' '(' e1::Expr ')' -{ - propagate flowDeps; -} - -aspect production toStringFunction -top::Expr ::= 'toString' '(' e1::Expr ')' -{ - propagate flowDeps; -} - -aspect production reifyFunctionLiteral -top::Expr ::= 'reify' -{ - propagate flowDeps; -} - aspect production newFunction top::Expr ::= 'new' '(' e1::Expr ')' { @@ -536,61 +280,6 @@ top::Expr ::= 'new' '(' e1::Expr ')' end; } -aspect production terminalConstructor -top::Expr ::= 'terminal' '(' t::TypeExpr ',' es::Expr ',' el::Expr ')' -{ - propagate flowDeps; -} - - - ----- FROM COPPER TODO ---grammar silver:modification:copper; - --- These are all errors, basically. - -aspect production failureTerminalIdExpr -top::Expr ::= 'disambiguationFailure' -{ - propagate flowDeps; -} - -aspect production actionChildReference -top::Expr ::= q::Decorated QName -{ - propagate flowDeps; -} - -aspect production pluckTerminalReference -top::Expr ::= q::Decorated QName -{ - propagate flowDeps; -} - -aspect production terminalIdReference -top::Expr ::= q::Decorated QName -{ - propagate flowDeps; -} - -aspect production lexerClassReference -top::Expr ::= q::Decorated QName -{ - propagate flowDeps; -} - -aspect production parserAttributeReference -top::Expr ::= q::Decorated QName -{ - propagate flowDeps; -} - -aspect production termAttrValueReference -top::Expr ::= q::Decorated QName -{ - propagate flowDeps; -} - -- FROM LET TODO attribute flowDefs, flowEnv occurs on AssignExpr; From 8469ae084489854e02898b357229662cf6264e79 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 3 Apr 2020 17:14:18 -0500 Subject: [PATCH 40/57] 'excluding' keyword for propagate --- grammars/silver/extension/autoattr/Propagate.sv | 15 ++++++++++++--- grammars/silver/extension/autoattr/Terminals.sv | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/grammars/silver/extension/autoattr/Propagate.sv b/grammars/silver/extension/autoattr/Propagate.sv index 3c643e590..66c8eac9c 100644 --- a/grammars/silver/extension/autoattr/Propagate.sv +++ b/grammars/silver/extension/autoattr/Propagate.sv @@ -9,7 +9,16 @@ top::AGDcl ::= 'propagate' attrs::NameList 'on' nts::NameList 'except' ps::ProdN forwards to propagateOnNTListDcl(attrs, nts, ps, location=top.location); } -concrete production propagateOnNTListNoExceptDcl +concrete production propagateOnNTListExcludingDcl_c +top::AGDcl ::= 'propagate' attrs::NameList 'on' nts::NameList 'excluding' ps::ProdNameList ';' +{ + top.unparse = s"propagate ${attrs.unparse} on ${nts.unparse} excluding ${ps.unparse};"; + + top.errors <- ps.errors; + forwards to propagateOnNTListDcl(attrs, nts, ps, location=top.location); +} + +concrete production propagateOnNTListDcl_c top::AGDcl ::= 'propagate' attrs::NameList 'on' nts::NameList ';' { top.unparse = s"propagate ${attrs.unparse} on ${nts.unparse};"; @@ -21,7 +30,7 @@ top::AGDcl ::= 'propagate' attrs::NameList 'on' nts::NameList ';' abstract production propagateOnNTListDcl top::AGDcl ::= attrs::NameList nts::NameList ps::ProdNameList { - top.unparse = s"propagate ${attrs.unparse} on ${nts.unparse} except ${ps.unparse};"; + top.unparse = s"propagate ${attrs.unparse} on ${nts.unparse} excluding ${ps.unparse};"; forwards to case nts of @@ -41,7 +50,7 @@ top::AGDcl ::= attrs::NameList nts::NameList ps::ProdNameList abstract production propagateOnOneNTDcl top::AGDcl ::= attrs::NameList nt::QName ps::ProdNameList { - top.unparse = s"propagate ${attrs.unparse} on ${nt.unparse} except ${ps.unparse};"; + top.unparse = s"propagate ${attrs.unparse} on ${nt.unparse} excluding ${ps.unparse};"; -- Ugh, workaround for circular dependency top.defs := []; diff --git a/grammars/silver/extension/autoattr/Terminals.sv b/grammars/silver/extension/autoattr/Terminals.sv index 56095c5fa..dfb7caa79 100644 --- a/grammars/silver/extension/autoattr/Terminals.sv +++ b/grammars/silver/extension/autoattr/Terminals.sv @@ -2,6 +2,7 @@ grammar silver:extension:autoattr; terminal Propagate_kwd 'propagate' lexer classes {KEYWORD,RESERVED}; terminal Except_kwd 'except' lexer classes {KEYWORD}; +terminal Excluding_kwd 'excluding' lexer classes {KEYWORD}; terminal Functor_kwd 'functor' lexer classes {KEYWORD,RESERVED}; terminal Monoid_kwd 'monoid' lexer classes {KEYWORD,RESERVED}; From 95c44372d0bd9623c15f5e0649565009436fe9a8 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 3 Apr 2020 17:24:02 -0500 Subject: [PATCH 41/57] Use excluding keyword instead of except --- grammars/silver/definition/flow/env/Expr.sv | 5 +++-- grammars/silver/extension/autoattr/Propagate.sv | 9 --------- grammars/silver/extension/autoattr/Terminals.sv | 1 - 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/grammars/silver/definition/flow/env/Expr.sv b/grammars/silver/definition/flow/env/Expr.sv index 661a5f1fc..700642b90 100644 --- a/grammars/silver/definition/flow/env/Expr.sv +++ b/grammars/silver/definition/flow/env/Expr.sv @@ -22,8 +22,9 @@ attribute flowDeps, flowDefs, flowEnv occurs on Expr, ExprInhs, ExprInh, Exprs, attribute flowVertexInfo occurs on Expr; propagate flowDeps on Expr, ExprInhs, ExprInh, Exprs, AppExprs, AppExpr, AnnoAppExprs, AnnoExpr - except childReference, lhsReference, localReference, forwardReference, forwardAccess, synDecoratedAccessHandler, inhDecoratedAccessHandler, - decorateExprWith, newFunction, letp, lexicalLocalReference, matchPrimitiveReal; + excluding + childReference, lhsReference, localReference, forwardReference, forwardAccess, synDecoratedAccessHandler, inhDecoratedAccessHandler, + decorateExprWith, newFunction, letp, lexicalLocalReference, matchPrimitiveReal; propagate flowDefs on Expr, ExprInhs, ExprInh, Exprs, AppExprs, AppExpr, AnnoAppExprs, AnnoExpr; diff --git a/grammars/silver/extension/autoattr/Propagate.sv b/grammars/silver/extension/autoattr/Propagate.sv index 66c8eac9c..2e8a463b9 100644 --- a/grammars/silver/extension/autoattr/Propagate.sv +++ b/grammars/silver/extension/autoattr/Propagate.sv @@ -1,14 +1,5 @@ grammar silver:extension:autoattr; -concrete production propagateOnNTListExceptDcl -top::AGDcl ::= 'propagate' attrs::NameList 'on' nts::NameList 'except' ps::ProdNameList ';' -{ - top.unparse = s"propagate ${attrs.unparse} on ${nts.unparse} except ${ps.unparse};"; - - top.errors <- ps.errors; - forwards to propagateOnNTListDcl(attrs, nts, ps, location=top.location); -} - concrete production propagateOnNTListExcludingDcl_c top::AGDcl ::= 'propagate' attrs::NameList 'on' nts::NameList 'excluding' ps::ProdNameList ';' { diff --git a/grammars/silver/extension/autoattr/Terminals.sv b/grammars/silver/extension/autoattr/Terminals.sv index dfb7caa79..03433e4f7 100644 --- a/grammars/silver/extension/autoattr/Terminals.sv +++ b/grammars/silver/extension/autoattr/Terminals.sv @@ -1,7 +1,6 @@ grammar silver:extension:autoattr; terminal Propagate_kwd 'propagate' lexer classes {KEYWORD,RESERVED}; -terminal Except_kwd 'except' lexer classes {KEYWORD}; terminal Excluding_kwd 'excluding' lexer classes {KEYWORD}; terminal Functor_kwd 'functor' lexer classes {KEYWORD,RESERVED}; From ac58f25bd8556c46dcfadf1c56c6f13a83c7898c Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Mon, 27 Apr 2020 17:36:43 -0500 Subject: [PATCH 42/57] Fix build bug involving whole-grammar prefixes --- .../concrete_syntax/NonTerminalDcl.sv | 2 +- .../definition/concrete_syntax/ParserSpec.sv | 44 +++++++++++++++-- .../definition/concrete_syntax/ast/CstAst.sv | 10 ++-- .../definition/concrete_syntax/ast/Syntax.sv | 13 ++--- .../concrete_syntax/ast/TerminalModifiers.sv | 26 +++++++--- .../silver/modification/copper/ParserDcl.sv | 18 +++---- grammars/silver/modification/copper/Prefix.sv | 47 +++++++------------ .../modification/copper_mda/Analysis.sv | 8 ++-- .../modification/copper_mda/SyntaxMdaRoot.sv | 8 +++- .../modification/impide/cstast/CstAst.sv | 2 +- 10 files changed, 112 insertions(+), 66 deletions(-) diff --git a/grammars/silver/definition/concrete_syntax/NonTerminalDcl.sv b/grammars/silver/definition/concrete_syntax/NonTerminalDcl.sv index dafbafcf4..2ef7a8673 100644 --- a/grammars/silver/definition/concrete_syntax/NonTerminalDcl.sv +++ b/grammars/silver/definition/concrete_syntax/NonTerminalDcl.sv @@ -18,7 +18,7 @@ top::AGDcl ::= cl::ClosedOrNot 'nonterminal' id::Name tl::BracketedOptTypeExprs syntax.superClasses = error("This shouldn't be needed..."); syntax.subClasses = error("This shouldn't be needed..."); - local exportedLayoutTerms::[String] = map((.fullName), syntax.allIgnoreTerminals); + local exportedLayoutTerms::[String] = syntax.allIgnoreTerminals; local exportedProds::[String] = map((.fullName), syntax.allProductions); top.syntaxAst := diff --git a/grammars/silver/definition/concrete_syntax/ParserSpec.sv b/grammars/silver/definition/concrete_syntax/ParserSpec.sv index 613d2eaa9..162cc6180 100644 --- a/grammars/silver/definition/concrete_syntax/ParserSpec.sv +++ b/grammars/silver/definition/concrete_syntax/ParserSpec.sv @@ -21,13 +21,22 @@ synthesized attribute cstAst :: SyntaxRoot; synthesized attribute startNT :: String; {-- - - Prefixes to inject onto marking terminals in the composed parser. + - Prefixes to inject onto terminals in the composed parser. -} monoid attribute terminalPrefixes :: [Pair] with [], ++; +{-- + - Prefixes to inject onto the marking terminals of grammars in the composed parser. + -} +monoid attribute grammarTerminalPrefixes :: [Pair] with [], ++; + abstract production parserSpec -top::ParserSpec ::= sl::Location sg::String fn::String snt::String grams::[String] customStartLayout::Maybe<[String]> terminalPrefixes::[Pair] addedDcls::[SyntaxDcl] +top::ParserSpec ::= + sl::Location sg::String fn::String snt::String grams::[String] + customStartLayout::Maybe<[String]> + terminalPrefixes::[Pair] grammarTerminalPrefixes::[Pair] + addedDcls::[SyntaxDcl] { top.sourceLocation = sl; top.sourceGrammar = sg; @@ -38,9 +47,34 @@ top::ParserSpec ::= sl::Location sg::String fn::String snt::String grams::[S -- We've decided we're using only the grammars in this parser to compute dependencies, as opposed -- to all grammars imported in the env. -- This could affect which conditional imports get triggered, and thus what gets included in the parser - production med :: ModuleExportedDefs = - moduleExportedDefs(sl, top.compiledGrammars, computeDependencies(grams, top.compiledGrammars), grams, []); + production deps :: [String] = computeDependencies(grams, top.compiledGrammars); + production med :: ModuleExportedDefs = moduleExportedDefs(sl, top.compiledGrammars, deps, grams, []); + + -- Compute the list of terminal prefixes for marking terminals here, because the set of marking + -- terminals exported by a grammar depends on conditional imports that may be triggered by other + -- grammars included in the parser. + -- Also works around a build bug (https://github.com/melt-umn/silver/issues/36) - the grammar + -- containing the parser spec (and thus the ParserSpec itself) does not get rebuilt when only its + -- dependencies are modified, thus the set of marking terminals exported by a grammar when the + -- ParserSpec is built may be out of date. + -- componentGrammarMarkingTerminals is also needed to help determine the prefix seperator. + production componentGrammarMarkingTerminals::[Pair] = + map( + \ g::String -> + pair(g, + foldr( + consSyntax, nilSyntax(), + moduleExportedDefs(sl, top.compiledGrammars, deps, [g], []).syntaxAst).allMarkingTerminals), + grams); + production markingTerminalPrefixes::[Pair] = + flatMap( + \ gp::Pair -> + map(pair(_, gp.snd), lookupBy(stringEq, gp.fst, componentGrammarMarkingTerminals).fromJust), + grammarTerminalPrefixes); - top.cstAst = cstRoot(fn, snt, foldr(consSyntax, nilSyntax(), addedDcls ++ med.syntaxAst), customStartLayout, terminalPrefixes); + top.cstAst = + cstRoot( + fn, snt, foldr(consSyntax, nilSyntax(), addedDcls ++ med.syntaxAst), + customStartLayout, terminalPrefixes ++ markingTerminalPrefixes, componentGrammarMarkingTerminals); } diff --git a/grammars/silver/definition/concrete_syntax/ast/CstAst.sv b/grammars/silver/definition/concrete_syntax/ast/CstAst.sv index c922a8f60..d8370fbd0 100644 --- a/grammars/silver/definition/concrete_syntax/ast/CstAst.sv +++ b/grammars/silver/definition/concrete_syntax/ast/CstAst.sv @@ -21,7 +21,9 @@ closed nonterminal SyntaxRoot with cstErrors, xmlCopper; synthesized attribute xmlCopper :: String; abstract production cstRoot -top::SyntaxRoot ::= parsername::String startnt::String s::Syntax customStartLayout::Maybe<[String]> terminalPrefixes::[Pair] +top::SyntaxRoot ::= + parsername::String startnt::String s::Syntax + customStartLayout::Maybe<[String]> terminalPrefixes::[Pair] componentGrammarMarkingTerminals::[Pair] { s.cstEnv = directBuildTree(s.cstDcls); s.cstNTProds = directBuildTree(s.cstProds); @@ -48,11 +50,12 @@ top::SyntaxRoot ::= parsername::String startnt::String s::Syntax customStartL map((.fullName), s.allProductions ++ s.allNonterminals), s.layoutContribs); s.prefixesForTerminals = directBuildTree(terminalPrefixes); + s.componentGrammarMarkingTerminals = directBuildTree(componentGrammarMarkingTerminals); -- Move productions under their nonterminal, and sort the declarations production s2 :: Syntax = foldr(consSyntax, nilSyntax(), sortBy(syntaxDclLte, s.cstNormalize)); - s2.cstEnv = directBuildTree(s.cstDcls); + s2.cstEnv = s.cstEnv; s2.containingGrammar = "host"; s2.cstNTProds = error("TODO: make this environment not be decorated?"); -- TODO s2.classTerminals = s.classTerminals; @@ -61,12 +64,13 @@ top::SyntaxRoot ::= parsername::String startnt::String s::Syntax customStartL s2.parserAttributeAspects = s.parserAttributeAspects; s2.layoutTerms = s.layoutTerms; s2.prefixesForTerminals = s.prefixesForTerminals; + s2.componentGrammarMarkingTerminals = s.componentGrammarMarkingTerminals; -- This should be on s1, because the s2 transform assumes everything is well formed. -- In particular, it drops productions it can't find an NT for. top.cstErrors := s.cstErrors; - production startFound :: [Decorated SyntaxDcl] = searchEnvTree(startnt, s2.cstEnv); + production startFound :: [Decorated SyntaxDcl] = searchEnvTree(startnt, s.cstEnv); top.cstErrors <- if !null(startFound) then [] else ["Nonterminal " ++ startnt ++ " was referenced but " ++ diff --git a/grammars/silver/definition/concrete_syntax/ast/Syntax.sv b/grammars/silver/definition/concrete_syntax/ast/Syntax.sv index 69f5d37a1..5e4b2eed0 100644 --- a/grammars/silver/definition/concrete_syntax/ast/Syntax.sv +++ b/grammars/silver/definition/concrete_syntax/ast/Syntax.sv @@ -24,8 +24,8 @@ monoid attribute parserAttributeAspectContribs::[Pair] with [], + autocopy attribute parserAttributeAspects::EnvTree; monoid attribute allTerminals :: [Decorated SyntaxDcl] with [], ++; -monoid attribute allIgnoreTerminals :: [Decorated SyntaxDcl] with [], ++; -monoid attribute allMarkingTerminals :: [Decorated SyntaxDcl] with [], ++; +monoid attribute allIgnoreTerminals :: [String] with [], ++; +monoid attribute allMarkingTerminals :: [String] with [], ++; monoid attribute allProductions :: [Decorated SyntaxDcl] with [], ++; monoid attribute allNonterminals :: [Decorated SyntaxDcl] with [], ++; monoid attribute disambiguationClasses :: [Decorated SyntaxDcl] with [], ++; @@ -39,12 +39,13 @@ monoid attribute layoutContribs :: [Pair] with [], ++; -- prod/nt autocopy attribute layoutTerms::EnvTree; autocopy attribute prefixesForTerminals :: EnvTree; +autocopy attribute componentGrammarMarkingTerminals :: EnvTree<[String]>; {-- - An abstract syntax tree for representing concrete syntax. -} -nonterminal Syntax with cstDcls, cstEnv, cstErrors, cstProds, cstNTProds, cstNormalize, allTerminals, allIgnoreTerminals, allMarkingTerminals, allProductions, allNonterminals, disambiguationClasses, classTerminalContribs, classTerminals, superClassContribs, superClasses, subClasses, parserAttributeAspectContribs, parserAttributeAspects, lexerClassRefDcls, layoutContribs, layoutTerms, xmlCopper, containingGrammar, prefixesForTerminals; +nonterminal Syntax with cstDcls, cstEnv, cstErrors, cstProds, cstNTProds, cstNormalize, allTerminals, allIgnoreTerminals, allMarkingTerminals, allProductions, allNonterminals, disambiguationClasses, classTerminalContribs, classTerminals, superClassContribs, superClasses, subClasses, parserAttributeAspectContribs, parserAttributeAspects, lexerClassRefDcls, layoutContribs, layoutTerms, xmlCopper, containingGrammar, prefixesForTerminals, componentGrammarMarkingTerminals; propagate cstDcls, cstErrors, cstProds, cstNormalize, allTerminals, allIgnoreTerminals, allMarkingTerminals, allProductions, allNonterminals, disambiguationClasses, classTerminalContribs, superClassContribs, parserAttributeAspectContribs, lexerClassRefDcls, layoutContribs on Syntax; @@ -64,7 +65,7 @@ top::Syntax ::= s1::SyntaxDcl s2::Syntax {-- - An individual declaration of a concrete syntax element. -} -nonterminal SyntaxDcl with cstDcls, cstEnv, cstErrors, cstProds, cstNTProds, cstNormalize, fullName, sortKey, allTerminals, allIgnoreTerminals, allMarkingTerminals, allProductions, allNonterminals, disambiguationClasses, classTerminalContribs, classTerminals, superClassContribs, superClasses, subClasses, parserAttributeAspectContribs, parserAttributeAspects, lexerClassRefDcls, exportedProds, hasCustomLayout, layoutContribs, layoutTerms, xmlCopper, classDomContribs, classSubContribs, prefixSeperator, containingGrammar, prefixesForTerminals; +nonterminal SyntaxDcl with cstDcls, cstEnv, cstErrors, cstProds, cstNTProds, cstNormalize, fullName, sortKey, allTerminals, allIgnoreTerminals, allMarkingTerminals, allProductions, allNonterminals, disambiguationClasses, classTerminalContribs, classTerminals, superClassContribs, superClasses, subClasses, parserAttributeAspectContribs, parserAttributeAspects, lexerClassRefDcls, exportedProds, hasCustomLayout, layoutContribs, layoutTerms, xmlCopper, classDomContribs, classSubContribs, prefixSeperator, containingGrammar, prefixesForTerminals, componentGrammarMarkingTerminals; synthesized attribute sortKey :: String; @@ -134,8 +135,8 @@ top::SyntaxDcl ::= n::String regex::Regex modifiers::SyntaxTerminalModifiers modifiers.terminalName = n; top.allTerminals := [top]; - top.allIgnoreTerminals := if modifiers.ignored then [top] else []; - top.allMarkingTerminals := if modifiers.marking then [top] else []; + top.allIgnoreTerminals := if modifiers.ignored then [top.fullName] else []; + top.allMarkingTerminals := if modifiers.marking then [top.fullName] else []; top.classTerminalContribs := modifiers.classTerminalContribs; -- left(terminal name) or right(string prefix) diff --git a/grammars/silver/definition/concrete_syntax/ast/TerminalModifiers.sv b/grammars/silver/definition/concrete_syntax/ast/TerminalModifiers.sv index a9df7dbd6..9c3cf0335 100644 --- a/grammars/silver/definition/concrete_syntax/ast/TerminalModifiers.sv +++ b/grammars/silver/definition/concrete_syntax/ast/TerminalModifiers.sv @@ -17,7 +17,7 @@ autocopy attribute terminalName :: String; - Modifiers for terminals. -} nonterminal SyntaxTerminalModifiers with cstEnv, cstErrors, classTerminalContribs, superClasses, subClasses, dominatesXML, - submitsXML, ignored, acode, lexerclassesXML, opPrecedence, opAssociation, prefixSeperator, prefixSeperatorToApply, + submitsXML, ignored, acode, lexerclassesXML, opPrecedence, opAssociation, prefixSeperator, prefixSeperatorToApply, componentGrammarMarkingTerminals, marking, terminalName, prettyName; propagate cstErrors, classTerminalContribs, dominatesXML, @@ -44,7 +44,7 @@ top::SyntaxTerminalModifiers ::= - Modifiers for terminals. -} closed nonterminal SyntaxTerminalModifier with cstEnv, cstErrors, classTerminalContribs, superClasses, subClasses, dominatesXML, - submitsXML, ignored, acode, lexerclassesXML, opPrecedence, opAssociation, prefixSeperator, prefixSeperatorToApply, + submitsXML, ignored, acode, lexerclassesXML, opPrecedence, opAssociation, prefixSeperator, prefixSeperatorToApply, componentGrammarMarkingTerminals, marking, terminalName, prettyName; {- We default ALL attributes, so we can focus only on those that are interesting in each case... -} @@ -178,13 +178,20 @@ top::SyntaxTerminalModifier ::= sep::String top.prefixSeperator := just(sep); } {-- - - The terminals prefixed by this terminal, for which to use their separator. + - The terminals/grammars prefixed by this terminal, for which to use their separator. -} abstract production termUsePrefixSeperatorFor -top::SyntaxTerminalModifier ::= terms::[String] +top::SyntaxTerminalModifier ::= terms::[String] grams::[String] { - production termRefs :: [[Decorated SyntaxDcl]] = lookupStrings(terms, top.cstEnv); - top.prefixSeperatorToApply := head(head(termRefs)).prefixSeperator; + production allTerms :: [String] = terms ++ concat(concat(lookupStrings(grams, top.componentGrammarMarkingTerminals))); + + production termRefs :: [[Decorated SyntaxDcl]] = lookupStrings(allTerms, top.cstEnv); + top.prefixSeperatorToApply := + case termRefs of + | [] -> nothing() + | [ref] :: _ -> ref.prefixSeperator + | _ -> error("Lookup failure not caught during error checking") + end; top.cstErrors := flatMap(\ a::Pair -> if !null(a.snd) then [] @@ -200,6 +207,13 @@ top::SyntaxTerminalModifier ::= terms::[String] else [], map(head, termRefs)); + {- TODO: This really should be some sort of warning, not an error, I think. + top.cstErrors <- + if null(allTerms) + then [top.terminalName ++ " does not prefix any terminals"] + else []; + -} + local distinctSepTermRefs :: [Decorated SyntaxDcl] = nubBy( \ s1::Decorated SyntaxDcl s2::Decorated SyntaxDcl -> diff --git a/grammars/silver/modification/copper/ParserDcl.sv b/grammars/silver/modification/copper/ParserDcl.sv index 83fab3ea9..d1dc16ca4 100644 --- a/grammars/silver/modification/copper/ParserDcl.sv +++ b/grammars/silver/modification/copper/ParserDcl.sv @@ -36,15 +36,15 @@ top::AGDcl ::= 'parser' n::Name '::' t::TypeExpr '{' m::ParserComponents '}' []); production spec :: ParserSpec = - parserSpec(top.location, top.grammarName, fName, t.typerep.typeName, m.moduleNames, m.customLayout, m.terminalPrefixes, m.syntaxAst); + parserSpec(top.location, top.grammarName, fName, t.typerep.typeName, m.moduleNames, m.customLayout, m.terminalPrefixes, m.grammarTerminalPrefixes, m.syntaxAst); spec.compiledGrammars = top.compiledGrammars; top.parserSpecs := [spec]; -- Note that this is undecorated. } -nonterminal ParserComponents with config, env, flowEnv, grammarName, location, unparse, errors, moduleNames, compiledGrammars, grammarDependencies, terminalPrefixes, syntaxAst, genFiles; +nonterminal ParserComponents with config, env, flowEnv, grammarName, location, unparse, errors, moduleNames, compiledGrammars, grammarDependencies, terminalPrefixes, grammarTerminalPrefixes, syntaxAst, genFiles; -propagate errors, moduleNames, terminalPrefixes, syntaxAst, genFiles on ParserComponents; +propagate errors, moduleNames, terminalPrefixes, grammarTerminalPrefixes, syntaxAst, genFiles on ParserComponents; concrete production nilParserComponent top::ParserComponents ::= @@ -58,9 +58,9 @@ top::ParserComponents ::= c1::ParserComponent c2::ParserComponents top.unparse = c1.unparse ++ ", " ++ c2.unparse; } -closed nonterminal ParserComponent with config, env, flowEnv, grammarName, location, unparse, errors, moduleNames, compiledGrammars, grammarDependencies, terminalPrefixes, syntaxAst, genFiles; +closed nonterminal ParserComponent with config, env, flowEnv, grammarName, location, unparse, errors, moduleNames, compiledGrammars, grammarDependencies, terminalPrefixes, grammarTerminalPrefixes, syntaxAst, genFiles; -propagate errors, moduleNames, terminalPrefixes, syntaxAst, genFiles on ParserComponent; +propagate errors, moduleNames, terminalPrefixes, grammarTerminalPrefixes, syntaxAst, genFiles on ParserComponent; aspect default production top::ParserComponent ::= @@ -79,9 +79,9 @@ top::ParserComponent ::= m::ModuleName mods::ParserComponentModifiers ';' autocopy attribute componentGrammarName::String; {-- Have special env built from just this parser component and the global env -} -nonterminal ParserComponentModifiers with config, env, flowEnv, grammarName, componentGrammarName, compiledGrammars, grammarDependencies, location, unparse, errors, terminalPrefixes, syntaxAst, genFiles; +nonterminal ParserComponentModifiers with config, env, flowEnv, grammarName, componentGrammarName, compiledGrammars, grammarDependencies, location, unparse, errors, terminalPrefixes, grammarTerminalPrefixes, syntaxAst, genFiles; -propagate errors, terminalPrefixes, syntaxAst, genFiles on ParserComponentModifiers; +propagate errors, terminalPrefixes, grammarTerminalPrefixes, syntaxAst, genFiles on ParserComponentModifiers; concrete production nilParserComponentModifier top::ParserComponentModifiers ::= @@ -95,9 +95,9 @@ top::ParserComponentModifiers ::= h::ParserComponentModifier t::ParserComponentM top.unparse = h.unparse ++ t.unparse; } -nonterminal ParserComponentModifier with config, env, flowEnv, grammarName, componentGrammarName, compiledGrammars, grammarDependencies, location, unparse, errors, terminalPrefixes, syntaxAst, genFiles; +nonterminal ParserComponentModifier with config, env, flowEnv, grammarName, componentGrammarName, compiledGrammars, grammarDependencies, location, unparse, errors, terminalPrefixes, grammarTerminalPrefixes, syntaxAst, genFiles; -propagate errors, terminalPrefixes, syntaxAst, genFiles on ParserComponentModifier; +propagate errors, terminalPrefixes, grammarTerminalPrefixes, syntaxAst, genFiles on ParserComponentModifier; aspect default production top::ParserComponentModifier ::= diff --git a/grammars/silver/modification/copper/Prefix.sv b/grammars/silver/modification/copper/Prefix.sv index a84ce4aed..b0c31ac55 100644 --- a/grammars/silver/modification/copper/Prefix.sv +++ b/grammars/silver/modification/copper/Prefix.sv @@ -12,12 +12,16 @@ top::ParserComponentModifier ::= 'prefix' ts::TerminalPrefixItems 'with' s::Term { top.unparse = "prefix " ++ ts.unparse ++ " with " ++ s.unparse; top.terminalPrefixes <- map(pair(_, s.terminalPrefix), ts.prefixItemNames); + top.grammarTerminalPrefixes <- + if ts.isAllMarking then [pair(top.componentGrammarName, s.terminalPrefix)] else []; s.prefixedTerminals = ts.prefixItemNames; + s.prefixedGrammars = if ts.isAllMarking then [top.componentGrammarName] else []; } autocopy attribute prefixedTerminals::[String]; +autocopy attribute prefixedGrammars::[String]; synthesized attribute terminalPrefix::String; -nonterminal TerminalPrefix with config, env, flowEnv, grammarName, componentGrammarName, compiledGrammars, prefixedTerminals, location, unparse, errors, syntaxAst, genFiles, terminalPrefix; +nonterminal TerminalPrefix with config, env, flowEnv, grammarName, componentGrammarName, compiledGrammars, prefixedTerminals, prefixedGrammars, location, unparse, errors, syntaxAst, genFiles, terminalPrefix; propagate errors, syntaxAst, genFiles on TerminalPrefix; @@ -67,23 +71,24 @@ top::TerminalPrefix ::= t::String_t -- Specify which terminals this prefix prefixes. This is used to find the separator to -- append to the regex when normalizing the CST AST terminalModifierSingle( - terminalModifierUsePrefixSeperatorFor(top.prefixedTerminals, location=top.location), + terminalModifierUsePrefixSeperatorFor(top.prefixedTerminals, top.prefixedGrammars, location=top.location), location=top.location), location=top.location); } -- Needed when generating seperated terminal declarations, this is pretty useless otherwise so abstract only abstract production terminalModifierUsePrefixSeperatorFor -top::TerminalModifier ::= terms::[String] +top::TerminalModifier ::= terms::[String] grams::[String] { - top.unparse = s"use prefix separator for {${implode(", ", terms)}}"; + top.unparse = s"use prefix separator for {${implode(", ", terms)}} {${implode(", ", grams)}}"; - top.terminalModifiers := [termUsePrefixSeperatorFor(terms)]; + top.terminalModifiers := [termUsePrefixSeperatorFor(terms, grams)]; top.errors := []; } synthesized attribute prefixItemNames::[String]; -nonterminal TerminalPrefixItems with config, env, grammarName, componentGrammarName, compiledGrammars, grammarDependencies, location, unparse, errors, prefixItemNames; +synthesized attribute isAllMarking::Boolean; +nonterminal TerminalPrefixItems with config, env, grammarName, componentGrammarName, compiledGrammars, grammarDependencies, location, unparse, errors, prefixItemNames, isAllMarking; propagate errors on TerminalPrefixItems; @@ -92,6 +97,7 @@ top::TerminalPrefixItems ::= t::TerminalPrefixItem ',' ts::TerminalPrefixItems { top.unparse = ts.unparse ++ ", " ++ t.unparse; top.prefixItemNames = ts.prefixItemNames ++ t.prefixItemNames; + top.isAllMarking = ts.isAllMarking; } concrete production oneTerminalPrefixItem @@ -99,6 +105,7 @@ top::TerminalPrefixItems ::= t::TerminalPrefixItem { top.unparse = t.unparse; top.prefixItemNames = t.prefixItemNames; + top.isAllMarking = false; } abstract production nilTerminalPrefixItem @@ -106,34 +113,16 @@ top::TerminalPrefixItems ::= { top.unparse = ""; top.prefixItemNames = []; + top.isAllMarking = false; } -- Empty list = prefix all marking terminals -concrete production allTerminalPrefixItems +concrete production allMarkingTerminalPrefixItems top::TerminalPrefixItems ::= { - -- TODO: Potentially missing marking terminals from conditionally exported grammars - production med :: ModuleExportedDefs = - moduleExportedDefs(top.location, top.compiledGrammars, top.grammarDependencies, [top.componentGrammarName], []); - - local syntax::Syntax = foldr(consSyntax, nilSyntax(), med.syntaxAst); - syntax.containingGrammar = error("This shouldn't be needed..."); - syntax.cstEnv = error("This shouldn't be needed..."); - syntax.cstNTProds = error("This shouldn't be needed..."); - syntax.classTerminals = error("This shouldn't be needed..."); - syntax.parserAttributeAspects = error("This shouldn't be needed..."); - syntax.layoutTerms = error("This shouldn't be needed..."); - syntax.prefixesForTerminals = error("This shouldn't be needed..."); - syntax.superClasses = error("This shouldn't be needed..."); - syntax.subClasses = error("This shouldn't be needed..."); - - forwards to - foldr( - consTerminalPrefixItem(_, ',', _, location=top.location), - nilTerminalPrefixItem(location=top.location), - map(\ sd::Decorated SyntaxDcl -> - qNameTerminalPrefixItem(qName(top.location, sd.fullName), location=top.location), - syntax.allMarkingTerminals)); + top.unparse = "all_marking"; -- Doesn't match cst but whatever + top.prefixItemNames = []; + top.isAllMarking = true; } nonterminal TerminalPrefixItem with config, env, grammarName, componentGrammarName, compiledGrammars, location, unparse, errors, prefixItemNames; diff --git a/grammars/silver/modification/copper_mda/Analysis.sv b/grammars/silver/modification/copper_mda/Analysis.sv index 2b54d05ab..b76e7fe31 100644 --- a/grammars/silver/modification/copper_mda/Analysis.sv +++ b/grammars/silver/modification/copper_mda/Analysis.sv @@ -28,10 +28,10 @@ top::AGDcl ::= 'copper_mda' testname::Name '(' orig::QName ')' '{' m::ParserComp top.errors <- if !orig.lookupValue.found || !null(spec) then [] else [err(orig.location, orig.name ++ " is not a parser.")]; - -- Ignoring any AGDcls generated by the ParserComponents for now... + -- Ignoring prefixes and any SyntaxDcls generated by the ParserComponents for now... top.mdaSpecs = case spec of - | parserSpec(_,_,fn,snt,hg,csl,pfxs, _) :: _ -> [mdaSpec(top.grammarName, top.grammarName ++":"++ testname.name, snt, hg, m.moduleNames, csl, pfxs)] + | parserSpec(_,_,fn,snt,hg,csl,_,_,_) :: _ -> [mdaSpec(top.grammarName, top.grammarName ++":"++ testname.name, snt, hg, m.moduleNames, csl)] | _ -> [] end; } @@ -47,7 +47,7 @@ function findSpec nonterminal MdaSpec with sourceGrammar, fullName, compiledGrammars,cstAst; abstract production mdaSpec -top::MdaSpec ::= sg::String fn::String snt::String hostgrams::[String] extgrams::[String] customStartLayout::Maybe<[String]> terminalPrefixes::[Pair] +top::MdaSpec ::= sg::String fn::String snt::String hostgrams::[String] extgrams::[String] customStartLayout::Maybe<[String]> { top.sourceGrammar = sg; top.fullName = fn; @@ -65,6 +65,6 @@ top::MdaSpec ::= sg::String fn::String snt::String hostgrams::[String] extgra cstCopperMdaRoot(fn, snt, foldr(consSyntax, nilSyntax(), hostmed.syntaxAst), foldr(consSyntax, nilSyntax(), extmed.syntaxAst), - customStartLayout, terminalPrefixes); + customStartLayout); } diff --git a/grammars/silver/modification/copper_mda/SyntaxMdaRoot.sv b/grammars/silver/modification/copper_mda/SyntaxMdaRoot.sv index 647874b71..ca51a9421 100644 --- a/grammars/silver/modification/copper_mda/SyntaxMdaRoot.sv +++ b/grammars/silver/modification/copper_mda/SyntaxMdaRoot.sv @@ -3,7 +3,7 @@ grammar silver:modification:copper_mda; import silver:util:raw:graph as g; abstract production cstCopperMdaRoot -top::SyntaxRoot ::= parsername::String startnt::String host::Syntax ext::Syntax customStartLayout::Maybe<[String]> terminalPrefixes::[Pair] +top::SyntaxRoot ::= parsername::String startnt::String host::Syntax ext::Syntax customStartLayout::Maybe<[String]> { -- Because there may be references between the grammars, we cannot do the -- usual normalization. @@ -37,7 +37,9 @@ top::SyntaxRoot ::= parsername::String startnt::String host::Syntax ext::Synt map((.fullName), host.allTerminals ++ ext.allTerminals), map((.fullName), host.allProductions ++ ext.allProductions ++ host.allNonterminals ++ ext.allNonterminals), host.layoutContribs ++ ext.layoutContribs); - host.prefixesForTerminals = directBuildTree(terminalPrefixes); + host.prefixesForTerminals = directBuildTree([]); + host.componentGrammarMarkingTerminals = directBuildTree([]); + ext.cstEnv = host.cstEnv; ext.containingGrammar = "ext"; ext.cstNTProds = error("TODO: this should only be used by normalize"); -- TODO @@ -47,6 +49,7 @@ top::SyntaxRoot ::= parsername::String startnt::String host::Syntax ext::Synt ext.parserAttributeAspects = host.parserAttributeAspects; ext.layoutTerms = host.layoutTerms; ext.prefixesForTerminals = host.prefixesForTerminals; + ext.componentGrammarMarkingTerminals = host.componentGrammarMarkingTerminals; local startFound :: [Decorated SyntaxDcl] = searchEnvTree(startnt, host.cstEnv); @@ -117,6 +120,7 @@ top::SyntaxRoot ::= parsername::String startnt::String host::Syntax ext::Synt parserAttributeAspects = host.parserAttributeAspects; layoutTerms = host.layoutTerms; prefixesForTerminals = host.prefixesForTerminals; + componentGrammarMarkingTerminals = host.componentGrammarMarkingTerminals; }, host.disambiguationClasses))) ++ implode("", map(xmlCopperRef, ext.disambiguationClasses)) ++ diff --git a/grammars/silver/modification/impide/cstast/CstAst.sv b/grammars/silver/modification/impide/cstast/CstAst.sv index 97b2eefa5..f6ff33734 100644 --- a/grammars/silver/modification/impide/cstast/CstAst.sv +++ b/grammars/silver/modification/impide/cstast/CstAst.sv @@ -14,7 +14,7 @@ top::SyntaxRoot ::= } aspect production cstRoot -top::SyntaxRoot ::= parsername::String startnt::String s::Syntax customStartLayout::Maybe<[String]> terminalPrefixes::[Pair] +top::SyntaxRoot ::= parsername::String startnt::String s::Syntax customStartLayout::Maybe<[String]> terminalPrefixes::[Pair] componentGrammarMarkingTerminals::[Pair] { -- 1) font information top.fontList := s2.fontList; From 23ab4ee2d2ee2ba30abd4bfcf2b252d7b769b800 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Mon, 27 Apr 2020 17:56:34 -0500 Subject: [PATCH 43/57] Update CST error test case --- test/csterrors/silver-compile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/csterrors/silver-compile b/test/csterrors/silver-compile index 029a28727..0f122eb22 100755 --- a/test/csterrors/silver-compile +++ b/test/csterrors/silver-compile @@ -25,7 +25,7 @@ silver $ARGS terminalLexer | grep "lexer_b:B" > /dev/null || ((count++)) silver $ARGS lexerSubmit | grep "B_t" > /dev/null || ((count++)) silver $ARGS lexerDominate | grep "B_t" > /dev/null || ((count++)) silver $ARGS missingSeparator | grep "test:nonterm_b:Mangle_t" > /dev/null || ((count++)) -silver $ARGS multipleSeparators | grep "multipleSeparators:B_t, multipleSeparators:A_t" > /dev/null || ((count++)) +silver $ARGS multipleSeparators | grep "multipleSeparators:A_t, multipleSeparators:B_t" > /dev/null || ((count++)) rm -f build.xml From 655e6c8a5091af350034eac6fa9c2df61a401517 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Sun, 7 Jun 2020 12:43:19 -0500 Subject: [PATCH 44/57] Remove superfluous imports in doc artifact grammar to get website building on Jenkins again --- grammars/silver/extension/doc/extra/Main.sv | 38 ++------------------- 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/grammars/silver/extension/doc/extra/Main.sv b/grammars/silver/extension/doc/extra/Main.sv index bfec384cf..4916f1954 100644 --- a/grammars/silver/extension/doc/extra/Main.sv +++ b/grammars/silver/extension/doc/extra/Main.sv @@ -38,22 +38,7 @@ import silver:driver; import silver:driver:util; import silver:extension; -import silver:extension:auto_ast; -import silver:extension:convenience; -import silver:extension:deprecation; -import silver:extension:doc; -import silver:extension:doc:core; -import silver:extension:doc:driver; -import silver:extension:easyterminal; ---import silver:extension:extendedorigins; -import silver:extension:functorattrib; -import silver:extension:list; -import silver:extension:list:java; -import silver:extension:patternmatching; -import silver:extension:templating; -import silver:extension:templating:syntax; -import silver:extension:testing; -import silver:extension:treegen; +-- Individual extensions built by silver:composed:Default import silver:host; @@ -61,26 +46,7 @@ import silver:langutil; import silver:langutil:pp; import silver:modification; -import silver:modification:autocopyattr; -import silver:modification:autocopyattr:convenience; -import silver:modification:autocopyattr:java; -import silver:modification:collection; -import silver:modification:collection:java; -import silver:modification:copper; -import silver:modification:copper_mda; -import silver:modification:defaultattr; -import silver:modification:ffi; -import silver:modification:ffi:java; -import silver:modification:ffi:util; -import silver:modification:impide; -import silver:modification:impide:cstast; -import silver:modification:impide:spec; -import silver:modification:lambda_fn; -import silver:modification:lambda_fn:java; -import silver:modification:let_fix; -import silver:modification:let_fix:java; -import silver:modification:primitivepattern; -import silver:modification:typedecl; +-- Individual modifications built by silver:composed:Default import silver:support:monto; From 2c1751a2cd53aa20cf5bf4e7feb57b387907c56c Mon Sep 17 00:00:00 2001 From: Louis Goessling Date: Wed, 17 Jun 2020 18:15:27 -0500 Subject: [PATCH 45/57] Add error for cases where reification with a skolem is known to be impossible, warn on cases where it is impossible most of the time --- .../typechecking/core/BuiltInFunctions.sv | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/grammars/silver/analysis/typechecking/core/BuiltInFunctions.sv b/grammars/silver/analysis/typechecking/core/BuiltInFunctions.sv index 62f910a29..14c403a29 100644 --- a/grammars/silver/analysis/typechecking/core/BuiltInFunctions.sv +++ b/grammars/silver/analysis/typechecking/core/BuiltInFunctions.sv @@ -65,10 +65,32 @@ top::Expr ::= 'toString' '(' e1::Expr ')' else [err(top.location, "Operand to toString must be concrete types String, Integer, Float, or Boolean. Instead it is of type " ++ prettyType(performSubstitution(e1.typerep, top.finalSubst)))]; } +function containsSkolem +Boolean ::= ty::Type +{ + return case ty of + | skolemType(_) -> true + | nonterminalType(_, args) -> any(map(containsSkolem, args)) + | decoratedType(ty) -> containsSkolem(ty) + | functionType(out, params, namedParams) -> containsSkolem(out) || any(map(containsSkolem, params)) || any(map((\x::NamedArgType -> containsSkolem(x.argType)), namedParams)) + | _ -> false + end; +} + aspect production reifyFunctionLiteral top::Expr ::= 'reify' { top.upSubst = top.downSubst; + + top.errors <- + case performSubstitution(top.typerep, top.finalSubst) of + | functionType(nonterminalType("core:Either", [stringType(), resultType]), [nonterminalType("core:reflect:AST", [])], []) -> + case resultType of + | skolemType(_) -> [err(top.location, "reify invocation attempts to reify to a skolem type - this will never succeed, see https://github.com/melt-umn/silver/issues/368")] + | ty -> if containsSkolem(ty) then [wrn(top.location, "reify invocation attempts to reify to a type containing a skolem - this will only succeed in the case that the value does not actually contain an instance of the skolem type, see https://github.com/melt-umn/silver/issues/368")] else [] + end + | _ -> error("insane final type for reify implementation") + end; } aspect production newFunction From ae39d6360f15c5370568ce4fcc24daf16fb0ba3c Mon Sep 17 00:00:00 2001 From: Louis Goessling Date: Thu, 18 Jun 2020 13:39:45 -0500 Subject: [PATCH 46/57] Add warnCode for testing warnings, make wrongCode and wrongFlowCode ignore non-error messages --- grammars/silver/definition/core/AGDcl.sv | 9 +++++++ .../silver/extension/testing/WrongCode.sv | 25 +++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/grammars/silver/definition/core/AGDcl.sv b/grammars/silver/definition/core/AGDcl.sv index 119195b3d..2f971a0f3 100644 --- a/grammars/silver/definition/core/AGDcl.sv +++ b/grammars/silver/definition/core/AGDcl.sv @@ -64,6 +64,15 @@ top::AGDcl ::= h::AGDcl t::AGDcl top.errors <- warnIfMultJarName(h.jarName, t.jarName, top.location); } +function makeAppendAGDclOfAGDcls +AGDcl ::= dcls::AGDcls +{ + return case dcls of + | nilAGDcls(location=l) -> emptyAGDcl(location=l) + | consAGDcls(dcl, rest, location=l) -> appendAGDcl(dcl, makeAppendAGDclOfAGDcls(rest), location=l) + end; +} + abstract production jarNameDcl top::AGDcl ::= n::Name { diff --git a/grammars/silver/extension/testing/WrongCode.sv b/grammars/silver/extension/testing/WrongCode.sv index 73116e58e..239cc3c3e 100644 --- a/grammars/silver/extension/testing/WrongCode.sv +++ b/grammars/silver/extension/testing/WrongCode.sv @@ -4,15 +4,22 @@ import silver:definition:core; import silver:definition:env; terminal WrongCode_kwd 'wrongCode' lexer classes {KEYWORD}; +terminal WarnCode_kwd 'warnCode' lexer classes {KEYWORD}; terminal WrongFlowCode_kwd 'wrongFlowCode' lexer classes {KEYWORD}; +function containsMessage +Boolean ::= text::String severity::Integer msgs::[Message] +{ + return any(map((\x::Message -> x.severity==severity && indexOf(text, x.message)!=-1), msgs)); +} + concrete production wrongDecl top::AGDcl ::= 'wrongCode' s::String_t '{' ags::AGDcls '}' { top.unparse = "wrongCode" ++ s.lexeme ++ "{" ++ ags.unparse ++ "}"; top.errors := - if indexOf(substring(1, length(s.lexeme) - 1, s.lexeme), messagesToString(ags.errors)) == -1 + if !containsMessage(substring(1, length(s.lexeme) - 1, s.lexeme), 2, ags.errors) then [err(top.location, "Wrong code did not raise an error containing " ++ s.lexeme ++ ". Bubbling up errors from lines " ++ toString($3.line) ++ " to " ++ toString($5.line))] ++ ags.errors else []; @@ -22,13 +29,27 @@ top::AGDcl ::= 'wrongCode' s::String_t '{' ags::AGDcls '}' forwards to emptyAGDcl(location=top.location); } +concrete production warnDecl +top::AGDcl ::= 'warnCode' s::String_t '{' ags::AGDcls '}' +{ + top.unparse = "warnCode" ++ s.lexeme ++ "{" ++ ags.unparse ++ "}"; + + top.errors := + if !containsMessage(substring(1, length(s.lexeme) - 1, s.lexeme), 1, ags.errors) + then [err(top.location, "Warn code did not raise a warning containing " ++ s.lexeme ++ ". Bubbling up errors from lines " ++ toString($3.line) ++ " to " ++ toString($5.line))] ++ ags.errors + else []; + + forwards to makeAppendAGDclOfAGDcls(ags); + -- Forward to the decls so that we can use the stuff declared with warnings in other tests +} + concrete production wrongFlowDecl top::AGDcl ::= 'wrongFlowCode' s::String_t '{' ags::AGDcls '}' { top.unparse = "wrongFlowCode" ++ s.lexeme ++ "{" ++ ags.unparse ++ "}"; top.errors := - if indexOf(substring(1, length(s.lexeme) - 1, s.lexeme), messagesToString(ags.errors)) == -1 + if !containsMessage(substring(1, length(s.lexeme) - 1, s.lexeme), 2, ags.errors) then [err(top.location, "Wrong code did not raise an error containing " ++ s.lexeme ++ ". Bubbling up errors from lines " ++ toString($3.line) ++ " to " ++ toString($5.line))] ++ ags.errors else []; From 8f68ebb44415c91859fd1a7fe805436d4207f08c Mon Sep 17 00:00:00 2001 From: Louis Goessling Date: Thu, 18 Jun 2020 13:40:08 -0500 Subject: [PATCH 47/57] Update tests for new reify-to-skolem warnings + errors --- test/silver_features/Reflection.sv | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/test/silver_features/Reflection.sv b/test/silver_features/Reflection.sv index d716fe2a5..2366f90e4 100644 --- a/test/silver_features/Reflection.sv +++ b/test/silver_features/Reflection.sv @@ -173,20 +173,21 @@ equalityTest(reifyResToString(reify(anyAST(baz(anno2=_, anno1=_)))), "", String, silver_tests); equalityTest(reifyResToString(reify(anyAST(baz(anno1=_, anno2=2.0)))), "", String, silver_tests); -function reifySkolem -Either ::= x::AST -{ - return reify(x); +wrongCode "skolem" { + function reifySkolem + Either ::= x::AST + { + return reify(x); + } } --- This will have some sort of runtime type error involving skolems, but we can't test for it exactly since the exact message may vary. -equalityTest(case reifySkolem(floatAST(4.0)) of left(_) -> true | right(_) -> false end, true, Boolean, silver_tests); - -function reifySkolem2 -Either ::= -{ - local fn::(a ::= Integer) = \ i::Integer -> error(toString(i)); - return reify(anyAST(fn)); +warnCode "skolem" { + function reifySkolem2 + Either ::= + { + local fn::(a ::= Integer) = \ i::Integer -> error(toString(i)); + return reify(anyAST(fn)); + } } equalityTest(case reifySkolem2() of left(_) -> false | right(_) -> true end, true, Boolean, silver_tests); From fcd59f1b8a03b12ad1076d550ab3f77a74a6807a Mon Sep 17 00:00:00 2001 From: Louis Goessling Date: Thu, 18 Jun 2020 13:41:27 -0500 Subject: [PATCH 48/57] Use pretty-print output instead of message contents because some tests are testing that the reported line number (in pretty-print output) is right --- grammars/silver/extension/testing/WrongCode.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grammars/silver/extension/testing/WrongCode.sv b/grammars/silver/extension/testing/WrongCode.sv index 239cc3c3e..ba4832717 100644 --- a/grammars/silver/extension/testing/WrongCode.sv +++ b/grammars/silver/extension/testing/WrongCode.sv @@ -10,7 +10,7 @@ terminal WrongFlowCode_kwd 'wrongFlowCode' lexer classes {KEYWORD}; function containsMessage Boolean ::= text::String severity::Integer msgs::[Message] { - return any(map((\x::Message -> x.severity==severity && indexOf(text, x.message)!=-1), msgs)); + return any(map((\x::Message -> x.severity==severity && indexOf(text, x.output)!=-1), msgs)); } concrete production wrongDecl From 02b990c425e940e7851ee612729c4a84286a3af9 Mon Sep 17 00:00:00 2001 From: Louis Goessling Date: Thu, 18 Jun 2020 13:48:20 -0500 Subject: [PATCH 49/57] Style fixes :) --- .../typechecking/core/BuiltInFunctions.sv | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/grammars/silver/analysis/typechecking/core/BuiltInFunctions.sv b/grammars/silver/analysis/typechecking/core/BuiltInFunctions.sv index 14c403a29..0a8e6f7a9 100644 --- a/grammars/silver/analysis/typechecking/core/BuiltInFunctions.sv +++ b/grammars/silver/analysis/typechecking/core/BuiltInFunctions.sv @@ -69,12 +69,12 @@ function containsSkolem Boolean ::= ty::Type { return case ty of - | skolemType(_) -> true - | nonterminalType(_, args) -> any(map(containsSkolem, args)) - | decoratedType(ty) -> containsSkolem(ty) - | functionType(out, params, namedParams) -> containsSkolem(out) || any(map(containsSkolem, params)) || any(map((\x::NamedArgType -> containsSkolem(x.argType)), namedParams)) - | _ -> false - end; + | skolemType(_) -> true + | nonterminalType(_, args) -> any(map(containsSkolem, args)) + | decoratedType(ty) -> containsSkolem(ty) + | functionType(out, params, namedParams) -> containsSkolem(out) || any(map(containsSkolem, params)) || any(map((\x::NamedArgType -> containsSkolem(x.argType)), namedParams)) + | _ -> false + end; } aspect production reifyFunctionLiteral @@ -85,10 +85,11 @@ top::Expr ::= 'reify' top.errors <- case performSubstitution(top.typerep, top.finalSubst) of | functionType(nonterminalType("core:Either", [stringType(), resultType]), [nonterminalType("core:reflect:AST", [])], []) -> - case resultType of - | skolemType(_) -> [err(top.location, "reify invocation attempts to reify to a skolem type - this will never succeed, see https://github.com/melt-umn/silver/issues/368")] - | ty -> if containsSkolem(ty) then [wrn(top.location, "reify invocation attempts to reify to a type containing a skolem - this will only succeed in the case that the value does not actually contain an instance of the skolem type, see https://github.com/melt-umn/silver/issues/368")] else [] - end + case resultType of + | skolemType(_) -> [err(top.location, "reify invocation attempts to reify to a skolem type - this will never succeed, see https://github.com/melt-umn/silver/issues/368")] + | ty when containsSkolem(ty) -> [wrn(top.location, "reify invocation attempts to reify to a type containing a skolem - this will only succeed in the case that the value does not actually contain an instance of the skolem type, see https://github.com/melt-umn/silver/issues/368")] + | _ -> [] + end | _ -> error("insane final type for reify implementation") end; } From 90635046c7c770a871d831af4fb6f1e7078e5be6 Mon Sep 17 00:00:00 2001 From: Louis Goessling Date: Thu, 18 Jun 2020 13:49:12 -0500 Subject: [PATCH 50/57] Style fix 2 --- grammars/silver/analysis/typechecking/core/BuiltInFunctions.sv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grammars/silver/analysis/typechecking/core/BuiltInFunctions.sv b/grammars/silver/analysis/typechecking/core/BuiltInFunctions.sv index 0a8e6f7a9..7066e2943 100644 --- a/grammars/silver/analysis/typechecking/core/BuiltInFunctions.sv +++ b/grammars/silver/analysis/typechecking/core/BuiltInFunctions.sv @@ -74,7 +74,7 @@ Boolean ::= ty::Type | decoratedType(ty) -> containsSkolem(ty) | functionType(out, params, namedParams) -> containsSkolem(out) || any(map(containsSkolem, params)) || any(map((\x::NamedArgType -> containsSkolem(x.argType)), namedParams)) | _ -> false - end; + end; } aspect production reifyFunctionLiteral From 81454421d1f108791eb7dd7ae4f4c066856dc199 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 26 Jun 2020 15:09:01 -0500 Subject: [PATCH 51/57] Workaround for broken NFS on coldpress, look for nailgun jar under home directory --- support/nailgun/sv-nailgun | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/nailgun/sv-nailgun b/support/nailgun/sv-nailgun index accd5e80e..e5ed9d83a 100755 --- a/support/nailgun/sv-nailgun +++ b/support/nailgun/sv-nailgun @@ -9,7 +9,7 @@ fi export NAILGUN_PORT=$(($RANDOM + 20000)) # Try a few possible locations, pick the first -SV_NAILGUN_CANDIDATES=$(shopt -s nullglob; echo /project/melt4/People/ted/nailgun/bin/nailgun-*.jar /usr/share/java/nailgun-server*.jar /usr/share/java/nailgun-*.jar) +SV_NAILGUN_CANDIDATES=$(shopt -s nullglob; echo /project/melt4/People/ted/nailgun/bin/nailgun-*.jar /usr/share/java/nailgun-server*.jar /usr/share/java/nailgun-*.jar ~/.m2/repository/com/facebook/nailgun-server/*/nailgun-server*.jar) SV_NAILGUN_ARRAY=($SV_NAILGUN_CANDIDATES) export SV_NAILGUN_JAR=${SV_NAILGUN_ARRAY[0]} From 1483bfe911b97d2205c0efff6dfd44ae87e91666 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 26 Jun 2020 15:16:38 -0500 Subject: [PATCH 52/57] Look for nailgun in /export/scratch instead --- support/nailgun/sv-nailgun | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/nailgun/sv-nailgun b/support/nailgun/sv-nailgun index e5ed9d83a..1be997ea1 100755 --- a/support/nailgun/sv-nailgun +++ b/support/nailgun/sv-nailgun @@ -9,7 +9,7 @@ fi export NAILGUN_PORT=$(($RANDOM + 20000)) # Try a few possible locations, pick the first -SV_NAILGUN_CANDIDATES=$(shopt -s nullglob; echo /project/melt4/People/ted/nailgun/bin/nailgun-*.jar /usr/share/java/nailgun-server*.jar /usr/share/java/nailgun-*.jar ~/.m2/repository/com/facebook/nailgun-server/*/nailgun-server*.jar) +SV_NAILGUN_CANDIDATES=$(shopt -s nullglob; echo /project/melt4/People/ted/nailgun/bin/nailgun-*.jar /usr/share/java/nailgun-server*.jar /usr/share/java/nailgun-*.jar /export/scratch/nailgun-server*.jar) SV_NAILGUN_ARRAY=($SV_NAILGUN_CANDIDATES) export SV_NAILGUN_JAR=${SV_NAILGUN_ARRAY[0]} From c02003d926099bb5b3fd671a936529c080e880f5 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 26 Jun 2020 18:10:52 -0500 Subject: [PATCH 53/57] Third time's the charm? --- support/nailgun/sv-nailgun | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/support/nailgun/sv-nailgun b/support/nailgun/sv-nailgun index 1be997ea1..81875d269 100755 --- a/support/nailgun/sv-nailgun +++ b/support/nailgun/sv-nailgun @@ -9,7 +9,7 @@ fi export NAILGUN_PORT=$(($RANDOM + 20000)) # Try a few possible locations, pick the first -SV_NAILGUN_CANDIDATES=$(shopt -s nullglob; echo /project/melt4/People/ted/nailgun/bin/nailgun-*.jar /usr/share/java/nailgun-server*.jar /usr/share/java/nailgun-*.jar /export/scratch/nailgun-server*.jar) +SV_NAILGUN_CANDIDATES=$(shopt -s nullglob; echo /project/melt4/People/ted/nailgun/bin/nailgun-*.jar /usr/share/java/nailgun-server*.jar /usr/share/java/nailgun-*.jar /export/scratch/nailgun/bin/nailgun-server*.jar) SV_NAILGUN_ARRAY=($SV_NAILGUN_CANDIDATES) export SV_NAILGUN_JAR=${SV_NAILGUN_ARRAY[0]} @@ -32,6 +32,8 @@ elif [[ -f /usr/bin/ng-nailgun ]]; then fi elif [[ -f /project/melt4/People/ted/nailgun/bin/ng ]]; then export SV_NAILGUN="/project/melt4/People/ted/nailgun/bin/ng" +elif [[ -f /export/scratch/nailgun/bin/ng ]]; then + export SV_NAILGUN="/export/scratch/nailgun/bin/ng" elif [[ -f `which ng` ]]; then export SV_NAILGUN=`which ng` else From 911f7c04b8839dbeafc765730c7e93edbb7042fb Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 26 Jun 2020 19:13:44 -0500 Subject: [PATCH 54/57] Temporarily disable integration phase for debugging purposes Note that this testing unfortunately has to happen on the develop branch, due to branch-specific logic in the Jenkins configuration --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index c4c337697..e4f40d0c8 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -91,7 +91,7 @@ melt.trynode('silver') { // Clean sh "rm -rf silver-latest" } - +/* stage("Integration") { // Projects with 'develop' as main branch, we'll try to build specific branch names if they exist def github_projects = ["/melt-umn/ableC", "/melt-umn/Oberon0", "/melt-umn/ableJ14", "/melt-umn/meta-ocaml-lite", "/melt-umn/rewriting-lambda-calculus", @@ -111,7 +111,7 @@ melt.trynode('silver') { // Do downstream integration testing parallel tasks } - +*/ if (env.BRANCH_NAME == 'develop') { stage("Deploy") { sh "rsync -a --exclude .git --exclude generated --exclude silver-latest.tar.gz --delete --delete-excluded ./ ${silver.SILVER_WORKSPACE}/" From 1e5931361ac71eb9b8f93a44c01bbe553b4f2579 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 26 Jun 2020 19:29:58 -0500 Subject: [PATCH 55/57] Update sv-nailgun --- support/nailgun/sv-nailgun | 2 ++ 1 file changed, 2 insertions(+) diff --git a/support/nailgun/sv-nailgun b/support/nailgun/sv-nailgun index 81875d269..983abe820 100755 --- a/support/nailgun/sv-nailgun +++ b/support/nailgun/sv-nailgun @@ -5,6 +5,8 @@ if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then exit 5 fi +echo "Using modified nailgun script" + # Try to avoid colliding with other users of nailgun: 1/32k chance export NAILGUN_PORT=$(($RANDOM + 20000)) From 76c1650f7ff372a2d6c602a7497dd216292fefbc Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 26 Jun 2020 19:55:23 -0500 Subject: [PATCH 56/57] Revert "Update sv-nailgun" This reverts commit 1e5931361ac71eb9b8f93a44c01bbe553b4f2579. --- support/nailgun/sv-nailgun | 2 -- 1 file changed, 2 deletions(-) diff --git a/support/nailgun/sv-nailgun b/support/nailgun/sv-nailgun index 983abe820..81875d269 100755 --- a/support/nailgun/sv-nailgun +++ b/support/nailgun/sv-nailgun @@ -5,8 +5,6 @@ if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then exit 5 fi -echo "Using modified nailgun script" - # Try to avoid colliding with other users of nailgun: 1/32k chance export NAILGUN_PORT=$(($RANDOM + 20000)) From 74ac7a08d5209b13320c7a68bfd8d38c72fee880 Mon Sep 17 00:00:00 2001 From: Lucas Kramer Date: Fri, 26 Jun 2020 19:56:36 -0500 Subject: [PATCH 57/57] Revert "Temporarily disable integration phase for debugging purposes" This reverts commit 911f7c04b8839dbeafc765730c7e93edbb7042fb. --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index e4f40d0c8..c4c337697 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -91,7 +91,7 @@ melt.trynode('silver') { // Clean sh "rm -rf silver-latest" } -/* + stage("Integration") { // Projects with 'develop' as main branch, we'll try to build specific branch names if they exist def github_projects = ["/melt-umn/ableC", "/melt-umn/Oberon0", "/melt-umn/ableJ14", "/melt-umn/meta-ocaml-lite", "/melt-umn/rewriting-lambda-calculus", @@ -111,7 +111,7 @@ melt.trynode('silver') { // Do downstream integration testing parallel tasks } -*/ + if (env.BRANCH_NAME == 'develop') { stage("Deploy") { sh "rsync -a --exclude .git --exclude generated --exclude silver-latest.tar.gz --delete --delete-excluded ./ ${silver.SILVER_WORKSPACE}/"