The Labs \ Source Viewer \ SSCLI \ Microsoft.JScript \ JSLocalField

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace Microsoft.JScript
  16. {
  17.    
  18.     using System;
  19.     using System.Collections;
  20.     using System.Globalization;
  21.     using System.Reflection;
  22.    
  23.     public sealed class JSLocalField : JSVariableField
  24.     {
  25.         internal int slotNumber;
  26.         internal IReflect inferred_type;
  27.         //Records a guess of what the type of the field is. null = unknown.
  28.         private ArrayList dependents;
  29.         //A list of other fields whose types have been inferred (guessed) based on the inferred type of this field.
  30.         //The dependend fields need to have their guesses changed.
  31.         internal bool debugOn;
  32.         // whether this local field was in a section of code with debug set or not. Control emitting debug info for the local
  33.         internal JSLocalField outerField;
  34.         //If this field is a copy of an outer scope field, the outer scope field is kept in here.
  35.         internal bool isDefined;
  36.         //Indicates whether an assignment to the field has been encountered.
  37.         internal bool isUsedBeforeDefinition;
  38.        
  39.         public JSLocalField(string name, RuntimeTypeHandle handle, int slotNumber) : this(name, null, slotNumber, Missing.Value)
  40.         {
  41.             this.type = new TypeExpression(new ConstantWrapper(Type.GetTypeFromHandle(handle), null));
  42.             this.isDefined = true;
  43.         }
  44.        
  45.         internal JSLocalField(string name, FunctionScope scope, int slotNumber, object value) : base(name, scope, FieldAttributes.Static | FieldAttributes.Public)
  46.         {
  47.             this.slotNumber = slotNumber;
  48.             this.inferred_type = null;
  49.             this.dependents = null;
  50.             this.value = value;
  51.             this.debugOn = false;
  52.             this.outerField = null;
  53.             this.isDefined = false;
  54.             this.isUsedBeforeDefinition = false;
  55.         }
  56.        
  57.         public override Type FieldType {
  58.             get {
  59.                 if (this.type != null)
  60.                     return base.FieldType;
  61.                 else
  62.                     return Convert.ToType(this.GetInferredType(null));
  63.             }
  64.         }
  65.        
  66.         internal override IReflect GetInferredType(JSField inference_target)
  67.         {
  68.             if (this.outerField != null)
  69.                 return this.outerField.GetInferredType(inference_target);
  70.             if (this.type != null)
  71.                 return base.GetInferredType(inference_target);
  72.             if (this.inferred_type == null || this.inferred_type == Typeob.Object)
  73.                 return Typeob.Object;
  74.             if (inference_target != null && inference_target != this) {
  75.                 if (this.dependents == null)
  76.                     this.dependents = new ArrayList();
  77.                 this.dependents.Add(inference_target);
  78.             }
  79.             return this.inferred_type;
  80.         }
  81.        
  82.         public override object GetValue(object obj)
  83.         {
  84.             if ((this.attributeFlags & FieldAttributes.Literal) != (FieldAttributes)0 && !(this.value is FunctionObject))
  85.                 return this.value;
  86.             else {
  87.                 while (obj is BlockScope)
  88.                     obj = ((BlockScope)obj).GetParent();
  89.                 StackFrame sf = (StackFrame)obj;
  90.                 JSLocalField f = this.outerField;
  91.                 int slot = this.slotNumber;
  92.                 while (f != null) {
  93.                     slot = f.slotNumber;
  94.                     sf = (StackFrame)sf.GetParent();
  95.                     f = f.outerField;
  96.                 }
  97.                 return sf.localVars[slot];
  98.             }
  99.         }
  100.        
  101.         internal void SetInferredType(IReflect ir, AST expr)
  102.         {
  103.             this.isDefined = true;
  104.             if (this.type != null)
  105.                 return;
  106.             //The local variable has a type annotation.
  107.             if (this.outerField != null) {
  108.                 this.outerField.SetInferredType(ir, expr);
  109.                 return;
  110.             }
  111.             if (Convert.IsPrimitiveNumericTypeFitForDouble(ir))
  112.                 ir = Typeob.Double;
  113.             else if (ir == Typeob.Void)
  114.                 ir = Typeob.Object;
  115.             if (this.inferred_type == null)
  116.                 this.inferred_type = ir;
  117.             else {
  118.                 //Check to see if ir is compatible with this.inferred_type. If not, generalize this.inferred_type to Object and invalidate dependants.
  119.                 if (ir == this.inferred_type)
  120.                     return;
  121.                 if (!Convert.IsPrimitiveNumericType(this.inferred_type) || !Convert.IsPrimitiveNumericType(ir) || !Convert.IsPromotableTo(ir, this.inferred_type)) {
  122.                     this.inferred_type = Typeob.Object;
  123.                     if (this.dependents != null)
  124.                         for (int i = 0int n = this.dependents.Count; i < n; i++)
  125.                             ((JSLocalField)this.dependents[i]).SetInferredType(Typeob.Object, null);
  126.                 }
  127.             }
  128.         }
  129.        
  130.         public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, CultureInfo locale)
  131.         {
  132.             if (this.type != null)
  133.                 value = Convert.Coerce(value, this.type);
  134.             while (obj is BlockScope)
  135.                 obj = ((BlockScope)obj).GetParent();
  136.             StackFrame sf = (StackFrame)obj;
  137.             JSLocalField f = this.outerField;
  138.             int slot = this.slotNumber;
  139.             while (f != null) {
  140.                 slot = f.slotNumber;
  141.                 sf = (StackFrame)sf.GetParent();
  142.                 f = f.outerField;
  143.             }
  144.             if (sf.localVars == null)
  145.                 return;
  146.             //happens when assigning to a constant from latebound code
  147.             sf.localVars[slot] = value;
  148.         }
  149.     }
  150. }

Developer Fusion