diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/check/AType.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/check/AType.rsc index 86895a1a..526021df 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/AType.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/AType.rsc @@ -180,6 +180,11 @@ bool asubtype(achar(int c), \achar-class(list[ACharRange] ranges)) { } bool asubtype(l:\achar-class(list[ACharRange] _), achar(int c)) = l == \achar-class([arange(c,c)]); +// amodifyTo (presumes normalizing rewrite rules have been applied from ATypeBase) +bool asubtype(amodifyTo(x, role), amodifyTo(y, role)) = amodifyTo(x, y); +bool asubtype(amodifyTo(l, rx), r:aadt(_, rx)) = asubtype(l, r); +bool asubtype(l:aadt(_, _, rx), amodifyTo(r, rx)) = asubtype(l, r); + // Utilities bool asubtype(atypeList(list[AType] l), atypeList(list[AType] r)) = asubtype(l, r); @@ -371,6 +376,10 @@ AType addADTLabel(AType a1, AType a2, AType adt){ return adt; } +// JV: TODO remove acons as a type. We don't have it fully working in the runtime-type system either and +// it has a confusing relationship with afunc. The type of a constructor function's name. ConstructorType +// in vallang should also be removed from the type hierarchy and simply become `Constructor` or `Production`. +// should be a function type: `ADT (parameters, keywordparams)` //AType alub(acons(AType la, list[AType] _, list[Keyword] _), acons(AType ra, list[AType] _, list[Keyword] _)) = alub(la,ra); AType alub(acons(AType lr, list[AType] lp, list[Keyword] lkw), acons(AType rr, list[AType] rp, list[Keyword] rkw)) { if(/*lr == rr && */size(lp) == size(rp)){ @@ -408,6 +417,38 @@ AType alub(AType l, aparameter(str _, AType bound)) = alub(l, bound) when aparam AType alub(areified(AType l), areified(AType r)) = areified(alub(l,r)); AType alub(areified(AType l), anode(_)) = anode([]); +// note that lub on modifyTo works under assumptions of normals forms affected by rewrite rules on modifyTo(..) terms +AType alub(amodifyTo(AType l, SyntaxRole sr), amodifyTo(AType r, sr)) + = amodifyTo(alub(l, r), sr); + +AType alub(amodifyTo(AType l, SyntaxRole sr), amodifyTo(AType r, sr)) + = amodifyTo(alub(l, r), sr); + +AType alub(amodifyTo(AType l, contextFreeSyntax()), amodifyTo(AType r, dataSyntax())) = anode([]); +AType alub(amodifyTo(AType l, contextFreeSyntax()), amodifyTo(AType r, lexicalSyntax())) = aadt("Tree", [], dataSyntax()); +AType alub(amodifyTo(AType l, contextFreeSyntax()), amodifyTo(AType r, keywordSyntax())) = aadt("Tree", [], dataSyntax()); +AType alub(amodifyTo(AType l, contextFreeSyntax()), amodifyTo(AType r, layoutSyntax())) = aadt("Tree", [], dataSyntax()); + +AType alub(amodifyTo(AType l, dataSyntax()), amodifyTo(AType r, contextFreeSyntax())) = anode([]); +AType alub(amodifyTo(AType l, dataSyntax()), amodifyTo(AType r, lexicalSyntax())) = anode([]); +AType alub(amodifyTo(AType l, dataSyntax()), amodifyTo(AType r, keywordSyntax())) = anode([]); +AType alub(amodifyTo(AType l, dataSyntax()), amodifyTo(AType r, layoutSyntax())) = anode([]); + +AType alub(amodifyTo(AType l, lexicalSyntax()), amodifyTo(AType r, dataSyntax())) = anode([]); +AType alub(amodifyTo(AType l, lexicalSyntax()), amodifyTo(AType r, contextFreeSyntax())) = aadt("Tree", [], dataSyntax()); +AType alub(amodifyTo(AType l, lexicalSyntax()), amodifyTo(AType r, keywordSyntax())) = aadt("Tree", [], dataSyntax()); +AType alub(amodifyTo(AType l, lexicalSyntax()), amodifyTo(AType r, layoutSyntax())) = aadt("Tree", [], dataSyntax()); + +AType alub(amodifyTo(AType l, keywordSyntax()), amodifyTo(AType r, dataSyntax())) = anode([]); +AType alub(amodifyTo(AType l, keywordSyntax()), amodifyTo(AType r, contextFreeSyntax())) = aadt("Tree", [], dataSyntax()); +AType alub(amodifyTo(AType l, keywordSyntax()), amodifyTo(AType r, lexicalSyntax())) = aadt("Tree", [], dataSyntax()); +AType alub(amodifyTo(AType l, keywordSyntax()), amodifyTo(AType r, layoutSyntax())) = aadt("Tree", [], dataSyntax()); + +AType alub(amodifyTo(AType l, layoutSyntax()), amodifyTo(AType r, dataSyntax())) = anode([]); +AType alub(amodifyTo(AType l, layoutSyntax()), amodifyTo(AType r, contextFreeSyntax())) = aadt("Tree", [], dataSyntax()); +AType alub(amodifyTo(AType l, layoutSyntax()), amodifyTo(AType r, lexicalSyntax())) = aadt("Tree", [], dataSyntax()); +AType alub(amodifyTo(AType l, layoutSyntax()), amodifyTo(AType r, keywordSyntax())) = aadt("Tree", [], dataSyntax()); + AType alub(l:\achar-class(_), r:\achar-class(_)) = union(l, r); AType alub(l:aadt("Tree", _, _), \achar-class(_)) = l; AType alub(\achar-class(_), r:aadt("Tree", _, _)) = r; diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/check/ATypeBase.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/check/ATypeBase.rsc index 57886e21..8181c0c2 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/ATypeBase.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/ATypeBase.rsc @@ -48,6 +48,7 @@ data AType (str alabel = "") | anode(list[AType] fields) | aadt(str adtName, list[AType] parameters, SyntaxRole syntaxRole) + | amodifyTo(AType atype, SyntaxRole syntaxRole) | acons(AType adt, list[AType] fields, list[Keyword] kwFields) | aprod(AProduction production) @@ -439,6 +440,10 @@ public AGrammar compose(AGrammar g1, AGrammar g2) { return grammar(g1.starts, reduced_rules); } +@synopsis{Semantics of syntax role modifiers} +// with nested modification the outermost (last applied) role wins +AType amodifyTo(amodifyTo(t, _), SyntaxRole to) = amodifyTo(t, to); - +// syntax role modification preserves the name and the parameters +AType amodifyTo(aadt(name, ps, _), SyntaxRole to) = aadt(name, ps, to); diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/check/ATypeInstantiation.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/check/ATypeInstantiation.rsc index e20abe5c..b54a100d 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/ATypeInstantiation.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/ATypeInstantiation.rsc @@ -114,7 +114,22 @@ public Bindings matchRascalTypeParams0(AType r, AType s, Bindings b) { for (idx <- index(rparams)) b = matchRascalTypeParams0(rparams[idx], sparams[idx], b); return b; } - + + // parametrized role modifiers match ADTs with the same syntax role! + if (amodifyTo(aparameter(n,_), sr) := r && aadt(_,_,sr) := s) { + b[n] = s; + return b; + } + + // two parametrized role modifiers can match if their parameters can match and they have the same role + if (amodifyTo(t1:aparameter(_,_), sr) := r && amodifyTo(t2:aparameter(_,_), sr) := s) { + b = matchRascalTypeParams0(t1, t2, b); + return b; + } + + // nested amodifyTo's are rewritten, also if applied to aadt's they are rewritten. + // all the other amodifyTo applications do not match anything because they don't have semantics (yet) + // For constructors, match when the constructor name, ADT name, and arity are the same, then we can check params if ( isConstructorType(r) && isConstructorType(s) && getADTName(r) == getADTName(s)) { b = matchRascalTypeParams0(getConstructorArgumentTypesAsTuple(r), getConstructorArgumentTypesAsTuple(s), b); @@ -190,6 +205,8 @@ AType instantiateRascalTypeParams(AType pt:aparameter(str s, AType t), Bindings = pt when s notin bindings; AType instantiateRascalTypeParams(a: aadt(str s, list[AType] ps, SyntaxRole sr), Bindings bindings) = aadt(s, [instantiateRascalTypeParams(p,bindings) | p <- ps], sr); +AType instantiateRascalTypeParams(a: amodifyTo(t, SyntaxRole sr), Bindings bindings) + = amodifyTo(instantiateRascalTypeParams(t, bindings), sr); AType instantiateRascalTypeParams(acons(AType a, /*str name,*/ list[AType/*NamedField*/] fields, list[Keyword] kwFields, alabel=consName), Bindings bindings) = //acons(instantiateRascalTypeParams(a,bindings), /*name,*/ [ | <- fields], [ | <- kwFields], alabel=consName); acons(instantiateRascalTypeParams(a,bindings), /*name,*/ [instantiateRascalTypeParams(ft,bindings) | ft <- fields], [ | <- kwFields], alabel=consName); diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectType.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectType.rsc index 23aa1569..97f64667 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectType.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectType.rsc @@ -12,6 +12,7 @@ module lang::rascalcore::check::CollectType extend lang::rascalcore::check::ATypeInstantiation; +extend lang::rascalcore::check::CheckerCommon; import lang::rascal::\syntax::Rascal; import lang::rascalcore::grammar::definition::Symbols; @@ -19,7 +20,6 @@ import lang::rascalcore::grammar::definition::Characters; import lang::rascalcore::grammar::definition::Literals; import lang::rascalcore::check::ScopeInfo; -import IO; import List; import Node; import Set; @@ -101,6 +101,57 @@ public list[&T] dup(list[&T] lst) { } } +// ---- role modifiers +void collect(current:(Type)`syntax[]`, Collector c){ + collect(t, c); + + try { + c.fact(current, amodifyTo(c.getType(targs[0]), contextFreeSyntax())); + } catch TypeUnavailable():{ + c.calculate("role modifier", current, targs, AType(Solver s){ return amodifyTo(c.getType(targs[0]), syntaxRole()); }); + } +} + +void collect(current:(Type)`data[]`, Collector c){ + collect(t, c); + + try { + c.fact(current, amodifyTo(c.getType(targs[0]), dataSyntax())); + } catch TypeUnavailable():{ + c.calculate("role modifier", current, targs, AType(Solver s){ return amodifyTo(c.getType(targs[0]), dataRole()); }); + } +} + +void collect(current:(Type)`lexical[]`, Collector c){ + collect(t, c); + + try { + c.fact(current, amodifyTo(c.getType(targs[0]), lexicalSyntax())); + } catch TypeUnavailable():{ + c.calculate("role modifier", current, targs, AType(Solver s){ return amodifyTo(c.getType(targs[0]), lexicalRole()); }); + } +} + +void collect(current:(Type)`layout[]`, Collector c){ + collect(t, c); + + try { + c.fact(current, amodifyTo(c.getType(targs[0]), layoutSyntax())); + } catch TypeUnavailable():{ + c.calculate("role modifier", current, targs, AType(Solver s){ return amodifyTo(c.getType(targs[0]), layoutRole()); }); + } +} + +void collect(current:(Type)`keyword[]`, Collector c){ + collect(t, c); + + try { + c.fact(current, amodifyTo(c.getType(targs[0]), keywordSyntax())); + } catch TypeUnavailable():{ + c.calculate("role modifier", current, targs, AType(Solver s){ return amodifyTo(c.getType(targs[0]), keywordSyntax()); }); + } +} + // ---- list void collect(current:(Type)`list [ < {TypeArg ","}+ tas > ]`, Collector c){