Exemplo n.º 1
0
        /// <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;
        }
Exemplo n.º 2
0
 /// <summary>
 /// Adds an agrument expression to the argument list
 /// </summary>
 /// <param name="expr">Argument expression</param>
 public void AddArgument(Expression expr)
 {
     arguments.Add(expr);
 }
Exemplo n.º 3
0
        /// <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;
        }
Exemplo n.º 4
0
        /// <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;
        }
Exemplo n.º 5
0
 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);
     }
 }
Exemplo n.º 6
0
 void Expression(out Expression expr)
 {
     expr = null;
     UnaryExpr(out expr);
     Expression leftOperand = expr;
     EqExpr(out expr, leftOperand);
 }
Exemplo n.º 7
0
 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);
 }
Exemplo n.º 8
0
 /// <summary>
 /// Creates a new BinaryExpression given a left operand
 /// </summary>
 /// <param name="leftOperand"></param>
 public BinaryExpression(Expression leftOperand)
 {
     this.leftOperand = leftOperand;
 }
Exemplo n.º 9
0
        /// <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>();
        }
Exemplo n.º 10
0
        /// <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;
        }
Exemplo n.º 11
0
        /// <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;
        }
Exemplo n.º 12
0
        /// <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;
        }
Exemplo n.º 13
0
        /// <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;
        }
Exemplo n.º 14
0
 /// <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;
 }
Exemplo n.º 15
0
 /// <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);
Exemplo n.º 16
0
 /// <summary>
 /// Adds an indexer to the expression
 /// </summary>
 /// <param name="indexer">Indexer expression</param>
 public void AddIndexer(Expression indexer)
 {
     indexers.Add(indexer);
 }
Exemplo n.º 17
0
        /// <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;
        }
Exemplo n.º 18
0
        /// <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"));
        }
Exemplo n.º 19
0
        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);
            }
        }
Exemplo n.º 20
0
        /// <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;
        }
Exemplo n.º 21
0
        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);
            }
        }
Exemplo n.º 22
0
        /// <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;
        }
Exemplo n.º 23
0
        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);
            }
        }
Exemplo n.º 24
0
        /// <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);
        }
Exemplo n.º 25
0
        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;
            }
        }
Exemplo n.º 26
0
 /// <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;
 }