Esempio n. 1
0
        Literal EvaluateBinaryOp(BinaryOp op)
        {
            var left = Evaluate(op.Left);
            var right = Evaluate(op.Right);

            return BinaryEvaluator.Calculate(op, left, right);
        }
Esempio n. 2
0
 public static Literal Calculate(BinaryOp op, Literal left, Literal right)
 {
     var range = new CodeRange(left, right);
     object val = CalculateValue(op, left, right);
     var type = TypeEvaluator.GetType(left.ValueType, op, right.ValueType);
     return new Literal(range, type, val);
 }
Esempio n. 3
0
 public static LaxType GetType(LaxType left, BinaryOp op, LaxType right)
 {
     return new LaxType(
         GetTypes(left.Type, op, right.Type),
         GetUnit(left.Unit, op, right.Unit)
         );
 }
Esempio n. 4
0
 /// <summary>
 /// return a new <seealso cref="Assignment"/> with Left and Right assigned.
 /// </summary>
 /// <param name="left"></param>
 /// <param name="right"></param>
 /// <returns></returns>
 public BinaryOp WithOperands(LaxExpression left, LaxExpression right)
 {
     var op = new BinaryOp(CodeRange, Operator);
     op.Left = left;
     op.Right = right;
     op.CodeRange = CodeRange.Expand2(left).Expand2(right);
     return op;
 }
Esempio n. 5
0
        //Although this could be infered from the object type in CalculateValue we implement it here for other runtimes.
        static DataType GetTypes(DataType left, BinaryOp op, DataType right)
        {
            if (left == DataType.Unit)
                return right;
            if (right == DataType.Unit)
                return left;

            string key = (left + " " + right).ToLowerInvariant();
            switch (key)
            {
                case "double double": return DataType.Double;
                case "double int": return DataType.Double;
                case "int double": return DataType.Double;
                case "int int": return DataType.Int;
                case "boolean boolean": return DataType.Boolean;

                default:
                    throw new SemanticError(op, "Not supported: " + key);
            }
        }
Esempio n. 6
0
        static LaxExpression EvaluateOp(BinaryOp op)
        {
            var left = Evaluate(op.Left);
            var right = Evaluate(op.Right);

            var result = new BinaryOp(op.CodeRange, op.Operator).WithOperands(left, right);
            result.ValueType = op.ValueType;

            if (result.Left.Type == ExprType.Literal && result.Right.Type == ExprType.Literal)
            {
                //Operation with two literals, precalculate
                var interpreter = new Interpreter();
                var literal = interpreter.Evaluate(result);
                return literal;
            }

            //No change
            if (left == op.Left && right == op.Right)
                return op; //No change, no evaluation possible

            return result;
        }
Esempio n. 7
0
 public string FormatBinaryOp(BinaryOp bo)
 {
     string l = ExpressionParenLeft;
     string r = ExpressionParenRight;
     return l + FormatExpression(bo.Left) + " " + bo.Operator + " " + FormatExpression(bo.Right) + r;
 }
Esempio n. 8
0
        private static object CalculateValue(BinaryOp op, Literal left, Literal right)
        {
            if (op.Operator == "*")
            {
                if (left.ValueType.Type == DataType.Unit)
                    return right.Value;
                if (right.ValueType.Type == DataType.Unit)
                    return left.Value;
            }
            if (op.Operator == "/")
            {
                if (right.ValueType.Type == DataType.Unit)
                    return left.Value;
            }

            string key = (left.ValueType.Type + " " + op.Operator + " " + right.ValueType.Type).ToLowerInvariant();
            switch (key)
            {
                case "double + double":
                    return (double)left.Value + (double)right.Value;
                case "double - double":
                    return (double)left.Value - (double)right.Value;
                case "double * double":
                    return (double)left.Value * (double)right.Value;
                case "double / double":
                    return (double)left.Value / (double)right.Value;

                case "int + int":
                    return (int)left.Value + (int)right.Value;
                case "int - int":
                    return (int)left.Value - (int)right.Value;
                case "int * int":
                    return (int)left.Value * (int)right.Value;
                case "int / int":
                    return (int)left.Value / (int)right.Value;

                case "double + int":
                    return (double)left.Value + (int)right.Value;
                case "int + double":
                    return (int)left.Value + (double)right.Value;

                case "double - int":
                    return (double)left.Value - (int)right.Value;
                case "int - double":
                    return (int)left.Value - (double)right.Value;

                case "double * int":
                    return (double)left.Value * (int)right.Value;
                case "int * double":
                    return (int)left.Value * (double)right.Value;

                case "double / int":
                    return (double)left.Value / (int)right.Value;
                case "int / double":
                    return (int)left.Value / (double)right.Value;

                case "boolean and boolean":
                    return (bool)left.Value && (bool)right.Value;
                case "boolean or boolean":
                    return (bool)left.Value || (bool)right.Value;

                default:
                    throw new SyntaxError(op.CodeRange, "Operator-type not implemented: " + key);
            }
        }
Esempio n. 9
0
        static Unit GetUnit(Unit left, BinaryOp op, Unit right)
        {
            switch (op.Operator)
            {
                case "+":
                case "-":
                case "and":
                case "or":
                    if (left != right)
                        throw new SemanticError(op, "Unit mismatch: " + left + op.Operator + right);
                    return left;

                case "*":
                    return left * right;

                case "/":
                    return left / right;

                default:
                    throw new NotImplementedException(op.Operator);
            }
        }
Esempio n. 10
0
        void EvalBinaryOperator(BinaryOp op)
        {
            Eval(op.Left);
            Debug.Assert(op.Left.ValueType != null);
            Eval(op.Right);
            Debug.Assert(op.Right.ValueType != null);

            var t = GetType(op.Left.ValueType, op, op.Right.ValueType);
            if (op.ValueType != null)
            {
                if (op.ValueType != t)
                    throw new SemanticError(op, "Type mismatch");
            }

            op.ValueType = t;
        }
Esempio n. 11
0
 /// <summary>
 /// Generate a BinaryOp that strongly connects a value with the unit following directly afterwards.
 /// </summary>
 public static BinaryOp UnitOp(CodeRange pos)
 {
     var bop = new BinaryOp("*", 18, Associate.LeftToRight);
     bop.CodeRange = pos;
     return bop;
 }