Exemple #1
0
        private Statement VariableDeclaration()
        {
            // TODO : multiple declarations style int a, b, c;

            TypeToken type            = Type();
            WordToken identifierToken = look as WordToken;

            Match(Tags.ID);

            Expression initialValue = null;

            if (look.Tag == '=')
            {
                Match('=');
                initialValue = Bool();
            }

            Match(';');

            LocalVariableSymbol symbol = symbolTable.PutVar(identifierToken.Lexeme, type.DotNetType);

            memoryUsed += type.Width;

            return(new VariableDeclarationStatement(symbol, initialValue));
        }
 public BoundVariableDeclaration(VariableDeclarationStatementSyntax syntax, LocalVariableSymbol variableSymbol, TypeSymbol declaredType, BoundExpression initializerOpt)
     : base(BoundNodeKind.VariableDeclaration, syntax)
 {
     VariableSymbol = variableSymbol;
     DeclaredType   = declaredType;
     InitializerOpt = initializerOpt;
 }
Exemple #3
0
        public VariableDeclarationStatement(LocalVariableSymbol symbol, Expression initialValue = null)
        {
            this.symbol       = symbol;
            this.initialValue = initialValue;

            // TODO : Type checking
        }
 public static void AssignValue_ToArrayIndexZero(this InstructionWriter instructionWriter, LocalVariableSymbol array, Action valueGetter)
 {
     instructionWriter.Get_LocalVariable(array);
     instructionWriter.EmitInstruction(OpCodeNumber.Ldc_I4_0);
     valueGetter();
     instructionWriter.EmitInstruction(OpCodeNumber.Stelem_Ref);
 }
 public static void AssignValue_ToArrayIndexOne(this InstructionWriter instructionWriter, LocalVariableSymbol array, LocalVariableSymbol value)
 {
     instructionWriter.Get_LocalVariable(array);
     instructionWriter.EmitInstruction(OpCodeNumber.Ldc_I4_1);
     instructionWriter.Get_LocalVariable(value);
     instructionWriter.EmitInstruction(OpCodeNumber.Stelem_Ref);
 }
Exemple #6
0
            public int CompareTo(LocalVariableSymbol <T> other)
            {
                Contract.ThrowIfNull(other);

                if (this == other)
                {
                    return(0);
                }

                Contract.ThrowIfFalse(_localSymbol.Locations.Length == 1);
                Contract.ThrowIfFalse(other._localSymbol.Locations.Length == 1);
                Contract.ThrowIfFalse(_localSymbol.Locations[0].IsInSource);
                Contract.ThrowIfFalse(other._localSymbol.Locations[0].IsInSource);
                Contract.ThrowIfFalse(
                    _localSymbol.Locations[0].SourceTree
                    == other._localSymbol.Locations[0].SourceTree
                    );
                Contract.ThrowIfFalse(
                    _localSymbol.Locations[0].SourceSpan.Start
                    != other._localSymbol.Locations[0].SourceSpan.Start
                    );

                return(_localSymbol.Locations[0].SourceSpan.Start
                       - other._localSymbol.Locations[0].SourceSpan.Start);
            }
                protected override void ImplementOnException(InstructionBlock block, ITypeSignature exceptionType, InstructionWriter writer)
                {
                    MethodDefDeclaration targetMethod = this.transformationInstance.AspectWeaverInstance.TargetElement as MethodDefDeclaration;

                    if (targetMethod == null)
                    {
                        return;
                    }

                    // TODO: nested types
                    string category = targetMethod.DeclaringType.Name;
                    ILoggingCategoryBuilder builder  = this.backendInstance.GetCategoryBuilder(category);
                    InstructionSequence     sequence = block.AddInstructionSequence(null, NodePosition.After, null);

                    writer.AttachInstructionSequence(sequence);

                    LocalVariableSymbol exceptionLocal = block.MethodBody.RootInstructionBlock.DefineLocalVariable(
                        exceptionType, DebuggerSpecialNames.GetVariableSpecialName("ex"));

                    LogSeverity logSeverity = LogSeverity.Warning;

                    if (builder.SupportsIsEnabled)
                    {
                        builder.EmitGetIsEnabled(writer, logSeverity);
                        InstructionSequence branchSequence = block.AddInstructionSequence(null, NodePosition.After, sequence);
                        writer.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, branchSequence);
                    }

                    builder.EmitWrite(writer, block, "An exception occurred:\n{0}", 1, logSeverity,
                                      w => w.EmitInstructionLocalVariable(OpCodeNumber.Stloc, exceptionLocal),
                                      (i, w) => w.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, exceptionLocal));

                    writer.EmitInstruction(OpCodeNumber.Rethrow);
                    writer.DetachInstructionSequence();
                }
Exemple #8
0
        private void AddCollectionLoop(LocalVariableSymbol resultVariable, InstructionWriter t,
                                       LocalVariableSymbol enumeratorVariable, LocalVariableSymbol currentVariable)
        {
            t.WhileNotZero(
                c =>
            {
                c.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, enumeratorVariable);
                c.EmitInstructionMethod(OpCodeNumber.Callvirt, MoveNext);
            },
                b =>
            {
                b.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, resultVariable);
                b.EmitInstructionInt32(OpCodeNumber.Ldc_I4, magicNumber);
                b.EmitInstruction(OpCodeNumber.Mul);

                b.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, enumeratorVariable);
                b.EmitInstructionMethod(OpCodeNumber.Callvirt, GetCurrent);
                b.EmitInstructionLocalVariable(OpCodeNumber.Stloc, currentVariable);

                b.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, currentVariable);

                b.IfNotZero(
                    bt =>
                {
                    bt.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, currentVariable);
                    bt.EmitInstructionMethod(OpCodeNumber.Callvirt, Object_GetHashCode);
                },
                    et => { et.EmitInstruction(OpCodeNumber.Ldc_I4_0); });

                b.EmitInstruction(OpCodeNumber.Xor);
                b.EmitInstructionLocalVariable(OpCodeNumber.Stloc, resultVariable);
            });
        }
Exemple #9
0
        private void AddFieldCode(FieldDefDeclaration field, bool isFirst, InstructionWriter writer,
                                  LocalVariableSymbol resultVariable, MethodDefDeclaration method, TypeDefDeclaration enhancedType)
        {
            bool isCollection;
            var  propType           = field.FieldType;
            bool isValueType        = propType.IsValueTypeSafe() == true;
            bool isGenericParameter = false;

            if (propType.TypeSignatureElementKind == TypeSignatureElementKind.GenericParameter ||
                propType.TypeSignatureElementKind == TypeSignatureElementKind.GenericParameterReference)
            {
                // TODO what does this mean?
                // maybe something else also needs to be checked?
                isCollection       = false;
                isGenericParameter = true;
            }
            else
            {
                isCollection = propType.IsCollection() ||
                               propType.TypeSignatureElementKind == TypeSignatureElementKind.Array;
            }

            AddMultiplicityByMagicNumber(isFirst, writer, resultVariable, isCollection);

            if (propType.GetReflectionName().StartsWith("System.Nullable"))
            {
                AddNullableProperty(field, writer);
            }
            else if (isCollection && propType.GetReflectionName() != "System.String")
            {
                AddCollectionCode(field, writer, resultVariable, method, enhancedType);
            }
            else if (isValueType || isGenericParameter)
            {
                LoadVariable(field, writer);
                if (propType.GetReflectionName() != "System.Int32")
                {
                    writer.EmitInstructionType(OpCodeNumber.Box, propType);
                    writer.EmitInstructionMethod(OpCodeNumber.Callvirt, Object_GetHashCode);
                }
            }
            else
            {
                LoadVariable(field, writer);
                AddNormalCode(field, writer, enhancedType);
            }

            if (!isFirst && !isCollection)
            {
                writer.EmitInstruction(OpCodeNumber.Xor);
            }

            if (!isCollection)
            {
                writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, resultVariable);
            }
        }
 protected internal override void OnPopulate(TreeViewCancelEventArgs e)
 {
     for (int i = 0; i < block.LocalVariableSymbolCount; i++)
     {
         LocalVariableSymbol symbol = block.GetLocalVariableSymbol(i);
         TreeNode            node   = new TreeNode(symbol.Name + ": " + symbol.LocalVariable.Ordinal.ToString());
         this.Nodes.Add(node);
     }
 }
Exemple #11
0
        private VariableUseExpression VariableUseExpression()
        {
            LocalVariableSymbol var = symbolTable.GetVar((prev as WordToken).Lexeme);

            if (var == null)
            {
                Error("Undeclared identifier : " + prev);
            }
            return(new VariableUseExpression(var));
        }
Exemple #12
0
        void AddGetEnumerator(InstructionWriter ins, LocalVariableSymbol variable, FieldDefDeclaration field)
        {
            if (field.FieldType.IsValueTypeSafe() == true)
            {
                ins.EmitInstructionType(OpCodeNumber.Box, field.FieldType);
            }

            ins.EmitInstructionMethod(OpCodeNumber.Callvirt, GetEnumerator);
            ins.EmitInstructionLocalVariable(OpCodeNumber.Stloc, variable);
        }
Exemple #13
0
        private static void WriteLocalVariableTo(LocalVariableSymbol symbol, TextWriter writer)
        {
            writer.WriteKeyword(symbol.IsReadOnly ? SyntaxKind.LetKeyword : SyntaxKind.VarKeyword);
            writer.WriteSpace();
            writer.WriteIdentifier(symbol.Name);
            writer.WritePunctuation(SyntaxKind.ColonToken);
            writer.WriteSpace();

            symbol.Type.WriteTo(writer);
        }
Exemple #14
0
        private bool IsLocalAccessibleAfterMove(LocalVariableSymbol symbol, SyntaxBase newParent)
        {
            // find out the scope where the local symbol starts being accessible
            // (the declaration is outside of that node)
            var bindingContainer = GetScopeBindingContainer(symbol);

            // the symbol remains accessible IFF the newParent is the binding container or is below the binding container
            return(ReferenceEquals(newParent, bindingContainer) ||
                   this.semanticModel.SourceFile.Hierarchy.IsDescendant(node: newParent, potentialAncestor: bindingContainer));
        }
Exemple #15
0
 private void AddMultiplicityByMagicNumber(bool isFirst, InstructionWriter writer,
                                           LocalVariableSymbol resultVariable, bool isCollection)
 {
     if (!isFirst && !isCollection)
     {
         writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, resultVariable);
         writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, magicNumber);
         writer.EmitInstruction(OpCodeNumber.Mul);
     }
 }
Exemple #16
0
        protected override BoundStatement RewriteForStatement(BoundForStatement node)
        {
            // for <var> = <lower> to <upper>
            //     <body>
            //
            // ---->
            // {
            //      var <var> = <lower>
            //      let upperBound = <upper>
            //      while (<var> <= upperBound)
            //      {
            //          <body>
            //          continue:
            //          <var> = <var> + 1
            //      }
            // }

            var variableDeclaration   = new BoundVariableDeclaration(node.Variable, node.LowerBound);
            var variableExpression    = new BoundVariableExpression(node.Variable);
            var upperBoundSymbol      = new LocalVariableSymbol("upperBound", true, TypeSymbol.Int);
            var upperBoundDeclaration = new BoundVariableDeclaration(upperBoundSymbol, node.UpperBound);
            var condition             = new BoundBinaryExpression(
                variableExpression,
                BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualsToken, TypeSymbol.Int, TypeSymbol.Int),
                new BoundVariableExpression(upperBoundSymbol)
                );
            var continueLabelStatement = new BoundLabelStatement(node.ContinueLabel);
            var increment = new BoundExpressionStatement(
                new BoundAssignmentExpression(
                    node.Variable,
                    new BoundBinaryExpression(
                        variableExpression,
                        BoundBinaryOperator.Bind(SyntaxKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int),
                        new BoundLiteralExpression(1)
                        )
                    )
                );
            var whileBody = new BoundBlockStatement(
                ImmutableArray.Create <BoundStatement>(
                    node.Body,
                    continueLabelStatement,
                    increment
                    )
                );
            var whileStatement = new BoundWhileStatement(condition, whileBody, node.BreakLabel, GenerateLabel());
            var result         = new BoundBlockStatement(
                ImmutableArray.Create <BoundStatement>(
                    variableDeclaration,
                    upperBoundDeclaration,
                    whileStatement
                    )
                );

            return(RewriteStatement(result));
        }
Exemple #17
0
        /// <summary>
        /// Gets the syntax in which the specified symbol starts being accessible.
        /// </summary>
        /// <param name="symbol">the local variable symbol</param>
        private SyntaxBase GetScopeBindingContainer(LocalVariableSymbol symbol)
        {
            var parent = this.semanticModel.GetSymbolParent(symbol);

            if (parent is LocalScope scope)
            {
                return(scope.BindingSyntax);
            }

            throw new InvalidOperationException($"Unexpected local variable parent type '{parent?.GetType().Name}'");
        }
        private LanguageExpression GetLocalVariableExpression(LocalVariableSymbol localVariableSymbol)
        {
            if (this.localReplacements.TryGetValue(localVariableSymbol, out var replacement))
            {
                // the current context has specified an expression to be used for this local variable symbol
                // to override the regular conversion
                return(replacement);
            }

            var @for = GetEnclosingForExpression(localVariableSymbol);

            return(GetLoopVariableExpression(localVariableSymbol, @for, CreateCopyIndexFunction(@for)));
        }
        private LanguageExpression GetLoopVariableExpression(LocalVariableSymbol localVariableSymbol, ForSyntax @for, LanguageExpression indexExpression)
        {
            return(localVariableSymbol.LocalKind switch
            {
                // this is the "item" variable of a for-expression
                // to emit this, we need to index the array expression by the copyIndex() function
                LocalKind.ForExpressionItemVariable => GetLoopItemVariableExpression(@for, indexExpression),

                // this is the "index" variable of a for-expression inside a variable block
                // to emit this, we need to return a copyIndex(...) function
                LocalKind.ForExpressionIndexVariable => indexExpression,

                _ => throw new NotImplementedException($"Unexpected local variable kind '{localVariableSymbol.LocalKind}'."),
            });
Exemple #20
0
        protected override BoundStatement RewriteForToStatement(BoundForToStatement node)
        {
            // for <var> = <lower> to <upper> <body>
            // --- to --->
            // {
            // var <var> = <lower>
            // let upperBound = <upper>
            // while <var> <= upperBound
            //     <body>
            //     continue:
            //     <var> = <var> + 1
            // }

            var variableDeclaration
                = new BoundVariableDeclarationStatement(node.Variable, node.LowerBound);

            var upperBoundSymbol = new LocalVariableSymbol("upperBound", true, TypeSymbol.Int);
            var upperBoundDeclaration
                = new BoundVariableDeclarationStatement(upperBoundSymbol, node.UpperBound);
            var upperBoundExpression = new BoundVariableExpression(upperBoundSymbol);

            var condition = new BoundBinaryExpression(
                new BoundVariableExpression(node.Variable),
                BoundBinaryOperator.Bind(Lexing.TokenKind.LessOrEquals, TypeSymbol.Int, TypeSymbol.Int),
                upperBoundExpression);

            var increment = new BoundExpressionStatement(
                new BoundAssignmentExpression(
                    node.Variable,
                    new BoundBinaryExpression(
                        new BoundVariableExpression(node.Variable),
                        BoundBinaryOperator.Bind(Lexing.TokenKind.Plus, TypeSymbol.Int, TypeSymbol.Int),
                        new BoundLiteralExpression(1))));

            var whileBlock =
                new BoundBlockStatement(
                    node.Body,
                    increment);

            var whileStatement
                = new BoundWhileStatement(condition, whileBlock, node.BreakLabel, node.ContinueLabel);

            var result = new BoundBlockStatement(
                variableDeclaration,
                upperBoundDeclaration,
                whileStatement);

            return(RewriteStatement(result));
        }
Exemple #21
0
        private void AddCollectionCodeInternal(FieldDefDeclaration field, LocalVariableSymbol resultVariable,
                                               MethodDefDeclaration method, TypeDefDeclaration enhancedType, InstructionWriter writer)
        {
            LoadVariable(field, writer);

            var enumeratorVariable =
                method.MethodBody.RootInstructionBlock.DefineLocalVariable(IEnumeratorType, "enumeratorVariable");
            var currentVariable =
                method.MethodBody.RootInstructionBlock.DefineLocalVariable(
                    method.Module.Cache.GetIntrinsic(IntrinsicType.Object), "enumeratorObject");

            AddGetEnumerator(writer, enumeratorVariable, field);

            AddCollectionLoop(resultVariable, writer, enumeratorVariable, currentVariable);
        }
Exemple #22
0
 private void AddCollectionCode(FieldDefDeclaration field, InstructionWriter writer,
                                LocalVariableSymbol resultVariable, MethodDefDeclaration method, TypeDefDeclaration enhancedType)
 {
     if (field.FieldType.IsValueTypeSafe() == true)
     {
         AddCollectionCodeInternal(field, resultVariable, method, enhancedType, writer);
     }
     else
     {
         LoadVariable(field, writer);
         writer.IfNotZero(
             thenw => { AddCollectionCodeInternal(field, resultVariable, method, enhancedType, thenw); },
             elsew => { });
     }
 }
Exemple #23
0
        protected override BoundStatement RewriteForStatement(BoundForStatement node)
        {
            BoundVariableDeclaration variableDeclaration      = new BoundVariableDeclaration(node.Variable, node.LowerBound);
            BoundVariableExpression  variableExpression       = new BoundVariableExpression(node.Variable);
            VariableSymbol           upperVariableSymbol      = new LocalVariableSymbol("upperBound", true, TypeSymbol.Int);
            BoundVariableDeclaration upperVariableDeclaration = new BoundVariableDeclaration(upperVariableSymbol, node.UpperBound);

            BoundBinaryExpression condition = new BoundBinaryExpression(
                variableExpression,
                BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualsToken, TypeSymbol.Int, TypeSymbol.Int),
                new BoundVariableExpression(upperVariableSymbol)
                );
            BoundLabelStatement      continueLabelStatement = new BoundLabelStatement(node.ContinueLabel);
            BoundExpressionStatement increment = new BoundExpressionStatement(
                new BoundAssignmentExpression(
                    node.Variable,
                    new BoundBinaryExpression(
                        variableExpression,
                        BoundBinaryOperator.Bind(SyntaxKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int),
                        new BoundLiteralExpression(1)
                        )
                    )
                );

            BoundBlockStatement whileBody = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(
                                                                        node.Body,
                                                                        continueLabelStatement,
                                                                        increment
                                                                        ));
            BoundWhileStatement whileStatement = new BoundWhileStatement(condition, whileBody, node.BreakLabel, GenerateLabel());

            BoundBlockStatement result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(
                                                                     variableDeclaration,
                                                                     upperVariableDeclaration,
                                                                     whileStatement
                                                                     ));

            return(RewriteStatement(result));
        }
                private void EmitMessage(InstructionBlock block, InstructionWriter writer,
                                         LogLevel logLevel, string messageFormatString, int[] arguments, ITypeSignature exceptionType = null)
                {
                    MethodDefDeclaration targetMethod = Context.TargetElement as MethodDefDeclaration;

                    if (targetMethod == null)
                    {
                        return;
                    }

                    // TODO: nested types
                    string category = targetMethod.DeclaringType.Name;
                    ILoggingCategoryBuilder builder = this.backendInstance.GetCategoryBuilder(category);

                    InstructionSequence sequence = block.AddInstructionSequence(null, NodePosition.After, null);

                    writer.AttachInstructionSequence(sequence);

                    LocalVariableSymbol exceptionLocal = null;

                    if (exceptionType != null)
                    {
                        exceptionLocal = block.MethodBody.RootInstructionBlock.DefineLocalVariable(
                            exceptionType, DebuggerSpecialNames.GetVariableSpecialName("ex"));
                    }

                    if (builder.SupportsIsEnabled)
                    {
                        builder.EmitGetIsEnabled(writer, logLevel);
                        InstructionSequence branchSequence = block.AddInstructionSequence(null, NodePosition.After, sequence);
                        writer.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, branchSequence);
                    }

                    bool useWrapper = ShouldUseWrapper(targetMethod);

                    Action <InstructionWriter> getExceptionAction = exceptionLocal != null ? (Action <InstructionWriter>)(w => w.EmitInstructionLocalVariable(OpCodeNumber.Stloc, exceptionLocal)) : null;

                    builder.EmitWrite(writer,
                                      messageFormatString,
                                      exceptionType == null ? arguments.Length : arguments.Length + 1,
                                      logLevel,
                                      getExceptionAction,
                                      (i, instructionWriter) =>
                    {
                        if (i < arguments.Length)
                        {
                            int index = arguments[i];
                            if (index == MessageArgumentsFormatter.ThisArgumentPosition)
                            {
                                this.methodMappingWriter.EmitLoadInstance(false, instructionWriter);
                            }
                            else if (index == MessageArgumentsFormatter.ReturnParameterPosition)
                            {
                                instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, Context.ReturnValueVariable);
                                instructionWriter.EmitConvertToObject(
                                    Context.MethodMapping.MethodSignature.ReturnType);
                            }
                            else
                            {
                                this.methodMappingWriter.EmitLoadArgument(index, instructionWriter);

                                instructionWriter.EmitConvertToObject(this.methodMappingWriter.MethodMapping.MethodSignature.GetParameterType(index).GetNakedType(TypeNakingOptions.IgnoreManagedPointers));
                            }
                        }
                        else
                        {
                            //Emit exception parameter
                            instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, exceptionLocal);
                        }
                    },
                                      useWrapper);
                    if (exceptionType == null)
                    {
                        writer.DetachInstructionSequence();
                    }
                }
            public override void Implement(TransformationContext context)
            {
                TypeDefDeclaration typeDef = (TypeDefDeclaration)context.TargetElement;

                ModuleDeclaration module         = this.AspectWeaver.Module;
                ITypeSignature    baseEntityType = module.Cache.GetType(typeof(BaseEntity));

                // Find the base method.
                IMethod         baseCopyToMethod = null;
                IType           baseTypeCursor   = typeDef;
                MethodSignature methodSignature  =
                    new MethodSignature(module, CallingConvention.HasThis, module.Cache.GetIntrinsic(IntrinsicType.Void),
                                        new[] { baseEntityType }, 0);

                while (baseCopyToMethod == null && baseTypeCursor != null)
                {
                    TypeDefDeclaration baseTypeCursorTypeDef = baseTypeCursor.GetTypeDefinition();

                    baseCopyToMethod =
                        baseTypeCursorTypeDef.Methods.GetMethod("CopyTo",
                                                                methodSignature.Translate(baseTypeCursorTypeDef.Module),
                                                                BindingOptions.OnlyExisting |
                                                                BindingOptions.DontThrowException);

                    baseTypeCursor = baseTypeCursorTypeDef.BaseType;
                }

                if (baseCopyToMethod == null)
                {
                    throw new AssertionFailedException("Could not find a method CopyTo.");
                }

                if (baseCopyToMethod.DeclaringType == typeDef)
                {
                    return;
                }


                // Declare the method.
                MethodDefDeclaration methodDef = new MethodDefDeclaration
                {
                    Name       = "CopyTo",
                    Attributes =
                        (MethodAttributes.Family | MethodAttributes.ReuseSlot |
                         MethodAttributes.Virtual),
                    CallingConvention = CallingConvention.HasThis
                };

                typeDef.Methods.Add(methodDef);
                methodDef.CustomAttributes.Add(this.AspectWeaver.AspectInfrastructureTask.WeavingHelper.GetDebuggerNonUserCodeAttribute());

                // Define parameter.
                methodDef.ReturnParameter = new ParameterDeclaration
                {
                    ParameterType = module.Cache.GetIntrinsic(IntrinsicType.Void),
                    Attributes    = ParameterAttributes.Retval
                };

                ParameterDeclaration cloneParameter =
                    new ParameterDeclaration(0, "clone", baseEntityType);

                methodDef.Parameters.Add(cloneParameter);

                // Define the body
                MethodBodyDeclaration methodBody = new MethodBodyDeclaration();

                methodDef.MethodBody = methodBody;
                InstructionBlock instructionBlock = methodBody.CreateInstructionBlock();

                methodBody.RootInstructionBlock = instructionBlock;
                InstructionSequence sequence = methodBody.CreateInstructionSequence();

                instructionBlock.AddInstructionSequence(sequence, NodePosition.After, null);
                using (InstructionWriter writer = new InstructionWriter())
                {
                    writer.AttachInstructionSequence(sequence);

                    // Cast the argument and store it in a local variable.
                    IType typeSpec = GenericHelper.GetTypeCanonicalGenericInstance(typeDef);
                    LocalVariableSymbol castedCloneLocal = instructionBlock.DefineLocalVariable(typeSpec, "typedClone");
                    writer.EmitInstruction(OpCodeNumber.Ldarg_1);
                    writer.EmitInstructionType(OpCodeNumber.Castclass, typeSpec);
                    writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, castedCloneLocal);


                    // TODO: support generic base types.


                    // Call the base method.
                    writer.EmitInstruction(OpCodeNumber.Ldarg_0);
                    writer.EmitInstruction(OpCodeNumber.Ldarg_1);
                    writer.EmitInstructionMethod(OpCodeNumber.Call, (IMethod)baseCopyToMethod.Translate(typeDef.Module));

                    // Loop on all fields and clone cloneable ones.
                    TypeRefDeclaration cloneableTypeRef = (TypeRefDeclaration)
                                                          module.Cache.GetType(typeof(ICloneable));
                    MethodRefDeclaration cloneMethodRef = (MethodRefDeclaration)cloneableTypeRef.MethodRefs.GetMethod(
                        "Clone",
                        new MethodSignature(
                            module,
                            CallingConvention.HasThis,
                            module.Cache.GetIntrinsic(
                                IntrinsicType.Object),
                            new ITypeSignature[0], 0),
                        BindingOptions.Default);

                    foreach (FieldDefDeclaration fieldDef in typeDef.Fields)
                    {
                        if ((fieldDef.Attributes & FieldAttributes.Static) != 0)
                        {
                            continue;
                        }

                        if (fieldDef.FieldType == module.Cache.GetIntrinsic(IntrinsicType.String))
                        {
                            continue;
                        }

                        // Does not work?
                        //bool cloneable = fieldDef.FieldType.Inherits(cloneableTypeRef, GenericMap.Empty);
                        bool cloneable = typeof(ICloneable).IsAssignableFrom(fieldDef.FieldType.GetSystemType(null, null));


                        if (cloneable)
                        {
                            IField fieldSpec   = GenericHelper.GetFieldCanonicalGenericInstance(fieldDef);
                            bool   isValueType =
                                fieldSpec.FieldType.BelongsToClassification(TypeClassifications.ValueType).Equals(
                                    NullableBool.True);

                            InstructionSequence nextSequence = null;
                            if (!isValueType)
                            {
                                nextSequence = methodBody.CreateInstructionSequence();
                                writer.EmitInstruction(OpCodeNumber.Ldarg_0);
                                writer.EmitInstructionField(OpCodeNumber.Ldfld, fieldSpec);
                                writer.EmitBranchingInstruction(OpCodeNumber.Brfalse, nextSequence);
                            }
                            writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, castedCloneLocal);
                            writer.EmitInstruction(OpCodeNumber.Ldarg_0);
                            writer.EmitInstructionField(OpCodeNumber.Ldfld, fieldSpec);
                            if (isValueType)
                            {
                                writer.EmitInstructionType(OpCodeNumber.Box, fieldSpec.FieldType);
                            }
                            //writer.EmitInstructionType(OpCodeNumber.Castclass, cloneableTypeRef);
                            writer.EmitInstructionMethod(OpCodeNumber.Callvirt, cloneMethodRef);
                            if (isValueType)
                            {
                                writer.EmitInstructionType(OpCodeNumber.Unbox, fieldSpec.FieldType);
                                writer.EmitInstructionType(OpCodeNumber.Ldobj, fieldSpec.FieldType);
                            }
                            else
                            {
                                writer.EmitInstructionType(OpCodeNumber.Castclass, fieldSpec.FieldType);
                            }
                            writer.EmitInstructionField(OpCodeNumber.Stfld, fieldSpec);


                            if (!isValueType)
                            {
                                writer.DetachInstructionSequence();
                                instructionBlock.AddInstructionSequence(nextSequence, NodePosition.After, sequence);
                                sequence = nextSequence;
                                writer.AttachInstructionSequence(sequence);
                            }
                        }
                    }

                    writer.EmitInstruction(OpCodeNumber.Ret);
                    writer.DetachInstructionSequence();
                }
            }
Exemple #26
0
        private static BoundVariableDeclaration VariableDeclarationInternal(SyntaxNode syntax, string name, BoundExpression initializer, bool isReadOnly)
        {
            var local = new LocalVariableSymbol(name, isReadOnly, initializer.Type, initializer.ConstantValue);

            return(new BoundVariableDeclaration(syntax, local, initializer));
        }
Exemple #27
0
        /// <inheritdoc/>
        protected override BoundStatement RewriteForEllipsisStatement(BoundForEllipsisStatement node)
        {
            // for <var> := <lower> ... <upper>
            //      <body>
            //
            // ---->
            //
            // {
            //     var <var> = <lower>
            //     const upperBound = <upper>
            //     var step = 1
            //     if <var> greaterthan upperBound {
            //          step = -1
            //     }
            //     goto start
            //     body:
            //     <body>
            //     continue:
            //     <var> = <var> + step
            //     start:
            //     gotoTrue ((step > 0 && lower < upper) || (step < 0 && lower > upper)) body
            //     break:
            // }
            var variableDeclaration   = new BoundVariableDeclaration(node.Variable, node.LowerBound);
            var upperBoundSymbol      = new LocalVariableSymbol("upperBound", isReadOnly: true, type: TypeSymbol.Int);
            var upperBoundDeclaration = new BoundVariableDeclaration(upperBoundSymbol, node.UpperBound);
            var stepBoundSymbol       = new LocalVariableSymbol("step", isReadOnly: false, type: TypeSymbol.Int);
            var stepBoundDeclaration  = new BoundVariableDeclaration(
                variable: stepBoundSymbol,
                initializer: new BoundLiteralExpression(1));
            var variableExpression   = new BoundVariableExpression(node.Variable);
            var upperBoundExpression = new BoundVariableExpression(upperBoundSymbol);
            var stepBoundExpression  = new BoundVariableExpression(stepBoundSymbol);
            var ifLowerIsGreaterThanUpperExpression = new BoundBinaryExpression(
                left: variableExpression,
                op: BoundBinaryOperator.Bind(SyntaxKind.GreaterToken, TypeSymbol.Int, TypeSymbol.Int),
                right: upperBoundExpression);
            var stepBoundAssingment = new BoundExpressionStatement(
                expression: new BoundAssignmentExpression(
                    variable: stepBoundSymbol,
                    expression: new BoundLiteralExpression(-1)));
            var ifLowerIsGreaterThanUpperIfStatement = new BoundIfStatement(
                condition: ifLowerIsGreaterThanUpperExpression,
                thenStatement: stepBoundAssingment,
                elseStatement: null);
            var startLabel             = GenerateLabel();
            var gotoStart              = new BoundGotoStatement(startLabel);
            var bodyLabel              = GenerateLabel();
            var bodyLabelStatement     = new BoundLabelStatement(bodyLabel);
            var continueLabelStatement = new BoundLabelStatement(node.ContinueLabel);
            var increment              = new BoundExpressionStatement(
                expression: new BoundAssignmentExpression(
                    variable: node.Variable,
                    expression: new BoundBinaryExpression(
                        left: variableExpression,
                        op: BoundBinaryOperator.Bind(SyntaxKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int),
                        right: stepBoundExpression)));
            var startLabelStatement           = new BoundLabelStatement(startLabel);
            var zeroLiteralExpression         = new BoundLiteralExpression(0);
            var stepGreaterThanZeroExpression = new BoundBinaryExpression(
                left: stepBoundExpression,
                op: BoundBinaryOperator.Bind(SyntaxKind.GreaterToken, TypeSymbol.Int, TypeSymbol.Int),
                right: zeroLiteralExpression);
            var lowerLessThanUpperExpression = new BoundBinaryExpression(
                left: variableExpression,
                op: BoundBinaryOperator.Bind(SyntaxKind.LessToken, TypeSymbol.Int, TypeSymbol.Int),
                right: upperBoundExpression);
            var positiveStepAndLowerLessThanUpper = new BoundBinaryExpression(
                left: stepGreaterThanZeroExpression,
                op: BoundBinaryOperator.Bind(SyntaxKind.AmpersandAmpersandToken, TypeSymbol.Bool, TypeSymbol.Bool),
                right: lowerLessThanUpperExpression);
            var stepLessThanZeroExpression = new BoundBinaryExpression(
                left: stepBoundExpression,
                op: BoundBinaryOperator.Bind(SyntaxKind.LessToken, TypeSymbol.Int, TypeSymbol.Int),
                right: zeroLiteralExpression);
            var lowerGreaterThanUpperExpression = new BoundBinaryExpression(
                left: variableExpression,
                op: BoundBinaryOperator.Bind(SyntaxKind.GreaterToken, TypeSymbol.Int, TypeSymbol.Int),
                right: upperBoundExpression);
            var negativeStepAndLowerGreaterThanUpper = new BoundBinaryExpression(
                left: stepLessThanZeroExpression,
                op: BoundBinaryOperator.Bind(SyntaxKind.AmpersandAmpersandToken, TypeSymbol.Bool, TypeSymbol.Bool),
                right: lowerGreaterThanUpperExpression);
            var condition = new BoundBinaryExpression(
                positiveStepAndLowerLessThanUpper,
                BoundBinaryOperator.Bind(SyntaxKind.PipePipeToken, TypeSymbol.Bool, TypeSymbol.Bool),
                negativeStepAndLowerGreaterThanUpper);
            var gotoTrue            = new BoundConditionalGotoStatement(bodyLabel, condition, jumpIfTrue: true);
            var breakLabelStatement = new BoundLabelStatement(node.BreakLabel);

            var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>(
                                                     variableDeclaration,
                                                     upperBoundDeclaration,
                                                     stepBoundDeclaration,
                                                     ifLowerIsGreaterThanUpperIfStatement,
                                                     gotoStart,
                                                     bodyLabelStatement,
                                                     node.Body,
                                                     continueLabelStatement,
                                                     increment,
                                                     startLabelStatement,
                                                     gotoTrue,
                                                     breakLabelStatement));

            return(RewriteStatement(result));
        }
 public CreatedEmptyMethod(MethodDefDeclaration methodDeclaration, InstructionBlock principalBlock, LocalVariableSymbol returnVariable, InstructionSequence returnSequence)
 {
     this.MethodDeclaration = methodDeclaration;
     this.PrincipalBlock    = principalBlock;
     this.ReturnVariable    = returnVariable;
     this.ReturnSequence    = returnSequence;
 }
        /// <summary>
        /// Emits the MSIL that calls the logging method with the specified format provider, message and arguments.
        /// </summary>
        /// <param name="emitter">IL emitter.</param>
        /// <param name="log">Field that stores reference to the logger.</param>
        /// <param name="method">Logging method to use. The method must return no value and must take 3 arguments of types <see cref="IFormatProvider"/>, <see cref="string"/> and <see cref="Array"/> of <see cref="object"/>s.</param>
        /// <param name="formatProviderGetter">Getter of the property that returns the <see cref="IFormatProvider"/> instance.</param>
        /// <param name="formatString">Format string for the log.</param>
        /// <param name="args">Variable storing reference to array of arguments for placeholders used in the format string.</param>
        /// <exception cref="ArgumentNullException"><paramref name="emitter"/>, <paramref name="log"/>, <paramref name="formatProviderGetter"/>, <paramref name="formatString"/> or <paramref name="args"/> is <see langword="null"/>.</exception>
        /// <remarks>
        /// <para>Code emitted by this method makes no assumptions on the state of the evaluation stack 
        /// and it leaves the stack unmodified.</para>
        /// </remarks>
        private static void EmitLogProviderStringArgs(InstructionWriter emitter, FieldDefDeclaration log, IMethod method, IMethod formatProviderGetter, string formatString, LocalVariableSymbol args)
        {
            if (emitter == null)
              {
            throw new ArgumentNullException("emitter");
              }
              if (log == null)
              {
            throw new ArgumentNullException("log");
              }
              if (method == null)
              {
            throw new ArgumentNullException("method");
              }
              if (formatProviderGetter == null)
              {
            throw new ArgumentNullException("formatProviderGetter");
              }
              if (args == null)
              {
            throw new ArgumentNullException("args");
              }

              emitter.EmitInstructionField(OpCodeNumber.Ldsfld, GenericHelper.GetCanonicalGenericInstance(log));
              emitter.EmitInstructionMethod(OpCodeNumber.Call, formatProviderGetter);
              emitter.EmitInstructionString(OpCodeNumber.Ldstr, formatString);
              emitter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, args);
              emitter.EmitInstructionMethod(OpCodeNumber.Callvirt, method);
        }
 public ExpressionConverter AppendReplacement(LocalVariableSymbol symbol, LanguageExpression replacement)
 {
     // Allow local variable symbol replacements to be overwritten, as there are scenarios where we recursively generate expressions for the same index symbol
     return(new(this.context, this.localReplacements.SetItem(symbol, replacement)));
 }
 public static void Box_LocalVariableIfNeeded(this InstructionWriter instructionWriter, LocalVariableSymbol symbol)
 {
     instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, symbol);
     EmitBoxIfNeeded(instructionWriter, symbol.LocalVariable.Type);
 }
 public ExpressionConverter AppendReplacement(LocalVariableSymbol symbol, LanguageExpression replacement) =>
 public static void Get_LocalVariable(this InstructionWriter instructionWriter, LocalVariableSymbol symbol)
 {
     instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, symbol);
 }
 public static void AssignValue_ToArrayIndexZero(this InstructionWriter instructionWriter, LocalVariableSymbol array, LocalVariableSymbol value)
 {
     instructionWriter.AssignValue_ToArrayIndexZero(
         array,
         () => instructionWriter.Get_LocalVariable(value));
 }
 public static void AssignValue_LocalVariable(this InstructionWriter instructionWriter, LocalVariableSymbol symbol, Action argument)
 {
     argument();
     instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Stloc_S, symbol);
 }
Exemple #36
0
 public VariableUseExpression(LocalVariableSymbol symbol) : base(symbol.VariableType)
 {
     this.symbol = symbol;
 }
Exemple #37
0
            public override void Implement(TransformationContext context)
            {
                ModuleDeclaration module = this.AspectWeaver.Module;

                TypeDefDeclaration typeDef = (TypeDefDeclaration)context.TargetElement;

                // Declare the method.
                MethodDefDeclaration methodDef = new MethodDefDeclaration
                {
                    Name              = "AutoGeneratedValidate",
                    Attributes        = (MethodAttributes.Family | MethodAttributes.ReuseSlot | MethodAttributes.Virtual),
                    CallingConvention = CallingConvention.HasThis
                };

                typeDef.Methods.Add(methodDef);
                methodDef.CustomAttributes.Add(this.AspectWeaver.AspectInfrastructureTask.WeavingHelper.GetDebuggerNonUserCodeAttribute());

                // Define parameter.
                methodDef.ReturnParameter = new ParameterDeclaration
                {
                    ParameterType = module.Cache.GetIntrinsic(IntrinsicType.Void),
                    Attributes    = ParameterAttributes.Retval
                };

                // Define the body
                MethodBodyDeclaration methodBody = new MethodBodyDeclaration();

                methodDef.MethodBody = methodBody;
                InstructionBlock instructionBlock = methodBody.CreateInstructionBlock();

                methodBody.RootInstructionBlock = instructionBlock;
                InstructionSequence sequence = methodBody.CreateInstructionSequence();

                instructionBlock.AddInstructionSequence(sequence, NodePosition.After, null);

                using (InstructionWriter writer = new InstructionWriter())
                {
                    writer.AttachInstructionSequence(sequence);

                    // Find the base method.
                    IMethod         baseValidateMethod = null;
                    IType           baseTypeCursor     = typeDef.BaseType;
                    MethodSignature methodSignature    =
                        new MethodSignature(module, CallingConvention.HasThis, module.Cache.GetIntrinsic(IntrinsicType.Void),
                                            new ITypeSignature[0], 0);

                    while (baseValidateMethod == null)
                    {
                        TypeDefDeclaration baseTypeCursorTypeDef = baseTypeCursor.GetTypeDefinition();

                        baseValidateMethod =
                            baseTypeCursorTypeDef.Methods.GetMethod("AutoGeneratedValidate",
                                                                    methodSignature.Translate(baseTypeCursorTypeDef.Module),
                                                                    BindingOptions.OnlyExisting |
                                                                    BindingOptions.DontThrowException);

                        baseTypeCursor = baseTypeCursorTypeDef.BaseType;
                    }

                    // TODO: support generic base types.

                    // Call the base method.
                    writer.EmitInstruction(OpCodeNumber.Ldarg_0);
                    writer.EmitInstructionMethod(OpCodeNumber.Call, (IMethod)baseValidateMethod.Translate(typeDef.Module));

                    // Make an array with the boxed field values.
                    TypeValidationAspect aspect = (TypeValidationAspect)this.AspectWeaverInstance.Aspect;
                    LocalVariableSymbol  fieldValuesArrayLocal = instructionBlock.DefineLocalVariable(
                        module.Cache.GetType(typeof(object[])), "fieldValues");
                    writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, aspect.Validators.Count);
                    writer.EmitInstructionType(OpCodeNumber.Newarr, module.Cache.GetIntrinsic(IntrinsicType.Object));
                    writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, fieldValuesArrayLocal);

                    int i = 0;
                    foreach (FieldValidationAttribute validator in aspect.Validators)
                    {
                        FieldDefDeclaration fieldDef = typeDef.Fields.GetByName(validator.TargetLocation.Name);
                        IField fieldSpec             = GenericHelper.GetFieldCanonicalGenericInstance(fieldDef);

                        writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, fieldValuesArrayLocal);
                        writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, i);
                        writer.EmitInstruction(OpCodeNumber.Ldarg_0);
                        writer.EmitInstructionField(OpCodeNumber.Ldfld, fieldSpec);
                        writer.EmitConvertToObject(fieldSpec.FieldType);
                        writer.EmitInstruction(OpCodeNumber.Stelem_Ref);

                        i++;
                    }

                    // Get the validator method.
                    IMethod validateMethod = module.Cache.GetItem(
                        () => module.FindMethod(
                            typeof(TypeValidationAspect).GetMethod("Validate"),
                            BindingOptions.Default));

                    // Call the validator.
                    this.AspectWeaverInstance.AspectRuntimeInstanceField.EmitLoadField(writer, null);
                    writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, fieldValuesArrayLocal);
                    writer.EmitInstructionMethod(OpCodeNumber.Callvirt, validateMethod);

                    writer.EmitInstruction(OpCodeNumber.Ret);
                    writer.DetachInstructionSequence();
                }
            }
        /// <summary>
        /// Emits the MSIL that calls the logging method with the specified message and exception.
        /// </summary>
        /// <param name="emitter">IL emitter.</param>
        /// <param name="log">Field that stores reference to the logger.</param>
        /// <param name="method">Logging method to use. The method must return no value and must take 2 parameters of types <see cref="string"/> and <see cref="Exception"/>.</param>
        /// <param name="message">Message to log.</param>
        /// <param name="exception">Local variable where reference to the exception is stored.</param>
        /// <exception cref="ArgumentNullException"><paramref name="emitter"/>, <paramref name="log"/>, <paramref name="method"/>, <paramref name="message"/> or <paramref name="exception"/> is <see langword="null"/>.</exception>
        /// <remarks>
        /// <para>Code emitted by this method makes no assumptions on the state of the evaluation stack 
        /// and it leaves the stack unmodified.</para>
        /// </remarks>
        private static void EmitLogStringException(InstructionWriter emitter, FieldDefDeclaration log, IMethod method, string message, LocalVariableSymbol exception)
        {
            if (emitter == null)
              {
            throw new ArgumentNullException("emitter");
              }
              if (log == null)
              {
            throw new ArgumentNullException("log");
              }
              if (method == null)
              {
            throw new ArgumentNullException("method");
              }
              if (message == null)
              {
            throw new ArgumentNullException("message");
              }
              if (exception == null)
              {
            throw new ArgumentNullException("exception");
              }

              emitter.EmitInstructionField(OpCodeNumber.Ldsfld, GenericHelper.GetCanonicalGenericInstance(log));
              emitter.EmitInstructionString(OpCodeNumber.Ldstr, message);
              emitter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc_S, exception);
              emitter.EmitInstructionMethod(OpCodeNumber.Callvirt, method);
        }
 public static void Get_AddressOf(this InstructionWriter instructionWriter, LocalVariableSymbol localVariable)
 {
     instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloca, localVariable);
 }