Skip to content

Commit

Permalink
Merge pull request #378 from melt-umn/develop
Browse files Browse the repository at this point in the history
Silver 0.4.3 release
  • Loading branch information
krame505 authored Sep 11, 2020
2 parents 267ed8e + 8515654 commit 7f925ad
Show file tree
Hide file tree
Showing 119 changed files with 2,000 additions and 2,460 deletions.
4 changes: 2 additions & 2 deletions grammars/silver/analysis/typechecking/core/AspectDcl.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down
23 changes: 23 additions & 0 deletions grammars/silver/analysis/typechecking/core/BuiltInFunctions.sv
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,33 @@ 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 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;
}

aspect production newFunction
Expand Down
2 changes: 2 additions & 0 deletions grammars/silver/composed/idetest/Analyze.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

12 changes: 11 additions & 1 deletion grammars/silver/composed/idetest/Main.sv
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
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.
Expand Down Expand Up @@ -88,7 +91,14 @@ IOVal<[Message]> ::= project::IdeProject args::[IdeProperty] i::IO
function fold
[Location] ::= cst::Root
{
return cst.foldableRanges; -- see ./Folding.sv
-- 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
}

function getStubForNewFile
Expand Down
30 changes: 5 additions & 25 deletions grammars/silver/definition/concrete_syntax/NonTerminalDcl.sv
Original file line number Diff line number Diff line change
Expand Up @@ -18,36 +18,16 @@ 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 =
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;
}
monoid attribute nonterminalModifiers :: [SyntaxNonterminalModifier] with [], ++;
attribute nonterminalModifiers occurs on NonterminalModifiers, NonterminalModifierList, NonterminalModifier;
propagate nonterminalModifiers on NonterminalModifiers, NonterminalModifierList;
48 changes: 41 additions & 7 deletions grammars/silver/definition/concrete_syntax/ParserSpec.sv
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,60 @@ 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.
-}
synthesized attribute terminalPrefixes :: [Pair<String String>];
monoid attribute terminalPrefixes :: [Pair<String String>] with [], ++;

{--
- Prefixes to inject onto the marking terminals of grammars in the composed parser.
-}
monoid attribute grammarTerminalPrefixes :: [Pair<String String>] with [], ++;


abstract production parserSpec
top::ParserSpec ::= sl::Location sg::String fn::String snt::String grams::[String] customStartLayout::Maybe<[String]> terminalPrefixes::[Pair<String String>] addedDcls::[SyntaxDcl]
top::ParserSpec ::=
sl::Location sg::String fn::String snt::String grams::[String]
customStartLayout::Maybe<[String]>
terminalPrefixes::[Pair<String String>] grammarTerminalPrefixes::[Pair<String String>]
addedDcls::[SyntaxDcl]
{
top.sourceLocation = sl;
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.
-- 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<String [String]>] =
map(
\ g::String ->
pair(g,
foldr(
consSyntax, nilSyntax(),
moduleExportedDefs(sl, top.compiledGrammars, deps, [g], []).syntaxAst).allMarkingTerminals),
grams);
production markingTerminalPrefixes::[Pair<String String>] =
flatMap(
\ gp::Pair<String String> ->
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);
}

46 changes: 11 additions & 35 deletions grammars/silver/definition/concrete_syntax/ProductionDcl.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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))];

Expand All @@ -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;
}


Expand All @@ -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};
Expand All @@ -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 [];
Expand All @@ -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;

Expand Down Expand Up @@ -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")];
}
Expand Down
33 changes: 6 additions & 27 deletions grammars/silver/definition/concrete_syntax/Root.sv
Original file line number Diff line number Diff line change
@@ -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;
}

Loading

0 comments on commit 7f925ad

Please sign in to comment.