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

  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.Reflection;
  20.     using System.Reflection.Emit;
  21.    
  22.     internal sealed class Constant : AST
  23.     {
  24.         internal FieldAttributes attributes;
  25.         private Completion completion;
  26.         internal CustomAttributeList customAttributes;
  27.         internal JSVariableField field;
  28.         private FieldBuilder valueField;
  29.         private Lookup identifier;
  30.         internal string name;
  31.         internal AST value;
  32.        
  33.         internal Constant(Context context, Lookup identifier, TypeExpression type, AST value, FieldAttributes attributes, CustomAttributeList customAttributes) : base(context)
  34.         {
  35.             this.attributes = attributes | FieldAttributes.InitOnly;
  36.             this.customAttributes = customAttributes;
  37.             this.completion = new Completion();
  38.             this.identifier = identifier;
  39.             this.name = identifier.ToString();
  40.             this.value = value;
  41.             ScriptObject current_scope = (ScriptObject)Globals.ScopeStack.Peek();
  42.             while (current_scope is WithObject)
  43.                 //Can only happen at run time and only if there is an eval
  44.                 current_scope = current_scope.GetParent();
  45.             if (current_scope is ClassScope) {
  46.                 if (this.name == ((ClassScope)current_scope).name) {
  47.                     identifier.context.HandleError(JSError.CannotUseNameOfClass);
  48.                     this.name = this.name + " const";
  49.                 }
  50.                 if (attributes == 0)
  51.                     attributes = FieldAttributes.Public;
  52.             }
  53.             else {
  54.                 if (attributes != 0)
  55.                     this.context.HandleError(JSError.NotInsideClass);
  56.                 attributes = FieldAttributes.Public;
  57.             }
  58.             FieldInfo field = ((IActivationObject)current_scope).GetLocalField(this.name);
  59.             if (field != null) {
  60.                 identifier.context.HandleError(JSError.DuplicateName, true);
  61.                 this.name = this.name + " const";
  62.             }
  63.             if (current_scope is ActivationObject)
  64.                 this.field = ((ActivationObject)current_scope).AddNewField(this.identifier.ToString(), value, attributes);
  65.             else
  66.                 this.field = ((StackFrame)current_scope).AddNewField(this.identifier.ToString(), value, attributes | FieldAttributes.Static);
  67.             this.field.type = type;
  68.             this.field.customAttributes = customAttributes;
  69.             this.field.originalContext = context;
  70.             if (this.field is JSLocalField)
  71.                 // emit debug info for the local only if this block of code is in a section that has debug set
  72.                 ((JSLocalField)this.field).debugOn = this.identifier.context.document.debugOn;
  73.         }
  74.        
  75.         internal override object Evaluate()
  76.         {
  77.             if (this.value == null)
  78.                 this.completion.value = this.field.value;
  79.             else
  80.                 this.completion.value = this.value.Evaluate();
  81.             return this.completion;
  82.         }
  83.        
  84.         internal override AST PartiallyEvaluate()
  85.         {
  86.             this.field.attributeFlags &= ~FieldAttributes.InitOnly;
  87.             this.identifier.PartiallyEvaluateAsReference();
  88.             if (this.field.type != null)
  89.                 this.field.type.PartiallyEvaluate();
  90.             ScriptObject scope = (ScriptObject)Globals.ScopeStack.Peek();
  91.             if (this.value != null) {
  92.                 this.value = this.value.PartiallyEvaluate();
  93.                 this.identifier.SetPartialValue(this.value);
  94.                 if (this.value is ConstantWrapper) {
  95.                     object val = this.field.value = this.value.Evaluate();
  96.                     if (this.field.type != null)
  97.                         this.field.value = Convert.Coerce(val, this.field.type, true);
  98.                     if (this.field.IsStatic && (val is Type || val is ClassScope || val is TypedArray || Convert.GetTypeCode(val) != TypeCode.Object)) {
  99.                         this.field.attributeFlags |= FieldAttributes.Literal;
  100.                         goto set_field_type;
  101.                     }
  102.                 }
  103.                 this.field.attributeFlags |= FieldAttributes.InitOnly;
  104.                 set_field_type:
  105.                 if (this.field.type == null)
  106.                     this.field.type = new TypeExpression(new ConstantWrapper(this.value.InferType(null), null));
  107.             }
  108.             else {
  109.                 this.value = new ConstantWrapper(null, this.context);
  110.                 this.field.attributeFlags |= FieldAttributes.InitOnly;
  111.             }
  112.             // deal with custom attributes
  113.             if (this.field != null && this.field.customAttributes != null)
  114.                 this.field.customAttributes.PartiallyEvaluate();
  115.             return this;
  116.         }
  117.        
  118.         internal override void TranslateToIL(ILGenerator il, Type rtype)
  119.         {
  120.             if ((this.field.attributeFlags & FieldAttributes.Literal) != 0) {
  121.                 object val = this.field.value;
  122.                 if (val is Type || val is ClassScope || val is TypedArray) {
  123.                     this.field.attributeFlags &= ~FieldAttributes.Literal;
  124.                     this.identifier.TranslateToILPreSet(il);
  125.                     this.identifier.TranslateToILSet(il, new ConstantWrapper(val, null));
  126.                     this.field.attributeFlags |= FieldAttributes.Literal;
  127.                 }
  128.             }
  129.             else {
  130.                 if (!this.field.IsStatic) {
  131.                     FieldBuilder fb = this.valueField = this.field.metaData as FieldBuilder;
  132.                     if (fb != null)
  133.                         this.field.metaData = ((TypeBuilder)fb.DeclaringType).DefineField(this.name + " value", this.field.type.ToType(), FieldAttributes.Private);
  134.                 }
  135.                 this.field.attributeFlags &= ~FieldAttributes.InitOnly;
  136.                 this.identifier.TranslateToILPreSet(il);
  137.                 this.identifier.TranslateToILSet(il, this.value);
  138.                 this.field.attributeFlags |= FieldAttributes.InitOnly;
  139.             }
  140.         }
  141.        
  142.         internal void TranslateToILInitOnlyInitializers(ILGenerator il)
  143.         {
  144.             FieldBuilder fb = this.valueField;
  145.             if (fb != null) {
  146.                 il.Emit(OpCodes.Ldarg_0);
  147.                 il.Emit(OpCodes.Dup);
  148.                 il.Emit(OpCodes.Ldfld, (FieldBuilder)this.field.metaData);
  149.                 il.Emit(OpCodes.Stfld, fb);
  150.                 this.valueField = (FieldBuilder)this.field.metaData;
  151.                 this.field.metaData = fb;
  152.             }
  153.         }
  154.        
  155.         internal override void TranslateToILInitializer(ILGenerator il)
  156.         {
  157.             if (this.value != null)
  158.                 this.value.TranslateToILInitializer(il);
  159.         }
  160.        
  161.     }
  162. }

Developer Fusion