package de.peeeq.wurstscript.attributes; import de.peeeq.wurstscript.ast.Element; import de.peeeq.wurstscript.ast.FunctionDefinition; import de.peeeq.wurstscript.ast.WParameter; import de.peeeq.wurstscript.types.VariableBinding; import de.peeeq.wurstscript.types.WurstType; import java.util.Optional; public class CheckHelper { /** * check if the signature of "f" is a refinement of the signature of "of" * * Returns an error if it is not a refinement */ public static Optional checkIfIsRefinement(VariableBinding typeParamMapping, FunctionDefinition f, FunctionDefinition of, String errorMessage) { String funcName = f.getName(); // check static-ness if (f.attrIsStatic() && !of.attrIsStatic()) { return Optional.of("Function " + funcName + " must not be static."); } if (!f.attrIsStatic() && of.attrIsStatic()) { return Optional.of("Function " + funcName + " must be static."); } // check returntype WurstType f_type = getRealType(f, typeParamMapping, f.attrReturnTyp()); WurstType of_type = getRealType(f, typeParamMapping, of.attrReturnTyp()); if (!f_type.isSubtypeOf(of_type, f)) { return Optional.of(errorMessage + funcName + ": The return type is " + f_type + " but it should be " + of_type + "."); } // check parameter count int f_count = f.getParameters().size(); int of_count = of.getParameters().size(); // check parameters if (f_count != of_count) { return Optional.of(errorMessage + funcName + ": The number of parameters of function " + funcName + " must be equal to " + of_count + ", as defined by the overriden function."); } int i = 0; for (WParameter f_p : f.getParameters()) { WParameter of_p = of.getParameters().get(i); WurstType f_p_type = getRealType(f, typeParamMapping, f_p.attrTyp()); WurstType of_p_type = getRealType(f, typeParamMapping, of_p.attrTyp()); if (!f_p_type.isSupertypeOf(of_p_type, f)) { return Optional.of(errorMessage + funcName + ": The type of parameter " + f_p.getName() + " is " + f_p_type + " but it should be " + of_p_type); } i++; } return Optional.empty(); } private static WurstType getRealType(Element context, VariableBinding typeParamMapping, WurstType t) { return t.setTypeArgs(typeParamMapping); } public static boolean isRefinement(VariableBinding typeParamMapping, FunctionDefinition f, FunctionDefinition of) { return !checkIfIsRefinement(typeParamMapping, f, of, "").isPresent(); } }