Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package de.peeeq.wurstscript.attributes;

import com.google.common.collect.ImmutableCollection;
import de.peeeq.wurstscript.ast.*;
import de.peeeq.wurstscript.attributes.names.FuncLink;
import de.peeeq.wurstscript.attributes.names.NameLink;
import org.eclipse.jdt.annotation.Nullable;

Expand All @@ -27,16 +25,24 @@ public static NameDef calculate(GlobalVarDef g) {
}

public static NameDef calculate(FuncDef f) {
return configuredFunctionOrSelf(f);
}

public static NameDef calculate(ExtensionFuncDef f) {
return configuredFunctionOrSelf(f);
}

private static NameDef configuredFunctionOrSelf(FunctionDefinition f) {
if (f instanceof FuncDef && f.attrNearestStructureDef() != null) {
return f;
}
WPackage p = getConfigPackage(f);
if (p != null) {
ImmutableCollection<FuncLink> links = p.getElements().lookupFuncsNoConfig(f.getName(), false);
for (NameLink link : links) {
if (hasConfigAnnotation(link.getDef())) {
return link.getDef();
}
FunctionDefinition configured = ConfigFunctionMatcher.findMatchingFunction(p, f, true);
if (configured != null) {
return configured;
}
}
// not configured
return f;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package de.peeeq.wurstscript.attributes;

import de.peeeq.wurstscript.ast.*;
import de.peeeq.wurstscript.attributes.names.DefLink;
import de.peeeq.wurstscript.types.VariableBinding;
import de.peeeq.wurstscript.types.WurstType;
import de.peeeq.wurstscript.types.WurstTypeBoundTypeParam;
import org.eclipse.jdt.annotation.Nullable;

/** Exact ABI matching for package functions replaced through {@code @config}. */
public final class ConfigFunctionMatcher {

private ConfigFunctionMatcher() {
}

public static @Nullable FunctionDefinition findMatchingFunction(WPackage pack, FunctionDefinition function) {
return findMatchingFunction(pack, function, false);
}

public static @Nullable FunctionDefinition findMatchingFunction(WPackage pack, FunctionDefinition function,
boolean requireConfigAnnotation) {
for (DefLink link : pack.getElements().attrNameLinks().get(function.getName())) {
if (link.getDef() instanceof FunctionDefinition candidate
&& isPackageFunction(candidate, pack)
&& (!requireConfigAnnotation || candidate.hasAnnotation("@config"))
&& matches(function, candidate)) {
return candidate;
}
}
return null;
}

private static boolean isPackageFunction(FunctionDefinition function, WPackage pack) {
return function.attrNearestPackage() == pack
&& (!(function instanceof FuncDef) || function.attrNearestStructureDef() == null);
}

public static boolean matches(FunctionDefinition first, FunctionDefinition second) {
if (!first.getName().equals(second.getName())) {
return false;
}
if ((first instanceof ExtensionFuncDef) != (second instanceof ExtensionFuncDef)) {
return false;
}
if (!(first instanceof AstElementWithTypeParameters firstGeneric)
|| !(second instanceof AstElementWithTypeParameters secondGeneric)) {
return false;
}
TypeParamDefs firstTypeParams = firstGeneric.getTypeParameters();
TypeParamDefs secondTypeParams = secondGeneric.getTypeParameters();
if (firstTypeParams.size() != secondTypeParams.size()) {
return false;
}

VariableBinding alphaMapping = VariableBinding.emptyMapping();
for (int i = 0; i < firstTypeParams.size(); i++) {
TypeParamDef firstTypeParam = firstTypeParams.get(i);
TypeParamDef secondTypeParam = secondTypeParams.get(i);
alphaMapping = alphaMapping.set(firstTypeParam,
new WurstTypeBoundTypeParam(firstTypeParam, secondTypeParam.attrTyp(), first));
}
for (int i = 0; i < firstTypeParams.size(); i++) {
TypeParamDef firstTypeParam = firstTypeParams.get(i);
TypeParamDef secondTypeParam = secondTypeParams.get(i);
if (!equalConstraints(firstTypeParam, secondTypeParam, alphaMapping, first)) {
return false;
}
}

if (first instanceof ExtensionFuncDef firstExtension) {
ExtensionFuncDef secondExtension = (ExtensionFuncDef) second;
if (!equalType(firstExtension.getExtendedType().attrTyp(),
secondExtension.getExtendedType().attrTyp(), alphaMapping, first)) {
return false;
}
}
if (first.getParameters().size() != second.getParameters().size()) {
return false;
}
for (int i = 0; i < first.getParameters().size(); i++) {
if (!equalType(first.getParameters().get(i).attrTyp(), second.getParameters().get(i).attrTyp(),
alphaMapping, first)) {
return false;
}
}
return equalType(first.attrReturnTyp(), second.attrReturnTyp(), alphaMapping, first);
}

private static boolean equalConstraints(TypeParamDef first, TypeParamDef second,
VariableBinding alphaMapping, Element location) {
if ((first.getTypeParamConstraints() instanceof TypeExprList)
!= (second.getTypeParamConstraints() instanceof TypeExprList)) {
return false;
}
if (!(first.getTypeParamConstraints() instanceof TypeExprList firstConstraints)) {
return true;
}
TypeExprList secondConstraints = (TypeExprList) second.getTypeParamConstraints();
if (firstConstraints.size() != secondConstraints.size()) {
return false;
}
for (int i = 0; i < firstConstraints.size(); i++) {
if (!equalType(firstConstraints.get(i).attrTyp(), secondConstraints.get(i).attrTyp(),
alphaMapping, location)) {
return false;
}
}
return true;
}

private static boolean equalType(WurstType first, WurstType second,
VariableBinding alphaMapping, Element location) {
return first.setTypeArgs(alphaMapping).equalsType(second, location);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,10 @@ public boolean isVarargMethod() {

public FuncLink withConfigDef() {
FunctionDefinition def = (FunctionDefinition) this.def.attrConfigActualNameDef();
return new FuncLink(getVisibility(), getDefinedIn(), getTypeParams(), getReceiverType(), def, parameterNames, parameterTypes, returnType, mapping);
if (def == this.def) {
return this;
}
return FuncLink.create(def, getDefinedIn()).withVisibility(getVisibility());
}

public FuncLink hidingPrivate() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public static ImmutableCollection<FuncLink> lookupMemberFuncs(Element node, Wurs
List<FuncLink> fromType = new ArrayList<>(4);
addMemberMethods(node, receiverType, name, fromType);
for (FuncLink cand : fromType) {
DefLink m = matchDefLinkReceiver(cand, receiverType, node, showErrors);
DefLink m = matchDefLinkReceiver(cand.withConfigDef(), receiverType, node, showErrors);
if (m instanceof FuncLink) {
result.add((FuncLink) m);
}
Expand Down Expand Up @@ -185,7 +185,7 @@ public static ImmutableCollection<FuncLink> lookupMemberFuncs(Element node, Wurs
if (!(n instanceof FuncLink)) {
continue;
}
DefLink n2 = matchDefLinkReceiver(n, receiverType, node, false);
DefLink n2 = matchDefLinkReceiver(((FuncLink) n).withConfigDef(), receiverType, node, false);
if (n2 != null) {
FuncLink f = (FuncLink) n2;
result.add(f);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import de.peeeq.wurstscript.attributes.AttrFuncDef;
import de.peeeq.wurstscript.attributes.CofigOverridePackages;
import de.peeeq.wurstscript.attributes.CompileError;
import de.peeeq.wurstscript.attributes.ConfigFunctionMatcher;
import de.peeeq.wurstscript.attributes.ImplicitFuncs;
import de.peeeq.wurstscript.attributes.OverloadingResolver;
import de.peeeq.wurstscript.attributes.names.DefLink;
Expand Down Expand Up @@ -805,19 +806,9 @@ private void checkConfigOverride(NameDef e) {
+ "It is still possible to configure this var but it is not recommended.");
}

} else if (e instanceof FuncDef) {
FuncDef funcDef = (FuncDef) e;
Collection<FuncLink> funcs = origPackage.getElements().lookupFuncsNoConfig(funcDef.getName(), false);
FuncDef configuredFunc = null;
for (NameLink nameLink : funcs) {
if (nameLink.getDef() instanceof FuncDef) {
FuncDef f = (FuncDef) nameLink.getDef();
if (equalSignatures(funcDef, f)) {
configuredFunc = f;
break;
}
}
}
} else if (e instanceof FuncDef || e instanceof ExtensionFuncDef) {
FunctionDefinition funcDef = (FunctionDefinition) e;
FunctionDefinition configuredFunc = ConfigFunctionMatcher.findMatchingFunction(origPackage, funcDef);
if (configuredFunc == null) {
funcDef.addError("Could not find a function " + funcDef.getName()
+ " with the same signature in the configured package.");
Expand All @@ -833,22 +824,6 @@ private void checkConfigOverride(NameDef e) {
}
}

private boolean equalSignatures(FuncDef f, FuncDef g) {
if (f.getParameters().size() != g.getParameters().size()) {
return false;
}
if (!f.attrReturnTyp().equalsType(g.attrReturnTyp(), f)) {
return false;
}
for (int i = 0; i < f.getParameters().size(); i++) {
if (!f.getParameters().get(i).attrTyp().equalsType(g.getParameters().get(i).attrTyp(), f)) {
return false;
}
}

return true;
}

private void checkExprEmpty(ExprEmpty e) {
e.addError("Incomplete expression...");

Expand Down
Loading
Loading