internal override Executable ResolveWithTypeContext(PastelCompiler compiler) { if (this.Target is BracketIndex) { if (this.OpToken.Value != "=") { // Java will need to be special as it will require things to be broken down into a get-then-set. throw new ParserException(this.OpToken, "Incremental assignment on a key/index is not currently supported (although it really ought to be)."); } BracketIndex bi = (BracketIndex)this.Target; string rootType = bi.Root.ResolvedType.RootValue; Expression[] args = new Expression[] { bi.Root, bi.Index, this.Value }; CoreFunction nf; if (rootType == "Array") { nf = CoreFunction.ARRAY_SET; } else if (rootType == "List") { nf = CoreFunction.LIST_SET; } else if (rootType == "Dictionary") { nf = CoreFunction.DICTIONARY_SET; } else { throw new ParserException(bi.BracketToken, "Can't use brackets here."); } return(new ExpressionAsExecutable(new CoreFunctionInvocation( this.FirstToken, nf, args, bi.Owner)).ResolveWithTypeContext(compiler)); } this.Target = this.Target.ResolveWithTypeContext(compiler); this.Value = this.Value.ResolveWithTypeContext(compiler); return(this); }
private static Expression ParseAtomWithSuffix(ParserContext context, TokenStream tokens, TopLevelEntity parent) { Expression root; if (tokens.IsNext("(")) { Token openParen = tokens.Pop(); switch (IdentifyParenthesisSituation(tokens)) { case ParenthesisSituation.CAST: CSharpType castType = CSharpType.Parse(tokens); tokens.PopExpected(")"); Expression castValue = ParseAtomWithSuffix(context, tokens, parent); return(new CastExpression(openParen, castType, castValue, parent)); case ParenthesisSituation.LAMBDA_ARG: List <Token> lambdaArgs = new List <Token>() { tokens.PopWord() }; while (tokens.PopIfPresent(",")) { lambdaArgs.Add(tokens.PopWord()); } tokens.PopExpected(")"); Token arrowToken = tokens.PopExpected("=>"); Executable[] lambdaBody; if (tokens.IsNext("{")) { lambdaBody = ExecutableParser.ParseCodeBlock(context, tokens, parent, true); } else { Expression expr = Parse(context, tokens, parent); lambdaBody = new Executable[] { new ReturnStatement(expr.FirstToken, expr, parent) }; } return(new Lambda(openParen, lambdaArgs, arrowToken, lambdaBody, parent)); case ParenthesisSituation.WRAPPED_EXPRESSION: root = Parse(context, tokens, parent); tokens.PopExpected(")"); break; default: throw new Exception(); // not valid } } else { root = ParseAtom(context, tokens, parent); } bool anythingInteresting = true; string next = tokens.PeekValue(); while (anythingInteresting) { switch (next) { case ".": Token dotToken = tokens.Pop(); Token fieldName = tokens.PopWord(); root = new DotField(root.FirstToken, root, dotToken, fieldName, parent); break; case "[": Token openBracket = tokens.Pop(); Expression index = Parse(context, tokens, parent); tokens.PopExpected("]"); root = new BracketIndex(root, openBracket, index, parent); break; case "<": if (root is DotField) { CSharpType[] functionInvocationTypeSpecification = MaybeParseOutOneOfThoseInlineTypeSpecificationsForFunctionInvocations(tokens); if (functionInvocationTypeSpecification != null) { ((DotField)root).InlineTypeSpecification = functionInvocationTypeSpecification; } else { anythingInteresting = false; } } else { anythingInteresting = false; } break; case "(": Token openParen = tokens.Pop(); List <Expression> args = new List <Expression>(); List <Token> outTokens = new List <Token>(); while (!tokens.PopIfPresent(")")) { if (args.Count > 0) { tokens.PopExpected(","); } if (tokens.IsNext("out")) { outTokens.Add(tokens.Pop()); } else { outTokens.Add(null); } args.Add(Parse(context, tokens, parent)); } root = new FunctionInvocation(root.FirstToken, root, openParen, args, outTokens, parent); break; case "{": // e.g. new List<int>() { 1, 2, 3 }. This only follows a constructor. FunctionInvocation fi = root as FunctionInvocation; ConstructorInvocationFragment cif = fi == null ? null : (ConstructorInvocationFragment)fi.Root; if (root is FunctionInvocation && ((FunctionInvocation)root).Root is ConstructorInvocationFragment) { tokens.Pop(); // { ConstructorSuffixData format = DetermineConstructorSuffixDataFormat(tokens); bool nextAllowed = true; List <Expression> values = new List <Expression>(); List <Expression> kvpKeys = new List <Expression>(); List <Token> propertyNames = new List <Token>(); while (!tokens.PopIfPresent("}")) { if (!nextAllowed) { tokens.PopExpected("}"); // intentionally throw } switch (format) { case ConstructorSuffixData.KVP_ENTRIES: tokens.PopExpected("{"); kvpKeys.Add(Parse(context, tokens, parent)); tokens.PopExpected(","); values.Add(Parse(context, tokens, parent)); tokens.PopExpected("}"); break; case ConstructorSuffixData.PROPERTIES: propertyNames.Add(tokens.PopWord()); tokens.PopExpected("="); values.Add(Parse(context, tokens, parent)); break; case ConstructorSuffixData.SEQUENTIAL_ITEMS: values.Add(Parse(context, tokens, parent)); break; } nextAllowed = tokens.PopIfPresent(","); } cif.InitialDataValues = values.ToArray(); int t = cif.InitialDataValues.Length; if (kvpKeys.Count == t) { cif.InitialDataKeys = kvpKeys.ToArray(); } if (propertyNames.Count == t) { cif.InitialDataPropertyNames = propertyNames.ToArray(); } } else { throw new ParserException(tokens.Peek(), "Unexpected '{'"); } break; default: anythingInteresting = false; break; } next = tokens.PeekValue(); } if (next == "++" || next == "--") { Token incrementToken = tokens.Pop(); root = new InlineIncrement(root.FirstToken, incrementToken, false, root, parent); } return(root); }
public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, Assignment assignment) { Expression target = assignment.Target; Expression value = assignment.Value; ResolvedType targetAssignmentType = target.ResolvedType; if (targetAssignmentType == null) { throw new Exception(); // should be ANY if no type is set. } if (value.ResolvedType == ResolvedType.ANY && targetAssignmentType != ResolvedType.ANY) { value = new Cast(value.FirstToken, targetAssignmentType, value, value.Owner, false); } if (assignment.Op == Ops.EQUALS) { if (assignment.Target is Variable) { Variable varTarget = (Variable)assignment.Target; bcc.CompileExpression(parser, buffer, value, true); VariableId varId = varTarget.VarId; if (varId.UsedByClosure) { buffer.Add(assignment.OpToken, OpCode.ASSIGN_CLOSURE, varId.ClosureID); } else { buffer.Add(assignment.OpToken, OpCode.ASSIGN_LOCAL, varId.ID); } } else if (assignment.Target is BracketIndex) { BracketIndex bi = (BracketIndex)assignment.Target; bcc.CompileExpression(parser, buffer, bi.Root, true); bcc.CompileExpression(parser, buffer, bi.Index, true); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.ASSIGN_INDEX, 0); } else if (assignment.Target is DotField) { DotField dotStep = (DotField)assignment.Target; if (dotStep.Root is ThisKeyword) { bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.ASSIGN_THIS_FIELD, parser.GetId(dotStep.FieldToken.Value)); } else { bcc.CompileExpression(parser, buffer, dotStep.Root, true); bcc.CompileExpression(parser, buffer, value, true); int nameId = parser.GetId(dotStep.FieldToken.Value); int localeScopedNameId = nameId * parser.GetLocaleCount() + parser.GetLocaleId(dotStep.Owner.FileScope.CompilationScope.Locale); buffer.Add( assignment.OpToken, OpCode.ASSIGN_FIELD, nameId, 0, localeScopedNameId, assignment.ClassOwner == null ? -1 : assignment.ClassOwner.ClassID, assignment.CompilationScope.ScopeNumId, -1, 0); } } else if (assignment.Target is FieldReference) { bcc.CompileExpression(parser, buffer, value, true); FieldReference fieldReference = (FieldReference)assignment.Target; if (fieldReference.Field.Modifiers.HasStatic) { buffer.Add( assignment.OpToken, OpCode.ASSIGN_STATIC_FIELD, ((ClassDefinition)fieldReference.Field.Owner).ClassID, fieldReference.Field.StaticMemberID); } else { buffer.Add( assignment.OpToken, OpCode.ASSIGN_THIS_FIELD, fieldReference.Field.MemberID); } } else { throw new Exception("This shouldn't happen."); } } else { Ops op = assignment.Op; if (assignment.Target is Variable) { Variable varTarget = (Variable)assignment.Target; VariableId varId = varTarget.VarId; bool isClosure = varId.UsedByClosure; int scopeId = isClosure ? varId.ClosureID : varId.ID; buffer.Add(varTarget.FirstToken, isClosure ? OpCode.DEREF_CLOSURE : OpCode.LOCAL, scopeId); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op); buffer.Add(assignment.Target.FirstToken, isClosure ? OpCode.ASSIGN_CLOSURE : OpCode.ASSIGN_LOCAL, scopeId); } else if (assignment.Target is DotField) { DotField dotExpr = (DotField)assignment.Target; int fieldId = parser.GetId(dotExpr.FieldToken.Value); int localeScopedStepId = parser.GetLocaleCount() * fieldId + parser.GetLocaleId(dotExpr.Owner.FileScope.CompilationScope.Locale); bcc.CompileExpression(parser, buffer, dotExpr.Root, true); if (!(dotExpr.Root is ThisKeyword)) { buffer.Add(null, OpCode.DUPLICATE_STACK_TOP, 1); } buffer.Add( dotExpr.DotToken, OpCode.DEREF_DOT, fieldId, localeScopedStepId, assignment.ClassOwner == null ? -1 : assignment.ClassOwner.ClassID, assignment.CompilationScope.ScopeNumId, -1, 0); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op); if (dotExpr.Root is ThisKeyword) { buffer.Add(assignment.OpToken, OpCode.ASSIGN_THIS_FIELD, fieldId); } else { int localeScopedNameId = fieldId * parser.GetLocaleCount() + parser.GetLocaleId(dotExpr.Owner.FileScope.CompilationScope.Locale); buffer.Add( assignment.OpToken, OpCode.ASSIGN_FIELD, fieldId, 0, localeScopedNameId, assignment.ClassOwner == null ? -1 : assignment.ClassOwner.ClassID, assignment.CompilationScope.ScopeNumId, -1, 0); } } else if (assignment.Target is BracketIndex) { BracketIndex indexExpr = (BracketIndex)assignment.Target; bcc.CompileExpression(parser, buffer, indexExpr.Root, true); bcc.CompileExpression(parser, buffer, indexExpr.Index, true); buffer.Add(null, OpCode.DUPLICATE_STACK_TOP, 2); buffer.Add(indexExpr.BracketToken, OpCode.INDEX); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op); buffer.Add(assignment.OpToken, OpCode.ASSIGN_INDEX, 0); } else if (assignment.Target is FieldReference) { FieldReference fieldRef = (FieldReference)assignment.Target; FieldReferenceEncoder.Compile(parser, buffer, fieldRef, true); bcc.CompileExpression(parser, buffer, value, true); buffer.Add(assignment.OpToken, OpCode.BINARY_OP, (int)op); if (fieldRef.Field.Modifiers.HasStatic) { buffer.Add( assignment.OpToken, OpCode.ASSIGN_STATIC_FIELD, ((ClassDefinition)fieldRef.Field.Owner).ClassID, fieldRef.Field.StaticMemberID); } else { buffer.Add( assignment.OpToken, OpCode.ASSIGN_THIS_FIELD, fieldRef.Field.MemberID); } } else { throw new ParserException(assignment.OpToken, "Assignment is not allowed on this sort of expression."); } } }
public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, BracketIndex bracketIndex, bool outputUsed) { if (!outputUsed) { throw new ParserException(bracketIndex, "This expression does nothing."); } bcc.CompileExpression(parser, buffer, bracketIndex.Root, true); bcc.CompileExpression(parser, buffer, bracketIndex.Index, true); buffer.Add(bracketIndex.BracketToken, OpCode.INDEX); }
private static Expression ParseEntity(TokenStream tokens, Executable owner) { Expression root; if (tokens.PopIfPresent("(")) { root = Parse(tokens, owner); tokens.PopExpected(")"); } else { root = ParseEntityWithoutSuffixChain(tokens, owner); } bool anySuffixes = true; while (anySuffixes) { if (tokens.IsNext(".")) { Token dotToken = tokens.Pop(); Token stepToken = tokens.Pop(); Parser.VerifyIdentifier(stepToken); root = new DotStep(root, dotToken, stepToken, owner); } else if (tokens.IsNext("[")) { Token openBracket = tokens.Pop(); List <Expression> sliceComponents = new List <Expression>(); if (tokens.IsNext(":")) { sliceComponents.Add(null); } else { sliceComponents.Add(Parse(tokens, owner)); } for (int i = 0; i < 2; ++i) { if (tokens.PopIfPresent(":")) { if (tokens.IsNext(":") || tokens.IsNext("]")) { sliceComponents.Add(null); } else { sliceComponents.Add(Parse(tokens, owner)); } } } tokens.PopExpected("]"); if (sliceComponents.Count == 1) { Expression index = sliceComponents[0]; root = new BracketIndex(root, openBracket, index, owner); } else { root = new ListSlice(root, sliceComponents, openBracket, owner); } } else if (tokens.IsNext("(")) { Token openParen = tokens.Pop(); List <Expression> args = new List <Expression>(); while (!tokens.PopIfPresent(")")) { if (args.Count > 0) { tokens.PopExpected(","); } args.Add(Parse(tokens, owner)); } root = new FunctionCall(root, openParen, args, owner); } else if (tokens.IsNext("is")) { Token isToken = tokens.Pop(); Token classToken = tokens.Pop(); string className = PopClassName(tokens, classToken); root = new IsComparison(root, isToken, classToken, className, owner); } else { anySuffixes = false; } } return(root); }
private Expression ParseEntity(TokenStream tokens, Executable owner) { Expression root; if (tokens.PopIfPresent("(")) { root = this.Parse(tokens, owner); tokens.PopExpected(")"); } else { root = ParseEntityWithoutSuffixChain(tokens, owner); } bool anySuffixes = true; while (anySuffixes) { if (tokens.IsNext(".")) { Token dotToken = tokens.Pop(); Token stepToken = tokens.Pop(); // HACK alert: "class" is a valid field on a class. // ParserVerifyIdentifier is invoked downstream for non-resolved fields. if (stepToken.Value != this.parser.Keywords.CLASS) { this.parser.VerifyIdentifier(stepToken); } root = new DotStep(root, dotToken, stepToken, owner); } else if (tokens.IsNext("[")) { Token openBracket = tokens.Pop(); List <Expression> sliceComponents = new List <Expression>(); if (tokens.IsNext(":")) { sliceComponents.Add(null); } else { sliceComponents.Add(Parse(tokens, owner)); } for (int i = 0; i < 2; ++i) { if (tokens.PopIfPresent(":")) { if (tokens.IsNext(":") || tokens.IsNext("]")) { sliceComponents.Add(null); } else { sliceComponents.Add(Parse(tokens, owner)); } } } tokens.PopExpected("]"); if (sliceComponents.Count == 1) { Expression index = sliceComponents[0]; root = new BracketIndex(root, openBracket, index, owner); } else { root = new ListSlice(root, sliceComponents, openBracket, owner); } } else if (tokens.IsNext("(")) { Token openParen = tokens.Pop(); List <Expression> args = new List <Expression>(); while (!tokens.PopIfPresent(")")) { if (args.Count > 0) { tokens.PopExpected(","); } args.Add(Parse(tokens, owner)); } root = new FunctionCall(root, openParen, args, owner); } else if (tokens.IsNext(this.parser.Keywords.IS)) { Token isToken = tokens.Pop(); Token classToken = tokens.Pop(); string className = this.parser.PopClassNameWithFirstTokenAlreadyPopped(tokens, classToken); root = new IsComparison(root, isToken, classToken, className, owner); } else { anySuffixes = false; } } return(root); }
private Expression ParseEntity(TokenStream tokens, Node owner) { Expression root; Token firstToken = tokens.Peek(); AType castPrefix = firstToken.Value == "(" ? this.MaybeParseCastPrefix(tokens) : null; if (castPrefix != null) { root = this.ParseEntity(tokens, owner); return(new Cast(firstToken, castPrefix, root, owner, true)); } Token maybeOpenParen = tokens.Peek(); if (tokens.PopIfPresent("(")) { if (tokens.PopIfPresent(")")) { root = this.ParseLambda(tokens, firstToken, new AType[0], new Token[0], owner); } else { if (this.parser.CurrentScope.IsStaticallyTyped) { TokenStream.StreamState state = tokens.RecordState(); AType lambdaArgType = this.parser.TypeParser.TryParse(tokens); Token lambdaArg = null; if (lambdaArgType != null) { lambdaArg = tokens.PopIfWord(); } if (lambdaArg != null) { List <AType> lambdaArgTypes = new List <AType>() { lambdaArgType }; List <Token> lambdaArgs = new List <Token>() { lambdaArg }; while (tokens.PopIfPresent(",")) { lambdaArgTypes.Add(this.parser.TypeParser.Parse(tokens)); lambdaArgs.Add(tokens.PopWord()); } tokens.PopExpected(")"); return(this.ParseLambda(tokens, maybeOpenParen, lambdaArgTypes, lambdaArgs, owner)); } else { tokens.RestoreState(state); } } root = this.Parse(tokens, owner); if (root is Variable) { if (tokens.PopIfPresent(")")) { if (tokens.IsNext("=>")) { root = this.ParseLambda(tokens, firstToken, new AType[] { AType.Any(root.FirstToken) }, new Token[] { root.FirstToken }, owner); } } else if (tokens.IsNext(",")) { List <Token> lambdaArgs = new List <Token>() { root.FirstToken }; List <AType> lambdaArgTypes = new List <AType>() { AType.Any(root.FirstToken) }; Token comma = tokens.Peek(); while (tokens.PopIfPresent(",")) { Token nextArg = tokens.Pop(); if (nextArg.Type != TokenType.WORD) { throw new ParserException(comma, "Unexpected comma."); } lambdaArgTypes.Add(AType.Any(nextArg)); lambdaArgs.Add(nextArg); comma = tokens.Peek(); } tokens.PopExpected(")"); root = this.ParseLambda(tokens, firstToken, lambdaArgTypes, lambdaArgs, owner); } else { // This will purposely cause an unexpected token error // since it's none of the above conditions. tokens.PopExpected(")"); } } else { tokens.PopExpected(")"); } } } else { root = ParseEntityWithoutSuffixChain(tokens, owner); } bool anySuffixes = true; bool isPreviousADot = false; while (anySuffixes) { if (tokens.IsNext(".")) { isPreviousADot = true; Token dotToken = tokens.Pop(); Token fieldToken = tokens.Pop(); // HACK alert: "class" is a valid field on a class. // ParserVerifyIdentifier is invoked downstream for non-resolved fields. if (fieldToken.Value != this.parser.Keywords.CLASS) { this.parser.VerifyIdentifier(fieldToken); } root = new DotField(root, dotToken, fieldToken, owner); } else if (tokens.IsNext("[")) { Token openBracket = tokens.Pop(); List <Expression> sliceComponents = new List <Expression>(); if (tokens.IsNext(":")) { sliceComponents.Add(null); } else { sliceComponents.Add(Parse(tokens, owner)); } for (int i = 0; i < 2; ++i) { if (tokens.PopIfPresent(":")) { if (tokens.IsNext(":") || tokens.IsNext("]")) { sliceComponents.Add(null); } else { sliceComponents.Add(Parse(tokens, owner)); } } } tokens.PopExpected("]"); if (sliceComponents.Count == 1) { Expression index = sliceComponents[0]; root = new BracketIndex(root, openBracket, index, owner); } else { root = new ListSlice(root, sliceComponents, openBracket, owner); } } else if (tokens.IsNext("(")) { Token openParen = tokens.Pop(); List <Expression> args = new List <Expression>(); while (!tokens.PopIfPresent(")")) { if (args.Count > 0) { tokens.PopExpected(","); } args.Add(Parse(tokens, owner)); } root = new FunctionCall(root, openParen, args, owner); } else if (tokens.IsNext(this.parser.Keywords.IS)) { Token isToken = tokens.Pop(); Token classToken = tokens.Pop(); string className = this.parser.PopClassNameWithFirstTokenAlreadyPopped(tokens, classToken); root = new IsComparison(root, isToken, classToken, className, owner); } else if (isPreviousADot && this.parser.IsCSharpCompat && tokens.IsNext("<")) { TokenStream.StreamState s = tokens.RecordState(); Token openBracket = tokens.Pop(); AType funcType = this.parser.TypeParser.TryParse(tokens); List <AType> types = new List <AType>() { funcType }; if (funcType != null) { while (tokens.PopIfPresent(",")) { types.Add(this.parser.TypeParser.Parse(tokens)); } } if (funcType == null) { anySuffixes = false; tokens.RestoreState(s); } else if (!tokens.PopIfPresent(">") || !tokens.IsNext("(")) { anySuffixes = false; tokens.RestoreState(s); } else { // TODO(acrylic-conversion): do something with this types list. } } else { anySuffixes = false; } } return(root); }
public static void Compile(ByteCodeCompiler bcc, ParserContext parser, ByteBuffer buffer, Increment increment, bool outputUsed) { if (!outputUsed) { throw new Exception("This should have been optimized into a += or -="); } if (increment.Root is Variable) { // OpCode re-use be damned. This should be not one, but two top-level op codes. // INCREMENT_INLINE and INCREMENT_POP (depending on whether outputUsed is true) // In fact, the code here in its current form is actually WRONG because someString++ will have // a '1' appended to it when it really should be an error if the variable is not an integer. // Same for the others below. Ideally the DUPLICATE_STACK_TOP op should be removed. Variable variable = (Variable)increment.Root; VariableId varId = variable.VarId; bool isClosureVar = varId.UsedByClosure; int scopeId = isClosureVar ? varId.ClosureID : varId.ID; bcc.CompileExpression(parser, buffer, increment.Root, true); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); buffer.Add(variable.FirstToken, isClosureVar ? OpCode.ASSIGN_CLOSURE : OpCode.ASSIGN_LOCAL, scopeId); } else { buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(variable.FirstToken, isClosureVar ? OpCode.ASSIGN_CLOSURE : OpCode.ASSIGN_LOCAL, scopeId); } } else if (increment.Root is BracketIndex) { BracketIndex bracketIndex = (BracketIndex)increment.Root; bcc.CompileExpression(parser, buffer, bracketIndex.Root, true); bcc.CompileExpression(parser, buffer, bracketIndex.Index, true); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 2); buffer.Add(bracketIndex.BracketToken, OpCode.INDEX); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_INDEX, 1); } else { buffer.Add(increment.IncrementToken, OpCode.STACK_INSERTION_FOR_INCREMENT); buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_INDEX, 0); } } else if (increment.Root is DotField) { DotField dotStep = (DotField)increment.Root; bcc.CompileExpression(parser, buffer, dotStep.Root, true); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); int nameId = parser.GetId(dotStep.FieldToken.Value); int localeScopedNameId = nameId * parser.GetLocaleCount() + parser.GetLocaleId(dotStep.Owner.FileScope.CompilationScope.Locale); int originClassId = increment.ClassOwner == null ? -1 : increment.ClassOwner.ClassID; int originAssemblyId = increment.CompilationScope.ScopeNumId; buffer.Add( dotStep.DotToken, OpCode.DEREF_DOT, nameId, localeScopedNameId, originClassId, increment.CompilationScope.ScopeNumId, -1, 0); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_FIELD, nameId, 1, localeScopedNameId, originClassId, originAssemblyId, -1, 0); } else { buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 2); buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.ASSIGN_FIELD, nameId, 0, localeScopedNameId, originClassId, originAssemblyId, -1, 0); buffer.Add(increment.IncrementToken, OpCode.STACK_SWAP_POP); } } else if (increment.Root is FieldReference) { FieldReference fr = (FieldReference)increment.Root; bool isStatic = fr.Field.Modifiers.HasStatic; ClassDefinition cd = (ClassDefinition)fr.Field.Owner; int memberId = isStatic ? fr.Field.StaticMemberID : fr.Field.MemberID; bcc.CompileExpression(parser, buffer, fr, true); if (increment.IsPrefix) { buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); } else { buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1); buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1)); buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)Ops.ADDITION : (int)Ops.SUBTRACTION); } Token token = increment.IsPrefix ? increment.FirstToken : fr.FirstToken; if (isStatic) { buffer.Add(token, OpCode.ASSIGN_STATIC_FIELD, ((ClassDefinition)fr.Field.Owner).ClassID, memberId); } else { buffer.Add(token, OpCode.ASSIGN_THIS_FIELD, memberId); } } else { throw new ParserException(increment.IncrementToken, "Cannot apply " + (increment.IsIncrement ? "++" : "--") + " to this sort of expression."); } }