public void VisitPostfixDecrement(PostfixDecrement node) { if (node.Operand is VarAccess) { var varDef = GetVarDefinition((VarAccess)node.Operand); _emitter.Emit(OpCodes.Ldloc, varDef); if (!node.IsStatementExpression) { _emitter.Emit(OpCodes.Dup); } _emitter.Emit(OpCodes.Ldc_I4_1); _emitter.Emit(OpCodes.Sub); _emitter.Emit(OpCodes.Stloc, varDef); return; } throw new SemanticException("Posfix decrement is supported only for variables"); }
public static T DecreaseAndGetOriginal <T>(ref T value) => PostfixDecrement <T> .Invoke(ref value);
public void VisitPostfixDecrement(PostfixDecrement node) => InferSimpleType(node.Operand);
private Expression ParsePrimaryExpression(TokenSet followers) //^ ensures followers[this.currentToken] || this.currentToken == Token.EndOfFile; { ISourceLocation sctx = this.scanner.SourceLocationOfLastScannedToken; Expression expression = new DummyExpression(sctx); switch (this.currentToken) { case Token.ArgList: this.GetNextToken(); expression = new RuntimeArgumentHandleExpression(sctx); break; case Token.Delegate: expression = this.ParseAnonymousMethod(followers); break; case Token.New: expression = this.ParseNew(followers|Token.Dot|Token.LeftBracket|Token.Arrow); break; case Token.Identifier: expression = this.ParseSimpleName(followers|Token.Dot|Token.DoubleColon|Token.Lambda|Token.LeftParenthesis); if (this.currentToken == Token.DoubleColon) { if (((SimpleName)expression).Name == this.nameTable.global) expression = new RootNamespaceExpression(expression.SourceLocation); expression = this.ParseQualifiedName(expression, followers|Token.Dot|Token.LessThan|Token.LeftParenthesis|Token.AddOne|Token.SubtractOne); } else if (this.currentToken == Token.Lambda) { expression = this.ParseLambda((SimpleName)expression, followers); } break; case Token.Null: expression = new NullLiteral(sctx); this.GetNextToken(); break; case Token.True: expression = new CompileTimeConstant(true, false, sctx); this.GetNextToken(); break; case Token.False: expression = new CompileTimeConstant(false, false, sctx); this.GetNextToken(); break; case Token.CharLiteral: expression = new CompileTimeConstant(this.scanner.charLiteralValue, false, sctx); this.GetNextToken(); break; case Token.HexLiteral: expression = this.ParseHexLiteral(); break; case Token.IntegerLiteral: expression = this.ParseIntegerLiteral(); break; case Token.RealLiteral: expression = this.ParseRealLiteral(); break; case Token.StringLiteral: expression = new CompileTimeConstant(this.scanner.GetString(), false, sctx); this.GetNextToken(); break; case Token.This: expression = new ThisReference(sctx); this.GetNextToken(); break; case Token.Base: expression = new BaseClassReference(sctx); this.GetNextToken(); break; case Token.Typeof: case Token.Sizeof: case Token.Default: expression = this.ParseTypeofSizeofOrDefault(followers); break; case Token.Stackalloc: return this.ParseStackalloc(followers); case Token.Checked: case Token.MakeRef: case Token.RefType: case Token.Unchecked: expression = this.ParseCheckedOrMakeRefOrRefTypeOrUnchecked(followers); break; case Token.RefValue: expression = this.ParseGetValueOfTypedReference(followers); break; case Token.Bool: case Token.Decimal: case Token.Sbyte: case Token.Byte: case Token.Short: case Token.Ushort: case Token.Int: case Token.Uint: case Token.Long: case Token.Ulong: case Token.Char: case Token.Float: case Token.Double: case Token.Object: case Token.String: expression = this.RootQualifiedNameFor(this.currentToken, sctx); this.GetNextToken(); break; case Token.LeftParenthesis: expression = this.ParseCastExpression(followers|Token.Dot|Token.LeftBracket|Token.Arrow); break; default: if (Parser.IdentifierOrNonReservedKeyword[this.currentToken]) goto case Token.Identifier; if (Parser.InfixOperators[this.currentToken]) { this.HandleError(Error.InvalidExprTerm, this.scanner.GetTokenSource()); //^ assume this.currentToken != Token.EndOfFile; //should not be a member of InfixOperators this.GetNextToken(); } else this.SkipTo(followers|Parser.PrimaryStart, Error.InvalidExprTerm, this.scanner.GetTokenSource()); if (Parser.PrimaryStart[this.currentToken]) return this.ParsePrimaryExpression(followers); goto done; } expression = this.ParseIndexerCallOrSelector(expression, followers|Token.AddOne|Token.SubtractOne); for (; ; ) { switch (this.currentToken) { case Token.AddOne: SourceLocationBuilder slb = new SourceLocationBuilder(expression.SourceLocation); slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); expression = new PostfixIncrement(new TargetExpression(expression), slb); break; case Token.SubtractOne: slb = new SourceLocationBuilder(expression.SourceLocation); slb.UpdateToSpan(this.scanner.SourceLocationOfLastScannedToken); this.GetNextToken(); expression = new PostfixDecrement(new TargetExpression(expression), slb); break; case Token.Arrow: case Token.Dot: case Token.LeftBracket: expression = this.ParseIndexerCallOrSelector(expression, followers|Token.AddOne|Token.SubtractOne); break; default: goto done; } } done: this.SkipTo(followers); return expression; }