freeTemp(temp_val_reg); // temp_val_reg
}
}
else
{
Slot slot = node.ref.getSlot(cx,SET_TOKEN);
TypeInfo expr_type = node.ref.getType(cx);
int base_index = node.ref.getScopeIndex(SET_TOKEN);
int slot_index = node.ref.getSlotIndex(SET_TOKEN);
int scope_depth = cx.getScopes().size()-1;
int reg_offset = getRegisterOffset(cx);
int var_offset = cx.scope(scope_depth).builder.var_offset;
Builder bui = base_index>0?cx.scope(base_index).builder:null; // get the builder from lexical scope, null if object reference
boolean is_constinit = node.is_constinit?true:(is_ctor&&node.isThis())?true:(bui instanceof InstanceBuilder)?true:false;
boolean is_const = slot!=null?slot.isConst():false;
boolean is_localref = isLocalScope(cx, base_index);
boolean is_globalref = base_index == 0;
boolean is_dotref = base_index == -2;
boolean is_unbound_lexref = base_index == -1;
boolean is_unbound_dotref = is_dotref && slot_index < 0;
boolean is_unbound_globalref = is_globalref && slot_index < 0;
boolean is_unbound_ref = is_unbound_dotref || is_unbound_lexref || is_unbound_globalref;
if( is_unbound_ref )
{
// If it is a global ref, then the base object is not yet on the
// stack. Push it now
if( is_globalref )
{
GetGlobalScope();
}
// Push the value on the stack
node.args.evaluate(cx,this);
// See if we can tell if the reference is dynamic or not.
// This is only possible when it is a dot reference, but
// we don't worry about that here, to simplify
/* runtime error
ObjectValue bobj = node.ref.getBase();
TypeValue btyp = bobj != null ? bobj.getType(cx) : cx.noType();
if (btyp.isFinal() && !btyp.isDynamic())
{
cx.error(node.pos(), kError_UnknownPropertyInNonDynamicInstance, node.ref.name);
}
*/
{
if (!node.void_result)
{
Dup();
temp_val_reg = allocateTemp();
StoreRegister(reg_offset+temp_val_reg, expr_type.getTypeId());
}
SetProperty(node.ref.name, node.ref.getImmutableNamespaces(), node.ref.isQualified(), is_super, is_attribute, is_constinit);
}
if (!node.void_result)
{
LoadRegister(reg_offset+temp_val_reg, expr_type.getTypeId());
freeTemp(temp_val_reg); // temp_val_reg
}
}
else if (is_globalref)
{
// Found, global variable
int varIndex = slot.getVarIndex();
if (slot.declaredBy != cx.scope(0))
{
varIndex = -1;
}
if (slot.getMethodID() >= 0 || varIndex < 0) // Need to put global on stack
{
FindProperty(node.ref.name,node.ref.getImmutableNamespaces(),node.ref.isQualified(),is_super,is_attribute);
}
else
if( is_const )
{
GetBaseObject(0);
}
// Push the value
node.args.evaluate(cx,this);
if( !node.void_result )
{
Dup();
temp_val_reg = allocateTemp();
StoreRegister(reg_offset+temp_val_reg,expr_type.getTypeId());
}
if( slot.getMethodID() >= 0 && cx.globalScope() == slot.declaredBy) // If it is a setter, invoke it.
{
InvokeMethod(false/*is_virtual*/,GetMethodInfo(slot.getMethodName()), 1);
// callstatic's semantics leave a value on the stack; a void setter
// doesn't return anything, so pop this pseudo return value to keep
// the stack balanced.
if ( node.void_result )
Pop();
}
else // If it is a variable and we know the index, then store it
if( varIndex >= 0 && !is_const)
{
StoreGlobal(varIndex,expr_type.getTypeId());
}
else // Otherwise, just do a generic store global by name
{
SetProperty(node.ref.name, node.ref.getImmutableNamespaces(), node.ref.isQualified(), is_super, is_attribute, is_constinit);
}
if( !node.void_result )
{
LoadRegister(reg_offset+temp_val_reg,expr_type.getTypeId());
freeTemp(temp_val_reg); // temp_val_reg
}
}
else if (is_localref)
{
// Found, local variable
{
if( is_const && !is_constinit )
{
PushString("Illegal write to local const " + node.ref.name);
Throw();
}
if( slot.getMethodID() >= 0 || frame.registerScopeIndex != base_index)
{
GetActivationObject(base_index);
}
node.args.evaluate(cx,this);
if (!node.void_result)
{
Dup();
temp_val_reg = allocateTemp();
StoreRegister(reg_offset+temp_val_reg, expr_type.getTypeId());
}
if( slot.getMethodID() >= 0 )
{
InvokeMethod(true,slot.getMethodID(),1);
}
else
{
// issue this CheckType is too conservative
// explicit coerce before setting a local, in case VM doesn't know
// the type that we know here. (e.g. calling through an interface)
CheckType(slot.getType().getName(cx));
if (frame.registerScopeIndex != base_index)
{
StoreVar(var_offset+slot.getVarIndex());
}
else
{
//CheckType(slot.getType().name);
StoreRegister(reg_offset+slot.getVarIndex(),expr_type.getTypeId(),node.ref.name);
}
}
if (!node.void_result)
{