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

  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 Microsoft.JScript.Vsa;
  19.     using System;
  20.     using System.Reflection;
  21.     using System.Reflection.Emit;
  22.    
  23.     internal sealed class CallableExpression : Binding
  24.     {
  25.         internal AST expression;
  26.         private IReflect expressionInferredType;
  27.        
  28.         internal CallableExpression(AST expression) : base(expression.context, "")
  29.         {
  30.             this.expression = expression;
  31.             JSLocalField field = new JSLocalField("", null, 0, Missing.Value);
  32.             this.expressionInferredType = expression.InferType(field);
  33.             field.inferred_type = this.expressionInferredType;
  34.             this.member = field;
  35.             this.members = new MemberInfo[] {field};
  36.         }
  37.        
  38.         internal override LateBinding EvaluateAsLateBinding()
  39.         {
  40.             return new LateBinding(null, this.expression.Evaluate(), VsaEngine.executeForJSEE);
  41.         }
  42.        
  43.         protected override object GetObject()
  44.         {
  45.             return this.GetObject2();
  46.         }
  47.        
  48.         internal object GetObject2()
  49.         {
  50.             Call c = this.expression as Call;
  51.             if (c == null || !c.inBrackets)
  52.                 return Convert.ToObject(this.expression.Evaluate(), this.Engine);
  53.             else
  54.                 return Convert.ToObject(c.func.Evaluate(), this.Engine);
  55.         }
  56.        
  57.         protected override void HandleNoSuchMemberError()
  58.         {
  59.             throw new JScriptException(JSError.InternalError, this.context);
  60.         }
  61.        
  62.         internal override AST PartiallyEvaluate()
  63.         {
  64.             return this;
  65.         }
  66.        
  67.         //Called when there is an early binding to default members on rtype
  68.         internal override void TranslateToIL(ILGenerator il, Type rtype)
  69.         {
  70.             this.expression.TranslateToIL(il, rtype);
  71.         }
  72.        
  73.         internal override void TranslateToILCall(ILGenerator il, Type rtype, ASTList argList, bool construct, bool brackets)
  74.         {
  75.             if (this.defaultMember != null && construct && brackets) {
  76.                 base.TranslateToILCall(il, rtype, argList, construct, brackets);
  77.                 return;
  78.             }
  79.             JSGlobalField gf = this.member as JSGlobalField;
  80.             if (gf != null && gf.IsLiteral && argList.count == 1) {
  81.                 Type t = Convert.ToType((IReflect)gf.value);
  82.                 argList[0].TranslateToIL(il, t);
  83.                 Convert.Emit(this, il, t, rtype);
  84.                 return;
  85.             }
  86.             this.TranslateToILWithDupOfThisOb(il);
  87.             argList.TranslateToIL(il, Typeob.ArrayOfObject);
  88.             if (construct)
  89.                 il.Emit(OpCodes.Ldc_I4_1);
  90.             else
  91.                 il.Emit(OpCodes.Ldc_I4_0);
  92.             if (brackets)
  93.                 il.Emit(OpCodes.Ldc_I4_1);
  94.             else
  95.                 il.Emit(OpCodes.Ldc_I4_0);
  96.             this.EmitILToLoadEngine(il);
  97.             il.Emit(OpCodes.Call, CompilerGlobals.callValueMethod);
  98.             Convert.Emit(this, il, Typeob.Object, rtype);
  99.         }
  100.        
  101.        
  102.         protected override void TranslateToILObject(ILGenerator il, Type obType, bool noValue)
  103.         {
  104.             this.EmitILToLoadEngine(il);
  105.             il.Emit(OpCodes.Call, CompilerGlobals.scriptObjectStackTopMethod);
  106.             il.Emit(OpCodes.Castclass, Typeob.IActivationObject);
  107.             il.Emit(OpCodes.Callvirt, CompilerGlobals.getGlobalScopeMethod);
  108.         }
  109.        
  110.         //Called when a late bound call is being made
  111.         protected override void TranslateToILWithDupOfThisOb(ILGenerator il)
  112.         {
  113.             Call c = this.expression as Call;
  114.             if (c == null || !c.inBrackets)
  115.                 this.TranslateToILObject(il, null, false);
  116.             else if (c.isConstructor && c.inBrackets) {
  117.                 //Dealing with (new T[x])[..] or (new T[x])(...), being handled late bound because it is an edge case
  118.                 c.TranslateToIL(il, Typeob.Object);
  119.                 il.Emit(OpCodes.Dup);
  120.                 return;
  121.             }
  122.             else
  123.                 c.func.TranslateToIL(il, Typeob.Object);
  124.             this.expression.TranslateToIL(il, Typeob.Object);
  125.         }
  126.        
  127.         internal override void TranslateToILInitializer(ILGenerator il)
  128.         {
  129.             this.expression.TranslateToILInitializer(il);
  130.             if (!this.expressionInferredType.Equals(this.expression.InferType(null))) {
  131.                 MemberInfo[] savedMembers = this.members;
  132.                 this.InvalidateBinding();
  133.                 this.members = savedMembers;
  134.             }
  135.         }
  136.     }
  137. }

Developer Fusion