diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/AType.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/AType.rsc index 8a7ce513151..c40bcd4605f 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/AType.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/AType.rsc @@ -440,6 +440,8 @@ bool asubtype(a:anode(list[AType] l), AType b){ return true; case anode(list[AType] r): return l <= r; + case adt: aadt(str _, list[AType] _, _): + return true; case \start(t): return asubtype(a, t); case avalue(): diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectDeclaration.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectDeclaration.rsc index b50f602844d..93461fc600a 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectDeclaration.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectDeclaration.rsc @@ -304,7 +304,7 @@ void collect(current: (FunctionDeclaration) ``, Collec c.enterLubScope(decl); collect(decl.tags, c); scope = c.getScope(); - c.setScopeInfo(scope, functionScope(), signatureInfo(signature.\type)); + c.setScopeInfo(scope, functionScope(), signatureInfo(signature)); = collectSignature(decl.signature, c); dt = defType([signature], AType(Solver s) { @@ -389,7 +389,7 @@ void collect(current: (FunctionDeclaration) ``, Collec // We do in this case not check that the type of the expression as a whole is compatible with the return type. // TODO: cover the case that we leave the expression via a return AND via the value of the expression as a whole } else { - c.require("check on return type ``", decl.expression, [decl.expression], makeReturnRequirement(decl.expression, signature.\type)); + c.require("check on return type ``", decl.expression, [decl.expression, signature], makeReturnRequirement(decl.expression, signature)); } collect(decl.expression, c); } @@ -439,6 +439,7 @@ str md5Contrib4signature(Signature signature){ tuple[set[str], rel[str,Type]] collectSignature(Signature signature, Collector c){ returnType = signature.\type; parameters = signature.parameters; + formals = getFormals(parameters); kwFormals = getKwFormals(parameters); beginUseTypeParameters(c, closed=true); @@ -474,6 +475,16 @@ tuple[set[str], rel[str,Type]] collectSignature(Signature signature, Collector c formalsList = [ updateBounds(fm, minB) | fm <- formalsList ]; kwFormalsList = [ kwf[fieldType = updateBounds(kwf.fieldType, minB)] | kwf <- computeKwFormals(kwFormals, s) ]; ft = afunc(rtU, formalsList, kwFormalsList); + if(!isEmpty(tpnames)){ + for(int i <- index(formalsList)){ + s.fact(formals[i], formalsList[i]); + // println("*** add fact: =\> "); + } + for(int i <- index(kwFormalsList)){ + s.fact( kwFormals[i], kwFormalsList[i].fieldType); + // println("*** add fact: =\> "); + } + } //ft = updateBounds(afunc(s.getType(returnType), formalsList, computeKwFormals(kwFormals, s)), minB); return ft; }); @@ -552,7 +563,7 @@ private tuple[set[str], rel[str,Type]] computeBoundsAndDefineTypeParams(Signatur // during collection. We cannot declare or use type parameters as they are encountered during collect // since their open/closed status has to be taken into account and that depends on the more global // context of the signature or function declaration in which they occur. That is why we explicitly create - // uses and defs nof type parameters. + // uses and defs for type parameters. typeParamsInParameters = [*getTypeParams(t) | t <- formals + kwFormals]; @@ -572,6 +583,7 @@ private tuple[set[str], rel[str,Type]] computeBoundsAndDefineTypeParams(Signatur c.use(tpbound.name, {typeVarId()}); } } + seenInReturn += ""; c.use(tp.name, {typeVarId()}); c.calculate("typevar in result type", tp, [tp.name], makeTypeGetter(tp,closed=true)); } @@ -592,13 +604,20 @@ private tuple[set[str], rel[str,Type]] computeBoundsAndDefineTypeParams(Signatur c.define(tpname, typeVarId(), tp.name, defType(toList(typeParamBounds[tpname]), makeBoundDef(tp, typeParamBounds, closed=false))); c.fact(tp, tp.name); + // c.calculate("bounded type var", tp, [tp], makeTypeGetter(tp)); } } // Due to their special treatment, missing type parameters are not detected by typepal but have to - // detected explicitly. + // be detected explicitly. missing = seenInReturn - seenInParams; + for(TypeVar x <- typeParamsInReturn){ + xname = ""; + if(xname in missing && c.isAlreadyDefined(xname, x)){ + missing -= xname; + } + } if(!isEmpty(missing)){ missing = {"&" | m <- missing }; c.report(error(signature, "Type parameter(s) %v in return type of function %q not bound by its formal parameters", missing, signature.name)); @@ -624,7 +643,7 @@ void collect(Parameters parameters, Collector c){ } else { scope = c.getScope(); - c.calculate("formals", parameters, [], + c.calculate("formals", parameters, [], //formals+kwFormals, AType(Solver s) { formalTypes = [ getPatternType(f, avalue(), scope, s) | f <- formals ]; int last = size(formalTypes) -1; @@ -641,18 +660,33 @@ void collect(Parameters parameters, Collector c){ endPatternScope(c); } -void(Solver) makeReturnRequirement(Tree returnExpr, Type returnType) +void(Solver) makeReturnRequirement(Tree returnExpr, Signature signature) = void(Solver s){ - returnRequirement(returnExpr, s.getType(returnType), s); + returnRequirement(returnExpr, signature, s); }; -void(Solver) makeReturnRequirement(Tree returnExpr, AType returnAType) +void(Solver) makeReturnRequirement(Tree returnExpr, Type returnType) = void(Solver s){ - returnRequirement(returnExpr, returnAType, s); + returnRequirement(returnExpr, s.getType(returnType), s); }; + +// void(Solver) makeReturnRequirement(Tree returnExpr, AType returnAType, Parameters parameters) +// = void(Solver s){ +// returnRequirement(returnExpr, parameters, returnAType, s); +// }; + +void returnRequirement(Tree returnExpr, Signature signature, Solver s){ + sigType = s.getType(signature); + declaredReturnType = sigType.ret; + returnRequirement(returnExpr, s.getType(declaredReturnType), s); +} + void returnRequirement(Tree returnExpr, AType declaredReturnType, Solver s){ + // sigType = s.getType(signature); + // declaredReturnType = sigType.ret; returnExprType = s.getType(returnExpr); + // println("returnRequirement: , declared: , actual: "); FailMessage msg = p:/aparameter(_,_) := declaredReturnType ? error(returnExpr, "Returned type %t is not always a subtype of expected return type %t", returnExprType, declaredReturnType) : error(returnExpr, "Return type %t expected, found %t", declaredReturnType, returnExprType); @@ -690,11 +724,17 @@ void collect(current: (Statement) `return `, Collector c){ functionScopes = c.getScopeInfo(functionScope()); assert !isEmpty(functionScopes); for(<_, scopeInfo> <- functionScopes){ - if(signatureInfo(Type returnType) := scopeInfo){ - c.require("check return type", current, [statement, returnType], makeReturnRequirement(statement, returnType)); + if(signatureInfo(Type returnType, Parameters parameters) := scopeInfo){ + c.require("check return type", current, [statement, returnType, parameters], makeReturnRequirement(statement, returnType)); c.fact(current, returnType); // Note that type of the return statement as a whole is the function's return type collect(statement, c); return; + } else + if(signatureInfo(Signature signature) := scopeInfo){ + c.require("check return type", current, [statement, signature], makeReturnRequirement(statement, signature)); + c.fact(current, signature.\type); // Note that type of the return statement as a whole is the function's return type + collect(statement, c); + return; } else { throw rascalCheckerInternalError(getLoc(current), "Inconsistent info from function scope: "); } diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectExpression.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectExpression.rsc index 7403133a2cb..7136855fa40 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectExpression.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectExpression.rsc @@ -230,7 +230,8 @@ void collectClosure(Expression current, Type returnType, Parameters parameters, parentScope = c.getScope(); c.enterLubScope(current); scope = c.getScope(); - c.setScopeInfo(scope, functionScope(), signatureInfo(returnType)); + clos_name = closureName(current); + c.setScopeInfo(scope, functionScope(), signatureInfo(returnType, parameters)); beginUseTypeParameters(c, closed=true); collect(returnType, c); // any type parameters in return type remain closed (closed=true); @@ -242,7 +243,7 @@ void collectClosure(Expression current, Type returnType, Parameters parameters, collect(stats, c); // TODO take parameter bounds into account! - clos_name = closureName(current); + bool returnsViaAll = returnsViaAllPath(stats, clos_name, c); formals = getFormals(parameters); kwFormals = getKwFormals(parameters); @@ -454,7 +455,7 @@ void collect(current: (Comprehension) `[ <{Expression ","}+ results> | <{Express try { c.fact(current, makeListType(lubList([ c.getType(r) | r <- res]))); } catch TypeUnavailable(): { - c.calculate("list comprehension results", current, res, + c.calculate("list comprehension results", current, gens + res, AType(Solver s){ return makeListType(lubList([ s.getType(r) | r <- res])); }); diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectPattern.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectPattern.rsc index 1844b2549ba..90cba30c98d 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectPattern.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectPattern.rsc @@ -71,6 +71,8 @@ void collect(current: (Pattern) `{ <{Pattern ","}* elements0> }`, Collector c){ } c.push(patternContainer, "set"); collect(elements0, c); + c.calculate("set pattern", current, [e | e <- elements0], + AType (Solver s){ return aset(lubList([s.getType(e) | e <- elements0])); }); c.pop(patternContainer); } @@ -82,6 +84,8 @@ void collect(current: (Pattern) `[ <{Pattern ","}* elements0> ]`, Collector c){ } c.push(patternContainer, "list"); collect(elements0, c); + c.calculate("list pattern", current, [e | e <- elements0], + AType (Solver s){ return alist(lubList([s.getType(e) | e <- elements0])); }); c.pop(patternContainer); } @@ -92,21 +96,8 @@ void collect(current: (Pattern) ` `, Collector c){ if(tp is function) c.enterScope(current); collect(tp, c); if(tp is function) c.leaveScope(current); - calcDeps = [tp]; - functionScopes = c.getScopeInfo(functionScope()); - if(!isEmpty(functionScopes)){ - for(<_, scopeInfo> <- functionScopes){ - if(signatureInfo(Type returnType) := scopeInfo){ - calcDeps += returnType; - break; - } else { - throw rascalCheckerInternalError(getLoc(current), "Inconsistent info from function scope: "); - } - } - } - c.calculate("typed variable pattern", current, calcDeps, AType(Solver s){ return s.getType(tp)[alabel=uname]; }); + c.calculate("typed variable pattern", current, [tp], AType(Solver s){ return s.getType(tp)[alabel=uname]; }); - if(!isWildCard(uname)){ c.push(patternNames, ); orScopes = c.getScopeInfo(orScope()); @@ -120,7 +111,7 @@ void collect(current: (Pattern) ` `, Collector c){ } c.define(uname, formalOrPatternFormal(c), name, defType(tp)); } else { - c.fact(name, tp); + c.calculate("variable ", name, [tp], AType(Solver s) { return s.getType(tp); }); } } diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectType.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectType.rsc index 71e91d02998..540fcea638d 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectType.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/CollectType.rsc @@ -844,7 +844,6 @@ void collect(current:(TypeVar) `& `, Collector c){ void collect(current: (TypeVar) `& \<: `, Collector c){ pname = prettyPrintName(n); - if( := defineOrReuseTypeParameters(c)){ if(c.isAlreadyDefined(pname, n)){ c.use(n, {typeVarId() }); @@ -854,23 +853,26 @@ void collect(current: (TypeVar) `& \<: `, Collector c){ //if(debugTP)println("Define at "); } c.fact(current, n); + //c.calculate("type parameter, 1", current, [n, *calcDeps], AType (Solver s) { return s.getType(n)[closed=closed]; }); } else if( := useTypeParameters(c)){ c.use(n, {typeVarId() }); - c.calculate("xxx", current, [n], AType (Solver s) { return s.getType(n)[closed=closed]; }); + c.fact(current, tp); + // c.calculate("type parameter, 2", current, [n, tp], AType (Solver s) { + // return s.getType(n)[closed=closed]; }); //if(debugTP)println("Use at "); } else if( := useBoundedTypeParameters(c)){ if(!isEmpty(tpbounds[pname])){ bnds = toList(tpbounds[pname]); - c.calculate("type parameter with bound", n, bnds, + c.calculate("type parameter with bound, 1", n, bnds + [tp], AType(Solver s){ new_bnd = (avalue() | aglb(it, s.getType(bnd)) | bnd <- bnds); return aparameter(prettyPrintName(n), s.getType(new_bnd), closed=true); }); } else { - c.calculate("type parameter with bound", n, [tp], AType(Solver s){ return aparameter(prettyPrintName(n), s.getType(tp), closed=true); }); + c.calculate("type parameter with bound, 2", n, [tp], AType(Solver s){ return aparameter(prettyPrintName(n), s.getType(tp), closed=true); }); } - c.fact(current, n); - } + c.fact(current, tp); + } collect(tp, c); } diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/DependencyViewer.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/DependencyViewer.rsc new file mode 100644 index 00000000000..1af404473c2 --- /dev/null +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/DependencyViewer.rsc @@ -0,0 +1,208 @@ +module lang::rascalcore::check::DependencyViewer + +import analysis::typepal::TModel; +import analysis::typepal::Collector; +import vis::Graphs; +import IO; +import util::IDEServices; +import ListRelation; +import Map; +import Relation; +import Set; + +// Management of node identities +alias NodeId = str; +int nodeCounter = 0; + +map[NodeId, value] id2node = (); +map[value, NodeId] node2id = (); + +map[NodeId,loc] node2src = (); +map[NodeId,str] node2label = (); +map[loc,NodeId] src2calc = (); + +void initNodes(){ + nodeCounter = 0; + id2node = (); + node2id = (); + node2src = (); + node2label = (); + src2calc = (); +} + +NodeId getNodeId(value v){ + assert Calculator _ := v || Requirement _ := v || loc _ := v: "Illegal "; + if(v notin node2id) { + node2id[v] = ""; + id2node[""] = v; + nodeCounter += 1; + } + return node2id[v]; +} + +NodeId getNodeIdViaCalculator(loc l){ + if(l in src2calc){ + return src2calc[l]; + } + return getNodeId(l); +} + +loc getNodeSource(NodeId id) { + if(id in node2src) return node2src[id]; + v = id2node[id]; + if(loc l := v) return l; + return |unknown:///|; +} + +str getNodeLabel(NodeId id) { + if(id in node2label) return node2label[id]; + v = id2node[id]; + if(loc l := v) return ": "; + return ": ???:"; +} + +str getText(loc l) { + try return readFile(l); + catch _: return "???"; +} + +lrel[NodeId,NodeId] srcDependsOn(NodeId src, list[loc] dependsOn) + = [ | d <- dependsOn]; + +lrel[NodeId,NodeId] srcDependsOn(NodeId l, NodeId r, list[loc] dependsOn) + = srcDependsOn(l, dependsOn) + srcDependsOn(r, dependsOn); + +lrel[NodeId,NodeId] calcEdges(Calculator c:calcType(loc src, AType atype)) { + NodeId id = getNodeId(c); + node2src[id] = src; + node2label[id] = ": "; + src2calc[src] = id; + return []; +} + +lrel[NodeId,NodeId] calcEdges(c:calcLoc(loc src, list[loc] dependsOn)){ + NodeId id = getNodeId(c); + node2src[id] = src; + node2label[id] = ": "; + src2calc[src] = id; + return srcDependsOn(id, dependsOn); +} + +lrel[NodeId,NodeId] calcEdges(c:calc(str cname, loc src, list[loc] dependsOn, AType(Solver s) getAType)){ + NodeId id = getNodeId(c); + node2src[id] = src; + node2label[id] = "C , : "; + src2calc[src] = id; + return srcDependsOn(id, dependsOn); +} + +lrel[NodeId,NodeId] calcEdges(c:calcLub(str cname, list[loc] srcs, list[loc] dependsOn, list[AType(Solver s)] getATypes)){ + NodeId id = getNodeId(c); + node2label[id] = "C , : /<}>"; + for(src <- srcs) src2calc[src] = id; + return srcDependsOn(id, dependsOn); +} + +lrel[NodeId,NodeId] reqEdges(rq:req(str rname, loc src, list[loc] dependsOn, void(Solver s) preds)){ + NodeId id = getNodeId(rq); + node2src[id] = src; + node2label[id] = "R : "; + return srcDependsOn(id, dependsOn); +} + +lrel[NodeId,NodeId] reqEdges(rq:reqEqual(str rname, value l, value r, list[loc] dependsOn, FailMessage fm)){ + NodeId id = getNodeId(rq); + node2label[id] = "R "; + return srcDependsOn(getNodeId(l), getNodeId(r), dependsOn); +} + +lrel[NodeId,NodeId] reqEdges(rq:reqComparable(str rname, value l, value r, list[loc] dependsOn, FailMessage fm)){ + NodeId id = getNodeId(rq); + node2label[id] = "R "; + return srcDependsOn(getNodeId(l), getNodeId(r), dependsOn); +} + +lrel[NodeId,NodeId] reqEdges(rq:reqSubtype(str rname, value l, value r, list[loc] dependsOn, FailMessage fm)){ + NodeId id = getNodeId(rq); + node2label[id] = "R "; + return srcDependsOn(getNodeId(l), getNodeId(r), dependsOn); +} + +lrel[NodeId,NodeId] reqEdges(rq:reqUnify(str rname, value l, value r, list[loc] dependsOn, FailMessage fm)){ + NodeId id = getNodeId(rq); + node2label[id] = "R "; + return srcDependsOn(getNodeId(l), getNodeId(r), dependsOn); +} + +lrel[NodeId,NodeId] reqEdges(rq:reqError (loc src, list[loc] dependsOn, FailMessage fm)){ + NodeId id = getNodeId(rq); + node2src[id] = src; + node2label[id] = "R error: "; + return srcDependsOn(id, dependsOn); +} + +lrel[NodeId,NodeId] reqEdges(rq:reqErrors(loc src, list[loc] dependsOn, list[FailMessage] fms)){ + NodeId id = getNodeId(rq); + node2src[id] = src; + node2label[id] = "R errors: "; + return srcDependsOn(id, dependsOn); +} + +NodeId replaceByCalc(NodeId id){ + if(id in node2src){ + src = node2src[id]; + if(src in src2calc) return src2calc[src]; + } + return id; +} + +void viewDependencies(TModel tm){ + initNodes(); + for(Calculator c <- tm.calculators){ + NodeId id = getNodeId(c); + if(c has src){ + src2calc[c.src] = id; + } else if(c has srsc){ + for(src <- c.srcs){ + src2calc[src] = id; + } + } + } + + cedges = {*calcEdges(c) | Calculator c <- tm.calculators}; + redges = {*reqEdges(r) | Requirement r <- tm.requirements}; + edges = toList(cedges + redges); + println("edges: "); + for(NodeId id <- sort(domain(id2node))) { println(""); iprintln(id2node[id]); } + + list[str] nodeClassifier(NodeId id){ + res = []; + switch(id2node[id]){ + case Calculator _: res = ["calc"]; + case Requirement _: res = ["req"]; + case loc _: res = ["text"]; + } + return res; + } + + styles = [ + cytoStyleOf( + selector=\node(className("text")), + style=defaultNodeStyle()[shape=CytoNodeShape::rectangle()][\background-color="grey"]), + cytoStyleOf( + selector=\node(className("calc")), + style=defaultNodeStyle()[shape=CytoNodeShape::ellipse()][\background-color="green"]), + cytoStyleOf( + selector=\node(className("req")), + style=defaultNodeStyle()[shape=CytoNodeShape::diamond()][\background-color="blue"]) + ]; + cfg = cytoGraphConfig( + title="Graph: ", + nodeClassifier=nodeClassifier, + nodeLinker=getNodeSource, + nodeLabeler=getNodeLabel, + styles=styles, + \layout=defaultDagreLayout()[ranker=\tight-tree()]); + + showInteractiveContent(graph(edges, cfg=cfg)); +} \ No newline at end of file diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/RascalConfig.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/RascalConfig.rsc index 6e1f3894d83..5feaa6e3793 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/RascalConfig.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/RascalConfig.rsc @@ -47,6 +47,8 @@ import lang::rascalcore::compile::util::Names; import analysis::typepal::StringSimilarity; import analysis::typepal::LocationChecks; +import lang::rascalcore::check::DependencyViewer; + import IO; import List; import Map; @@ -403,6 +405,7 @@ rel[loc, PathRole,loc] enhancePathRelation(rel[MODID, PathRole, MODID] paths){ // Enhance TModel before running Solver by TModel rascalPreSolver(map[str,Tree] _namedTrees, TModel m){ + // viewDependencies(m); return m[paths = enhancePathRelation(m.paths)]; } @@ -438,7 +441,7 @@ void checkOverloading(map[str,Tree] namedTrees, Solver s){ r1 = visit(t1.ret) {case p:aparameter(_,_,closed=true) => p[closed=false] }; r2 = visit(t2.ret) {case p:aparameter(_,_,closed=true) => p[closed=false] }; if(!comparable(r1, r2)){ - causes = [ info("ther declaration with comparable arguments", d2.defined) ]; + causes = [ info("the declaration with comparable arguments", d2.defined) ]; msgs = [ error("Return type `` of function `` is not comparable with return type `` of other declaration with comparable arguments", d1.defined, causes=causes) ]; s.addMessages(msgs); } diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/ScopeInfo.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/ScopeInfo.rsc index 01a64d4467b..1afa0d32139 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/ScopeInfo.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/ScopeInfo.rsc @@ -79,7 +79,8 @@ data VisitOrSwitchInfo = visitOrSwitchInfo(Expression expression, bool isVisit); // Information needed for checking return statement data SignatureInfo - = signatureInfo(Type returnType) + = signatureInfo(Signature signature) + | signatureInfo(Type returnType, Parameters parameters) ; // Determine how type parameters (TypeVar in Rascal grammar) will be treated: diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/SyntaxGetters.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/SyntaxGetters.rsc index 01504fe9163..d3dc91e44b8 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/SyntaxGetters.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/SyntaxGetters.rsc @@ -122,20 +122,25 @@ tuple[bool, TagString] getExpected(Tags tags){ return ; } - list[TypeVar] getTypeParams(Tree t){ - res = []; + set[TypeVar] res = {}; top-down-break visit(t){ case TypeVar tp : { res += tp; - if(tp is bounded) res += getTypeParams(tp.bound); + if(tp is bounded) res += toSet(getTypeParams(tp.bound)); } - //case FunctionType tp: ; - // // only type parameters in return type of a function type will be considered - // res += getTypeParams(tp.\type); + case StructuredType tp: { + res += {*getTypeParams(t.\type) | TypeArg t <- tp.arguments }; + } + case FunctionType tp:{ + // only type parameters in return type of a function type will be considered + typeParamsInReturn = toSet(getTypeParams(tp.\type)); + typeParamsInParameters = {*getTypeParams(t.\type) | TypeArg t <- tp.arguments }; + typeParameterNamesInParameters = { "" | TypeVar tp <- typeParamsInParameters }; + res += { tp | TypeVar tp <- typeParamsInReturn, "" notin typeParameterNamesInParameters }; + } } - - return res; + return toList(res); } set[Name] getTypeParamNames(Tree t){ diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/Tst5.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/Tst5.rsc index c22e7c50b36..38493926425 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/Tst5.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/Tst5.rsc @@ -11,13 +11,16 @@ import lang::rascalcore::check::RascalConfig; import lang::rascalcore::check::Checker; import lang::rascal::\syntax::Rascal; -loc root = |memory://e0711529-477e-4a4c-b44b-44b00157728eXXX|; + +// this uuid matters +loc root = |memory://36a14c42-e4e6-41e0-a59a-ac11f637070c|; PathConfig pcfg = pathConfig( srcs = [root + "src"], bin = root + "bin", libs = [] ); + // this name matters str moduleName = "TestModule612d1"; @@ -25,7 +28,7 @@ loc writeModule() { loc moduleLoc = pcfg.srcs[0] + ".rsc"; // the spaces before &T seems to matter? writeFile(moduleLoc, - "module TestModule612d1\r\n \r\n &T \<: int f(&T \<: num _) = 1;" + "module TestModule612d1\n \n &T \<: int f(&T \<: num _) = 1;" ); return moduleLoc; } @@ -74,7 +77,7 @@ void findCollission(loc l) { } } - + void main() { remove(root, recursive = true); l = writeModule(); diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/Tst7.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/Tst7.rsc new file mode 100644 index 00000000000..5b1b4293d96 --- /dev/null +++ b/src/org/rascalmpl/compiler/lang/rascalcore/compile/Examples/Tst7.rsc @@ -0,0 +1,85 @@ +module lang::rascalcore::compile::Examples::Tst7 + + +@javaClass{org.rascalmpl.library.Prelude} +public java &T <: node setKeywordParameters(&T <: node x, map[str,value] keywordParameters); + +data Tree; + +Tree mergeRec(Tree t) { + return setKeywordParameters(t, ()); + } + +// list[int] f(list[int] L) = [x | x <- L, x > 0]; + +// bool isSorted(list[&T] l, bool (&T a, &T b) less = bool (&T a, &T b) { return a < b; }) +// = !any([*_, &T a, &T b, *_] := l, less(b, a)); + +// // int f(int n, int m, bool b = false) = 2; + +// // import ParseTree; + +// // syntax Aas +// // = nil: [a]* +// // | a: [a][a]* +// // | aas: [a][a][a]* +// // ; +// // &T <:Tree ambFilter(amb(set[&T <:Tree] alternatives)) { +// // set[&T <:Tree] result = {a | Aas a <- alternatives, !(a is nil)}; +// // if ({&T <: Tree oneTree} := result) { +// // return oneTree; +// // } +// // return ParseTree::amb(result); +// // } + +// @javaClass{org.rascalmpl.library.Prelude} +// java &U (type[&U] nonterminal, value input, loc origin) parsers(type[&T] grammar); + + + +// list[&T] emptyList(type[&T] _) = []; // ok + +// // &T f(&T x) { &T y = 1; return x;} // <==== error + +// // void f(&T x) { &T y = 1; } // <==== error + +// void g(&T x) { &T <: int y = 1; } // ok + +// // &T get1(list[&T] _) = 1; // <==== error + +// &T <: int get2(list[&T] _) = 1; // ok + +// &T <: num sub(&T <:num x, &T<:num y) = x - y; // ok + +// map[&K, &V] domainR1(map[&K, &V] M, set[&K] S) // ok +// = (k : M[k] | &K k <- M, k in S); + +// list[&T] tail([&T _, *&T t]) = t; // ok + +// &T top([&T t, *&T _]) = t; // ok + +// &T getFirstFrom([&T f, *&T _]) = f; // ok + +// &T max([&T h, *&T t]) = (h | e > it ? e : it | e <- t); //ok + +// &T <: int f(&T <: num _) = 1; // discussie; ik (en checker) denken ok + +// &T <: int f(&T <: num x = 0) = 1; // discussie; ik (en checker) denken ok + +// list[&U] mapper(list[&T] lst, &U (&T) fn) = [fn(elm) | &T elm <- lst]; // ok + +// // Following ok +// alias GatherResult[&T] = tuple[bool trueOnAllPaths, set[&T] results]; +// data Graph[&T]; +// data CFGNode; +// public GatherResult[&T] gatherOnAllReachedPaths(Graph[CFGNode] g, CFGNode startNode, bool(CFGNode cn) pred, bool(CFGNode cn) stop, &T (CFGNode cn) gather, bool includeStartNode = false) { +// GatherResult[&T] traverser(CFGNode currentNode) = traverser({currentNode}); + +// GatherResult[&T] traverser(set[CFGNode] currentNodes) { +// GatherResult[&T] res = < true, { } >; +// return res; +// } + +// return traverser(startNode); +// } +