/// <summary> /// Evaluates this node and all of its children /// </summary> /// <param name="scope">The scope of this statement</param> /// <returns></returns> public override Statement Evaluate(Scope scope) { // Check if left-side expression is assignable if (!(leftSide is AssignableExpression)) { // Issue error Compiler.Compiler.errors.SemErr(t.line, t.col, "Left side cannot be assigned to"); return this; } // Evaluate both expressions leftSide = leftSide.Evaluate(scope); rightSide = rightSide.Evaluate(scope); return this; }
/// <summary> /// Adds an agrument expression to the argument list /// </summary> /// <param name="expr">Argument expression</param> public void AddArgument(Expression expr) { arguments.Add(expr); }
/// <summary> /// Evaluates this node and all its children /// </summary> /// <param name="scope">The scope of this expression</param> /// <returns></returns> public override Expression Evaluate(Scope scope) { // Evaluate operands leftOperand = leftOperand.Evaluate(scope); rightOperand = rightOperand.Evaluate(scope); // Check if both operands are of the same type if (leftOperand.returnType.ToCLRType() != rightOperand.returnType.ToCLRType()) { // If not, check if left operand can be implicitely typecasted to right operand type if (leftOperand.returnType.IsCompatible(rightOperand.returnType)) { // Create implicit cast CastExpression implicitCast = new CastExpression(rightOperand.returnType); implicitCast.operand = leftOperand; // Evaluate typecast for folding this.leftOperand = implicitCast.Evaluate(scope); // Set return type this.returnType = rightOperand.returnType; } // If not, check if right operand can be implicitely typecasted to left operand type else if (rightOperand.returnType.IsCompatible(leftOperand.returnType)) { // Create implicit cast CastExpression implicitCast = new CastExpression(leftOperand.returnType); implicitCast.operand = rightOperand; // Evaluate for folding this.rightOperand = implicitCast.Evaluate(scope); // Set return type this.returnType = leftOperand.returnType; } else { // Types are incompatible - issue error Compiler.Compiler.errors.SemErr(t.line, t.col, "Incompatible types"); this.returnType = PrimitiveType.UNSUPPORTED; return this; } } // If operands are of the same type else { // Set return type this.returnType = leftOperand.returnType; } // If operand is not arithmetic, overwrite return type if ((int)op >= 6) { this.returnType = PrimitiveType.BOOL; } // Check if operator and operands are compatible switch (op) { // Addition is accepted for strings and numeric types case BinaryOperator.Add: // If type is not string, check if it is numerical if (!leftOperand.returnType.Equals(PrimitiveType.STRING)) { goto case BinaryOperator.Leq; } break; // Other arithmetic operators and comparisons (except equals and not equals) are accepted for numeric types case BinaryOperator.Sub: case BinaryOperator.Mul: case BinaryOperator.Div: case BinaryOperator.Gt: case BinaryOperator.Lt: case BinaryOperator.Geq: case BinaryOperator.Leq: // Check if type is not integer or double if (!leftOperand.returnType.Equals(PrimitiveType.INT) && !leftOperand.returnType.Equals(PrimitiveType.DOUBLE)) { // Issue error Compiler.Compiler.errors.SemErr(t.line, t.col, "Arithmetic operator can only be applied to numerical types"); } break; // Modulo operator is accepted only for integer type case BinaryOperator.Rem: // Check if type is not integer if (!leftOperand.returnType.Equals(PrimitiveType.INT)) { // Issue error Compiler.Compiler.errors.SemErr(t.line, t.col, "Reminder operator can only be applied to integer type"); } break; // Equality and non equality are accepted for all types case BinaryOperator.Eq: case BinaryOperator.Neq: break; // Default case stands for logical operators default: // Check if type is not boolean if (!leftOperand.returnType.Equals(PrimitiveType.BOOL)) { // Issue error Compiler.Compiler.errors.SemErr(t.line, t.col, "Logical operator can only be applied to boolean type"); } break; } // If both operands are constant expressions, perform constant folding if ((leftOperand is ConstantExpression) && (rightOperand is ConstantExpression)) { // Compile time evaluation of expressions is done based on type and operator // If type is boolean if (leftOperand.returnType.Equals(PrimitiveType.BOOL)) { switch (op) { // Compute equality case BinaryOperator.Eq: // Cast values to bool, compare and create new constant expression return new ConstantExpression(Primitive.Bool, (bool)(leftOperand as ConstantExpression).value == (bool)(rightOperand as ConstantExpression).value); // Compute non-equality case BinaryOperator.Neq: // Same as exclusive or for boolean values goto case BinaryOperator.Xor; // Compute logical and case BinaryOperator.And: // Cast values to bool, apply operation and create constant expression return new ConstantExpression(Primitive.Bool, (bool)(leftOperand as ConstantExpression).value && (bool)(rightOperand as ConstantExpression).value); // Compute logical or case BinaryOperator.Or: // Cast values to bool, apply operation and create constant expression return new ConstantExpression(Primitive.Bool, (bool)(leftOperand as ConstantExpression).value || (bool)(rightOperand as ConstantExpression).value); // Compute logical exclusive or case BinaryOperator.Xor: // Cast values to bool, apply operation and create constant expression (xor is equivalent to a // non-equality check) return new ConstantExpression(Primitive.Bool, (bool)(leftOperand as ConstantExpression).value != (bool)(rightOperand as ConstantExpression).value); } } // If type is double else if (leftOperand.returnType.Equals(PrimitiveType.DOUBLE)) { switch (op) { // Compute equality case BinaryOperator.Eq: // Cast values to double, apply operation and create constant (boolean) expression return new ConstantExpression(Primitive.Bool, (double)(leftOperand as ConstantExpression).value == (double)(rightOperand as ConstantExpression).value); // Compute non-equality case BinaryOperator.Neq: // Cast values to double, apply operation and create constant (boolean) expression return new ConstantExpression(Primitive.Bool, (double)(leftOperand as ConstantExpression).value != (double)(rightOperand as ConstantExpression).value); // Compute greater than case BinaryOperator.Gt: // Cast values to double, apply operation and create constant (boolean) expression return new ConstantExpression(Primitive.Bool, (double)(leftOperand as ConstantExpression).value > (double)(rightOperand as ConstantExpression).value); // Compute greater than or equal to case BinaryOperator.Geq: // Cast values to double, apply operation and create constant (boolean) expression return new ConstantExpression(Primitive.Bool, (double)(leftOperand as ConstantExpression).value >= (double)(rightOperand as ConstantExpression).value); // Compute less than case BinaryOperator.Lt: // Cast values to double, apply operation and create constant (boolean) expression return new ConstantExpression(Primitive.Bool, (double)(leftOperand as ConstantExpression).value < (double)(rightOperand as ConstantExpression).value); // Compute less than or equal to case BinaryOperator.Leq: // Cast values to double, apply operation and create constant (boolean) expression return new ConstantExpression(Primitive.Bool, (double)(leftOperand as ConstantExpression).value <= (double)(rightOperand as ConstantExpression).value); // Compute addition case BinaryOperator.Add: // Cast values to double, apply operation and create constant expression return new ConstantExpression(Primitive.Double, ((double)(leftOperand as ConstantExpression).value + (double)(rightOperand as ConstantExpression).value).ToString(NumberFormatInfo.InvariantInfo)); // Compute subtraction case BinaryOperator.Sub: // Cast values to double, apply operation and create constant expression return new ConstantExpression(Primitive.Double, ((double)(leftOperand as ConstantExpression).value - (double)(rightOperand as ConstantExpression).value).ToString(NumberFormatInfo.InvariantInfo)); // Compute multiplication case BinaryOperator.Mul: // Cast values to double, apply operation and create constant expression return new ConstantExpression(Primitive.Double, ((double)(leftOperand as ConstantExpression).value * (double)(rightOperand as ConstantExpression).value).ToString(NumberFormatInfo.InvariantInfo)); // Compute division case BinaryOperator.Div: // Cast values to double, apply operation and create constant expression return new ConstantExpression(Primitive.Double, ((double)(leftOperand as ConstantExpression).value / (double)(rightOperand as ConstantExpression).value).ToString(NumberFormatInfo.InvariantInfo)); } } // If type is integer else if (leftOperand.returnType.Equals(PrimitiveType.INT)) { switch (op) { // Compute equality case BinaryOperator.Eq: // Cast values to int, apply operation and create constant (boolean) expression return new ConstantExpression(Primitive.Bool, (int)(leftOperand as ConstantExpression).value == (int)(rightOperand as ConstantExpression).value); // Compute non-equality case BinaryOperator.Neq: // Cast values to int, apply operation and create constant (boolean) expression return new ConstantExpression(Primitive.Bool, (int)(leftOperand as ConstantExpression).value != (int)(rightOperand as ConstantExpression).value); // Compute greater than case BinaryOperator.Gt: // Cast values to int, apply operation and create constant (boolean) expression return new ConstantExpression(Primitive.Bool, (int)(leftOperand as ConstantExpression).value > (int)(rightOperand as ConstantExpression).value); // Compute greater than or equal to case BinaryOperator.Geq: // Cast values to int, apply operation and create constant (boolean) expression return new ConstantExpression(Primitive.Bool, (int)(leftOperand as ConstantExpression).value >= (int)(rightOperand as ConstantExpression).value); // Compute less than case BinaryOperator.Lt: // Cast values to int, apply operation and create constant (boolean) expression return new ConstantExpression(Primitive.Bool, (int)(leftOperand as ConstantExpression).value < (int)(rightOperand as ConstantExpression).value); // Compute less than or equal to case BinaryOperator.Leq: // Cast values to int, apply operation and create constant (boolean) expression return new ConstantExpression(Primitive.Bool, (int)(leftOperand as ConstantExpression).value <= (int)(rightOperand as ConstantExpression).value); // Compute addition case BinaryOperator.Add: // Cast values to int, apply operation and create constant expression return new ConstantExpression(Primitive.Int, ((int)(leftOperand as ConstantExpression).value + (int)(rightOperand as ConstantExpression).value).ToString(NumberFormatInfo.InvariantInfo)); // Compute subtraction case BinaryOperator.Sub: // Cast values to int, apply operation and create constant expression return new ConstantExpression(Primitive.Int, ((int)(leftOperand as ConstantExpression).value - (int)(rightOperand as ConstantExpression).value).ToString(NumberFormatInfo.InvariantInfo)); // Compute multiplication case BinaryOperator.Mul: // Cast values to int, apply operation and create constant expression return new ConstantExpression(Primitive.Int, ((int)(leftOperand as ConstantExpression).value * (int)(rightOperand as ConstantExpression).value).ToString(NumberFormatInfo.InvariantInfo)); // Compute division case BinaryOperator.Div: // Cast values to int, apply operation and create constant expression return new ConstantExpression(Primitive.Int, ((int)(leftOperand as ConstantExpression).value / (int)(rightOperand as ConstantExpression).value).ToString(NumberFormatInfo.InvariantInfo)); // Compute modulo case BinaryOperator.Rem: // Cast values to int, apply operation and create constant expression return new ConstantExpression(Primitive.Int, ((int)(leftOperand as ConstantExpression).value % (int)(rightOperand as ConstantExpression).value).ToString(NumberFormatInfo.InvariantInfo)); } } // If type is string else if (leftOperand.returnType.Equals(PrimitiveType.STRING)) { switch (op) { // Compute equality case BinaryOperator.Eq: // Convert values to string, apply operation and create constant (boolean) expression return new ConstantExpression(Primitive.Bool, (leftOperand as ConstantExpression).value.ToString() == (rightOperand as ConstantExpression).value.ToString()); // Compute non-equality case BinaryOperator.Neq: // Convert values to string, apply operation and create constant (boolean) expression return new ConstantExpression(Primitive.Bool, (leftOperand as ConstantExpression).value.ToString() != (rightOperand as ConstantExpression).value.ToString()); // Compute addition case BinaryOperator.Add: // Convert values to string, apply operation and create constant expression return new ConstantExpression(Primitive.String, (leftOperand as ConstantExpression).value.ToString() + (rightOperand as ConstantExpression).value.ToString()); } } } return this; }
/// <summary> /// Evaluates this node and all of its children /// </summary> /// <param name="scope">The scope of this statement</param> /// <returns></returns> public override Statement Evaluate(Scope scope) { // Evaluate condition expression condition = condition.Evaluate(scope); // Evaluate repetitive statement body = body.Evaluate(scope); // Perform dead code elimination if the value of the condition can be evaluated at compile time if (condition is ConstantExpression) { // If it is always false, replace the statement with the inner repetitive statement if (!(condition as ConstantExpression).IsTrue()) return body; } // Propagate return state - if inner statement returns, no code following this statement // will be reached returns = body.returns; return this; }
void MulExpr(out Expression expr, Expression leftOperand) { expr = leftOperand; while (la.kind == 47 || la.kind == 50 || la.kind == 51) { expr = new BinaryExpression(leftOperand); if (la.kind == 47) { Get(); (expr as BinaryExpression).op = BinaryOperator.Mul; } else if (la.kind == 50) { Get(); (expr as BinaryExpression).op = BinaryOperator.Div; } else { Get(); (expr as BinaryExpression).op = BinaryOperator.Rem; } expr.t = t; UnaryExpr(out (expr as BinaryExpression).rightOperand); } }
void Expression(out Expression expr) { expr = null; UnaryExpr(out expr); Expression leftOperand = expr; EqExpr(out expr, leftOperand); }
void ConstantExpression(out Expression expr) { expr = null; if (la.kind == 4) { Get(); expr = new ConstantExpression(CSR.AST.Primitive.String, t); } else if (la.kind == 2) { Get(); expr = new ConstantExpression(CSR.AST.Primitive.Int, t); } else if (la.kind == 3) { Get(); expr = new ConstantExpression(CSR.AST.Primitive.Double, t); } else if (la.kind == 27) { Get(); expr = new ConstantExpression(CSR.AST.Primitive.Bool, t); } else if (la.kind == 26) { Get(); expr = new ConstantExpression(CSR.AST.Primitive.Bool, t); } else SynErr(57); }
/// <summary> /// Creates a new BinaryExpression given a left operand /// </summary> /// <param name="leftOperand"></param> public BinaryExpression(Expression leftOperand) { this.leftOperand = leftOperand; }
/// <summary> /// Creates a new IndexerExpression given an array reference /// </summary> /// <param name="expr">Variable reference expression</param> public IndexerExpression(Expression expr) { // Initialize members operand = expr; t = expr.t; indexers = new List<Expression>(); }
/// <summary> /// Evaluates this node and all of its children /// </summary> /// <param name="scope">The scope of this statement</param> /// <returns></returns> public override Statement Evaluate(Scope scope) { // Evaluate condition condition = condition.Evaluate(scope); // Evaluate repetitive statement body = body.Evaluate(scope); // Perform dead code elimination if the value of the condition can be evaluated at compile time if (condition is ConstantExpression) { // If condition is always false, drop statement if (!(condition as ConstantExpression).IsTrue()) return null; } return this; }
/// <summary> /// Evaluates this node and all of its children /// </summary> /// <param name="scope">The scope of this statement</param> /// <returns></returns> public override Statement Evaluate(Scope scope) { LocalScope localScope = scope as LocalScope; // If expr is not null, we must match return value with function return type if (expr != null) { // Evaluate inner expression expr.Evaluate(scope); // If return type is different than function return type if (!expr.returnType.Equals(localScope.returnType)) { // Check if an implicit typecast exists if (expr.returnType.IsCompatible(localScope.returnType)) { // Create typecast CastExpression newExpr = new CastExpression(localScope.returnType); newExpr.operand = expr; this.expr = newExpr; } else { // Issue error Compiler.Compiler.errors.SemErr(t.line, t.col, "invalid return type"); } } } else { // If function returns void but we provide a different type if (localScope.returnType.ToCLRType() != Type.GetType("System.Void")) { // Issue error Compiler.Compiler.errors.SemErr(t.line, t.col, "function should return " + localScope.returnType); } } return this; }
/// <summary> /// Evaluates this node and all of its children /// </summary> /// <param name="scope">The scope of this statement</param> /// <returns></returns> public override Statement Evaluate(Scope scope) { // Evaluate the condition condition = condition.Evaluate(scope); // Evaluate the if branch ifBranch = ifBranch.Evaluate(scope); // Evaluate the else branch if it exists if (elseBranch != null) { elseBranch = elseBranch.Evaluate(scope); // Propagate return state if both branches return // This is the only case in which we can make sure code following the statement won't be reached returns = ifBranch.returns && elseBranch.returns; } // Perform dead code elimination if the value of the condition can be evaluated at compile time if (condition is ConstantExpression) { // If condition always holds, replace statement with the if branch if ((condition as ConstantExpression).IsTrue()) return ifBranch; else // If an else branch exists, replace statemnt with it, if not, drop statement if (elseBranch != null) return elseBranch; else return null; } return this; }
/// <summary> /// Evaluates this node and all of its children /// </summary> /// <param name="scope">The scope of this statement</param> /// <returns></returns> public override Statement Evaluate(Scope scope) { if (!(variable is AssignableExpression)) { // If variable is not assignable expression, issue error Compiler.Compiler.errors.SemErr(t.line, t.col, "Invalid variable for FOR statement"); return this; } // Evaluate all child nodes variable = variable.Evaluate(scope); initial = initial.Evaluate(scope); final = final.Evaluate(scope); body = body.Evaluate(scope); return this; }
/// <summary> /// Creates a new AssignementExpression given a left-side expression and a right-side expression /// </summary> /// <param name="leftSide">Left-side expression</param> /// <param name="rightSide">Right-side expression</param> public AssignementStatement(Expression leftSide, Expression rightSide) : base() { this.leftSide = leftSide; this.rightSide = rightSide; }
/// <summary> /// Emits code for an assignement given the right-side expression of the assignement /// </summary> /// <param name="ilGen">IL generator object</param> /// <param name="scope">The scope of this expression</param> /// <param name="rightSide">Right-side expression</param> public abstract void EmitAssignement(ILGenerator ilGen, Scope scope, Expression rightSide);
/// <summary> /// Adds an indexer to the expression /// </summary> /// <param name="indexer">Indexer expression</param> public void AddIndexer(Expression indexer) { indexers.Add(indexer); }
/// <summary> /// Evaluates this node and all its children /// </summary> /// <param name="scope">The scope of this expression</param> /// <returns></returns> public override Expression Evaluate(Scope scope) { // Evaluate operand operand = operand.Evaluate(scope); // If types are actually equal if (operand.returnType.Equals(this.returnType)) { // Issue warning Compiler.Compiler.errors.Warning(t.line, t.col, "Typecast to the same type"); // Drop the typecast expression return operand; } // If an implicit type cast exists, no need to evaluate further if (operand.returnType.IsCompatible(this.returnType)) { if (returnType.Equals(PrimitiveType.DOUBLE)) { // If operand is constant, fold typecast if (operand is ConstantExpression) { // Cast value to int, convert to double and create new constant expression return new ConstantExpression(Primitive.Double, Convert.ToDouble((int)(operand as ConstantExpression).value)); } return this; } } // Only explicit typecast implemented is from Double to Int if (operand.returnType.Equals(PrimitiveType.DOUBLE)) { if (returnType.Equals(PrimitiveType.INT)) { // If operand is constant, fold typecast if (operand is ConstantExpression) { // Cast value to double, convert to int and create new constant expression return new ConstantExpression(Primitive.Int, Convert.ToInt32((double)(operand as ConstantExpression).value)); } return this; } } // Execution shouldn't reach this line if cast is correct - issue error Compiler.Compiler.errors.SemErr(t.line, t.col, "Invalid typecast"); return this; }
/// <summary> /// Emits code for assignement /// </summary> /// <param name="ilGen">IL generator object</param> /// <param name="scope">The scope of this expression</param> /// <param name="rightSide">Right-side expression</param> public override void EmitAssignement(ILGenerator ilGen, Scope scope, Expression rightSide) { // Emit code to index array EmitIndexers(ilGen, scope); // Emit code for right-side expression rightSide.EmitCode(ilGen, scope); // Call Set to store value at indexed position ilGen.Emit(OpCodes.Call, ((ArrayType)operand.returnType).ToCLRType().GetMethod("Set")); }
void AddExpr(out Expression expr, Expression leftOperand) { expr = null; Expression rightOperand; MulExpr(out expr, leftOperand); while (la.kind == 40 || la.kind == 42) { expr = new BinaryExpression(expr); if (la.kind == 42) { Get(); (expr as BinaryExpression).op = BinaryOperator.Add; } else { Get(); (expr as BinaryExpression).op = BinaryOperator.Sub; } expr.t = t; UnaryExpr(out rightOperand); MulExpr(out (expr as BinaryExpression).rightOperand, rightOperand); } }
/// <summary> /// Evaluates this node and all its children /// </summary> /// <param name="scope">The scope of this expression</param> /// <returns></returns> public override Expression Evaluate(Scope scope) { // Iterate through indexers for (int i = 0; i < indexers.Count; i++) { // Evaluate indexer indexers[i] = indexers[i].Evaluate(scope); // Check if indexer is of integer type if (!indexers[i].returnType.Equals(PrimitiveType.INT)) { // Ilegal indexer type - issue error Compiler.Compiler.errors.SemErr(t.line, t.col, "Indexers must be of integer type"); return this; } } // Evaluate operand expression operand = operand.Evaluate(scope); if (operand is IndexerExpression) { Compiler.Compiler.errors.SemErr(operand.t.line, operand.t.col, "Cannot apply multiple indexers on array. Use [,] instead of [][]"); return this; } // Try to cast operand return type to ArrayType ArrayType refType = operand.returnType as ArrayType; // Check if cast was successful if (refType == null) { // Indexers can only be applied to array types - issue error Compiler.Compiler.errors.SemErr(t.line, t.col, "Cannot apply indexers to non-array type"); return this; } // Check if the dimension of the array is equal to the number of indexers if (refType.dimensions != indexers.Count) { // Cannot assign to arrays, only to values - issue error Compiler.Compiler.errors.SemErr(t.line, t.col, "Invalid number of indexers"); return this; } // Set return type this.returnType = refType.type; return this; }
void EqExpr(out Expression expr, Expression leftOperand) { expr = null; Expression rightOperand; LogExpr(out expr, leftOperand); while (StartOf(4)) { expr = new BinaryExpression(expr); switch (la.kind) { case 33: { Get(); (expr as BinaryExpression).op = BinaryOperator.Eq; break; } case 48: { Get(); (expr as BinaryExpression).op = BinaryOperator.Neq; break; } case 34: { Get(); (expr as BinaryExpression).op = BinaryOperator.Gt; break; } case 39: { Get(); (expr as BinaryExpression).op = BinaryOperator.Lt; break; } case 35: { Get(); (expr as BinaryExpression).op = BinaryOperator.Geq; break; } case 49: { Get(); (expr as BinaryExpression).op = BinaryOperator.Leq; break; } } expr.t = t; UnaryExpr(out rightOperand); LogExpr(out (expr as BinaryExpression).rightOperand, rightOperand); } }
/// <summary> /// Evaluates this node and all its children /// </summary> /// <param name="scope">The scope of this expression</param> /// <returns></returns> public override Expression Evaluate(Scope scope) { // Evaluate operand expression operand = operand.Evaluate(scope); // Save operand return type PrimitiveType pType = (PrimitiveType)operand.returnType; if (pType == null) { return null; } // Processing is done depending on operator switch (op) { // Process unary minus case UnaryOperator.UMinus: // If operand is integer or double if (pType.type == Primitive.Int || pType.type == Primitive.Double) { // Set return type this.returnType = new PrimitiveType(pType.type); // If operand is constant perform folding if (operand is ConstantExpression) { // Fold integer value if (pType.type == Primitive.Int) { // Cast value to int, add unary minus and create new constant expression return new ConstantExpression(Primitive.Int, (-(int)(operand as ConstantExpression).value).ToString()); } else if (pType.type == Primitive.Double) { // Cast value to double, add unary minus and create new constant expression return new ConstantExpression(Primitive.Double, (-(double)(operand as ConstantExpression).value).ToString()); } } } else { // Unary minus cannot be applied on other types this.returnType = PrimitiveType.UNSUPPORTED; // Issue error Compiler.Compiler.errors.SemErr(t.line, t.col, "Can only apply '-' to numeric types"); return this; } break; // Process logical negation case UnaryOperator.Not: // If operand is boolean if (pType.type == Primitive.Bool) { // Set return type this.returnType = new PrimitiveType(pType.type); // If oprand is constant perform folding if (operand is ConstantExpression) { // Cast value to bool, negate and create new constant expression return new ConstantExpression(Primitive.Bool, (bool)(operand as ConstantExpression).value ? "false" : "true"); } } else { // Logical negation cannot be applied on other types this.returnType = PrimitiveType.UNSUPPORTED; // Issue error Compiler.Compiler.errors.SemErr(t.line, t.col, "Can only apply '!' to boolean types"); return this; } break; } return this; }
void LogExpr(out Expression expr, Expression leftOperand) { expr = null; Expression rightOperand; AddExpr(out expr, leftOperand); while (la.kind == 17 || la.kind == 18 || la.kind == 19) { expr = new BinaryExpression(expr); if (la.kind == 17) { Get(); (expr as BinaryExpression).op = BinaryOperator.And; } else if (la.kind == 18) { Get(); (expr as BinaryExpression).op = BinaryOperator.Or; } else { Get(); (expr as BinaryExpression).op = BinaryOperator.Xor; } expr.t = t; UnaryExpr(out rightOperand); AddExpr(out (expr as BinaryExpression).rightOperand, rightOperand); } }
/// <summary> /// Emits code for an assignement given the right-side expression of the assignement /// </summary> /// <param name="ilGen">IL generator object</param> /// <param name="scope">The scope of this expression</param> /// <param name="rightSide">Right-side expression</param> public override void EmitAssignement(ILGenerator ilGen, Scope scope, Expression rightSide) { // Emit code for right side expression rightSide.EmitCode(ilGen, scope); // Use symbol table to emit variable assignement scope.EmitVariableAssignement(name, ilGen); }
void UnaryExpr(out Expression expr) { expr = null; switch (la.kind) { case 40: { Get(); expr = new UnaryExpression(UnaryOperator.UMinus); expr.t = t; UnaryExpr(out (expr as UnaryExpression).operand); break; } case 41: { Get(); expr = new UnaryExpression(UnaryOperator.Not); expr.t = t; UnaryExpr(out (expr as UnaryExpression).operand); break; } case 2: case 3: case 4: case 26: case 27: { ConstantExpression(out expr); break; } case 36: { Get(); Expect(21); expr = new CastExpression(PrimitiveType.INT); expr.t = t; Expect(43); UnaryExpr(out (expr as CastExpression).operand); break; } case 1: { Get(); expr = new VariableReferenceExpression(t.val); expr.t = t; while (la.kind == 32) { Get(); Expect(1); (expr as VariableReferenceExpression).name += "." + t.val; } if (la.kind == 38) { Get(); expr = new CallExpression((expr as VariableReferenceExpression).name, expr.t); Expression argument; if (StartOf(3)) { Expression(out argument); (expr as CallExpression).AddArgument(argument); while (la.kind == 31) { Get(); Expression(out argument); (expr as CallExpression).AddArgument(argument); } } Expect(45); } if (la.kind == 37) { Get(); expr = new IndexerExpression(expr); Expression indexer; Expression(out indexer); (expr as IndexerExpression).AddIndexer(indexer); while (la.kind == 31) { Get(); Expression(out indexer); (expr as IndexerExpression).AddIndexer(indexer); } Expect(44); } break; } case 38: { Get(); Expression(out expr); Expect(45); break; } default: SynErr(56); break; } }
/// <summary> /// Creates a new CallStatement given a CallExpression /// </summary> /// <param name="expr">CallExpression object</param> public CallStatement(Expression expr) : base() { this.expr = expr as CallExpression; }