Files
yallie 9fa3874800 Added the contents of the archive.
Moved the original file to the archive subfolder.
2017-11-20 16:11:42 +03:00

137 lines
5.7 KiB
C#

// ==++==
//
//
// Copyright (c) 2002 Microsoft Corporation. All rights reserved.
//
// The use and distribution terms for this software are contained in the file
// named license.txt, which can be found in the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by the
// terms of this license.
//
// You must not remove this notice, or any other, from this software.
//
//
// ==--==
namespace Microsoft.JScript
{
using System;
using System.Collections;
using System.Globalization;
using System.Reflection;
public sealed class JSLocalField : JSVariableField{
internal int slotNumber;
internal IReflect inferred_type; //Records a guess of what the type of the field is. null = unknown.
private ArrayList dependents; //A list of other fields whose types have been inferred (guessed) based on the inferred type of this field.
//The dependend fields need to have their guesses changed.
internal bool debugOn; // whether this local field was in a section of code with debug set or not. Control emitting debug info for the local
internal JSLocalField outerField; //If this field is a copy of an outer scope field, the outer scope field is kept in here.
internal bool isDefined; //Indicates whether an assignment to the field has been encountered.
internal bool isUsedBeforeDefinition;
public JSLocalField(String name, RuntimeTypeHandle handle, int slotNumber)
: this(name, null, slotNumber, Missing.Value){
this.type = new TypeExpression(new ConstantWrapper(Type.GetTypeFromHandle(handle), null));
this.isDefined = true;
}
internal JSLocalField(String name, FunctionScope scope, int slotNumber, Object value)
: base(name, scope, FieldAttributes.Static|FieldAttributes.Public) {
this.slotNumber = slotNumber;
this.inferred_type = null;
this.dependents = null;
this.value = value;
this.debugOn = false;
this.outerField = null;
this.isDefined = false;
this.isUsedBeforeDefinition = false;
}
public override Type FieldType{
get{
if (this.type != null)
return base.FieldType;
else
return Convert.ToType(this.GetInferredType(null));
}
}
internal override IReflect GetInferredType(JSField inference_target){
if (this.outerField != null)
return this.outerField.GetInferredType(inference_target);
if (this.type != null)
return base.GetInferredType(inference_target);
if (this.inferred_type == null || this.inferred_type == Typeob.Object)
return Typeob.Object;
if (inference_target != null && inference_target != this){
if (this.dependents == null)
this.dependents = new ArrayList();
this.dependents.Add(inference_target);
}
return this.inferred_type;
}
public override Object GetValue(Object obj){
if ((this.attributeFlags&FieldAttributes.Literal) != (FieldAttributes)0 && !(this.value is FunctionObject))
return this.value;
else{
while (obj is BlockScope) obj = ((BlockScope)obj).GetParent();
StackFrame sf = (StackFrame)obj;
JSLocalField f = this.outerField;
int slot = this.slotNumber;
while (f != null){
slot = f.slotNumber;
sf = (StackFrame)sf.GetParent();
f = f.outerField;
}
return sf.localVars[slot];
}
}
internal void SetInferredType(IReflect ir, AST expr){
this.isDefined = true;
if (this.type != null)
return; //The local variable has a type annotation.
if (this.outerField != null){
this.outerField.SetInferredType(ir, expr);
return;
}
if (Convert.IsPrimitiveNumericType(ir))
ir = Typeob.Double;
else if (ir == Typeob.Void)
ir = Typeob.Object;
if (this.inferred_type == null)
this.inferred_type = ir;
else{
//Check to see if ir is compatible with this.inferred_type. If not, generalize this.inferred_type to Object and invalidate dependants.
if (ir == this.inferred_type) return;
if (!Convert.IsPrimitiveNumericType(this.inferred_type) || !Convert.IsPrimitiveNumericType(ir) ||
!Convert.IsPromotableTo(ir, this.inferred_type)){
this.inferred_type = Typeob.Object;
if (this.dependents != null) //Some other fields have had their inferred types set to something or other, based on this field's inferred type
//Since the inference for this field proved wrong, the inferences for the other fields might be wrong as well.
for (int i = 0, n = this.dependents.Count; i < n; i++)
((JSLocalField)this.dependents[i]).SetInferredType(Typeob.Object, null);
}
}
}
public override void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo locale){
if (this.type != null)
value = Convert.Coerce(value, this.type);
while (obj is BlockScope) obj = ((BlockScope)obj).GetParent();
StackFrame sf = (StackFrame)obj;
JSLocalField f = this.outerField;
int slot = this.slotNumber;
while (f != null){
slot = f.slotNumber;
sf = (StackFrame)sf.GetParent();
f = f.outerField;
}
if (sf.localVars == null) return; //happens when assigning to a constant from latebound code
sf.localVars[slot] = value;
}
}
}