package me.tomassetti.turin.parser.ast;
import me.tomassetti.turin.parser.ast.expressions.Expression;
import me.tomassetti.turin.parser.ast.typeusage.TypeUsageNode;
import me.tomassetti.turin.symbols.FormalParameter;
import me.tomassetti.turin.symbols.FormalParameterSymbol;
import me.tomassetti.turin.symbols.Symbol;
import me.tomassetti.turin.typesystem.TypeUsage;
import java.util.*;
public class FormalParameterNode extends Node implements Symbol, FormalParameter {
private TypeUsageNode type;
private String name;
private Optional<Expression> defaultValue;
@Override
public String toString() {
return "FormalParameter{" +
"type=" + type +
", name='" + name + '\'' +
", defaultValue=" + defaultValue +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof FormalParameterNode)) return false;
FormalParameterNode that = (FormalParameterNode) o;
if (!defaultValue.equals(that.defaultValue)) return false;
if (!name.equals(that.name)) return false;
if (!type.equals(that.type)) return false;
return true;
}
public Optional<Expression> getDefaultValue() {
return defaultValue;
}
@Override
public boolean hasDefaultValue() {
return defaultValue.isPresent();
}
@Override
public int hashCode() {
int result = type.hashCode();
result = 31 * result + name.hashCode();
result = 31 * result + defaultValue.hashCode();
return result;
}
private static class DefaultValuePlaceholder extends Expression {
@Override
public Iterable<Node> getChildren() {
return Collections.emptyList();
}
@Override
public TypeUsageNode calcType() {
throw new UnsupportedOperationException();
}
}
public static FormalParameterNode createWithDefaultValuePlaceholder(TypeUsageNode type, String name) {
return new FormalParameterNode(type, name, Optional.of(new DefaultValuePlaceholder()));
}
public FormalParameterNode(TypeUsageNode type, String name) {
this(type, name, Optional.empty());
}
public FormalParameterNode(TypeUsageNode type, String name, Optional<Expression> defaultValue) {
this.type = type;
this.type.parent = this;
this.name = name;
this.defaultValue = defaultValue;
if (defaultValue.isPresent()) {
defaultValue.get().setParent(this);
}
}
@Override
public Iterable<Node> getChildren() {
List<Node> children = new ArrayList<>();
children.add(type);
if (defaultValue.isPresent()) {
children.add(defaultValue.get());
}
return children;
}
@Override
public TypeUsageNode calcType() {
return type;
}
@Override
public TypeUsageNode getType() {
return type;
}
@Override
public String getName() {
return name;
}
@Override
public FormalParameter apply(Map<String, TypeUsage> typeParams) {
return new FormalParameterSymbol(type.replaceTypeVariables(typeParams), name, defaultValue.isPresent());
}
}