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

  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 VariableDeclaration : AST
  23.     {
  24.         internal Lookup identifier;
  25.         private TypeExpression type;
  26.         internal AST initializer;
  27.         internal JSVariableField field;
  28.         private Completion completion;
  29.        
  30.         internal VariableDeclaration(Context context, Lookup identifier, TypeExpression type, AST initializer, FieldAttributes attributes, CustomAttributeList customAttributes) : base(context)
  31.         {
  32.             if (initializer != null)
  33.                 this.context.UpdateWith(initializer.context);
  34.             else if (type != null)
  35.                 this.context.UpdateWith(type.context);
  36.             this.identifier = identifier;
  37.             this.type = type;
  38.             this.initializer = initializer;
  39.             ScriptObject current_scope = (ScriptObject)Globals.ScopeStack.Peek();
  40.             while (current_scope is WithObject)
  41.                 //Can only happen at run time and only if there is an eval
  42.                 current_scope = current_scope.GetParent();
  43.             string name = this.identifier.ToString();
  44.             if (current_scope is ClassScope) {
  45.                 if (name == ((ClassScope)current_scope).name) {
  46.                     identifier.context.HandleError(JSError.CannotUseNameOfClass);
  47.                     name = name + " var";
  48.                 }
  49.             }
  50.             else {
  51.                 if (attributes != (FieldAttributes)0) {
  52.                     this.context.HandleError(JSError.NotInsideClass);
  53.                     attributes = FieldAttributes.Public;
  54.                 }
  55.                 else
  56.                     attributes |= FieldAttributes.Public;
  57.             }
  58.             FieldInfo field = ((IActivationObject)current_scope).GetLocalField(name);
  59.             if (field != null) {
  60.                 if (field.IsLiteral || current_scope is ClassScope || type != null)
  61.                     identifier.context.HandleError(JSError.DuplicateName, true);
  62.                 this.type = type = null;
  63.             }
  64.             if (current_scope is ActivationObject)
  65.                 if (field == null || field is JSVariableField)
  66.                     this.field = ((ActivationObject)current_scope).AddFieldOrUseExistingField(this.identifier.ToString(), Missing.Value, attributes);
  67.                 else
  68.                     this.field = ((ActivationObject)current_scope).AddNewField(this.identifier.ToString(), null, attributes);
  69.             else
  70.                 this.field = ((StackFrame)current_scope).AddNewField(this.identifier.ToString(), null, attributes | FieldAttributes.Static);
  71.             this.field.type = type;
  72.             this.field.customAttributes = customAttributes;
  73.             this.field.originalContext = context;
  74.             if (this.field is JSLocalField)
  75.                 // emit debug info for the local only if this block of code is in a section that has debug set
  76.                 ((JSLocalField)this.field).debugOn = this.identifier.context.document.debugOn;
  77.             this.completion = new Completion();
  78.         }
  79.        
  80.         internal override object Evaluate()
  81.         {
  82.             ScriptObject scope = Globals.ScopeStack.Peek();
  83.             object value = null;
  84.             if (this.initializer != null)
  85.                 value = this.initializer.Evaluate();
  86.             if (this.type != null)
  87.                 value = Convert.Coerce(value, this.type);
  88.             else {
  89.                 while (scope is BlockScope)
  90.                     scope = scope.GetParent();
  91.                 if (scope is WithObject)
  92.                     this.identifier.SetWithValue((WithObject)scope, value);
  93.                 while (scope is WithObject || scope is BlockScope)
  94.                     scope = scope.GetParent();
  95.                 if (this.initializer == null && !(this.field.value is Missing)) {
  96.                     this.completion.value = this.field.value;
  97.                     return this.completion;
  98.                 }
  99.             }
  100.             this.field.SetValue(scope, this.completion.value = value);
  101.             return this.completion;
  102.         }
  103.        
  104.         internal override AST PartiallyEvaluate()
  105.         {
  106.             AST id = this.identifier = (Lookup)this.identifier.PartiallyEvaluateAsReference();
  107.             if (this.type != null)
  108.                 this.field.type = this.type = (TypeExpression)this.type.PartiallyEvaluate();
  109.             else if (this.initializer == null && !(this.field is JSLocalField) && this.field.value is Missing) {
  110.                 id.context.HandleError(JSError.VariableLeftUninitialized);
  111.                 this.field.type = this.type = new TypeExpression(new ConstantWrapper(Typeob.Object, id.context));
  112.             }
  113.             if (this.initializer != null) {
  114.                 if (this.field.IsStatic) {
  115.                     ScriptObject scope = this.Engine.ScriptObjectStackTop();
  116.                     ClassScope cscope = null;
  117.                     while (scope != null && (cscope = scope as ClassScope) == null)
  118.                         scope = scope.GetParent();
  119.                     if (cscope != null)
  120.                         cscope.inStaticInitializerCode = true;
  121.                     this.initializer = this.initializer.PartiallyEvaluate();
  122.                     if (cscope != null)
  123.                         cscope.inStaticInitializerCode = false;
  124.                 }
  125.                 else
  126.                     this.initializer = this.initializer.PartiallyEvaluate();
  127.                 id.SetPartialValue(this.initializer);
  128.             }
  129.             // deal with custom attributes
  130.             if (this.field != null && this.field.customAttributes != null)
  131.                 this.field.customAttributes.PartiallyEvaluate();
  132.             return this;
  133.         }
  134.        
  135.         internal override void TranslateToIL(ILGenerator il, Type rtype)
  136.         {
  137.             //This assumes that rtype == Void.class
  138.            
  139.             //If the initializer is missing. Do nothing, we're done.
  140.             if (this.initializer == null)
  141.                 return;
  142.            
  143.             // this.initializer.context can be null when a default initializer is forced in the variable (i.e. for_in case)
  144.             if (this.context.document.debugOn && this.initializer.context != null)
  145.                 this.context.EmitLineInfo(il);
  146.            
  147.             Lookup id = (Lookup)this.identifier;
  148.             id.TranslateToILPreSet(il, true);
  149.             id.TranslateToILSet(il, true, this.initializer);
  150.         }
  151.        
  152.         internal override void TranslateToILInitializer(ILGenerator il)
  153.         {
  154.             if (this.type != null)
  155.                 this.type.TranslateToILInitializer(il);
  156.             if (this.initializer != null)
  157.                 this.initializer.TranslateToILInitializer(il);
  158.         }
  159.        
  160.         internal override Context GetFirstExecutableContext()
  161.         {
  162.             if (this.initializer == null)
  163.                 return null;
  164.             else
  165.                 return this.context;
  166.         }
  167.        
  168.        
  169.     }
  170. }

Developer Fusion