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); }
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(); }