this.emitter = emitter;
this.interfaceScope = enclosing_scope.pushFrame();
// Create the class level structures.
InterfaceDefinition interfDef = interfaceNode.getDefinition();
this.interfaceName = interfDef.getMName(interfaceScope.getProject());
iinfo.name = this.interfaceName;
// Check for a duplicate interface name.
switch ( SemanticUtils.getMultiDefinitionType(interfaceNode.getDefinition(), interfaceScope.getProject()))
{
case AMBIGUOUS:
this.interfaceScope.addProblem(new DuplicateInterfaceDefinitionProblem(in, this.interfaceName.getBaseName()));
break;
case NONE:
break;
default:
assert false; // I don't think interfaces can have other type of multiple definitions
}
if (this.interfaceName != null)
{
SemanticUtils.checkScopedToDefaultNamespaceProblem(this.interfaceScope, in, interfDef, this.interfaceName.getBaseName());
}
// Check for circular definition by iterating over all parent interfaces.
Iterator<IInterfaceDefinition> ifaces = interfDef.interfaceIterator(interfaceScope.getProject(), false, interfaceScope.getProblems());
while (ifaces.hasNext()) {
ifaces.next();
}
// check that args are valid
// checkArguments(interfDef, interfaceScope.getProject(), interfaceScope.getProblems());
// Interfaces can't have a superclass.
iinfo.superName = null;
// Add implmented interfaces.
IExpressionNode[] raw_interfaces = this.interfaceNode.getExtendedInterfaceNodes();
iinfo.interfaceNames = new Name[raw_interfaces.length];
for ( int i = 0; i < raw_interfaces.length; i++)
{
IExpressionNode extendedInterface = raw_interfaces[i];
IDefinition extendedDefinition = extendedInterface.resolve(interfaceScope.getProject());
if ( extendedDefinition instanceof IInterfaceDefinition )
{
Name interfaceName = ((DefinitionBase)extendedDefinition).getMName(interfaceScope.getProject());
iinfo.interfaceNames[i] = interfaceName;
}
else if ( extendedDefinition instanceof ClassDefinition )
{
this.interfaceScope.addProblem(new CannotExtendClassProblem(extendedInterface, extendedDefinition.getBaseName()));
}
else if ( extendedDefinition instanceof AmbiguousDefinition )
{
if ( extendedInterface instanceof IIdentifierNode )
{
this.interfaceScope.addProblem(new AmbiguousReferenceProblem(extendedInterface, ((IIdentifierNode)extendedInterface).getName()));
}
else
{
// Parser let something weird through.
this.interfaceScope.addProblem(new AmbiguousReferenceProblem(extendedInterface, ""));
}
}
else if ( extendedDefinition != null )
{
this.interfaceScope.addProblem(new UnknownInterfaceProblem(extendedInterface, extendedDefinition.getBaseName()));
}
else
{
if ( extendedInterface instanceof IIdentifierNode )
{
this.interfaceScope.addProblem(new UnknownInterfaceProblem(extendedInterface, ((IIdentifierNode)extendedInterface).getName()));
}
else
{
// Parser let something weird through.
this.interfaceScope.addProblem(new UnknownInterfaceProblem(extendedInterface, ""));
}
}
// Report a problem if the interface is deprecated
// and the reference to it is not within a deprecated API.
if ( extendedDefinition != null && extendedDefinition.isDeprecated())
{
if (!SemanticUtils.hasDeprecatedAncestor(extendedInterface))
{
ICompilerProblem problem = SemanticUtils.createDeprecationProblem(extendedDefinition, extendedInterface);
this.interfaceScope.addProblem(problem);
}
}
}
iinfo.flags |= ABCConstants.CLASS_FLAG_interface;
this.cv = emitter.visitClass(iinfo, cinfo);
cv.visit();
this.itraits = cv.visitInstanceTraits();
// Define the interface in the init script.
InstructionList setup_insns = this.interfaceScope.getGlobalScope().getInitInstructions();
setup_insns.addInstruction(OP_getscopeobject, 0);
// Interfaces don't have a base class.
setup_insns.addInstruction(OP_pushnull);
setup_insns.addInstruction(OP_newclass, cinfo);
setup_insns.addInstruction(OP_initproperty, interfaceName);
ITraitVisitor tv = this.interfaceScope.getGlobalScope().traitsVisitor.visitClassTrait(TRAIT_Class, interfaceName, 0, cinfo);
this.interfaceScope.processMetadata(tv, interfDef.getAllMetaTags());
tv.visitEnd();
}