diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/compile/muRascal2Java/Resolvers.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/compile/muRascal2Java/Resolvers.rsc index 7b5f3e1b..f81911b1 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/compile/muRascal2Java/Resolvers.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/compile/muRascal2Java/Resolvers.rsc @@ -32,36 +32,36 @@ rel[Name_Arity, Define] getFunctionsAndConstructors(TModel tmodel, set[loc] modu throw "getFunctionsAndConstructors"; } mscope = tmodel.moduleLocs[tmodel.modelName]; - + overloads0 = {*{ ov | tuple[loc def, IdRole idRole, AType atype] ov <- ovl.overloads,(ov.idRole == functionId() || ov.idRole == constructorId()) } | loc u <- tmodel.facts, isContainedIn(u, mscope), /ovl:overloadedAType(rel[loc def, IdRole idRole, AType atype] overloads) := tmodel.facts[u] }; - overloads_used_in_module = {<, def> - | tuple[loc def, IdRole idRole, AType atype] ov <- overloads0, + overloads_used_in_module = {<, def> + | tuple[loc def, IdRole idRole, AType atype] ov <- overloads0, (ov.idRole == functionId() || ov.idRole == constructorId()), tmodel.definitions[ov.def]?, - Define def := tmodel.definitions[ov.def], + Define def := tmodel.definitions[ov.def], defType(AType tp) := def.defInfo, !isSyntheticFunctionName(def.id) }; - + overloads_created_in_module = - { <, def> - | Define def <- tmodel.defines, + { <, def> + | Define def <- tmodel.defines, defType(AType tp) := def.defInfo, (def.idRole == functionId() && any(me_scope <- module_and_extend_scopes, isContainedIn(def.defined, me_scope))) || def.idRole == constructorId(), !(acons(AType adt, list[AType] _, list[Keyword] _) := tp && isNonTerminalAType(adt)) }; - return overloads_used_in_module + overloads_created_in_module; + return overloads_used_in_module + overloads_created_in_module; } - + str varName(muVar(str name, str _fuid, int pos, AType _, IdRole idRole)){ // duplicate, see CodeGen - + result = asJavaName(name); if(name[0] == "$") return result; if(pos >= 0 || isWildCard(name)) result += "_"; return result; // TODO the above code replaces this (for the benefit of the compiler): // return (name[0] != "$") ? "<(pos >= 0 || isWildCard(name)) ? "_" : "">" : asJavaName(name); -} +} /*****************************************************************************/ /* Convert an AType to a test for that AType (represented as VType) */ @@ -71,8 +71,8 @@ str varName(muVar(str name, str _fuid, int pos, AType _, IdRole idRole)){ // dup str atype2istype(str e, overloadedAType(rel[loc, IdRole, AType] overloads), JGenie jg) = " instanceof IConstructor && ).getConstructorType().equivalent()" | <_, _, tp> <- overloads])>"; - -//str atype2istype(str e, t:acons(AType adt, list[AType] fields, list[Keyword] kwFields), JGenie jg) + +//str atype2istype(str e, t:acons(AType adt, list[AType] fields, list[Keyword] kwFields), JGenie jg) // = ".getConstructorType().comparable()"; str atype2istype(str e, a:aadt(str adtName, list[AType] parameters, dataSyntax()), JGenie jg) { @@ -114,33 +114,30 @@ public set[set[Define]] mygroup(set[Define] input, bool (Define a, Define b) sim remaining -= g; result += {g}; } - return result; + return result; } - + // Generate all resolvers for a given module -str generateResolvers(str moduleName, map[loc, MuFunction] loc2muFunction, set[str] imports, set[str] extends, map[str,TModel] tmodels, map[str,loc] module2loc, JGenie jg){ - //iprintln(tmodels); - - //tmodels = (mname : convertTModel2PhysicalLocs(tmodels[mname]) | mname <- tmodels); +str generateResolvers(str moduleName, map[loc, MuFunction] loc2muFunction, set[str] imports, set[str] extends, map[str,TModel] tmodels, map[str,loc] module2loc, JGenie jg){ module_scope = module2loc[moduleName]; - + loc2module = invertUnique(module2loc); module_scopes = domain(loc2module); extend_scopes = { module2loc[ext] | ext <- extends }; import_scopes = { module2loc[imp] | imp <- imports }; - + module_and_extend_scopes = module_scope + extend_scopes; - + rel[Name_Arity, Define] functions_and_constructors = { *getFunctionsAndConstructors(tmodels[mname], module_and_extend_scopes) | mname <- tmodels }; - + resolvers = ""; for( <- domain(functions_and_constructors), !isClosureName(fname)){ // Group all functions of same name and arity by scope set[Define] defs = functions_and_constructors[]; - - defs_in_disjoint_scopes = mygroup(defs, bool(Define a, Define b) { - return a.scope notin module_scopes && b.scope notin module_scopes && a.scope == b.scope + + defs_in_disjoint_scopes = mygroup(defs, bool(Define a, Define b) { + return a.scope notin module_scopes && b.scope notin module_scopes && a.scope == b.scope || a.scope in module_scopes && b.scope in module_scopes ; }); @@ -150,7 +147,7 @@ str generateResolvers(str moduleName, map[loc, MuFunction] loc2muFunction, set[s if(any(d <- sdefs, d.scope notin module_scopes)){ // All local functions trated samw wrt keyword parameters resolvers += generateResolver(moduleName, fname, sdefs, loc2muFunction, module_scope, import_scopes, extend_scopes, tmodels[moduleName].paths, tmodels[moduleName], loc2module, jg); - + } else { // For global functions we differentiate wrt keyword oarameters kwpFormals = {}; @@ -169,9 +166,9 @@ str generateResolvers(str moduleName, map[loc, MuFunction] loc2muFunction, set[s list[MuExp] getExternalRefs(Define fun_def, map[loc, MuFunction] loc2muFunction){ if(loc2muFunction[fun_def.defined]?){ - fun = loc2muFunction[fun_def.defined]; + fun = loc2muFunction[fun_def.defined]; return sort({ ev | ev <- fun.externalRefs, ev.pos >= 0, ev notin fun.formals }); - } else { + } else { return []; } } @@ -193,20 +190,20 @@ tuple[bool,loc] findImplementingModule(set[Define] fun_defs, set[loc] import_sco str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map[loc, MuFunction] loc2muFunction, loc module_scope, set[loc] import_scopes, set[loc] extend_scopes, Paths paths, TModel tm, map[loc, str] loc2module, JGenie jg){ //println("generate resolver for , "); - + module_scopes = domain(loc2module); - + set[Define] local_fun_defs = {def | def <- fun_defs, /**/isContainedIn(def.defined, module_scope)/*, "test" notin loc2muFunction[def.defined].modifiers*/ }; - - nonlocal_fun_defs0 = + + nonlocal_fun_defs0 = for(def <- fun_defs){ if(!isEmpty(extend_scopes) && any(ext <- extend_scopes, isContainedIn(def.defined, ext))) append def; if(!isEmpty(import_scopes) && any(imp <- import_scopes, isContainedIn(def.defined, imp))) append def; }; - nonlocal_fun_defs = toSet(nonlocal_fun_defs0); + nonlocal_fun_defs = toSet(nonlocal_fun_defs0); set[Define] relevant_fun_defs = local_fun_defs + nonlocal_fun_defs; cons_defs = { cdef | cdef <- relevant_fun_defs, defType(AType tp) := cdef.defInfo, isConstructorAType(tp) }; - + implementing_module = ""; if(isEmpty(local_fun_defs)){ = findImplementingModule(relevant_fun_defs, import_scopes, extend_scopes); @@ -214,31 +211,31 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map implementing_module = loc2module[im]; } } - + relevant_fun_defs -= cons_defs; - + if(isEmpty(relevant_fun_defs)) return ""; - + acons_adt = avoid(); list[AType] acons_fields = []; acons_kwfields = []; - + for(cdef <- cons_defs, defType(AType ctp) := cdef.defInfo){ acons_adt = alub(acons_adt, ctp.adt); acons_fields = acons_fields == [] ? ctp.fields : alubList(acons_fields, ctp.fields); acons_kwfields += ctp.kwFields; } - + acons_fun_type = afunc(acons_adt, acons_fields, acons_kwfields); - + resolver_fun_type = (avoid() | alub(it, tp) | fdef <- relevant_fun_defs, defType(AType tp) := fdef.defInfo); resolver_fun_type = isEmpty(relevant_fun_defs) ? acons_fun_type : (isEmpty(cons_defs) ? resolver_fun_type : alub(acons_fun_type, resolver_fun_type)); if(!isFunctionAType(resolver_fun_type)) return ""; - + inner_scope = ""; - + if(all(def <- relevant_fun_defs, def in local_fun_defs, def.scope notin module_scopes)){ for(def <- relevant_fun_defs, isContainedIn(def.defined, module_scope)){ fun = loc2muFunction[def.defined]; @@ -247,7 +244,7 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map } } resolver_name = ""; - + fun_kwFormals = acons_kwfields; for(def <- relevant_fun_defs, def notin cons_defs, defType(AType tp) := def.defInfo){ if(loc2muFunction[def.defined]?){ @@ -257,58 +254,58 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map fun_kwFormals += tp.kwFormals; } } - + resolver_fun_type = resolver_fun_type[kwFormals=fun_kwFormals]; resolver_formals_types = [ avalue() | _ <- resolver_fun_type.formals ]; resolver_arity_formal_types = size(resolver_formals_types); resolver_return_type = resolver_fun_type has ret ? resolver_fun_type.ret : resolver_fun_type.adt; - + if(resolver_arity_formal_types == 0 && size(relevant_fun_defs + cons_defs) > 1 - || size(relevant_fun_defs) == 0 - && size(cons_defs) > 1 - && ( size(acons_fields) == 1 + || size(relevant_fun_defs) == 0 + && size(cons_defs) > 1 + && ( size(acons_fields) == 1 || all(int i <- index(acons_fields), int j <- index(acons_fields), i != j, comparable(acons_fields[i], acons_fields[j])) ) ){ return "public (){ // Generated by Resolver - ' throw new RuntimeException(\"Constructor `` is overloaded and can only be called with qualifier\"); + ' throw new RuntimeException(\"Constructor `` is overloaded and can only be called with qualifier\"); '} '"; } resolver_returns_void = isVoidAType(resolver_return_type); argTypes = intercalate(", ", [" $P" | i <- index(resolver_formals_types), f := resolver_formals_types[i]]); - + actuals = intercalate(", ", ["$P" | i <- index(resolver_formals_types)]); body = resolver_returns_void ? "" : " $result = null;\n"; - + kwpActuals = "java.util.Map\ $kwpActuals"; - activeKwpFormals1 = { *jg.collectKwpFormals(fun) - | def <- local_fun_defs, - //def.defined in local_fun_defs, //.defined, - //def notin cons_defs, + activeKwpFormals1 = { *jg.collectKwpFormals(fun) + | def <- local_fun_defs, + //def.defined in local_fun_defs, //.defined, + //def notin cons_defs, loc2muFunction[def.defined]?, fun := loc2muFunction[def.defined]}; - + if(hasKeywordParameters(resolver_fun_type) || !isEmpty(activeKwpFormals1)) { //any(def <- local_fun_defs, def.scope != module_scope)){ argTypes = isEmpty(argTypes) ? kwpActuals : ", "; } - + onlyGlobalFuns = all(fd <- relevant_fun_defs, loc2module[fd.scope]?); // Only toplevel functions if(!onlyGlobalFuns){ externalRefs = getExternalRefs(relevant_fun_defs, loc2muFunction); - + if(!isEmpty(externalRefs) ){ argTypes += (isEmpty(argTypes) ? "" : ", ") + intercalate(", ", [ /*var.idRole in assignableRoles ?*/ "ValueRef\<\> " /*: " _"*/ | var <- externalRefs, jtype := atype2javatype(var.atype)]); } } - + extends = { | <- paths }+; - + arg_types = resolver_arity_formal_types == 0 ? [] : toList({ unsetRec(getFunctionOrConstructorArgumentTypes(ta), "alabel") | def <- relevant_fun_defs, defType(AType ta) := def.defInfo }); - + if(!isEmpty(implementing_module)){ if(all(fd <- relevant_fun_defs, !loc2module[fd.scope]?)){ return ""; @@ -319,40 +316,40 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map pref = resolver_returns_void ? "" : "return ()"; body = " .();"; resolvers = "public (){ // Generated by Resolver - ' + ' '} '"; return resolvers; } - + arg_types = sort(arg_types, bool (list[AType] a, list[AType] b){ return a != b && asubtypeList(a, b); }); // Most specifc types first - + bool funBeforeExtendedBeforeDefaultBeforeConstructor(Define a, Define b){ return a != b - && defType(AType ta) := a.defInfo - && defType(AType tb) := b.defInfo - && isFunctionAType(ta) - && (isConstructorAType(tb) + && defType(AType ta) := a.defInfo + && defType(AType tb) := b.defInfo + && isFunctionAType(ta) + && (isConstructorAType(tb) || !ta.isDefault && tb.isDefault || in extends || isBefore(a.defined, b.defined) ) ; } - + sorted_relevant_fun_defs = sort(relevant_fun_defs, funBeforeExtendedBeforeDefaultBeforeConstructor); - + sorted_default_fun_defs = [ def | def <- sorted_relevant_fun_defs, def.defInfo.atype.isDefault ]; - + sorted_nondefault_fun_defs = sorted_relevant_fun_defs - sorted_default_fun_defs; - + map[int, lrel[str,str]] overload_table = (); lrel[str,str] defaults_and_constructors = []; - + physical2logical = invertUnique(tm.logical2physical); - + // Handle a function or constructor defintion - + void handleDef(Define def){ inner_scope = ""; //if(def.scope notin module_scopes, /*isContainedIn(def.scope, module_scope) */def in local_fun_defs){ @@ -368,14 +365,14 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map } //i = findLast(path, "/"); //path = path[i+1..]; - + name = replaceAll(path, "/", "_"); uniqueName = ""; } //uniqueName = "$"; //uniqueName = "_A"; def_type = def.defInfo.atype; - + conds = []; call_actuals = []; def_type_formals = getFunctionOrConstructorArgumentTypes(def_type); @@ -387,9 +384,9 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map call_actuals += "$P"; } } - + actuals_text = intercalate(", ", call_actuals); - + activeKwpFormals = []; if(def in relevant_fun_defs /*local_fun_defs*/){ if(loc2muFunction[def.defined]?){ @@ -402,7 +399,7 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map if(hasKeywordParameters(def_type) || (def.scope notin module_scopes && !isEmpty(activeKwpFormals))){ actuals_text = isEmpty(actuals_text) ? "$kwpActuals" : ", $kwpActuals"; } - + if(!onlyGlobalFuns){ externalRefs = getExternalRefs(def, loc2muFunction); if(!isEmpty(externalRefs)){ @@ -411,7 +408,7 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map } key = isConstructorAType(def_type) ? 0 : (def_type.isConcreteArg ? def_type.concreteFingerprint : def_type.abstractFingerprint); //key = /*def_type.isDefault ? 0 :*/ (def_type.isConcreteArg ? def_type.concreteFingerprint : def_type.abstractFingerprint); - + call_code = base_call = ""; cst = resolver_returns_void ? "" : "()"; if(isFunctionAType(def_type)){ @@ -427,7 +424,7 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map call_code = "()"; } else if(/*isContainedIn(def.defined, def.scope),*/ loc2module[def.scope]?){ call_code = ".()"; // was uniqueName - } else { + } else { return; //do nothing } if(resolver_returns_void){ @@ -443,7 +440,7 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map base_call = "return $VF.constructor(, new IValue[]{});"; } } - + all_conds = intercalate(" && ", conds); if(key == 0){ defaults_and_constructors += ; @@ -455,9 +452,9 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map } } } - + // Process all functions - + if(resolver_arity_formal_types == 0){ for(def <- sorted_nondefault_fun_defs){ handleDef(def); @@ -467,21 +464,21 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map for(def <- sorted_nondefault_fun_defs){ if(unsetRec(getFunctionOrConstructorArgumentTypes(def.defInfo.atype), "alabel") == arg_type) handleDef(def); - } + } } for(def <- sorted_default_fun_defs){ handleDef(def); } } - + // Process all constructors - + for(cdef <- cons_defs){ handleDef(cdef); } - + // Generate calls for one switch case - + str processOverloads(lrel[str conds, str call] overloads){ calls = ""; int i = 0; @@ -495,12 +492,12 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map // Share common conditions calls_with_same_cond = call; constructor_seen = contains(call, "$VF.constructor"); - + while(i < size(overloads) -1 && conds == overloads[i+1].conds){ repeated_conses = constructor_seen && contains(overloads[i+1].call, "$VF.constructor"); i += 1; if(repeated_conses){ - calls_with_same_cond = "throw new RuntimeException(\"Constructor `` is overloaded and can only be called with qualifier\");"; + calls_with_same_cond = "throw new RuntimeException(\"Constructor `` is overloaded and can only be called with qualifier\");"; } else { calls_with_same_cond += "\n"; } @@ -514,23 +511,23 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map } return calls; } - + // Generate all cases - - if(resolver_arity_formal_types > 0){ + + if(resolver_arity_formal_types > 0){ switch_cases = ""; noswitch = size(overload_table) == 1 || resolver_returns_void; - + for(key <- overload_table){ calls = processOverloads(overload_table[key]); - if(!isEmpty(calls)){ + if(!isEmpty(calls)){ switch_cases += noswitch ? "" : "\t<(key == 0) ? "\ndefault" : "\ncase ">: '\t\t\t\tbreak;"; - } + } } default_and_constructor_cases = processOverloads(defaults_and_constructors); - + if(noswitch){ body += switch_cases + default_and_constructor_cases; } else { @@ -545,21 +542,21 @@ str generateResolver(str moduleName, str functionName, set[Define] fun_defs, map cases = ""; for(key <- overload_table){ calls = processOverloads(overload_table[key]); - if(!isEmpty(calls)){ + if(!isEmpty(calls)){ cases += calls; } } default_and_constructor_cases = processOverloads(defaults_and_constructors); body += cases + default_and_constructor_cases; } - + if(isEmpty(cons_defs) || resolver_arity_formal_types > 0){ body += "\nthrow RuntimeExceptionFactory.callFailed($VF.list(" | int i <- index(resolver_formals_types)/*, formal := resolver_formals_types[i]*/ ])>));"; } resolvers = "public (){ // Generated by Resolver - ' + ' '} '"; - + return resolvers; } \ No newline at end of file