/// <summary>
        /// Checks for less-than-visible member references in an expression.
        /// </summary>
        public override void VisitMemberBinding(MemberBinding binding)
        {
            if (binding == null) return;

            Member mem = binding.BoundMember;
            if (mem != null)
            {
                // Member visiting includes also all attributes for the method.
                // But from Code Contracts perspective public method can have less visible attributes
                // because they're not part of the precondition.
                if (IsAttribute(mem.DeclaringType)) return;

                Field f = mem as Field;
                bool specPublic = false;

                if (f != null)
                {
                    specPublic = IsSpecPublic(f);
                }
                
                if (!specPublic && !HelperMethods.IsCompilerGenerated(mem))
                {
                    // F: It seems there is some type-state like invariant here justifying why this.AsThisMemeber != null
                    Contract.Assume(this.AsThisMember != null);
                    
                    if (!HelperMethods.IsReferenceAsVisibleAs(mem, this.AsThisMember))
                    {
                        this.memberInErrorFound = mem;
                        return;
                    }
                }
            }

            base.VisitMemberBinding(binding);
        }
        /// <summary>
        /// Checks for less-than-visible member references in an expression.
        /// </summary>
        public override void VisitMemberBinding(MemberBinding binding)
        {
            if (binding == null) return;

            Member mem = binding.BoundMember;
            if (mem != null)
            {
                Field f = mem as Field;
                bool specPublic = false;

                if (f != null)
                {
                    specPublic = IsSpecPublic(f);
                }
                
                if (!specPublic && !HelperMethods.IsCompilerGenerated(mem))
                {
                    // F: It seems there is some type-state like invariant here justifying why this.AsThisMemeber != null
                    Contract.Assume(this.AsThisMember != null);
                    
                    if (!HelperMethods.IsReferenceAsVisibleAs(mem, this.AsThisMember))
                    {
                        this.memberInErrorFound = mem;
                        return;
                    }
                }
            }

            base.VisitMemberBinding(binding);
        }
        public override void VisitMemberBinding(MemberBinding memberBinding)
        {
            if (memberBinding.BoundMember != null)
            {
                if (HelperMethods.HasAttribute(memberBinding.BoundMember.Attributes, this.attributeToFind))
                {
                    this.foundAttribute = true;
                    return;
                }

                if (referencingType.Count > 0 &&
                    !HelperMethods.IsVisibleFrom(memberBinding.BoundMember, this.referencingType.Peek()))
                {
                    this.generatedMethodContainsInvisibleMemberReference = true;
                    this.foundAttribute = true;
                    return;
                }

                Method referencedMethod = HelperMethods.Unspecialize(memberBinding.BoundMember as Method);
                if (referencedMethod != null)
                {
                    if (HasAttribute(referencedMethod))
                    {
                        this.foundAttribute = true;
                        return;
                    }

                    if (this.skipQuantifiers &&
                        (this.contractNodes.IsForallMethod(referencedMethod) ||
                         this.contractNodes.IsGenericForallMethod(referencedMethod) ||
                         this.contractNodes.IsExistsMethod(referencedMethod) ||
                         this.contractNodes.IsGenericExistsMethod(referencedMethod))
                        )
                    {
                        this.foundAttribute = true;
                        return;
                    }

                    // check if we deal with a contract method on an interface/abstract method that is annotated
                    var origType = HelperMethods.IsContractTypeForSomeOtherTypeUnspecialized(referencedMethod.DeclaringType, this.contractNodes);
                    
                    if (origType != null)
                    {
                        var origMethod = HelperMethods.FindImplementedMethodSpecialized(origType, referencedMethod);
                        if (HasAttribute(origMethod))
                        {
                            this.foundAttribute = true;
                            return;
                        }
                    }
                }
            }

            base.VisitMemberBinding(memberBinding);
        }
 public override Expression VisitMemberBinding(MemberBinding memberBinding)
 {
     Local closureLocal;
     if (memberBinding.TargetObject != null &&
         this.closureLocals.TryGetValue(memberBinding.TargetObject.Type, out closureLocal))
     {
         return new MemberBinding(closureLocal, memberBinding.BoundMember);
     }
     
     return base.VisitMemberBinding(memberBinding);
 }
        public override void VisitMemberBinding(MemberBinding memberBinding)
        {
            if (memberBinding == null) return;

            base.VisitMemberBinding(memberBinding);

            var member = memberBinding.BoundMember;
            if (member == null) return;

            Contract.Assume(member.DeclaringType != null, "top-level types should not be memberbound");

            var declaringType = HelperMethods.Unspecialize(member.DeclaringType);
            if (declaringType == contractClass)
            {
                // must reroute
                Method method = member as Method;
                if (method != null)
                {
                    if (HelperMethods.IsClosureMethod(this.contractClass, HelperMethods.Unspecialize(method))) return;

                    var template = method.Template;

                    if (method.IsGeneric && template != null)
                    {
                        Method targetTemplate = HelperMethods.FindImplementedMethodSpecialized(this.OriginalType, template);
                        if (targetTemplate != null)
                        {
                            var target = targetTemplate.GetTemplateInstance(this.OriginalType, method.TemplateArguments);
                            memberBinding.BoundMember = target;
                            return;
                        }
                    }
                    else
                    {
                        Method target = HelperMethods.FindImplementedMethodSpecialized(this.OriginalType, method);
                        if (target != null)
                        {
                            memberBinding.BoundMember = target;
                            return;
                        }
                    }

                    // couldn't find target: must issue error
                    parent.HandleError(this.currentMethod, 1075,
                        string.Format(
                            "Contract class '{0}' references member '{1}' which is not part of the abstract class/interface being annotated.",
                            this.contractClass.FullName, member.FullName), currentSourceContext);
                }
            }
        }
        public override Expression VisitMemberBinding(MemberBinding memberBinding)
        {
            if (memberBinding.TargetObject != null &&
                (memberBinding.TargetObject.NodeType == NodeType.This
                 || memberBinding.TargetObject.NodeType == NodeType.Local))
            {
                // search in list of parameters to see if any have the same name as the bound member
                foreach (Parameter p in this.parameters)
                {
                    if (p.Name.UniqueIdKey == memberBinding.BoundMember.Name.UniqueIdKey)
                    {
                        return (Expression) this.map[p.UniqueKey];
                    }
                }

                return base.VisitMemberBinding(memberBinding);
            }
            
            return base.VisitMemberBinding(memberBinding);
        }
        public override void VisitMemberBinding(MemberBinding memberBinding)
        {
            if (memberBinding == null) return;

            if (memberBinding.TargetObject.NodeType == NodeType.This
                || memberBinding.TargetObject.NodeType == NodeType.Local)
            {
                // search in list of parameters to see if any have the same name as the bound member
                foreach (Parameter p in this.BoundVars)
                {
                    if (p.Name.UniqueIdKey == memberBinding.BoundMember.Name.UniqueIdKey)
                    {
                        if (!this.FoundVariables.Contains(p))
                        {
                            this.FoundVariables.Add(p);
                            this.FoundReferences.Add(memberBinding);
                        }
                    }
                }
            }

            base.VisitMemberBinding(memberBinding);
        }
            public override void VisitMemberBinding(MemberBinding memberBinding)
            {
                if (memberBinding == null) return;

                var method = TemplateOrMethod(memberBinding.BoundMember as Method);
                
                if (usedToExtract.IsInvariantMethod(method))
                {
                    // indicates invariant use inside a method not marked by ObjectInvariantAttribute
                    // F: Added the assumption, is it always true???
                    Contract.Assume(this.CurrentMethod != null);

                    var containingMethodName = this.CurrentMethod.FullName;
                    
                    this.errorHandler(new Error(1022,
                        string.Format("Bad use of method 'Contract.Invariant' in method body '{0}'",
                            containingMethodName), lastSC));
                    
                    return;
                }

                base.VisitMemberBinding(memberBinding);
            }
Exemple #9
0
 public override Expression VisitMemberBinding(MemberBinding memberBinding)
 {
     Expression result = base.VisitMemberBinding(memberBinding);
     return result;
 }
Exemple #10
0
 MemberBinding GetMemberBinding(Expression source, Member m) {
   MemberBinding src = new MemberBinding(source, m);
   src.Type = Checker.GetMemberType(m);
   return src;
 }
Exemple #11
0
    internal Class CreateSerializerFor(TypeNode type) {
      // todo: look in the genCache for other serializer assemblies that may have already
      // created the serializer for this type and make an assembly reference to that 
      // serializer instead of creating a complete duplicate.
      TypeNode saved = tempChecker.currentType;

      Class c = (Class)serializers[type];
      if (c != null) return c;
      c = new Class();      
      c.Flags = TypeFlags.Class | TypeFlags.BeforeFieldInit;
      // copy the accessibility of the type we are serializing.
      c.Flags |= (type.Flags & (TypeFlags.Public | TypeFlags.NestedAssembly));
      c.Name = Identifier.For(GetSerializerName(type));
      c.Namespace = Identifier.For(GetSerializerNamespace(type));
      c.DeclaringModule = this.module;
      c.Members = new MemberList();
      c.Attributes = new AttributeList();
      c.BaseClass = Runtime.XmlSerializer;
      tempChecker.currentType = c;

      InstanceInitializer ii = Runtime.XmlSerializerAttribute.GetConstructor();
      MemberBinding mb = new MemberBinding(null, ii);
      mb.Type = Runtime.XmlSerializerAttribute;
      c.Attributes.Add(new AttributeNode(mb, null));
      if (cunit != null) {
        cunit.Namespaces[0].Types.Add(c);
      }
      this.module.Types.Add(c);

      Identifier typeId = Identifier.For("type"); // what we are writing to.
      Identifier rootName = Identifier.For("rootName"); // what we are writing to.
      Identifier rootNamespace = Identifier.For("rootNamespace"); // what we are writing to.

      // Constructor
      Method constructor = new InstanceInitializer();
      constructor.Name = StandardIds.Ctor;
      constructor.DeclaringType = c;
      constructor.Flags = MethodFlags.Public|MethodFlags.HideBySig|MethodFlags.SpecialName|MethodFlags.RTSpecialName;
      constructor.Parameters = new ParameterList();
      constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, typeId, SystemTypes.Type, null, null));
      constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootName, SystemTypes.String, null, null));
      constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootNamespace, SystemTypes.String, null, null));
      constructor.ReturnType = SystemTypes.Void;
      c.Members.Add(constructor);

      // pass args thru to base XmlSerializer constructor.
      Block b = constructor.Body = new Block(new StatementList());
      b.Statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(new Base(), StandardIds.Ctor), 
        new ExpressionList(typeId, rootName, rootNamespace), NodeType.Call)));      
      //AddConsoleWrite(b.Statements, new Literal("Hello!!",SystemTypes.String));

      // Serialize(T source, XmlSerializationWriter writer) method
      Identifier src = Identifier.For("source"); // object being serialized.
      Identifier writer = Identifier.For("writer"); // what we are writing to.

      Method serialize = new Method();
      serialize.Name = Identifier.For("Serialize");        
      serialize.DeclaringType = c;
      serialize.Flags = MethodFlags.Public|MethodFlags.Static|MethodFlags.HideBySig;
      serialize.Parameters = new ParameterList();
      serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, src, type, null, null));
      serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, writer, Runtime.XmlSerializationWriter, null, null));
      serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootName, SystemTypes.String, null, null));
      serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootNamespace, SystemTypes.String, null, null));
      serialize.ReturnType = SystemTypes.Void;
      c.Members.Add(serialize);

      // T Deserialize(XmlReader reader, bool required, out bool result) method
      Identifier reader = Identifier.For("reader"); // what we are reading from.
      Identifier required = Identifier.For("required"); // whether an object is required or not.
      Identifier result = Identifier.For("result"); // whether we found anything.

      Method deserialize = new Method();
      deserialize.Name = Identifier.For("Deserialize");        
      deserialize.DeclaringType = c;
      deserialize.Flags = MethodFlags.Public|MethodFlags.Static|MethodFlags.HideBySig;
      deserialize.Parameters = new ParameterList();
      deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, reader, Runtime.XmlSerializationReader, null, null));
      deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, required, SystemTypes.Boolean, null, null));
      deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.Out, result, SystemTypes.Boolean.GetReferenceType(), null, null));
      deserialize.ReturnType = type;
      c.Members.Add(deserialize);

      // It is important that we add the serializer to the cache AFTER we create the methods, but 
      // BEFORE we create the method bodies so that we can handle recurrsive calls to AddCallSerializer which
      // happens in recurrsive structures like "class Foo { public Foo f; }".  Otherwise we'd get stuck in an
      // infinite loop.
      serializers[type] = c;

      // Body of serialize method.
      b = serialize.Body = new Block(new StatementList());
      StatementList statements = b.Statements;
      
      if (!AddWriteSimpleType(type, statements, c, writer, src, rootName, rootNamespace)) {
        MethodCall call = new MethodCall();
        call.Callee = new QualifiedIdentifier(writer,Identifier.For("WriteStartElement"));
        call.Operands = new ExpressionList();
        call.Operands.Add(rootName);
        call.Operands.Add(rootNamespace);
        statements.Add(new If(new BinaryExpression(rootName,Literal.Null,NodeType.Ne),
          new Block(new StatementList(new ExpressionStatement(call))),null));

        Expression source = src;

        if (type.Template == SystemTypes.GenericBoxed) {
          statements = AddCheckForNull(statements, Duplicate(src, c), type);
          type = Checker.GetCollectionElementType(type); 
          source = CastTo(src, type);//unbox it
        }

        if (type is TupleType) {
          AddWriteTuple(type as TupleType, statements, c, source, writer);
        } else if (type is TypeUnion) {
          AddWriteChoice(type as TypeUnion, statements, c, source, writer);
        } else if (IsStream(type)) {
          AddWriteStream(type, statements, c, source, writer);
        } else {
          SchemaElementDecl sd = SchemaElementDecl.Compile(this.module, type, Checker.GetCollectionElementType(type), this.errorHandler, schemaElementDeclCache);
          SchemaValidator validator = validator = sd.CreateValidator(this.errorHandler);      
          statements = AddCheckForNull(statements, Duplicate(src, c), type);
          AddWriteAttributes(statements, c, writer, source, validator);
          AddWriteContent(type, statements, c, writer, source, validator);        
        }
        call = new MethodCall();
        call.Callee = new QualifiedIdentifier(writer,Identifier.For("WriteEndElement"));
        call.Operands = new ExpressionList();
        statements.Add(new If(new BinaryExpression(rootName,Literal.Null,NodeType.Ne),
          new Block(new StatementList(new ExpressionStatement(call))),null));
      }
      // body of deserialize method.
      b = deserialize.Body = new Block(new StatementList());
      statements = b.Statements;

      Local target = new Local(Identifier.Empty, type);

      if (type.Template == SystemTypes.GenericBoxed){
        type = Checker.GetCollectionElementType(type);
      }

      if (type is TupleType) {
        AddReadTuple(b, type as TupleType, statements, reader, target, required, result);
      } else if (type is TypeUnion) {
        AddReadChoice(b, type as TypeUnion, statements, reader, target, required, result);
      } else if (IsStream(type)) {
        AddReadStream(b, type, statements, reader, target, result);
      } else {
        if (type is TypeAlias) {
          type = ((TypeAlias)type).AliasedType;
        }

        // Then we are already positioned on the element to be deserialized. 
        statements.Add(new AssignmentStatement(required, Literal.True));
        if (!AddReadSimpleType(type, statements, reader, target, result, false)) {
          if (!type.IsValueType && !type.IsAbstract && type.GetConstructor() != null) {
            Construct cons = new Construct(new MemberBinding(null, type), new ExpressionList(), type);
            statements.Add(new AssignmentStatement(target, cons));
          }
          SchemaElementDecl sd = SchemaElementDecl.Compile(this.module, type, Checker.GetCollectionElementType(type), this.errorHandler, schemaElementDeclCache);
          SchemaValidator validator = validator = sd.CreateValidator(this.errorHandler);      
          AddReadAttributes(type, statements, reader, target, validator);
          AddReadContent(c, b, type, statements, reader, target, required, result, validator);
        }
      }
      statements.Add(new Return(target));
      tempChecker.currentType = saved;
      return c;
    }
Exemple #12
0
    private bool ParseStatement(Block/*!*/ block) {
      //parse instructions and put in expression tree until an assignment, void call, branch target, or branch is encountered
      StatementList statementList = block.Statements;
      Expression expr = null;
      Statement statement = null;
      bool transferStatement = false;
      int startingAddress = 0;
#if !FxCop
      SourceContext sourceContext = new SourceContext();
      sourceContext.StartPos = this.counter;
#endif
#if !ROTOR
      if (this.method.contextForOffset != null){
        object sctx = this.method.contextForOffset[this.counter+1];
        if (sctx != null) sourceContext = (SourceContext)sctx;
      }
#endif
      while (true){
        bool isStatement = false;
        startingAddress = this.counter+1; //Add one so that it is never zero (the latter means no entry to the TrivialHashtable)
#if FxCop || ILOFFSETS
        this.ilOffset = this.counter;
        this.opCode = this.GetOpCode();
#else
        OpCode opCode = this.GetOpCode();
#endif
#if FxCop
        if (this.handlerMap.TryGetValue(this.ilOffset, out expr)){
          expr.sourceContext = sourceContext;
          expr.ILOffset = this.ilOffset;
          this.operandStack.Push(expr);
        }
#endif
        switch (opCode){
          case OpCode.Nop: statement = new Statement(NodeType.Nop); goto done;
          case OpCode.Break: statement = new Statement(NodeType.DebugBreak); goto done;
          case OpCode.Ldarg_0: expr = this.Parameters(0); break;
          case OpCode.Ldarg_1: expr = this.Parameters(1); break;
          case OpCode.Ldarg_2: expr = this.Parameters(2); break;
          case OpCode.Ldarg_3: expr = this.Parameters(3); break;
          case OpCode.Ldloc_0: expr = this.locals[0]; break;
          case OpCode.Ldloc_1: expr = this.locals[1]; break;
          case OpCode.Ldloc_2: expr = this.locals[2]; break;
          case OpCode.Ldloc_3: expr = this.locals[3]; break;
          case OpCode.Stloc_0: statement = new AssignmentStatement(this.locals[0], PopOperand()); goto done;
          case OpCode.Stloc_1: statement = new AssignmentStatement(this.locals[1], PopOperand()); goto done;
          case OpCode.Stloc_2: statement = new AssignmentStatement(this.locals[2], PopOperand()); goto done;
          case OpCode.Stloc_3: statement = new AssignmentStatement(this.locals[3], PopOperand()); goto done;
          case OpCode.Ldarg_S: expr = this.Parameters(this.GetByte()); break;
          case OpCode.Ldarga_S: expr = SetType(new UnaryExpression(this.Parameters(this.GetByte()), NodeType.AddressOf)); break;
          case OpCode.Starg_S: statement = new AssignmentStatement(this.Parameters(this.GetByte()), PopOperand()); goto done;
          case OpCode.Ldloc_S: expr = this.locals[this.GetByte()]; break;
          case OpCode.Ldloca_S: expr = SetType(new UnaryExpression(this.locals[this.GetByte()], NodeType.AddressOf)); break;
          case OpCode.Stloc_S: statement = new AssignmentStatement(this.locals[this.GetByte()], PopOperand()); goto done;
          case OpCode.Ldnull: expr = new Literal(null, CoreSystemTypes.Object); break;
          case OpCode.Ldc_I4_M1: expr = new Literal(-1, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_0: expr = new Literal(0, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_1: expr = new Literal(1, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_2: expr = new Literal(2, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_3: expr = new Literal(3, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_4: expr = new Literal(4, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_5: expr = new Literal(5, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_6: expr = new Literal(6, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_7: expr = new Literal(7, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_8: expr = new Literal(8, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_S: expr = new Literal((int)this.GetSByte(), CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4: expr = new Literal(this.GetInt32(), CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I8: expr = new Literal(this.GetInt64(), CoreSystemTypes.Int64); break;
          case OpCode.Ldc_R4: expr = new Literal(this.GetSingle(), CoreSystemTypes.Single); break;
          case OpCode.Ldc_R8: expr = new Literal(this.GetDouble(), CoreSystemTypes.Double); break;
          case OpCode.Dup: statement = new ExpressionStatement(new Expression(NodeType.Dup)); goto done;
          case OpCode.Pop: statement = new ExpressionStatement(new UnaryExpression(PopOperand(), NodeType.Pop)); goto done;
          case OpCode.Jmp: expr = this.ParseCall(NodeType.Jmp, out isStatement); if (isStatement) goto done; break;
          case OpCode.Call: expr = this.ParseCall(NodeType.Call, out isStatement); if (isStatement) goto done; break;
          case OpCode.Calli: expr = this.ParseCalli(out isStatement); if (isStatement) goto done; break;
          case OpCode.Ret:
            Expression retVal = BodyParser.TypeIsVoid(this.method.ReturnType) ? null : PopOperand();
            statement = new Return(retVal); 
            transferStatement = true; goto done;
          case OpCode.Br_S: statement = this.ParseBranch(NodeType.Nop, 0, true, false); transferStatement = true; goto done;
          case OpCode.Brfalse_S: statement = this.ParseBranch(NodeType.LogicalNot, 1, true, false); transferStatement = true; goto done;
          case OpCode.Brtrue_S: statement = this.ParseBranch(NodeType.Nop, 1, true, false); transferStatement = true; goto done;
          case OpCode.Beq_S: statement = this.ParseBranch(NodeType.Eq, 2, true, false); transferStatement = true; goto done;
          case OpCode.Bge_S: statement = this.ParseBranch(NodeType.Ge, 2, true, false); transferStatement = true; goto done;
          case OpCode.Bgt_S: statement = this.ParseBranch(NodeType.Gt, 2, true, false); transferStatement = true; goto done;
          case OpCode.Ble_S: statement = this.ParseBranch(NodeType.Le, 2, true, false); transferStatement = true; goto done;
          case OpCode.Blt_S: statement = this.ParseBranch(NodeType.Lt, 2, true, false); transferStatement = true; goto done;
          case OpCode.Bne_Un_S: statement = this.ParseBranch(NodeType.Ne, 2, true, true); transferStatement = true; goto done;
          case OpCode.Bge_Un_S: statement = this.ParseBranch(NodeType.Ge, 2, true, true); transferStatement = true; goto done;
          case OpCode.Bgt_Un_S: statement = this.ParseBranch(NodeType.Gt, 2, true, true); transferStatement = true; goto done;
          case OpCode.Ble_Un_S: statement = this.ParseBranch(NodeType.Le, 2, true, true); transferStatement = true; goto done;
          case OpCode.Blt_Un_S: statement = this.ParseBranch(NodeType.Lt, 2, true, true); transferStatement = true; goto done;
          case OpCode.Br: statement = this.ParseBranch(NodeType.Nop, 0, false, false); transferStatement = true; goto done;
          case OpCode.Brfalse: statement = this.ParseBranch(NodeType.LogicalNot, 1, false, false); transferStatement = true; goto done;
          case OpCode.Brtrue: statement = this.ParseBranch(NodeType.Nop, 1, false, false); transferStatement = true; goto done;
          case OpCode.Beq: statement = this.ParseBranch(NodeType.Eq, 2, false, false); transferStatement = true; goto done;
          case OpCode.Bge: statement = this.ParseBranch(NodeType.Ge, 2, false, false); transferStatement = true; goto done;
          case OpCode.Bgt: statement = this.ParseBranch(NodeType.Gt, 2, false, false); transferStatement = true; goto done;
          case OpCode.Ble: statement = this.ParseBranch(NodeType.Le, 2, false, false); transferStatement = true; goto done;
          case OpCode.Blt: statement = this.ParseBranch(NodeType.Lt, 2, false, false); transferStatement = true; goto done;
          case OpCode.Bne_Un: statement = this.ParseBranch(NodeType.Ne, 2, false, true); transferStatement = true; goto done;
          case OpCode.Bge_Un: statement = this.ParseBranch(NodeType.Ge, 2, false, true); transferStatement = true; goto done;
          case OpCode.Bgt_Un: statement = this.ParseBranch(NodeType.Gt, 2, false, true); transferStatement = true; goto done;
          case OpCode.Ble_Un: statement = this.ParseBranch(NodeType.Le, 2, false, true); transferStatement = true; goto done;
          case OpCode.Blt_Un: statement = this.ParseBranch(NodeType.Lt, 2, false, true); transferStatement = true; goto done;
          case OpCode.Switch: statement = this.ParseSwitchInstruction(); transferStatement = true; goto done;
          case OpCode.Ldind_I1: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int8, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_U1: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt8, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_I2: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int16, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_U2: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt16, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_I4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int32, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_U4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt32, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_I8: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int64, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_I: expr = new AddressDereference(PopOperand(), CoreSystemTypes.IntPtr, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_R4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Single, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_R8: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Double, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_Ref: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Object, this.isVolatile, this.alignment); break;
          case OpCode.Stind_Ref: statement = this.ParseStoreIndirect(CoreSystemTypes.Object); goto done;
          case OpCode.Stind_I1: statement = this.ParseStoreIndirect(CoreSystemTypes.Int8); goto done;
          case OpCode.Stind_I2: statement = this.ParseStoreIndirect(CoreSystemTypes.Int16); goto done;
          case OpCode.Stind_I4: statement = this.ParseStoreIndirect(CoreSystemTypes.Int32); goto done;
          case OpCode.Stind_I8: statement = this.ParseStoreIndirect(CoreSystemTypes.Int64); goto done;
          case OpCode.Stind_R4: statement = this.ParseStoreIndirect(CoreSystemTypes.Single); goto done;
          case OpCode.Stind_R8: statement = this.ParseStoreIndirect(CoreSystemTypes.Double); goto done;
          case OpCode.Add: expr = this.ParseBinaryOperation(NodeType.Add); break;
          case OpCode.Sub: expr = this.ParseBinaryOperation(NodeType.Sub); break;
          case OpCode.Mul: expr = this.ParseBinaryOperation(NodeType.Mul); break;
          case OpCode.Div: expr = this.ParseBinaryOperation(NodeType.Div); break;
          case OpCode.Div_Un: expr = this.ParseBinaryOperation(NodeType.Div_Un); break;
          case OpCode.Rem: expr = this.ParseBinaryOperation(NodeType.Rem); break;
          case OpCode.Rem_Un: expr = this.ParseBinaryOperation(NodeType.Rem_Un); break;
          case OpCode.And: expr = this.ParseBinaryOperation(NodeType.And); break;
          case OpCode.Or: expr = this.ParseBinaryOperation(NodeType.Or); break;
          case OpCode.Xor: expr = this.ParseBinaryOperation(NodeType.Xor); break;
          case OpCode.Shl: expr = this.ParseBinaryOperation(NodeType.Shl); break;
          case OpCode.Shr: expr = this.ParseBinaryOperation(NodeType.Shr); break;
          case OpCode.Shr_Un: expr = this.ParseBinaryOperation(NodeType.Shr_Un); break;
          case OpCode.Neg: expr = this.ParseUnaryOperation(NodeType.Neg); break;
          case OpCode.Not: expr = this.ParseUnaryOperation(NodeType.Not); break;
          case OpCode.Conv_I1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I1, CoreSystemTypes.Int8); break;
          case OpCode.Conv_I2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I2, CoreSystemTypes.Int16); break;
          case OpCode.Conv_I4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I4, CoreSystemTypes.Int32); break;
          case OpCode.Conv_I8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I8, CoreSystemTypes.Int64); break;
          case OpCode.Conv_R4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R4, CoreSystemTypes.Single); break;
          case OpCode.Conv_R8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R8, CoreSystemTypes.Double); break;
          case OpCode.Conv_U4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U4, CoreSystemTypes.UInt32); break;
          case OpCode.Conv_U8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U8, CoreSystemTypes.UInt64); break;
          case OpCode.Callvirt: expr = this.ParseCall(NodeType.Callvirt, out isStatement); if (isStatement) goto done; break;
          case OpCode.Cpobj: statement = this.ParseCopyObject(); goto done;
          case OpCode.Ldobj: expr = new AddressDereference(PopOperand(), (TypeNode)this.GetMemberFromToken(), this.isVolatile, this.alignment); break;
          case OpCode.Ldstr: expr = new Literal(this.GetStringFromToken(), CoreSystemTypes.String); break;
          case OpCode.Newobj: expr = this.ParseConstruct(); break;
          case OpCode.Castclass: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Castclass); break;
          case OpCode.Isinst: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Isinst); break;
          case OpCode.Conv_R_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R_Un, CoreSystemTypes.Double); break;
          case OpCode.Unbox: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Unbox); break;
          case OpCode.Throw: statement = new Throw(PopOperand()); transferStatement = true; goto done;
          case OpCode.Ldfld: 
            expr = new MemberBinding(PopOperand(), this.GetMemberFromToken(), this.isVolatile, this.alignment);
            break;
          case OpCode.Ldflda: 
            expr = SetType(new UnaryExpression(new MemberBinding(PopOperand(), this.GetMemberFromToken(), this.isVolatile, this.alignment), NodeType.AddressOf)); 
            break;
          case OpCode.Stfld: statement = this.ParseStoreField(); goto done;
          case OpCode.Ldsfld: expr = new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment); break;
          case OpCode.Ldsflda: expr = SetType(new UnaryExpression(new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment), NodeType.AddressOf)); break;
          case OpCode.Stsfld: statement = new AssignmentStatement(new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment), PopOperand()); goto done;
          case OpCode.Stobj: statement = this.ParseStoreIndirect((TypeNode)this.GetMemberFromToken()); goto done;
          case OpCode.Conv_Ovf_I1_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I1_Un, CoreSystemTypes.Int8); break;
          case OpCode.Conv_Ovf_I2_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I2_Un, CoreSystemTypes.Int16); break;
          case OpCode.Conv_Ovf_I4_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I4_Un, CoreSystemTypes.Int32); break;
          case OpCode.Conv_Ovf_I8_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I8_Un, CoreSystemTypes.Int64); break;
          case OpCode.Conv_Ovf_U1_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U1_Un, CoreSystemTypes.UInt8); break;
          case OpCode.Conv_Ovf_U2_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U2_Un, CoreSystemTypes.UInt16); break;
          case OpCode.Conv_Ovf_U4_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U4_Un, CoreSystemTypes.UInt32); break;
          case OpCode.Conv_Ovf_U8_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U8_Un, CoreSystemTypes.UInt64); break;
          case OpCode.Conv_Ovf_I_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I_Un, CoreSystemTypes.IntPtr); break;
          case OpCode.Conv_Ovf_U_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U_Un, CoreSystemTypes.UIntPtr); break;
          case OpCode.Box: 
            TypeNode t = (TypeNode)this.GetMemberFromToken();
            TypeNode bt = t is EnumNode ? CoreSystemTypes.Enum : CoreSystemTypes.ValueType;
            expr = new BinaryExpression(PopOperand(), new Literal(t, CoreSystemTypes.Type), NodeType.Box, bt); break;
          case OpCode.Newarr: expr = this.ParseNewArray(); break;
          case OpCode.Ldlen: expr = new UnaryExpression(PopOperand(), NodeType.Ldlen, CoreSystemTypes.UIntPtr); break;
          case OpCode.Ldelema: expr = this.ParseArrayElementLoadAddress(); break;
          case OpCode.Ldelem_I1: 
          case OpCode.Ldelem_U1: 
          case OpCode.Ldelem_I2: 
          case OpCode.Ldelem_U2: 
          case OpCode.Ldelem_I4: 
          case OpCode.Ldelem_U4: 
          case OpCode.Ldelem_I8: 
          case OpCode.Ldelem_I: 
          case OpCode.Ldelem_R4: 
          case OpCode.Ldelem_R8: 
          case OpCode.Ldelem_Ref: expr = this.ParseArrayElementLoad(opCode, null); break;
          case OpCode.Stelem_I:
          case OpCode.Stelem_I1:
          case OpCode.Stelem_I2:
          case OpCode.Stelem_I4:
          case OpCode.Stelem_I8:
          case OpCode.Stelem_R4:
          case OpCode.Stelem_R8:
          case OpCode.Stelem_Ref: statement = this.ParseArrayElementAssignment(opCode); goto done;
          case OpCode.Ldelem: expr = this.ParseArrayElementLoad(opCode, null); break;
          case OpCode.Stelem: statement = this.ParseArrayElementAssignment(opCode); goto done;
          case OpCode.Unbox_Any: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.UnboxAny); break;
          case OpCode.Conv_Ovf_I1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I1, CoreSystemTypes.Int8); break;
          case OpCode.Conv_Ovf_U1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U1, CoreSystemTypes.UInt8); break;
          case OpCode.Conv_Ovf_I2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I2, CoreSystemTypes.Int16); break;
          case OpCode.Conv_Ovf_U2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U2, CoreSystemTypes.UInt16); break;
          case OpCode.Conv_Ovf_I4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I4, CoreSystemTypes.Int32); break;
          case OpCode.Conv_Ovf_U4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U4, CoreSystemTypes.UInt32); break;
          case OpCode.Conv_Ovf_I8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I8, CoreSystemTypes.Int64); break;
          case OpCode.Conv_Ovf_U8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U8, CoreSystemTypes.UInt64); break;
          case OpCode.Refanyval: expr = new BinaryExpression(PopOperand(), new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Refanyval, CoreSystemTypes.IntPtr); break;
          case OpCode.Ckfinite: expr = this.ParseUnaryOperation(NodeType.Ckfinite); break;
          case OpCode.Mkrefany: expr = new BinaryExpression(PopOperand(), new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Mkrefany, CoreSystemTypes.DynamicallyTypedReference); break;
          case OpCode.Ldtoken: expr = ParseLoadRuntimeMetadataToken(); break;
          case OpCode.Conv_U2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U2, CoreSystemTypes.UInt16); break;
          case OpCode.Conv_U1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U1, CoreSystemTypes.UInt8); break;
          case OpCode.Conv_I: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I, CoreSystemTypes.IntPtr); break;
          case OpCode.Conv_Ovf_I: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I, CoreSystemTypes.IntPtr); break;
          case OpCode.Conv_Ovf_U: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U, CoreSystemTypes.UIntPtr); break;
          case OpCode.Add_Ovf: expr = this.ParseBinaryOperation(NodeType.Add_Ovf); break;
          case OpCode.Add_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Add_Ovf_Un); break;
          case OpCode.Mul_Ovf: expr = this.ParseBinaryOperation(NodeType.Mul_Ovf); break;
          case OpCode.Mul_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Mul_Ovf_Un); break;
          case OpCode.Sub_Ovf: expr = this.ParseBinaryOperation(NodeType.Sub_Ovf); break;
          case OpCode.Sub_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Sub_Ovf_Un); break;
          case OpCode.Endfinally: statement = new EndFinally(); transferStatement = true; goto done;
          case OpCode.Leave: statement = this.ParseBranch(NodeType.Nop, 0, false, false, true); transferStatement = true; goto done;
          case OpCode.Leave_S: statement = this.ParseBranch(NodeType.Nop, 0, true, false, true); transferStatement = true; goto done;
          case OpCode.Stind_I: statement = this.ParseStoreIndirect(CoreSystemTypes.IntPtr); goto done;
          case OpCode.Conv_U: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U, CoreSystemTypes.UIntPtr); break;
          case OpCode.Arglist: expr = new Expression(NodeType.Arglist, CoreSystemTypes.ArgIterator); break;
          case OpCode.Ceq: expr = this.ParseBinaryComparison(NodeType.Ceq); break;
          case OpCode.Cgt: expr = this.ParseBinaryComparison(NodeType.Cgt); break;
          case OpCode.Cgt_Un: expr = this.ParseBinaryComparison(NodeType.Cgt_Un); break;
          case OpCode.Clt: expr = this.ParseBinaryComparison(NodeType.Clt); break;
          case OpCode.Clt_Un: expr = this.ParseBinaryComparison(NodeType.Clt_Un); break;
          case OpCode.Ldftn: expr = new UnaryExpression(new MemberBinding(null, this.GetMemberFromToken()), NodeType.Ldftn, CoreSystemTypes.IntPtr); break;
          case OpCode.Ldvirtftn: expr = new BinaryExpression(PopOperand(), new MemberBinding(null, this.GetMemberFromToken()), NodeType.Ldvirtftn, CoreSystemTypes.IntPtr); break;
          case OpCode.Ldarg: expr = this.Parameters((ushort)this.GetInt16()); break;
          case OpCode.Ldarga: expr = SetType(new UnaryExpression(this.Parameters((ushort)this.GetInt16()), NodeType.AddressOf)); break;
          case OpCode.Starg: statement = new AssignmentStatement(this.Parameters((ushort)this.GetInt16()), PopOperand()); goto done;
          case OpCode.Ldloc: expr = this.locals[(ushort)this.GetInt16()]; break;
          case OpCode.Ldloca: expr = SetType(new UnaryExpression(this.locals[(ushort)this.GetInt16()], NodeType.AddressOf)); break;
          case OpCode.Stloc: statement = new AssignmentStatement(this.locals[(ushort)this.GetInt16()], PopOperand()); goto done;
          case OpCode.Localloc: expr = new UnaryExpression(PopOperand(), NodeType.Localloc, CoreSystemTypes.Void); break;
          case OpCode.Endfilter: statement = new EndFilter(PopOperand()); transferStatement = true; goto done;
          case OpCode.Unaligned_: this.alignment = this.GetByte(); continue;
          case OpCode.Volatile_: this.isVolatile = true; continue;
          case OpCode.Tail_: this.isTailCall = true; continue;
          case OpCode.Initobj: statement = this.ParseInitObject(); goto done;
          case OpCode.Constrained_: this.constraint = this.GetMemberFromToken() as TypeNode; continue;
          case OpCode.Cpblk: expr = this.ParseTernaryOperation(NodeType.Cpblk); goto done;
          case OpCode.Initblk: expr = this.ParseTernaryOperation(NodeType.Initblk); goto done;
          case OpCode.Rethrow: statement = new Throw(null); statement.NodeType = NodeType.Rethrow; transferStatement = true; goto done;
          case OpCode.Sizeof: expr = new UnaryExpression(new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Sizeof, CoreSystemTypes.Int32); break;
          case OpCode.Refanytype: expr = new UnaryExpression(PopOperand(), NodeType.Refanytype, CoreSystemTypes.RuntimeTypeHandle); break;
          case OpCode.Readonly_: this.isReadOnly = true; continue;
          default: throw new InvalidMetadataException(ExceptionStrings.UnknownOpCode);
        }
        if (this.blockMap[this.counter+1] != null){
          transferStatement = true; //Falls through to the next basic block, so implicitly a "transfer" statement
          goto done;
        }
        //^ assume expr != null;
#if FxCop
        expr.sourceContext = sourceContext;
#endif
#if FxCop || ILOFFSETS
        expr.ILOffset = this.ilOffset;
#endif
        this.operandStack.Push(expr);
        this.isReadOnly = false;
        this.isVolatile = false;
        this.isTailCall = false;        
        this.alignment = -1;
      }
    done:
      for (int i = 0; i <= this.operandStack.top; i++){
        Expression e = this.operandStack.elements[i];
        //^ assume e != null;
        Statement s = new ExpressionStatement(e);
#if FxCop
        s.SourceContext = this.sourceContext;
#endif
#if FxCop || ILOFFSETS
        s.ILOffset = this.ilOffset;
#endif
        statementList.Add(s);
      }
      this.operandStack.top = -1;
      if (statement == null) {
        statement = new ExpressionStatement(expr);
#if FxCop
        expr.sourceContext = this.sourceContext;
#endif
#if FxCop || ILOFFSETS
        expr.ILOffset = this.ilOffset;
#endif
      }
      statement.SourceContext = sourceContext;
#if FxCop || ILOFFSETS
      statement.ILOffset = this.ilOffset;
#endif
#if ILOFFSETS
      this.lastSourceContext = sourceContext;
#endif
      statementList.Add(statement);
      if (transferStatement) return true;
      return this.blockMap[this.counter+1] != null;
    }
Exemple #13
0
 private MethodCall/*!*/ ParseCalli(out bool isStatement) {
   FunctionPointer fp = this.reader.GetCalliSignature(this.GetInt32());
   if (fp == null) throw new InvalidMetadataException(ExceptionStrings.BaddCalliSignature);
   isStatement = BodyParser.TypeIsVoid(fp.ReturnType);
   int n = fp.ParameterTypes.Count; 
   Expression[] args = new Expression[n+1];
   ExpressionList arguments = new ExpressionList(n+1);
   for (int i = n; i >= 0; i--) args[i] = PopOperand();
   for (int i = 0; i <= n; i++) arguments.Add(args[i]);
   Expression thisob = fp.IsStatic ? null : PopOperand();
   MemberBinding methBinding = new MemberBinding(thisob, fp);
   MethodCall result = new MethodCall(methBinding, arguments, NodeType.Calli);
   result.Type = fp.ReturnType;
   result.IsTailCall = this.isTailCall;
   return result;
 }
 public virtual Expression VisitMemberBinding(MemberBinding memberBinding)
 {
     if (memberBinding == null) return null;
     memberBinding.TargetObject = this.VisitExpression(memberBinding.TargetObject);
     return memberBinding;
 }
Exemple #15
0
    public override Expression VisitOldExpression(OldExpression oldExpression) {
      if (this.topLevelClosureClass != null) {
        #region In Closure ==> Create a field
        // Since we're within a closure, we can't create a local to hold the value of the old expression
        // but instead have to create a field for it. That field can be a member of the top-level
        // closure class since nothing mentioned in the old expression (except possibly for the
        // bound variables of enclosing quantifications) should be anything captured from
        // an inner anonymous delegate.

        // BUT, first we have to know if the old expression depends on any of the bound
        // variables of the closures in which it is located. If not, then we can implement
        // it as a scalar and just generate the assignment "closure_class.field := e" for
        // "Old(e)" to take a snapshot of e's value in the prestate. If it does depend on
        // any of the bound variables, then we need to generate a set of for-loops that
        // compute the indices and values of e for each tuple of indices so it can be retrieved
        // (given the indices) in the post-state.
        CollectBoundVariables cbv = new CollectBoundVariables(this.stackOfBoundVariables);
        cbv.VisitExpression(oldExpression.expression);

        SubstituteClosureClassWithinOldExpressions subst =
            new SubstituteClosureClassWithinOldExpressions(this.closureLocals);
        Expression e = subst.VisitExpression(oldExpression.expression);
        if (cbv.FoundVariables.Count == 0) {
          #region Use a scalar for the old variable
          Local closureLocal;
          if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal))
          {
            Contract.Assume(false, "can't find closure local!");
          }
          #region Define a scalar
          var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass);
          Field f = new Field(clTemplate,
            null,
            FieldFlags.CompilerControlled | FieldFlags.Public,
            Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()), // unique name for this old expr.
            oldExpression.Type,
            null);
          clTemplate.Members.Add(f);
          // now produce properly instantiated field
          f = (Field)Rewriter.GetMemberInstanceReference(f, this.topLevelClosureClass);
          #endregion
          #region Generate code to store value in prestate
          this.prestateValuesOfOldExpressions.Statements.Add(new AssignmentStatement(new MemberBinding(closureLocal, f), e));
          #endregion
          #region Return expression to be used in poststate
          // Return an expression that will evaluate in the poststate to the value of the old
          // expression in the prestate. This will be this.up.f where "up" is the field C#
          // generated to point to the instance of the top-level closure class.
          if (this.PointerToTopLevelClosureClass == null) {
            // then the old expression occurs in the top-level closure class. Just return "this.f"
            // where "this" refers to the top-level closure class.
            return new MemberBinding(new This(this.currentClosureClass), f);
          } else {
            return new MemberBinding(
              new MemberBinding(new This(this.currentClosureClass), this.PointerToTopLevelClosureClass),
              f);
          }
          #endregion
          #endregion
        } else {
          // the Old expression *does* depend upon at least one of the bound variable
          // in a ForAll or Exists expression
          #region Use an indexed variable for the old variable
          TypeNode oldVariableTypeDomain;
          #region Decide if domain is one-dimensional or not
          bool oneDimensional = cbv.FoundVariables.Count == 1 && cbv.FoundVariables[0].Type.IsValueType;
          if (oneDimensional) {
            // a one-dimensional old-expression can use the index variable directly
            oldVariableTypeDomain = cbv.FoundVariables[0].Type;
          } else {
            oldVariableTypeDomain = SystemTypes.GenericList.GetTemplateInstance(this.module, SystemTypes.Int32);
          }
          #endregion
          TypeNode oldVariableTypeRange = oldExpression.Type;
          TypeNode oldVariableType = SystemTypes.GenericDictionary.GetTemplateInstance(this.module, oldVariableTypeDomain, oldVariableTypeRange);
          Local closureLocal;
          if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal))
          {
            Contract.Assume(false, "can't find closure local");
          }
          #region Define an indexed variable
          var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass);
          Field f = new Field(clTemplate,
            null,
            FieldFlags.CompilerControlled | FieldFlags.Assembly, // can't be private or protected because it needs to be accessed from inner (closure) classes that don't inherit from the class this field is added to.
            Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()), // unique name for this old expr.
            oldVariableType,
            null);
          clTemplate.Members.Add(f);
          // instantiate f
          f = (Field)Rewriter.GetMemberInstanceReference(f, closureLocal.Type);
          #endregion
          #region Generate code to initialize the indexed variable
          Statement init = new AssignmentStatement(
            new MemberBinding(closureLocal, f),
            new Construct(new MemberBinding(null, oldVariableType.GetConstructor()), null));
          this.prestateValuesOfOldExpressions.Statements.Add(init);
          #endregion
          #region Generate code to store values in prestate
          #region Create assignment: this.closure.f[i,j,k,...] = e;
          Method setItem = oldVariableType.GetMethod(Identifier.For("set_Item"), oldVariableTypeDomain, oldVariableTypeRange);
          Expression index;
          if (oneDimensional) {
            index = cbv.FoundVariables[0];
          } else {
            //InstanceInitializer ctor =
            //  ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1));
            //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList(
            index = Literal.Null;
          }
          MethodCall mc = new MethodCall(new MemberBinding(new MemberBinding(closureLocal, f), setItem),
            new ExpressionList(index, e));
          Statement stat = new ExpressionStatement(mc);
          #endregion
          List<Local> locals = new List<Local>(this.stackOfBoundVariables.Count);
          TrivialHashtable paramMap = new TrivialHashtable();
          #region Generate a local for each bound variable to use in for-loop
          foreach (Variable v in this.stackOfBoundVariables) {
            Local l = new Local(Identifier.Empty, v.Type);
            paramMap[v.UniqueKey] = l;
            locals.Add(l);
          }
          #endregion
          #region Substitute locals for bound variables in old expression *AND* in inner loop bounds
          SubstituteParameters sps = new SubstituteParameters(paramMap, this.stackOfBoundVariables);
          sps.Visit(stat);
          #endregion
          #region Create nested for-loops around assignment
          // keep track of when the first variable is used (from innermost to outermost)
          // as soon as the first one is needed because the old expression depends on it,
          // then keep all enclosing loops. It would be possible to keep only those where
          // the necessary loops have loop bounds that depend on an enclosing loop, but I
          // haven't calculated that, so just keep them all. For instance, if the old expression
          // depends on j and the loops are "for i,0,n" and inside that "for j,0,i", then need
          // both loops. If the inner loop bounds were 0 and n, then wouldn't need the outer
          // loop.
          bool usedAVariable = false;
          for (int i = this.stackOfBoundVariables.Count - 1; 0 <= i; i--) {
            if (!usedAVariable
              && !cbv.FoundVariables.Contains(this.stackOfBoundVariables[i])) continue;
            usedAVariable = true;
            Expression lowerBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression(
              this.stackOfMethods[i].Operands[0]);
            lowerBound = subst.VisitExpression(lowerBound);
            lowerBound = sps.VisitExpression(lowerBound);
            Expression upperBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression(
              this.stackOfMethods[i].Operands[1]);
            upperBound = subst.VisitExpression(upperBound);
            upperBound = sps.VisitExpression(upperBound);
            stat = RewriteHelper.GenerateForLoop(locals[i], lowerBound, upperBound, stat);
          }
          #endregion
          this.prestateValuesOfOldExpressions.Statements.Add(stat);
          #endregion
          #region Return expression to be used in poststate
          Method getItem = oldVariableType.GetMethod(Identifier.For("get_Item"), oldVariableTypeDomain);
          if (oneDimensional) {
            index = cbv.FoundReferences[0];
          } else {
            //InstanceInitializer ctor =
            //  ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1));
            //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList(
            index = Literal.Null;
          }
          // Return an expression that will evaluate in the poststate to the value of the old
          // expression in the prestate. This will be this.up.f[i,j,k,...] where "up" is the field C#
          // generated to point to the instance of the top-level closure class.
          MemberBinding thisDotF;
          if (this.PointerToTopLevelClosureClass == null) {
            // then the old expression occurs in the top-level closure class. Just return "this.f"
            // where "this" refers to the top-level closure class.
            Contract.Assume(f != null);
            thisDotF = new MemberBinding(new This(clTemplate), HelperMethods.Unspecialize(f));
          } else {
            thisDotF = new MemberBinding(
              new MemberBinding(new This(clTemplate), this.PointerToTopLevelClosureClass),
              f);
          }
          return new MethodCall(new MemberBinding(thisDotF, getItem), new ExpressionList(index));
          #endregion
          #endregion
        }
        #endregion
      } else {
        #region Not in closure ==> Create a local variable
        Local l = GetLocalForOldExpression(oldExpression);
        #region Make sure local can be seen in the debugger (for the entire method, unfortunately)
        if (currentMethod.LocalList == null) {
          currentMethod.LocalList = new LocalList();
        }
        currentMethod.LocalList.Add(l);
        currentMethod.Body.HasLocals = true;
        #endregion
        this.prestateValuesOfOldExpressions.Statements.Add(
          new AssignmentStatement(l, oldExpression.expression));

        // Return an expression that will evaluate in the poststate to the value of the old
        // expression in the prestate. When we're not in a closure, this is just the local
        // itself.
        return l;
        #endregion
      }
    }
Exemple #16
0
 public override Expression VisitMemberBinding(MemberBinding memberBinding)
 {
     if (memberBinding == null) return null;
     Field f = memberBinding.BoundMember as Field;
     if (f == null || !this.substitution.ContainsKey(f))
         return base.VisitMemberBinding(memberBinding);
     Method m = this.substitution[f];
     return new MethodCall(
       new MemberBinding(memberBinding.TargetObject, m),
       null,
       m.IsVirtual ? NodeType.Callvirt : NodeType.Call,
       f.Type
       );
 }
Exemple #17
0
 private MethodCall/*!*/ ParseCall(NodeType typeOfCall, out bool isStatement) {
   TypeNodeList varArgTypes;
   Method meth = (Method)this.GetMemberFromToken(out varArgTypes);
   int numVarArgs = varArgTypes == null ? 0 : varArgTypes.Count;
   isStatement = BodyParser.TypeIsVoid(meth.ReturnType);
   int n = meth.Parameters == null ? 0 : meth.Parameters.Count; 
   if (typeOfCall == NodeType.Jmp) n = 0;
   else n += numVarArgs;
   Expression[] args = new Expression[n];
   ExpressionList arguments = new ExpressionList(n);
   for (int i = n-1; i >= 0; i--) args[i] = PopOperand();
   for (int i = 0; i < n; i++) arguments.Add(args[i]);
   if (varArgTypes != null) {
     for (int i = n-1, j = numVarArgs; j > 0; j--, i--) {
       Expression e = arguments[i];
       TypeNode t = varArgTypes[j-1];
       if (e != null && t != null) e.Type = t;
     }
   }
   Expression thisob = meth.IsStatic ? null : PopOperand();
   MemberBinding methBinding = new MemberBinding(thisob, meth);
   MethodCall result = new MethodCall(methBinding, arguments, typeOfCall);
   result.Type = meth.ReturnType;
   result.IsTailCall = this.isTailCall;
   if (this.constraint != null){
     result.Constraint = this.constraint;
     this.constraint = null;
   }
   return result;
 }
            public override Expression VisitMemberBinding(MemberBinding memberBinding)
            {
                Field field = memberBinding.BoundMember as Field;
                if (field != null)
                {
                    // Case 1: iterator_closure's this.field should be turned into either a parameter or a local.
                    if (memberBinding.TargetObject is This)
                    {
                        var thisParam = (This) memberBinding.TargetObject;
                        var declType = thisParam.Type;

                        Reference declRef = declType as Reference;
                        if (declRef != null)
                        {
                            declType = declRef.ElementType;
                        }

                        declType = HelperMethods.Unspecialize(declType);
                        if (declType == this.closureUnspec)
                        {
                            // actually a closure field.

                            if (closureParametersMapping.ContainsKey(field.Name.Name))
                            {
                                return closureParametersMapping[field.Name.Name];
                            }
                            if (closureLocalsMapping.ContainsKey(field.Name.Name))
                            {
                                return closureLocalsMapping[field.Name.Name];
                            }
                            
                            if (field.Name.Name.Contains("__locals" /* csc.exe */) ||
                                field.Name.Name.Contains("<>8__") /* roslyn-based csc */||
                                field.Name.Name.Contains("<>9__")
                                /* roslyn-based cached anonymous method delegates */||
                                field.Name.Name.Contains("__spill") /* rcsc.exe */||
                                field.Name.Name.Contains("__CachedAnonymousMethodDelegate") /* junk, revisit */)
                            {
                                Local newLocal = new Local(field.Name, field.Type);
                                closureLocalsMapping.Add(field.Name.Name, newLocal);
                                return newLocal;
                            }

                            throw new NotImplementedException(
                                String.Format("Found field {0} in contract that shouldn't be here", field.Name.Name));
                        }
                        else
                        {
                            // some other field. Leave it alone.
                        }
                    }
                }

                // case 2: assert (memberbinding.targetObject is memberbinding &&  memberbinding.boundmember is capturing 
                // either a parameter or a local). Then targetObject is hopefully turned into a parameter or a local, with
                // the boundmember untouched. We simply use base.VisitMemberBinding for this case. 
                return base.VisitMemberBinding(memberBinding);
            }
Exemple #19
0
 private UnaryExpression /*!*/ ParseLoadRuntimeMetadataToken() {
   Expression expr = null;
   TypeNode exprType = null;
   Member member = this.GetMemberFromToken();
   TypeNode t = member as TypeNode;
   if (t == null) {
     exprType = (member.NodeType == NodeType.Field)
       ? CoreSystemTypes.RuntimeFieldHandle : CoreSystemTypes.RuntimeMethodHandle;
     expr = new MemberBinding(null, member);
   } else {
     exprType = CoreSystemTypes.RuntimeTypeHandle;
     expr = new Literal(t, CoreSystemTypes.Type);
   }
   return new UnaryExpression(expr, NodeType.Ldtoken, exprType);
 }
            private bool IsAutoPropGetterCall(MemberBinding mb)
            {
                if (!(mb.TargetObject is This)) return false;

                if (mb.BoundMember == autoProp.Getter) return true;

                return false;
            }
Exemple #21
0
    void AddReadStream(Block block, TypeNode type, StatementList statements, Identifier reader, 
      Expression target, Expression result){
      // Read next element and figure out if it matches the stream element type, if so read it and add it to the list
      // If not, then return (throw an error if there are no items and the list is the non-empty type).

      // flexArray = new flexarray();
      // while (reader.Read() && read.NodeType != XmlNodeType.EndElement) {
      //    if (reader.NodeType == XmlNodeType.Element) {
      //      readchild(flexarray);
      //    }
      // }
      // target = flexArray; 

      Local nameLocal = new Local(Identifier.For("name"),SystemTypes.String, block);
      Local nsLocal = new Local(Identifier.For("ns"),SystemTypes.String, block);
      Local nodeType = new Local(Identifier.For("nodeType"),Runtime.XmlNodeType, block);
      Local optional = new Local(Identifier.Empty, SystemTypes.Boolean, block);
      Local foundChild = new Local(Identifier.Empty, SystemTypes.Boolean, block);
      statements.Add(new AssignmentStatement(optional, Literal.False));

      TypeNode eType = Checker.GetCollectionElementType(type);
      Local local = new Local(Identifier.Empty, eType, block);
      Method addMethod = null;
      Local localArray = null;

      if (type.Template == SystemTypes.GenericBoxed) {

        addMethod = null; // only needs one!

      } else if (Checker.IsGenericList(type)) {
        //TODO: this call is invalid if the eType is not public
        TypeNode flexArrayType = SystemTypes.GenericList.GetTemplateInstance(this.module, eType);
        localArray = new Local(Identifier.For("stream"+streamCount++), flexArrayType, block);

        statements.Add(new AssignmentStatement(localArray,
          new Construct(new MemberBinding(null, flexArrayType), new ExpressionList(), flexArrayType)));

        addMethod = flexArrayType.GetMethod(Identifier.For("Add"), eType);
      } else  {        
        TypeNode arrayType = SystemTypes.ArrayList;
        localArray = new Local(Identifier.Empty, arrayType, block);
        statements.Add(new AssignmentStatement(localArray,
          new Construct(new MemberBinding(null, arrayType), new ExpressionList(), arrayType)));

        addMethod = arrayType.GetMethod(Identifier.For("Add"), SystemTypes.Object);
      }

      Block whileBody = new Block(new StatementList());
      MethodCall moveToContent = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("MoveToContent")), new ExpressionList());
      BinaryExpression notAtEnd = new BinaryExpression(moveToContent, 
        new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("EndElement")), NodeType.Ne);
      BinaryExpression notEOF = new BinaryExpression(
        new QualifiedIdentifier(reader, Identifier.For("EOF")), Literal.True, NodeType.Ne);

      While w = new While(new BinaryExpression(notAtEnd, notEOF, NodeType.And), whileBody);
      statements.Add(w);

      whileBody.Statements.Add(new AssignmentStatement(nameLocal, new QualifiedIdentifier(reader, Identifier.For("LocalName"))));
      whileBody.Statements.Add(new AssignmentStatement(nsLocal, new QualifiedIdentifier(reader, Identifier.For("NamespaceURI"))));
      whileBody.Statements.Add(new AssignmentStatement(nodeType, new QualifiedIdentifier(reader, Identifier.For("NodeType"))));

      StatementList trueStatements = whileBody.Statements;
      if (type.Template == SystemTypes.GenericBoxed){
        type = Checker.GetCollectionElementType(type);
      }

      trueStatements.Add(new AssignmentStatement(foundChild, Literal.False));

      if (eType is TupleType || eType is TypeUnion || IsStream(eType)) {
        AddCallDeserializer(eType, trueStatements, reader, local, optional, foundChild);        
      } else  {
        AddReadChild(whileBody, trueStatements, Checker.GetDefaultElementName(eType), eType, local, reader, foundChild, true, false);
      }

      If ifFound = new If(new BinaryExpression(foundChild, Literal.True, NodeType.Eq),
        new Block(new StatementList()), new Block(new StatementList()));
      ifFound.TrueBlock.Statements.Add(new AssignmentStatement(result, Literal.True)); // set our result to true then.
      ifFound.FalseBlock.Statements.Add(new Exit()); // break out of loop then.

      trueStatements.Add(ifFound);

      if (addMethod == null) {        
        trueStatements.Add(new AssignmentStatement(target, 
          CastTo(local, type))); // box the result.
        trueStatements.Add(new Exit()); // break out of loop we have it!
      } else {
        MemberBinding addCall = new MemberBinding(localArray, addMethod);
        trueStatements.Add(new ExpressionStatement(new MethodCall(addCall, 
          new ExpressionList(new Expression[1] {local}))));
      }

      // clear out the local, it is a struct of some sort.
      if (local.Type.IsValueType && ! local.Type.IsPrimitive) {
        trueStatements.Add(new AssignmentStatement(local, 
          new Construct(new MemberBinding(null,local.Type), new ExpressionList(), local.Type)));
      }

      // end while
      // assign resulting array to the target object (if we have anything to assign).
      If ifResult = new If(new BinaryExpression(result, Literal.True, NodeType.Eq),
        new Block(new StatementList()), null);
      statements.Add(ifResult);
      statements = ifResult.TrueBlock.Statements;

      if (addMethod != null) {
        if (type is ArrayType) {
          // target = (type)localArray.ToArray(etype);
          Method toArray = SystemTypes.ArrayList.GetMethod(Identifier.For("ToArray"), SystemTypes.Type);
          ExpressionList args = new ExpressionList();
          args.Add(new UnaryExpression(new Literal(eType, SystemTypes.Type), NodeType.Typeof, SystemTypes.Type));
          statements.Add(new AssignmentStatement(target, 
            CastTo(new MethodCall(new MemberBinding(localArray, toArray), 
                     args, NodeType.Callvirt, SystemTypes.Array), type)));

        } else if (type.Template == SystemTypes.GenericNonEmptyIEnumerable) {
          // Explicit coercion of IEnumerable to NonEmptyIEnumerable requires constructing 
          // the NonEmptyIEnumerable object passing in the IEnumerable as an argument.
          TypeNode ienumtype = Checker.GetIEnumerableTypeFromNonEmptyIEnumerableStruct(this.module, type);
          Debug.Assert(ienumtype!=null);
          //TODO: this call is invalid if the eType is not public
          TypeNode nonEmptyIEnum = SystemTypes.GenericNonEmptyIEnumerable.GetTemplateInstance(this.module, eType);

          InstanceInitializer ii = nonEmptyIEnum.GetConstructor(ienumtype);
          Construct c = new Construct(new MemberBinding(null, ii), new ExpressionList(localArray), nonEmptyIEnum);
          statements.Add(new AssignmentStatement(target, c));
        } else {
          statements.Add(new AssignmentStatement(target, localArray));
        }
      }
    }
            private bool IsInvariantCall(MemberBinding mb)
            {
                if (mb.TargetObject != null) return false;

                if (this.parent.contractNodes.IsInvariantMethod(mb.BoundMember as Method)) return true;

                return false;
            }
Exemple #23
0
    Expression GetConvertFromString(TypeNode targetType, Expression src, bool always) {
      if (targetType == SystemTypes.String) 
        return src;// nothing to do!

      if (targetType is EnumNode) {
        // e.g. return (DayOfWeek)Enum.Parse(typeof(DayOfWeek),"Sunday");
        Method method = SystemTypes.Enum.GetMethod(Identifier.For("Parse"), new TypeNode[2]{ SystemTypes.Type, SystemTypes.String});
        UnaryExpression typeOfEnum = new UnaryExpression(new MemberBinding(null, targetType), NodeType.Typeof);
        MethodCall call = new MethodCall(new MemberBinding(new MemberBinding(null, targetType), method), 
          new ExpressionList(new Expression[2]{typeOfEnum, src }), NodeType.Call, SystemTypes.Object);
        return CastTo(call, targetType);
      }
      // See if it has a type converter.
      Class converterClass = Checker.GetTypeConverter(targetType);
      if (converterClass != null) {
        TypeConverter converter = TypeDescriptor.GetConverter(targetType.GetRuntimeType());
        if (converter != null) {
          Type converterType = converter.GetType();
          AssemblyNode converterAssembly = AssemblyNode.GetAssembly(converterType.Assembly, cache, false, true);
          converterClass = converterAssembly.GetType(Identifier.For(converterType.Namespace), Identifier.For(converterType.Name)) as Class;          
          Expression e = tempChecker.GetConverterFromString(converter, converterClass, SystemTypes.String, src, SystemTypes.Object);
          if (e != null) {
            //Do I need to add namespace and assembly reference for type converter?
            return CastTo(e, targetType);
          }
        }   
      }
      if (always) {
        // e.g. return PointArray.Parse("10,20 30,40 50,60");
        Method method = targetType.GetImplicitCoercionFromMethod(SystemTypes.String);
        if (method == null) {
          method = targetType.GetMethod(Identifier.For("Parse"), new TypeNode[1]{ SystemTypes.String});
        }
        if (method != null) {
          MemberBinding typeBinding  = new MemberBinding(null, targetType);
          MethodCall call = new MethodCall(new MemberBinding(typeBinding, method), 
            new ExpressionList(new Expression[1]{ src }), NodeType.Call, targetType );
          return call;
        }
      }
      return null;
    }
            public override void VisitMemberBinding(MemberBinding memberBinding)
            {
                if (memberBinding == null) return;

                if (memberBinding.BoundMember != null)
                {
                    if (memberBinding.BoundMember.Name.Matches(ContractNodes.InvariantName) &&
                        memberBinding.BoundMember.DeclaringType.Name.Matches(ContractNodes.ContractClassName))
                    {
                        // skip
                    }
                    else
                    {
                        this.referencedMembers.Add(memberBinding.BoundMember);
                    }
                }

                base.VisitMemberBinding(memberBinding);
            }
Exemple #25
0
 MemberBinding GetMemberBinding(Expression source, Member m, TypeNode t) {
   MemberBinding src = new MemberBinding(source, m);
   src.Type = t;
   return src;
 }
            public override void VisitMemberBinding(MemberBinding memberBinding)
            {
                Field f = memberBinding.BoundMember as Field;
                if (f != null)
                {
                    this.Found = f;
                    return;
                }

                base.VisitMemberBinding(memberBinding);
            }
Exemple #27
0
        public override Expression VisitMemberBinding(MemberBinding memberBinding)
        {
            // TODO: Just guessing here for now - need to understand this better.

            if (memberBinding == null) return null;
            if (memberBinding.TargetObject != null)
                this.VisitExpression(memberBinding.TargetObject);
            else if (memberBinding.BoundMember is TypeExpression)
                this.VisitExpression(((TypeExpression)memberBinding.BoundMember).Expression);
            else if (memberBinding.BoundMember is TypeNode)
                this.VisitTypeReference((TypeNode)memberBinding.BoundMember);
            else if (memberBinding.BoundMember is InstanceInitializer)
                this.VisitTypeReference(((InstanceInitializer)memberBinding.BoundMember).DeclaringType);
            else
                throw new NotImplementedException("Unexpected scenario in VisitMemberBinding");
            return memberBinding;
        }
Exemple #28
0
 public override Expression VisitMemberBinding(MemberBinding binding)
 {
     Debug.Assert(false, "Reached a member binding node unexpectedly");
     return null;
 }
            public override void VisitMemberBinding(MemberBinding mb)
            {
                if (mb == null) return;

                var m = mb.BoundMember as Method;
                if (m == null) return;
                
                Method invMethod = this.InvariantMethods[m.UniqueKey] as Method;
                if (invMethod != null)
                {
                    this.parent.HandleError(new Error(1042,
                        "Explicit use of invariant method '" + invMethod.FullName + "' is not allowed.", this.lastSC));
                }
            }
Exemple #30
0
        private Expression VisitMemberBindingExpression(MemberBinding binding)
        {
            if (binding.BoundMember.NodeType != NodeType.Field)
            {
                Debug.Assert(false, "MemberBinding scenario not yet supported");
                return null;
            }

            if (binding.BoundMember is ParameterField)
            {
                Parameter param = ((ParameterField)binding.BoundMember).Parameter;
                if ((param.Flags & ParameterFlags.Out) != 0)
                    return new QualifiedIdentifier(refOutputs, param.Name);
                else
                    return new QualifiedIdentifier(refInputs, param.Name);
            }

            Field field = (Field)binding.BoundMember;
            Expression targetObject = binding.TargetObject;
            // for output parameters
            while (targetObject is AddressDereference)
                targetObject = ((AddressDereference)targetObject).Address;

            if (field.IsStatic)
            {
                // This is a reference to a global variable.
                Expression globalAccess = Templates.GetExpressionTemplate("GlobalFieldAccess");
                Replacer.Replace(globalAccess, "_fieldName",
                    new Identifier(string.Format(CultureInfo.InvariantCulture,
                        "{0}_{1}", field.DeclaringType.Name.Name, field.Name.Name)));

                return globalAccess;
            }
            else if (field.DeclaringType is BlockScope)
            {
                return new QualifiedIdentifier(refLocals, field.Name);
            }
            else if (targetObject is ImplicitThis || targetObject is This)
            {
                Expression thisExpr = Templates.GetExpressionTemplate("ThisFieldAccess");
                Replacer.Replace(thisExpr, "_objectType", targetObject.Type.Name);
                Replacer.Replace(thisExpr, "_fieldName", field.Name);

                return thisExpr;
            }
            else if (targetObject is MemberBinding || targetObject is Indexer)
            {
                // Need to distinguish between class field and struct field access.
                // Structs are not on the heap, so the pointer deref isn't appropriate.
                if (!field.DeclaringType.IsPrimitive && field.DeclaringType is Struct)
                {
                    // we're gradually transforming struct
                    // fields into properties so far, we've
                    // done it for globals only, locals will
                    // be added next, then heap objects...
                    string propName = field.Name.Name;
                    bool pFlatten = true;
                    Expression prefix = null;

                    // search for pattern var.struct1...structn.member
                    while (true)
                    {
                        Field vField = null;
                        MemberBinding vBinding = targetObject as MemberBinding;

                        if (vBinding != null)
                        {
                            ParameterField pf = vBinding.BoundMember as ParameterField;
                            if (pf != null)
                            {
                                // param.struct1...structn.member
                                Parameter param = pf.Parameter;
                                propName = param.Name.Name + "_" + propName;
                                if ((param.Flags & ParameterFlags.Out) != 0)
                                    prefix = refOutputs;
                                else
                                    prefix = refInputs;
                                break;
                            }
                        }
                        else
                        {
                            pFlatten = false;
                            break;
                        }

                        vField = vBinding.BoundMember as Field;
                        if (vField == null)
                        {
                            pFlatten = false;
                            break;
                        }

                        propName = vField.Name.Name + "_" + propName;

                        if (vField.IsStatic)
                        {
                            // global.struct1...structn.member
                            propName = vField.DeclaringType.Name.Name + "_" + propName;
                            prefix = new QualifiedIdentifier(Identifier.For("application"),
                                Identifier.For("globals"));
                            break;
                        }
                        else if (vField.DeclaringType is BlockScope)
                        {
                            // local.struct1...structn.member
                            prefix = refLocals;
                            break;
                        }

                        if (vField.DeclaringType.IsPrimitive || !(vField.DeclaringType is Struct))
                        {
                            // can't match the pattern. let's bail
                            prefix = null;
                            pFlatten = false;
                            break;
                        }

                        binding = vBinding;
                        targetObject = binding.TargetObject;
                        // for output parameters
                        while (targetObject is AddressDereference)
                            targetObject = ((AddressDereference)targetObject).Address;
                    }

                    if (pFlatten)
                    {
                        Debug.Assert(prefix != null);
                        propName = "__strprops_" + propName;
                        return new QualifiedIdentifier(prefix, Identifier.For(propName));
                    }
                    else
                    {
                        Expression structRefExpr = Templates.GetExpressionTemplate("StructFieldAccess");
                        Replacer.Replace(structRefExpr, "_structExpr", this.VisitExpression(targetObject));
                        Replacer.Replace(structRefExpr, "_fieldName", field.Name);

                        return structRefExpr;
                    }
                }
                else
                {
                    Expression derefExpr = Templates.GetExpressionTemplate("ClassFieldAccess");
                    Replacer.Replace(derefExpr, "_objectType", field.DeclaringType.Name);
                    Replacer.Replace(derefExpr, "_ptrExpr", this.VisitExpression(targetObject));
                    Replacer.Replace(derefExpr, "_fieldName", field.Name);

                    return derefExpr;
                }
            }
            else
                return base.VisitExpression(binding);
        }