Beispiel #1
0
        public override BoundNode VisitElementAccessExpression(ElementAccessExpressionSyntax node)
        {
            BoundExpression accessExpression = VisitExpression(node.Expression);

            // if (node.ArgumentList.Arguments.Count != 1)
            //     throw new NotSupportedException("UdonSharp does not currently support multidimensional arrays", node.GetLocation());

            if (accessExpression.ValueType == Context.GetTypeSymbol(SpecialType.System_String))
            {
                return(new BoundStringAccessExpression(Context, node, accessExpression, VisitExpression(node.ArgumentList.Arguments[0].Expression, Context.GetTypeSymbol(SpecialType.System_Int32))));
            }

            PropertySymbol accessorSymbol = GetSymbol(node) as PropertySymbol;

            BoundExpression[] indexers = new BoundExpression[node.ArgumentList.Arguments.Count];

            // There's some extern/user defined indexer, so use that
            if (accessorSymbol != null)
            {
                for (int i = 0; i < indexers.Length; ++i)
                {
                    indexers[i] = VisitExpression(node.ArgumentList.Arguments[i].Expression, accessorSymbol.Parameters[i].Type);
                }

                return(BoundAccessExpression.BindElementAccess(Context, node, accessorSymbol, accessExpression, indexers));
            }

            for (int i = 0; i < indexers.Length; ++i)
            {
                indexers[i] = VisitExpression(node.ArgumentList.Arguments[i].Expression, typeof(int));
            }

            return(BoundAccessExpression.BindElementAccess(Context, node, accessExpression, indexers));
        }
        public override Value EmitValue(EmitContext context)
        {
            Value returnValue = base.EmitValue(context);

            if (Initializers != null)
            {
                BoundAccessExpression arrayAccess = BoundAccessExpression.BindAccess(returnValue);
                TypeSymbol            intType     = context.GetTypeSymbol(SpecialType.System_Int32);

                using (context.InterruptAssignmentScope())
                {
                    // This is quite wasteful for allocations in the compile, todo: look at caching these safely
                    for (int i = 0; i < Initializers.Length; ++i)
                    {
                        BoundAccessExpression elementAccess = BoundAccessExpression.BindElementAccess(context,
                                                                                                      SyntaxNode, arrayAccess,
                                                                                                      new BoundExpression[]
                                                                                                      { new BoundConstantExpression(new ConstantValue <int>(i), intType, SyntaxNode) });
                        context.EmitSet(elementAccess, Initializers[i]);
                    }
                }
            }

            return(returnValue);
        }
        public override Value EmitValue(EmitContext context)
        {
            Value returnValue;

            if (context.IsRecursiveMethodEmit)
            {
                using (context.InterruptAssignmentScope())
                {
                    returnValue = context.EmitValue(new BoundArrayCreationExpression(SyntaxNode, context, ArrayType,
                                                                                     new BoundExpression[]
                    {
                        BoundAccessExpression.BindAccess(
                            context.GetConstantValue(context.GetTypeSymbol(SpecialType.System_Int32),
                                                     Initializers.Length))
                    }, null));
                }
            }
            else
            {
                returnValue = context.CreateGlobalInternalValue(ArrayType);
                returnValue.DefaultValue = Activator.CreateInstance(ArrayType.UdonType.SystemType, Initializers.Length);
            }

            BoundAccessExpression arrayAccess = BoundAccessExpression.BindAccess(returnValue);
            TypeSymbol            intType     = context.GetTypeSymbol(SpecialType.System_Int32);

            // This is quite wasteful for allocations in the compile, todo: look at caching these safely
            for (int i = 0; i < Initializers.Length; ++i)
            {
                BoundAccessExpression elementAccess = BoundAccessExpression.BindElementAccess(context, SyntaxNode, arrayAccess, new BoundExpression[] { new BoundConstantExpression(new ConstantValue <int>(i), intType, SyntaxNode) });
                context.EmitSet(elementAccess, Initializers[i]);
            }

            return(returnValue);
        }
Beispiel #4
0
        public override void Emit(EmitContext context)
        {
            var blockScope = context.OpenBlockScope();

            TypeSymbol intType = context.GetTypeSymbol(SpecialType.System_Int32);

            MethodSymbol   toCharArrayMethod = context.GetTypeSymbol(SpecialType.System_String).GetMembers <MethodSymbol>("ToCharArray", context).First(e => e.Parameters.Length == 0);
            PropertySymbol lengthProperty    = context.GetTypeSymbol(SpecialType.System_Array).GetMember <PropertySymbol>("Length", context);

            Value iteratorValue = context.EmitValue(BoundInvocationExpression.CreateBoundInvocation(context, SyntaxNode, toCharArrayMethod, IteratorSource, new BoundExpression[] {}));

            iteratorValue.MarkUsedRecursively();
            var iteratorAccess = BoundAccessExpression.BindAccess(iteratorValue);

            Value arraySize = context.CreateInternalValue(intType);

            arraySize.MarkUsedRecursively();

            BoundAccessExpression getLength = BoundAccessExpression.BindAccess(context, SyntaxNode, lengthProperty, iteratorAccess);

            context.EmitValueAssignment(arraySize, getLength);

            // Declare and reset incrementor value
            Value incrementorValue = context.CreateInternalValue(intType);

            incrementorValue.MarkUsedRecursively();
            context.EmitValueAssignment(incrementorValue, BoundAccessExpression.BindAccess(context.GetConstantValue(intType, 0)));

            JumpLabel loopLabel = context.Module.CreateLabel();

            context.Module.LabelJump(loopLabel);

            var incrementorAccess = BoundAccessExpression.BindAccess(incrementorValue);

            BoundExpression increment = new BoundInvocationExpression.BoundPrefixOperatorExpression(context, SyntaxNode,
                                                                                                    incrementorAccess, new ExternSynthesizedOperatorSymbol(BuiltinOperatorType.Addition, intType, context));

            var lengthCheck = BoundInvocationExpression.CreateBoundInvocation(context, SyntaxNode,
                                                                              new ExternSynthesizedOperatorSymbol(BuiltinOperatorType.LessThan, intType, context), null,
                                                                              new BoundExpression[]
            {
                incrementorAccess,
                BoundAccessExpression.BindAccess(arraySize)
            });

            JumpLabel exitLoopLabel = context.PushBreakLabel();
            JumpLabel continueLabel = context.PushContinueLabel();

            Value lengthCheckResult = context.EmitValue(lengthCheck);

            context.Module.AddJumpIfFalse(exitLoopLabel, lengthCheckResult);

            context.EmitValueAssignment(context.GetUserValue(ValueSymbol),
                                        BoundAccessExpression.BindElementAccess(context, SyntaxNode, iteratorAccess,
                                                                                new BoundExpression[] { incrementorAccess }));

            context.Emit(BodyStatement);

            context.Module.LabelJump(continueLabel);

            context.Emit(increment);

            context.Module.AddJump(loopLabel);

            context.Module.LabelJump(exitLoopLabel);

            context.PopBreakLabel();
            context.PopContinueLabel();

            blockScope.Dispose();
        }