Example #1
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;
            }
        }
Example #2
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;
        }
Example #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 all arguments
            for (int i = 0; i < arguments.Count; i++)
            {
                arguments[i] = arguments[i].Evaluate(scope);
            }

            // Get signature from symbol table
            Signature sig = scope.GetFunction(this);

            // If no function is retrieved
            if (sig == null)
            {
                // Unknown function error
                Compiler.Compiler.errors.SemErr(t.line, t.col, "Unknown function or ambiguos call to " + methodName);
            }
            else
            {
                // Set return type
                this.returnType = sig.returnType;

                // Step through each argument
                for (int i = 0; i < sig.arguments.Count; i++)
                {
                    // If argument expression type is different than expected argument
                    // Arguments are guaranteed to be compatible since a matching signature was found in the symbol table
                    if (!arguments[i].returnType.Equals(sig.arguments[i]))
                    {
                        // Create implicit type cast to expected argument
                        Expression expr = arguments[i];
                        arguments[i] = new CastExpression(sig.arguments[i]);
                        (arguments[i] as CastExpression).operand = expr;
                    }
                }
            }

            return this;
        }
Example #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)
        {
            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;
        }