in modules/asc/src/java/macromedia/asc/semantics/FlowAnalyzer.java [2182:2514]
public Value evaluate(Context unused_cx, FunctionCommonNode node)
{
if (debug)
{
System.out.print("\n// +FunctionCommonNode");
}
Context cx = node.cx; // switch to original context
PackageDefinitionNode pkgdef = node.def != null ? node.def.pkgdef : null;
if( pkgdef != null && cx.getScopes().size() == 1 )
{
public_namespaces.push_back(pkgdef.publicNamespace);
default_namespaces.push_back(pkgdef.internalNamespace);
usednamespaces_sets.push_back(pkgdef.used_namespaces);
used_def_namespaces_sets.push_back(pkgdef.used_def_namespaces);
importednames_sets.push_back(pkgdef.imported_names);
}
int savedWithDepth = cx.statics.withDepth;
if( node.with_depth != -1)
{
// FCN was hoisted by an earlier pass
cx.statics.withDepth = node.with_depth;
}
ObjectList<ObjectValue>saved_scopes = null;
if( node.scope_chain != null )
{
saved_scopes = cx.swapScopeChain(node.scope_chain);
}
// First time through, initialize the compile-time constant function value.
if (node.fun == null)
{
if(node.used_namespaces == null) node.used_namespaces = new Namespaces(usednamespaces_sets.back().size());
node.used_namespaces.addAll(usednamespaces_sets.back()); // makes a copy
if(node.imported_names == null) node.imported_names = new Multinames();
node.imported_names.putAll(importednames_sets.back()); // makes a copy
node.private_namespace = (private_namespaces.size() != 0) ? private_namespaces.back() : null;
node.default_namespace = default_namespaces.back();
node.public_namespace = cx.publicNamespace(); //public_namespaces.back();
node.fun = new ObjectValue(cx,new FunctionBuilder(),cx.functionType());
boolean is_named_anon = false;
if( !node.isFunctionDefinition() && node.identifier != null && !"anonymous".equals(node.identifier.name) && node.isUserDefinedBody() )
{
is_named_anon = true;
node.setNamedInnerFunc(true);
// Create a slot in the FunctionBuilder to represent this function so that it can recursively
// call itself.
Namespaces temp_ns = new Namespaces(cx.publicNamespace());
int method_id = node.fun.builder.Method(cx,node.fun,node.identifier.name,temp_ns,false);
node.fun.builder.ExplicitCall(cx,node.fun,node.identifier.name,temp_ns,cx.noType(),false,false,-1,method_id,-1);
cx.pushScope(node.fun);
}
// Save the with depth, if there is one, since the FunctionCommonNode is going to get hoisted
// and there won't be a WithStatementNode above it anymore after hoisting.
if( cx.statics.withDepth != -1 )
node.with_depth = cx.statics.withDepth;
ObjectList<ObjectValue> scope_chain = cx.getScopes();
for(int s = scope_chain.size(); s > 0; --s )
{
ObjectValue scope = scope_chain.get(s-1);
if( scope.builder instanceof CatchBuilder ||
scope.builder instanceof WithBuilder ||
scope.builder instanceof ActivationBuilder)
{
node.scope_chain = new ObjectList<ObjectValue>(scope_chain); // copy the scope chain, since the func will be hoisted
break;
}
}
if( is_named_anon )
{
// We can pop the scope now since it's been saved by the function.
cx.popScope();
}
// fexpr_sets is a stack of sets of function expressions.
// Each set contains the functions at a particular scope level.
ObjectValue scope = cx.scope();
Builder b = scope.builder;
if (b instanceof ClassBuilder)
{
int size = staticfexprs_sets.last().size();
int i;
// Look for the current node in the set for the current scope.
for (i = 0; i < size && staticfexprs_sets.last().get(i) != node; ++i);
// If it is not in the set, then add it.
if (i >= size)
{
staticfexprs_sets.last().add(node);
}
}
else
{
int size = fexprs_sets.last().size();
int i;
// Look for the current node in the set for the current scope.
for (i = 0; i < size && fexprs_sets.last().get(i) != node; ++i);
// If it is not in the set, then add it.
if (i >= size)
{
fexprs_sets.last().add(node);
}
}
}
else
if( doingMethod() )
{
}
else
if (node.ref == null)
{
if(node.used_namespaces != null)
usednamespaces_sets.push_back(node.used_namespaces);
if(node.imported_names != null)
importednames_sets.push_back(node.imported_names);
// Start processing a new function. Add an empty function set to the
// function sets.
fexprs_sets.add(new ObjectList<FunctionCommonNode>());
staticfexprs_sets.push_back(new ObjectList<FunctionCommonNode>());
instanceinits_sets.push_back(new ObjectList<Node>());
// Create a reference to the name.
Value val = node.identifier.evaluate(cx, this);
node.ref = ((val instanceof ReferenceValue) ? (ReferenceValue)val : null);
node.fun.name = node.internal_name; // ISSUE: don't know if this is necessary.
region_name_stack.push_back(cx.debugName(region_name_stack.back(),node.ref.name,node.namespace_ids,node.kind));
// The activation object is the compile-time model of the
// function activation. It is different than the function
// object, which represents the function constructor.
node.fun.activation = new ObjectValue(cx, new ActivationBuilder(),cx.noType());
{
ObjectValue obj = cx.scope(cx.getScopes().size()-1);
node.fun.activation.builder.classname = obj.builder.classname;
node.fun.activation.name = node.internal_name;
}
ObjectValue fun = node.fun;
cx.pushScope(fun.activation);
// The following stacks are not actually used. They are
// left here for their side effects.
// ISSUE: remove references to these stacks.
fun_name_stack.add(node.internal_name);
max_params_stack.add(node.signature.size());
max_locals_stack.add(node.body != null ? node.var_count : 0);
max_temps_stack.add(node.body != null ? node.temp_count : 0);
with_used_stack.add(0);
exceptions_used_stack.add(0);
if( node.use_stmts != null )
{
node.use_stmts.evaluate(cx,this);
}
rt_unresolved_sets.last().addAll(unresolved);
unresolved.clear();
node.signature.evaluate(cx, this);
ce_unresolved_sets.last().addAll(unresolved);
unresolved.clear();
int scope_index = cx.getScopes().size()-1;
ObjectValue obj = cx.scope(scope_index);
if( (node.needsArguments&METHOD_Arguments) != 0 )
{
ObjectValue namespace = node.default_namespace;
if( !obj.hasName(cx,GET_TOKEN,"arguments",namespace) )
{
Builder bui = obj.builder;
int var_id = bui.Variable(cx,obj);
bui.ExplicitVar(cx,obj,"arguments",namespace,cx.arrayType(),-1,-1,var_id);
}
else
{
node.needsArguments ^= METHOD_Arguments; // don't actually need 'arguments' since there is a parameter or var with the same name
}
}
boolean is_constructor = "$construct".equals(node.ref.name);
if (is_constructor)
{
if (node.signature.result != null)
{
cx.error(node.pos(), kError_CtorWithReturnType);
}
}
if (node.body != null)
{
if( !node.isFunctionDefinition() )
{
this_contexts.add(global_this);
}
int state = super_error;
if (is_constructor)
{
state = super_statement;
}
super_context.add(state);
if (node.signature.inits != null)
{
int scope_depth = cx.getScopeDepth();
ObjectValue iframe = cx.scope(scope_depth-2);
// Make get & method slots invisible, only set slots will be visible.
if( iframe.builder instanceof InstanceBuilder )
iframe.setInitOnly(true);
this_contexts.push_back(init_this);
node.signature.inits.evaluate(cx, this);
this_contexts.pop_back();
if( iframe.builder instanceof InstanceBuilder )
iframe.setInitOnly(false);
}
if (is_constructor && cx.dialect(11))
{
super_context.set(super_context.size()-1, super_error_es4);
}
node.body.evaluate(cx, this);
node.temp_count = getTempCount();
node.var_count = fun.activation.var_count-node.signature.size();
super_context.pop_back();
if( !node.isFunctionDefinition() )
{
this_contexts.pop_back();
}
}
else
{
StartMethod(fun_name_stack.last(), max_params_stack.last(), 0 /* no locals */);
}
TypeInfo type = null;
ObjectList<TypeInfo> types = null;
FinishMethod(cx,fun_name_stack.back(),type,types,node.fun.activation,node.needsArguments,cx.getScopes().size(),node.debug_name,node.isNative(),false, null);
if (with_used_stack.last() != 0)
{
node.setWithUsed(true);
}
with_used_stack.removeLast();
if (exceptions_used_stack.last() != 0)
{
node.setExceptionsUsed(true);
}
exceptions_used_stack.removeLast();
fun_name_stack.removeLast();
// Store the accumulated fexprs in this node for CodeGeneration
node.fexprs = fexprs_sets.back();
// Now evaluate each function expression
this_contexts.add(global_this);
for (Node fexpr : node.fexprs)
{
fexpr.evaluate(cx, this);
}
this_contexts.pop_back();
instanceinits_sets.pop_back();
staticfexprs_sets.pop_back();
fexprs_sets.pop_back();
cx.popScope(); // activation
region_name_stack.pop_back();
usednamespaces_sets.pop_back();
importednames_sets.pop_back();
}
// Restore the scope chain if it was changed
if( saved_scopes != null )
{
cx.swapScopeChain(saved_scopes);
}
// Reset the withDepth to whatever it was
cx.statics.withDepth = savedWithDepth;
if( pkgdef != null && cx.getScopes().size() == 1 )
{
public_namespaces.pop_back();
default_namespaces.pop_back();
usednamespaces_sets.pop_back();
used_def_namespaces_sets.pop_back();
importednames_sets.pop_back();
}
if (debug)
{
System.out.print("\n// -FunctionCommonNode");
}
return node.fun;
}