private void rewriteFuncRefs(final List<ImFuncRef> funcRefs, Set<ImFunction> affectedFuncs) { // rewrite funcrefs for (ImFuncRef fr : funcRefs) { ImFunction f = fr.getFunc(); if (!affectedFuncs.contains(f)) { continue; } ImFunction bridgeFunc = JassIm.ImFunction( f.getTrace(), "bridge_" + f.getName(), f.getParameters().copy(), (ImType) f.getReturnType().copy(), JassIm.ImVars(), JassIm.ImStmts(), f.getFlags()); prog.getFunctions().add(bridgeFunc); // remove statcktrace var from params bridgeFunc.getParameters().remove(getStackTraceVar(bridgeFunc)); ImStmt stmt; ImExprs args = JassIm.ImExprs(str("\n " + fr.attrTrace().attrSource().printShort())); ImFunctionCall call = JassIm.ImFunctionCall(fr.attrTrace(), f, args, true, CallType.NORMAL); if (bridgeFunc.getReturnType() instanceof ImVoid) { stmt = call; } else { stmt = JassIm.ImReturn(fr.attrTrace(), call); } bridgeFunc.getBody().add(stmt); fr.setFunc(bridgeFunc); } }
private void passStacktraceParams( final Multimap<ImFunction, ImFunctionCall> calls, Set<ImFunction> affectedFuncs) { // pass the stacktrace parameter at all cals for (ImFunction f : affectedFuncs) { for (ImFunctionCall call : calls.get(f)) { ImFunction caller = call.getNearestFunc(); ImExpr stExpr; if (isMainOrConfig(caller)) { stExpr = str(" " + f.getName()); } else { ImVar stackTraceVar = getStackTraceVar(caller); WPos source = call.attrTrace().attrSource(); String callPos; if (source.getFile().startsWith("<")) { callPos = ""; } else { callPos = "\n " + source.printShort(); } stExpr = JassIm.ImOperatorCall( WurstOperator.PLUS, JassIm.ImExprs(str(callPos), JassIm.ImVarAccess(stackTraceVar))); } call.getArguments().add(stExpr); } } }
private ImVar getStackTraceVar(ImFunction f) { if (!f.getParameters().isEmpty()) { ImVar v = f.getParameters().get(f.getParameters().size() - 1); if (v.getName().equals(WURST_STACK_TRACE)) { return v; } } throw new Error("no stacktrace var found in: " + f.getName()); }
private void addStackTraceParams(Set<ImFunction> affectedFuncs) { // add parameter to affected functions for (ImFunction f : affectedFuncs) { if (isMainOrConfig(f)) { continue; } f.getParameters() .add( JassIm.ImVar( f.getTrace(), WurstTypeString.instance().imTranslateType(), WURST_STACK_TRACE, false)); } }
private void translateInterfaceFuncDef( InterfaceDef interfaceDef, List<ClassDef> instances, FuncDef funcDef) { AstElement trace = funcDef; ImFunction f = translator.getDynamicDispatchFuncFor(funcDef); Map<ClassDef, FuncDef> instances2 = translator.getClassesWithImplementation(instances, funcDef); if (instances2.size() > 0) { int maxTypeId = translator.getMaxTypeId(instances); f.getBody() .addAll( translator.createDispatch(instances2, funcDef, f, maxTypeId, new TypeIdGetterImpl())); } if (!funcDef.attrHasEmptyBody()) { // TODO add default implementation f.getBody().addAll(translator.translateStatements(f, funcDef.getBody())); } else { // create dynamic message when not matched: String msg = "ERROR: invalid type for interface dispatch when calling " + interfaceDef.getName() + "." + funcDef.getName(); f.getBody() .add( JassIm.ImFunctionCall( trace, translator.getDebugPrintFunc(), ImExprs(ImStringVal(msg)))); if (!(funcDef.attrTyp() instanceof WurstTypeVoid)) { // add return statement ImType type = f.getReturnType(); ImExpr def = translator.getDefaultValueForJassType(type); f.getBody().add(JassIm.ImReturn(trace, def)); } } }
public String getMessage() { StringBuilder sb = new StringBuilder(); sb.append("... when calling " + f.getName() + "("); boolean first = true; for (ILconst arg : args) { if (!first) { sb.append(", "); } sb.append(arg); first = false; } sb.append(")"); return sb.toString(); }
private void translateInterfaceFuncDef(FuncDef f) { ImMethod imMeth = translator.getMethodFor(f); ImFunction imFunc = translator.getFuncFor(f); imClass.getMethods().add(imMeth); // translate implementation if (f.attrHasEmptyBody()) { imMeth.setIsAbstract(true); } else { // there is a default implementation imFunc.getBody().addAll(translator.translateStatements(imFunc, f.getBody())); } List<ClassDef> subClasses = Lists.newArrayList(translator.getInterfaceInstances(interfaceDef)); // TODO also add extended interfaces // set sub methods Map<ClassDef, FuncDef> subClasses2 = translator.getClassesWithImplementation(subClasses, f); for (Entry<ClassDef, FuncDef> subE : subClasses2.entrySet()) { ClassDef subC = subE.getKey(); ImmutableCollection<WurstTypeInterface> interfaces = subC.attrImplementedInterfaces(); Map<TypeParamDef, WurstTypeBoundTypeParam> typeBinding = interfaces .stream() .filter(t -> t.getDef() == interfaceDef) .map(t -> t.getTypeArgBinding()) .findFirst() .orElse(Collections.emptyMap()); FuncDef subM = subE.getValue(); ImMethod m = translator.getMethodFor(subM); ImClass mClass = translator.getClassFor(subC); OverrideUtils.addOverride(translator, f, mClass, m, subM, typeBinding); } }
private boolean isMainOrConfig(ImFunction f) { return f.getName().equals("main") || f.getName().equals("config"); }