package edu.ucsd.arcum.interpreter.ast; import static edu.ucsd.arcum.interpreter.ast.ASTUtil.*; import java.util.ArrayList; import java.util.List; import java.util.Set; import com.google.common.collect.Lists; import edu.ucsd.arcum.exceptions.ArcumError; import edu.ucsd.arcum.exceptions.SourceLocation; import edu.ucsd.arcum.interpreter.query.ArcumDeclarationTable; import edu.ucsd.arcum.interpreter.query.EntityDataBase; public class OptionInterface extends TopLevelConstruct { private final SourceLocation location; private final List<TraitSignature> traitSignatures; private final List<TraitSignature> subTraitConstraints; private final FreeStandingRequirements freeStandingRequirements; private OptionInterface(SourceLocation location, String name, String importsString) { super(name, importsString); this.location = location; this.traitSignatures = Lists.newArrayList(); this.subTraitConstraints = Lists.newArrayList(); this.freeStandingRequirements = new FreeStandingRequirements(); } public static OptionInterface newOptionInterface(final SourceLocation location, final String name, final String importsString, ArcumDeclarationTable table) { return table.conditionalCreate(name, new ConstructorThunk<OptionInterface>() { public OptionInterface create() { return new OptionInterface(location, name, importsString); } }); } public void addTupleSetType(TraitSignature set) { traitSignatures.add(set); } @Override public String toString() { StringBuilder buff = new StringBuilder(); buff.append("interface "); buff.append(getName()); buff.append("\n{"); for (TraitSignature tupleSet : traitSignatures) { buff.append("\n "); buff.append(tupleSet.toString()); buff.append("\n"); } buff.append("}\n"); return buff.toString(); } @Override public void doTypeCheck(ArcumDeclarationTable table) { traitSignatures.addAll(EntityDataBase.BUILT_IN_TRAIT_TYPES.values()); TraitSignature constructor = findConstructor(); for (FormalParameter formal : constructor.getFormals()) { if (formal.isSubTrait()) { TraitSignature subTrait = formal.getSubTraitType(); traitSignatures.add(subTrait); subTraitConstraints.add(subTrait); } } NameAccessor<TraitSignature> tupleSetNameExtractor; tupleSetNameExtractor = new NameAccessor<TraitSignature>() { public String getName(TraitSignature tupleSet) { return tupleSet.getName(); } }; checkRealizationConsistency(this); for (RealizationStatement stmt : getRealizationStatements()) { if (stmt.isStatic()) { List<TraitSignature> tuplesRealized = stmt.getTuplesRealized(); traitSignatures.addAll(tuplesRealized); } } checkNames(traitSignatures, tupleSetNameExtractor); for (TraitSignature tupleSet : traitSignatures) { checkFormals(tupleSet.getFormals()); checkModifiers(tupleSet.getModifiers()); } List<String> allNames = new ArrayList<String>(); extractNames(allNames, traitSignatures, tupleSetNameExtractor); checkNames(allNames, IDENTITY_ACCESSOR); for (RealizationStatement stmt : getRealizationStatements()) { checkExpressionPredicates(stmt, traitSignatures); } checkRequireClausePredicates(traitSignatures); Set<String> varsInScope = TraitSignature.getGlobals(traitSignatures); freeStandingRequirements.checkUserDefinedPredicates(traitSignatures, varsInScope); } private void checkModifiers(List<TraitModifier> modifiers) { if (modifiers.indexOf(TraitModifier.ABSTRACT) != modifiers .lastIndexOf(TraitModifier.ABSTRACT)) { ArcumError.fatalError("Keyword abstract present multiple times!"); } if (modifiers.indexOf(TraitModifier.ERROR) != -1) { ArcumError.fatalError("Strange modifier error"); } } // assumes a doTypeCheck has already been performed public List<FormalParameter> getSingletonParameters() { TraitSignature constructor = findConstructor(); if (constructor == null) { // parameters list can be empty return new ArrayList<FormalParameter>(); } if (!constructor.isSingleton()) { ArcumError.fatalError("The constructor tuple set must be" + " declared as a singleton"); } return constructor.getFormals(); } private TraitSignature findConstructor() { for (TraitSignature tupleSet : traitSignatures) { if (tupleSet.getName().equals(this.getName())) { return tupleSet; } } ArcumError.fatalUserError(location, "A constructor named %s must be present", getName()); return null; } public List<TraitSignature> getTraitSignatures() { return traitSignatures; } public List<TraitSignature> getSubTraitConstraints() { return subTraitConstraints; } public TraitSignature lookupTupleSet(String name) { for (TraitSignature tupleSet : traitSignatures) { if (tupleSet.getName().equals(name)) { return tupleSet; } } return null; } public boolean hasSingletonMember(String name) { TraitSignature type = lookupTupleSet(name); if (type != null && type.isSingleton()) { return true; } else { return false; } } public SourceLocation getLocation() { return location; } public boolean declaresAsAbstract(String traitName) { for (TraitSignature tupleSet : traitSignatures) { if (tupleSet.getName().equals(traitName)) { return tupleSet.isAbstract(); } } return false; } public TraitSignature getTraitSignature(String traitName) { for (TraitSignature tupleSet : traitSignatures) { if (tupleSet.getName().equals(traitName)) { return tupleSet; } } return null; } public FreeStandingRequirements getFreeStandingRequirements() { return freeStandingRequirements; } }