Skip to content

Commit

Permalink
Merge pull request #178 from ZenCodeLang/feature/refactor-incomplete-…
Browse files Browse the repository at this point in the history
…implementation

Check for incomplete implementations of interfaces
  • Loading branch information
stanhebben authored Oct 11, 2024
2 parents beaae44 + 0d59d2e commit aa11ee4
Show file tree
Hide file tree
Showing 29 changed files with 299 additions and 95 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import org.openzen.zenscript.codemodel.FunctionHeader;
import org.openzen.zenscript.codemodel.OperatorType;
import org.openzen.zenscript.codemodel.identifiers.MethodID;
import org.openzen.zenscript.codemodel.identifiers.MethodSymbol;
import org.openzen.zenscript.codemodel.identifiers.instances.MethodInstance;
import org.openzen.zenscript.codemodel.member.IDefinitionMember;
import org.openzen.zenscript.codemodel.type.BasicTypeID;
import org.openzen.zenscript.codemodel.type.TypeID;

Expand Down Expand Up @@ -579,4 +581,22 @@ public static CompileError invalidLambdaHeader(FunctionHeader header) {
public static CompileError unreachableStatement() {
return new CompileError(CompileExceptionCode.UNREACHABLE_STATEMENT, "Unreachable statement");
}

public static CompileError definitionNotAllowedHere(String text) {
return new CompileError(CompileExceptionCode.DEFINITION_NOT_ALLOWED_HERE, text);
}

public static CompileError incompleteImplementation(List<MethodSymbol> unimplementedMembers) {

String text;
if(unimplementedMembers.size() == 1) {
text = unimplementedMembers.get(0).toString() + " is not implemented";
} else {
text = unimplementedMembers.stream()
.map(MethodSymbol::toString)
.collect(Collectors.joining("\n - ", "Implementation incomplete: " + unimplementedMembers.size() + " members not yet implemented:\n", ""));
}

return new CompileError(CompileExceptionCode.INCOMPLETE_IMPLEMENTATION, text);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.openzen.zenscript.codemodel.expression.CallArguments;
import org.openzen.zenscript.codemodel.expression.Expression;
import org.openzen.zenscript.codemodel.expression.switchvalue.SwitchValue;
import org.openzen.zenscript.codemodel.identifiers.MethodSymbol;
import org.openzen.zenscript.codemodel.identifiers.TypeSymbol;
import org.openzen.zenscript.codemodel.identifiers.instances.IteratorInstance;
import org.openzen.zenscript.codemodel.type.TypeID;
Expand Down Expand Up @@ -84,6 +85,8 @@ default boolean canCastImplicitlyTo(TypeID target) {

Optional<StaticCallable> findStaticOperator(OperatorType operator);

List<MethodSymbol> getInterfaceMethodsToImplement();

interface SwitchMember {
SwitchValue toSwitchValue(List<CompilingVariable> bindings);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
import org.openzen.zenscript.codemodel.GenericMapper;
import org.openzen.zenscript.codemodel.HighLevelDefinition;
import org.openzen.zenscript.codemodel.Modifiers;
import org.openzen.zenscript.codemodel.compilation.ResolvedType;
import org.openzen.zenscript.codemodel.compilation.ResolvingType;
import org.openzen.zenscript.codemodel.identifiers.ModuleSymbol;
import org.openzen.zenscript.codemodel.identifiers.TypeSymbol;
import org.openzen.zenscript.codemodel.type.TypeID;
import org.openzen.zenscript.codemodel.type.member.InterfaceResolvingType;
import org.openzen.zenscript.codemodel.type.member.MemberSet;

import java.util.ArrayList;
Expand All @@ -19,10 +22,6 @@ public InterfaceDefinition(CodePosition position, ModuleSymbol module, ZSPackage
super(position, module, pkg, name, modifiers, outerDefinition);
}

public void addBaseInterface(TypeID baseInterface) {
baseInterfaces.add(baseInterface);
}

@Override
public boolean isStatic() {
return true;
Expand All @@ -39,9 +38,7 @@ public <C, R> R accept(C context, DefinitionVisitorWithContext<C, R> visitor) {
}

@Override
protected void resolveAdditional(TypeID type, MemberSet.Builder members, GenericMapper mapper) {
for (TypeID baseType : baseInterfaces) {
// TODO: register those members
}
public ResolvingType resolve(TypeID[] typeArguments) {
return InterfaceResolvingType.of(super.resolve(typeArguments), baseInterfaces);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,8 @@
import org.openzen.zenscript.codemodel.type.TypeID;
import org.openzen.zenscript.codemodel.type.member.MemberSet;

import java.util.Optional;

public class CasterMember extends FunctionalMember {
public TypeID toType;
public MethodInstance overrides;

public CasterMember(
CodePosition position,
Expand Down Expand Up @@ -67,11 +64,5 @@ public Modifiers getEffectiveModifiers() {
}

@Override
public Optional<MethodInstance> getOverrides() {
return Optional.ofNullable(overrides);
}

public void setOverrides(MethodInstance overrides) {
this.overrides = overrides;
}
protected void inferFromOverride(MethodInstance overrides) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ public Optional<MethodInstance> getOverrides() {
return Optional.empty();
}

@Override
protected void inferFromOverride(MethodInstance overrides) {}

@Override
public Modifiers getEffectiveModifiers() {
Modifiers result = modifiers.withStatic();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,22 @@
import org.openzen.zenscript.codemodel.FunctionHeader;
import org.openzen.zenscript.codemodel.HighLevelDefinition;
import org.openzen.zenscript.codemodel.Modifiers;
import org.openzen.zenscript.codemodel.OperatorType;
import org.openzen.zenscript.codemodel.identifiers.DefinitionSymbol;
import org.openzen.zenscript.codemodel.identifiers.MethodID;
import org.openzen.zenscript.codemodel.identifiers.MethodSymbol;
import org.openzen.zenscript.codemodel.identifiers.instances.MethodInstance;
import org.openzen.zenscript.codemodel.statement.Statement;
import org.openzen.zenscript.codemodel.type.TypeID;

import java.util.Optional;

public abstract class FunctionalMember extends DefinitionMember implements MethodSymbol {
public FunctionHeader header;
public Statement body = null;
private final MethodID id;
protected MethodInstance overrides;
private boolean expectsOverride = false;

public FunctionalMember(
CodePosition position,
Expand All @@ -34,6 +40,10 @@ public void setBody(Statement body) {

public abstract FunctionalKind getKind();

public boolean doesExpectOverride() {
return expectsOverride;
}

@Override
public Modifiers getModifiers() {
return getEffectiveModifiers();
Expand All @@ -46,6 +56,8 @@ public Modifiers getEffectiveModifiers() {
result = result.withPublic();
if (!result.hasAccessModifiers())
result = result.withInternal();
if (isImplicitlyAbstract())
result = result.withAbstract();

return result;
}
Expand Down Expand Up @@ -76,4 +88,25 @@ public MethodID getID() {
public FunctionHeader getHeader() {
return header;
}

@Override
public Optional<MethodInstance> getOverrides() {
return Optional.ofNullable(overrides);
}

public void setOverrides(MethodInstance overrides) {
this.overrides = overrides;
this.expectsOverride = true;
if (overrides != null) {
inferFromOverride(overrides);
}
}

protected abstract void inferFromOverride(MethodInstance overrides);

private boolean isImplicitlyAbstract() {
return definition.isInterface()
&& !modifiers.isStatic()
&& !getID().getOperator().filter(op -> op == OperatorType.CONSTRUCTOR).isPresent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public class GetterMember extends FunctionalMember {
public final String name;
public TypeID type;
public Statement body = null;
private MethodInstance overrides;

public GetterMember(
CodePosition position,
Expand Down Expand Up @@ -75,15 +74,9 @@ public <C, R> R accept(C context, MemberVisitorWithContext<C, R> visitor) {
}

@Override
public Optional<MethodInstance> getOverrides() {
return Optional.ofNullable(overrides);
}

public void setOverrides(MethodInstance override) {
this.overrides = override;

protected void inferFromOverride(MethodInstance overrides) {
if (type == BasicTypeID.UNDETERMINED)
type = override.getHeader().getReturnType();
type = overrides.getHeader().getReturnType();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
public class IteratorMember extends FunctionalMember {
private final TypeID[] iteratorTypes;
public Statement body;
public MethodInstance overrides;

public IteratorMember(CodePosition position, HighLevelDefinition definition, Modifiers modifiers, TypeID[] iteratorTypes) {
super(position, definition, modifiers, MethodID.iterator(iteratorTypes.length), createIteratorHeader(iteratorTypes));
Expand Down Expand Up @@ -69,11 +68,5 @@ public FunctionalKind getKind() {
}

@Override
public Optional<MethodInstance> getOverrides() {
return Optional.ofNullable(overrides);
}

public void setOverrides(MethodInstance overrides) {
this.overrides = overrides;
}
protected void inferFromOverride(MethodInstance overrides) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,8 @@
import org.openzen.zenscript.codemodel.type.TypeID;
import org.openzen.zenscript.codemodel.type.member.MemberSet;

import java.util.Optional;

public class MethodMember extends FunctionalMember {
public final String name;
private MethodInstance overrides;

public MethodMember(CodePosition position, HighLevelDefinition definition, Modifiers modifiers, String name, FunctionHeader header) {
super(position, definition, modifiers, modifiers.isStatic() ? MethodID.staticMethod(name) : MethodID.instanceMethod(name), header);
Expand Down Expand Up @@ -62,12 +59,7 @@ public Modifiers getEffectiveModifiers() {
}

@Override
public Optional<MethodInstance> getOverrides() {
return Optional.ofNullable(overrides);
}

public void setOverrides(MethodInstance overrides) {
this.overrides = overrides;
protected void inferFromOverride(MethodInstance overrides) {
header = header.inferFromOverride(overrides.getHeader());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

public class OperatorMember extends FunctionalMember {
public final OperatorType operator;
private MethodInstance overrides;

public OperatorMember(
CodePosition position,
Expand Down Expand Up @@ -67,12 +66,7 @@ public Modifiers getEffectiveModifiers() {
}

@Override
public Optional<MethodInstance> getOverrides() {
return Optional.ofNullable(overrides);
}

public void setOverrides(MethodInstance overrides) {
this.overrides = overrides;
protected void inferFromOverride(MethodInstance overrides) {
header = header.inferFromOverride(overrides.getHeader());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public class SetterMember extends FunctionalMember {
public TypeID type;
public Statement body;
public FunctionParameter parameter;
private MethodInstance overrides;

public SetterMember(
CodePosition position,
Expand Down Expand Up @@ -66,13 +65,7 @@ public <C, R> R accept(C context, MemberVisitorWithContext<C, R> visitor) {
}

@Override
public Optional<MethodInstance> getOverrides() {
return Optional.ofNullable(overrides);
}

public void setOverrides(MethodInstance overrides) {
this.overrides = overrides;

public void inferFromOverride(MethodInstance overrides) {
if (type == BasicTypeID.UNDETERMINED) {
this.type = overrides.getHeader().getReturnType();
parameter = new FunctionParameter(overrides.getHeader().getReturnType(), "$");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.openzen.zenscript.codemodel.OperatorType;
import org.openzen.zenscript.codemodel.compilation.*;
import org.openzen.zenscript.codemodel.identifiers.ExpansionSymbol;
import org.openzen.zenscript.codemodel.identifiers.MethodSymbol;
import org.openzen.zenscript.codemodel.identifiers.TypeSymbol;
import org.openzen.zenscript.codemodel.identifiers.instances.IteratorInstance;
import org.openzen.zenscript.codemodel.identifiers.instances.MethodInstance;
Expand Down Expand Up @@ -175,6 +176,11 @@ public Optional<StaticCallable> findStaticOperator(OperatorType operator) {
return Optional.ofNullable(result);
}

@Override
public List<MethodSymbol> getInterfaceMethodsToImplement() {
return base.getInterfaceMethodsToImplement();
}

@Override
public Optional<Field> findField(String name) {
return base.findField(name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.openzen.zenscript.codemodel.compilation.*;
import org.openzen.zenscript.codemodel.identifiers.ExpansionSymbol;
import org.openzen.zenscript.codemodel.identifiers.MethodID;
import org.openzen.zenscript.codemodel.identifiers.MethodSymbol;
import org.openzen.zenscript.codemodel.identifiers.TypeSymbol;
import org.openzen.zenscript.codemodel.identifiers.instances.FieldInstance;
import org.openzen.zenscript.codemodel.identifiers.instances.IteratorInstance;
Expand Down Expand Up @@ -116,6 +117,19 @@ public Optional<StaticCallable> findStaticOperator(OperatorType operator) {
return findStatic(MethodID.staticOperator(operator));
}

@Override
public List<MethodSymbol> getInterfaceMethodsToImplement() {
List<MethodSymbol> result = new ArrayList<>();
for (List<InstanceCallableMethod> methods : instanceMethods.values()) {
for (InstanceCallableMethod method : methods) {
if (method.getModifiers().isAbstract()) {
method.asMethod().ifPresent(m -> result.add(m.method));
}
}
}
return result;
}

@Override
public Optional<Field> findField(String name) {
return Optional.ofNullable(fields.get(name));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.openzen.zenscript.codemodel.FunctionHeader;
import org.openzen.zenscript.codemodel.OperatorType;
import org.openzen.zenscript.codemodel.compilation.*;
import org.openzen.zenscript.codemodel.identifiers.MethodSymbol;
import org.openzen.zenscript.codemodel.identifiers.TypeSymbol;
import org.openzen.zenscript.codemodel.identifiers.instances.IteratorInstance;
import org.openzen.zenscript.codemodel.identifiers.instances.MethodInstance;
Expand Down Expand Up @@ -135,4 +136,9 @@ public Optional<IteratorInstance> findIterator(int variables) {
public Optional<StaticCallable> findStaticOperator(OperatorType operator) {
return Optional.empty();
}

@Override
public List<MethodSymbol> getInterfaceMethodsToImplement() {
return Collections.emptyList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.openzen.zenscript.codemodel.expression.CallArguments;
import org.openzen.zenscript.codemodel.expression.Expression;
import org.openzen.zenscript.codemodel.expression.SupertypeCastExpression;
import org.openzen.zenscript.codemodel.identifiers.MethodSymbol;
import org.openzen.zenscript.codemodel.identifiers.TypeSymbol;
import org.openzen.zenscript.codemodel.identifiers.instances.IteratorInstance;
import org.openzen.zenscript.codemodel.identifiers.instances.MethodInstance;
Expand Down Expand Up @@ -163,6 +164,16 @@ public Optional<StaticCallable> findStaticOperator(OperatorType operator) {
return thisType.findStaticOperator(operator);
}

@Override
public List<MethodSymbol> getInterfaceMethodsToImplement() {
Set<MethodSymbol> overridden = new HashSet<>();
return Stream.concat(baseTypes.stream(), Stream.of(thisType))
.flatMap(type -> type.getInterfaceMethodsToImplement().stream())
.filter(method -> !overridden.contains(method))
.peek(m -> m.getOverrides().ifPresent(override -> overridden.add(override.method)))
.collect(Collectors.toList());
}

private <T> Optional<T> findFirstInLocalOrBaseTypes(Function<ResolvedType, Optional<T>> mapper) {
return streamAllTypes()
.map(mapper)
Expand Down
Loading

0 comments on commit aa11ee4

Please sign in to comment.