else
{
inheritClassSlots(node.cframe, node.iframe, type, cx);
// No matter what, if the base slot was from an import, we can't early bind.
Slot base_slot = node.baseref.getSlot(node.cx, node.baseref.getKind());
if( base_slot.isImported() && type != cx.noType() ) //Ok if it's object, doesn't have any methods...
{
((InstanceBuilder)node.iframe.builder).canEarlyBind = false;
}
// inherit protected namespaces
ClassBuilder classBuilder;
while( type != null && type != node.cframe && type.resolved)
{
classBuilder = (ClassBuilder) type.builder;
if( classBuilder.static_protected_namespace != null )
{
node.used_namespaces.push_back(classBuilder.static_protected_namespace);
node.used_def_namespaces.push_back(classBuilder.static_protected_namespace);
}
type = type.baseclass;
}
}
}
if (node.interfaces != null && node.interfaces.values != null)
{
ObjectList<ReferenceValue> interface_refs = ((InstanceBuilder)node.iframe.builder).interface_refs;
HashSet<TypeValue> seen_interfs = new HashSet<TypeValue>();
for (int i = 0; i < node.interfaces.values.size(); ++i )
{
Value v = node.interfaces.values.get(i);
if (v instanceof ReferenceValue)
{
ReferenceValue ref = (ReferenceValue) v;
Value v2 = v.getValue(cx);
TypeValue t = ((v2 instanceof TypeValue) ? (TypeValue)v2 : null);
if (t == null )
{
cx.error(node.interfaces.items.get(i).pos(), kError_UnknownInterface, ref.name);
}
else
{
if (t.builder instanceof ClassBuilder)
{
if (!(((ClassBuilder)t.builder).is_interface))
{
cx.error(node.interfaces.items.get(i).pos(), kError_CannotExtendClass, ref.name);
}
else
{
if( seen_interfs.contains(t) )
{
cx.error(node.interfaces.items.get(i).pos(), kError_DuplicateImplements, node.ref.name, ref.name);
}
else
{
seen_interfs.add(t);
}
interface_refs.push_back(ref);
if (node instanceof InterfaceDefinitionNode)
{
// If this is an interface, inherit the super-interface slots.
inheritClassSlots(node.cframe, node.iframe, t, cx);
}
}
}
else
{
cx.error(node.interfaces.items.get(i).pos(), kError_UnknownInterface, ref.name);
}
}
}
else
{
// uh oh, didn't resolve to anything, but we have a baseclass expression
cx.error(node.interfaces.items.get(i).pos(), kError_InvalidInterfaceTypeExpression);
}
}
}
Names lastInterfaceMethods = interfaceMethods;
interfaceMethods = null;
scanInterfaceMethods(cx, node);
processInterfacePublicMethods(cx, node.iframe);
StartClass(node.ref.name);
ObjectList<String> namespace_ids = new ObjectList<String>();
if( node.namespaces.size() != 0 )
{
namespace_ids.push_back(node.namespaces.back().name);
}
else
{
namespace_ids.push_back("error");
}
region_name_stack.push_back(cx.debugName(region_name_stack.back(),node.ref.name,namespace_ids,EMPTY_TOKEN));
/*
node->used_namespaces = *used_namespaces_sets.back() // save alias of outer namespaces
...
node->used_namespaces.push_back(node->private_namespace); // add implicitly used namespaces
...
usednamespaces_sets.back(&node->used_namespaces) // add current namespaces to nss sets
...
used_namespaces get deleted
*/
private_namespaces.push_back(node.private_namespace);
default_namespaces.push_back(node.default_namespace);
public_namespaces.push_back(node.public_namespace);
protected_namespaces.push_back(node.protected_namespace);
static_protected_namespaces.push_back(node.static_protected_namespace);
cx.pushStaticClassScopes(node);
this_contexts.removeLast();
this_contexts.add(cinit_this);
// Function expressions that occur in the current block will be
// compiled as though they had occured at the end of the block.
// The variable that references them is initialized at the beginning
// of the block.
fexprs_sets.add(new ObjectList<FunctionCommonNode>());
staticfexprs_sets.add(new ObjectList<FunctionCommonNode>());
instanceinits_sets.add(new ObjectList<Node>());
// Copy the set of nested functions into the node for use
// by later phases.
node.fexprs = fexprs_sets.last();
node.instanceinits = instanceinits_sets.last(); // Holds the static initializers for this class
node.staticfexprs = staticfexprs_sets.last(); // Holds the static initializers for this class
fun_name_stack.add(node.ref.name); // During flow analysis we use the class name
max_params_stack.add(0);
max_locals_stack.add(node.var_count);
max_temps_stack.add(node.temp_count);
StartMethod(fun_name_stack.last(), max_params_stack.last(), max_locals_stack.last());
if (node.statements != null)
{
// Evaluate the statements. When we are done, the static names
// are in the class object builder. The static initializers are
// in the inner staticdefs_sets sets. The instance names are in
// the instance object builder, and the instance initializers
// are in the
node.statements.evaluate(cx, this);
node.temp_count = getTempCount();
node.var_count = node.cframe.var_count;
}
else
{
StartMethod(fun_name_stack.last(), max_params_stack.last(), max_locals_stack.last());
}
node.temp_count = getTempCount(); // Remember the temp count
// Return(TYPE_none);
Return(TYPE_void);
FinishMethod(cx, fun_name_stack.back(), null,null,null,0, cx.getScopes().size(), "",false,false, null);
cx.pushScope(node.iframe);
this_contexts.removeLast();
this_contexts.add(instance_this);
// Evaluate the instance initializers
// (This must be done before we add the default
// constructor if needed, because this is where
// has_ctor gets set)
{
for (Node n : node.instanceinits)
{
if( cx.statics.es4_nullability && !n.isDefinition())
node.iframe.setInitOnly(true);
n.evaluate(cx, this);
if( cx.statics.es4_nullability && !n.isDefinition())
node.iframe.setInitOnly(false);
}
}
ObjectValue obj = node.iframe;
InstanceBuilder bui = ((obj.builder instanceof InstanceBuilder) ? (InstanceBuilder)obj.builder : null);
if( !bui.is_intrinsic && !bui.has_ctor )
{
NodeFactory nf = cx.getNodeFactory();
FunctionNameNode fname = nf.functionName(EMPTY_TOKEN, nf.identifier(node.ref.name,0));
nf.has_rest = false;
nf.has_arguments = false;
FunctionCommonNode fexpr = nf.functionCommon(cx, fname.identifier, nf.functionSignature(null, null, 0), null, 0);
AttributeListNode attrs = nf.attributeList(nf.identifier(PUBLIC,false,0),null);
attrs.evaluate(cx,this);
FunctionDefinitionNode fdef = nf.functionDefinition(cx, attrs, fname, fexpr);
fdef.pkgdef = node.pkgdef;
fdef.evaluate(cx,this);
Node init = fdef.initializerStatement(cx);
init.evaluate(cx,this);
if( null == node.statements )
{
node.statements = nf.statementList(null,init);
}
else
{
node.statements.items.add(0,init);
}
}
// Now turn the static names into definitions
// Generate code for the static property definitions
{
this_contexts.add(error_this);
cx.popScope(); // temporarily
for (Node n : node.staticfexprs)
{
n.evaluate(cx, this);
}
cx.pushScope(node.iframe);
this_contexts.removeLast();
}
fun_name_stack.removeLast();
max_params_stack.removeLast();
max_locals_stack.removeLast();
max_temps_stack.removeLast();
// Now evaluate each function expression
{
for (FunctionCommonNode n : node.fexprs)
{
n.evaluate(cx, this);
}
}
// Remove the top set of nested functions from the stack of sets
fexprs_sets.removeLast();
//ASSERT(fexprs_sets.size() == 0);
private_namespaces.pop_back();
default_namespaces.pop_back();
public_namespaces.pop_back();
protected_namespaces.pop_back();
static_protected_namespaces.pop_back();
usednamespaces_sets.pop_back();
used_def_namespaces_sets.pop_back();
importednames_sets.pop_back();
FinishClass(cx,node.cframe.builder.classname,null,false, false, false, node.cframe.is_nullable);
this_contexts.removeLast();
// pop the iframe now so we process class defs in static scope
cx.popScope(); // iframe
// Now evaluate each class definition
{
// node.clsdefs have the baseclass.cframe resolved, i.e. we've got fully-qualified class names.
// sort the class names based on "extends" and "implements"...
node.clsdefs = sortClassDefinitions(node.cx, node.clsdefs);
if (found_circular_or_duplicate_class_definition == false)
{
for (ClassDefinitionNode clsdef : node.clsdefs)
{
clsdef.evaluate(cx,this);
}
}
}
// Remove the top set of nested classes from the stack of sets
instanceinits_sets.removeLast();
staticfexprs_sets.removeLast();
cx.popStaticClassScopes(node);
node.debug_name = region_name_stack.back();
// store debug name on the slot as well. asDoc needs fully qualified debug_names for all
// type references.
Slot s = node.ref.getSlot(cx,GET_TOKEN);
if (s != null)
{
s.setDebugName(node.debug_name);
s.setConst(true); // class slots are const
}
region_name_stack.removeLast();
strict_context.pop_back();