예제 #1
0
        private IRestrictedValue GetParameterValue(long parameterValue)
        {
            IRestrictedValue value = null;

            if (BuilderHelper.UseBindings)
            {
                string name = GetDistinctAlias();

                value = new BindMarker()
                {
                    Identifier = name
                };

                Parameters.Add(name, parameterValue);
            }
            else
            {
                value = new IntegerConstant()
                {
                    Value = parameterValue
                };
            }

            return(value);
        }
예제 #2
0
        private static bool TryDecodePseudoFieldData(
            ClrFieldDefinition pseudoField,
            IType elementType,
            out IReadOnlyList <Constant> data)
        {
            var init    = pseudoField.Definition.InitialValue;
            var intSpec = elementType.GetIntegerSpecOrNull();

            if (intSpec != null && intSpec.Size % 8 == 0)
            {
                int bytesPerInt = intSpec.Size / 8;
                int intCount    = init.Length / bytesPerInt;
                var results     = new Constant[intCount];
                for (int i = 0; i < intCount; i++)
                {
                    var value = new IntegerConstant(0, intSpec);
                    for (int j = bytesPerInt - 1; j >= 0; j--)
                    {
                        value = value.ShiftLeft(8).Add(new IntegerConstant(init[i * bytesPerInt + j], intSpec));
                    }
                    results[i] = value.Normalized;
                }
                data = results;
                return(true);
            }
            else
            {
                data = null;
                return(false);
            }
        }
예제 #3
0
파일: AstBuilder.cs 프로젝트: xstos/Jace
        private void VerifyResultStack()
        {
            if (resultStack.Count > 1)
            {
                Operation[] operations = resultStack.ToArray();

                for (int i = 1; i < operations.Length; i++)
                {
                    Operation operation = operations[i];

                    if (operation.GetType() == typeof(IntegerConstant))
                    {
                        IntegerConstant constant = (IntegerConstant)operation;
                        throw new ParseException(string.Format("Unexpected integer constant \"{0}\" found.", constant.Value));
                    }
                    else if (operation.GetType() == typeof(FloatingPointConstant))
                    {
                        FloatingPointConstant constant = (FloatingPointConstant)operation;
                        throw new ParseException(string.Format("Unexpected floating point constant \"{0}\" found.", constant.Value));
                    }
                }

                throw new ParseException("The syntax of the provided formula is not valid.");
            }
        }
예제 #4
0
 public static void CompileInteger(ParserContext parser, ByteBuffer buffer, IntegerConstant intConst, bool outputUsed)
 {
     if (!outputUsed)
     {
         throw new ParserException(intConst, "This expression does nothing.");
     }
     buffer.Add(intConst.FirstToken, OpCode.LITERAL, parser.GetIntConstant(intConst.Value));
 }
예제 #5
0
        private ExpressionNode ParseFactor()
        {
            ExpressionNode x;

            if (_reader.Peek() is LeftParen)
            {
                Match <LeftParen>();
                x = ParseExpression();
                Match <RightParen>();

                return(x);
            }

            if (_reader.Peek() is IntegerLiteral)
            {
                var token = Match <IntegerLiteral>();
                x = new IntegerConstant(token.Value);
                return(x);
            }

            if (_reader.Peek() is FloatLiteral)
            {
                var token = Match <FloatLiteral>();
                x = new FloatConstant(token.Value);
                return(x);
            }

            if (_reader.Peek() is StringLiteral)
            {
                var token = Match <StringLiteral>();
                x = new StringConstant(token.Value);
                return(x);
            }

            if (_reader.Peek() is True)
            {
                Match <True>();
                x = BoolConstant.True;
                return(x);
            }

            if (_reader.Peek() is False)
            {
                Match <False>();
                x = BoolConstant.False;
                return(x);
            }

            if (_reader.Peek() is Identifier)
            {
                var token = Match <Identifier>();
                x = new IdentifierNode(token);
                return(x);
            }

            throw new Exception("syntax error");
        }
예제 #6
0
 public BitTestLowering(
     SwitchFlow flow,
     IntegerConstant minValue,
     IntegerConstant valueRange,
     TypeEnvironment typeEnvironment)
 {
     this.Flow            = flow;
     this.MinValue        = minValue;
     this.ValueRange      = valueRange;
     this.TypeEnvironment = typeEnvironment;
 }
예제 #7
0
        /// <summary>
        /// Tells if it is sensible to use a jump table to implement a
        /// particular integer switch.
        /// </summary>
        /// <param name="valueRange">
        /// The difference between the max and min values to switch on.
        /// </param>
        /// <param name="valueCount">
        /// The number of values to switch on.
        /// </param>
        /// <returns>
        /// <c>true</c> if a jump table should be used; otherwise, <c>false</c>.
        /// </returns>
        private bool ShouldUseJumpTable(IntegerConstant valueRange, int valueCount)
        {
            if (!AllowJumpTables)
            {
                // We may not be allowed to use jump tables.
                return(false);
            }

            double density = valueCount / (valueRange.ToFloat64() + 1);

            return(density >= 0.4);
        }
예제 #8
0
        public static void SpeedTest()
        {
            const int Num = 1000000;
            TimeSpan  t1  = new TimeSpan();
            TimeSpan  t2  = new TimeSpan();
            DateTime  start;


            Console.WriteLine("Running test 1: constructor call");
            Type            t      = typeof(IntegerConstant);
            ConstructorInfo constr = t.GetConstructor(new Type[] { typeof(ISyntaxNode), typeof(string).MakeByRefType() });

            ISyntaxNode.SyntaxNodeConstructor <IntegerConstant> del = (ISyntaxNode.SyntaxNodeConstructor <IntegerConstant>)constr.CreateDelegate(typeof(ISyntaxNode.SyntaxNodeConstructor <IntegerConstant>));;

            if (constr == null)
            {
                Console.WriteLine("No constructor found");
            }
            else
            {
                start = DateTime.Now;
                for (int i = 0; i < Num; i++)
                {
                    String test = "1421";
                    try
                    {
                        del(null, ref test);
                    }
                    catch (ParseException)
                    {
                    }
                }
                t2 = DateTime.Now - start;
            }



            Console.WriteLine("Running test 2: static function");
            start = DateTime.Now;
            for (int i = 0; i < Num; i++)
            {
                String test = "1421";
                IntegerConstant.Parse(null, ref test);
            }
            t1 = DateTime.Now - start;



            Console.WriteLine("Test 1: " + t1);
            Console.WriteLine("Test 2: " + t2);

            Console.ReadKey();
        }
예제 #9
0
        protected override void TranslateIntegerConstant(List <string> output, IntegerConstant intConstant)
        {
            int value = intConstant.Value;

            if (value >= 0)
            {
                output.Add("" + value);
            }
            else
            {
                output.Add("(" + value + ")");
            }
        }
예제 #10
0
        public static void Compile(
            ByteCodeCompiler bcc,
            ParserContext parser,
            ByteBuffer buffer,
            CoreFunctionInvocation coreFuncInvocation,
            Expression[] argsOverrideOrNull,
            Token tokenOverrideOrNull,
            bool outputUsed)
        {
            Token token = tokenOverrideOrNull ?? coreFuncInvocation.FirstToken;

            Expression[] args = argsOverrideOrNull ?? coreFuncInvocation.Args;

            if (coreFuncInvocation.FunctionId == (int)CoreFunctionID.TYPE_IS)
            {
                ByteCodeCompiler.EnsureUsed(coreFuncInvocation, outputUsed);

                bcc.CompileExpression(parser, buffer, args[0], true);
                int   typeCount  = args.Length - 1;
                int[] actualArgs = new int[typeCount + 3];
                actualArgs[0] = coreFuncInvocation.FunctionId;
                actualArgs[1] = 1; // output used
                actualArgs[2] = typeCount;
                for (int i = typeCount - 1; i >= 0; --i)
                {
                    IntegerConstant typeArg = args[args.Length - 1 - i] as IntegerConstant;
                    if (typeArg == null)
                    {
                        throw new ParserException(coreFuncInvocation, "typeis requires type enum values.");
                    }
                    actualArgs[3 + i] = typeArg.Value + 1;
                }
                buffer.Add(token, OpCode.CORE_FUNCTION, actualArgs);
                return;
            }

            foreach (Expression arg in args)
            {
                bcc.CompileExpression(parser, buffer, arg, true);
            }

            if (coreFuncInvocation.FunctionId == (int)CoreFunctionID.INT_QUEUE_WRITE_16)
            {
                buffer.Add(token, OpCode.CORE_FUNCTION, coreFuncInvocation.FunctionId, outputUsed ? 1 : 0, args.Length - 1);
                return;
            }

            buffer.Add(token, OpCode.CORE_FUNCTION, coreFuncInvocation.FunctionId, outputUsed ? 1 : 0);
        }
예제 #11
0
        /// <summary>
        /// Tells if it is both possible and sensible to use bit tests to implement
        /// a particular switch.
        /// </summary>
        /// <param name="valueRange">
        /// The difference between the largest and smallest value in the switch flow.
        /// </param>
        /// <param name="caseCount">
        /// The number of cases in the switch flow.
        /// </param>
        /// <param name="valueCount">
        /// The total number of values in the switch flow.
        /// </param>
        /// <returns><c>true</c> if bit tests should be used; otherwise, <c>false</c>.</returns>
        private bool ShouldUseBitTestSwitch(IntegerConstant valueRange, int caseCount, int valueCount)
        {
            if (!AllowBitTests)
            {
                // We may not be allowed to use bit tests.
                return(false);
            }

            // If the span's range is at least 64 then we can't use a bit mask.
            if (valueRange.IsGreaterThan(new IntegerConstant(64)))
            {
                return(false);
            }

            // We know that we can use bit tests for this range and we can now
            // decide if it's actually a good idea to do so.
            return((caseCount == 1 && valueCount >= 3) ||
                   (caseCount == 2 && valueCount >= 5) ||
                   (caseCount == 3 && valueCount >= 6));
        }
예제 #12
0
        private string GetLabelText(Operation operation)
        {
            Type operationType = operation.GetType();

            string name     = operationType.Name;
            string dataType = "" + operation.DataType;
            string value    = "";

            IntegerConstant integerConstant = operation as IntegerConstant;

            if (integerConstant != null)
            {
                value = "(" + integerConstant.Value + ")";
            }
            else
            {
                FloatingPointConstant floatingPointConstant = operation as FloatingPointConstant;
                if (floatingPointConstant != null)
                {
                    value = "(" + floatingPointConstant.Value + ")";
                }
                else
                {
                    Variable variable = operation as Variable;
                    if (variable != null)
                    {
                        value = "(" + variable.Name + ")";
                    }
                    else
                    {
                        Function function = operation as Function;
                        if (function != null)
                        {
                            value = "(" + function.FunctionName + ")";
                        }
                    }
                }
            }

            return(string.Format(CultureInfo.InvariantCulture, "{0}<{1}>{2}", name, dataType, value));
        }
예제 #13
0
파일: Lexer.cs 프로젝트: srakowski/WeeC
        private static NextToken ReadToken(this IEnumerable <CodeCharacter> code)
        {
            code = code.SkipWhile(c => c.IsWhitespace);

            if (!code.Any())
            {
                var token = new EndOfFile();
                return(new NextToken(token, () => ReadToken(code)));
            }

            var firstTokenChar = code.First();

            if (firstTokenChar.IsStartOfIdentifier)
            {
                var identifier = code
                                 .TakeWhile(c => c.IsBodyOfIdentifier)
                                 .Aggregate("", (s, c) => s + c.Value);

                code = code.SkipWhile(c => c.IsBodyOfIdentifier);

                var token = KeywordTable.ContainsKey(identifier)
                    ? KeywordTable[identifier].Invoke() as Token
                    : new Identifier();

                token.Value        = identifier;
                token.LineNumber   = firstTokenChar.LineNumber;
                token.LinePosition = firstTokenChar.LinePosition;
                return(new NextToken(token, () => ReadToken(code)));
            }

            if (firstTokenChar.IsDigit)
            {
                var number = code
                             .TakeWhile(c => c.IsDigit)
                             .Aggregate("", (s, c) => s + c.Value);

                code = code.Skip(number.Length);

                var token = new IntegerConstant();
                token.Value        = number;
                token.LineNumber   = firstTokenChar.LineNumber;
                token.LinePosition = firstTokenChar.LinePosition;
                return(new NextToken(token, () => ReadToken(code)));
            }

            if (firstTokenChar.IsStartOfStringLiteral)
            {
                var stringLiteral = code
                                    .Skip(1)
                                    .TakeWhile(c => c.Value != '"')
                                    .Aggregate("\"", (s, c) => s + c.Value)
                                    + '"';

                Debug.WriteLine(stringLiteral);

                code = code.Skip(stringLiteral.Length);

                var token = new StringLiteral();
                token.Value        = stringLiteral;
                token.LineNumber   = firstTokenChar.LineNumber;
                token.LinePosition = firstTokenChar.LinePosition;
                return(new NextToken(token, () => ReadToken(code)));
            }

            var t = new InvalidToken() as Token;

            switch (firstTokenChar.Value)
            {
            case '(': t = new LeftParen(); break;

            case ')': t = new RightParen(); break;

            case '{': t = new LeftCurlyBrace(); break;

            case '}': t = new RightCurlyBrace(); break;

            case '[': t = new LeftSquareBracket(); break;

            case ']': t = new RightSquareBracket(); break;

            case ',': t = new Comma(); break;

            case '*': t = new Asterisk(); break;

            case ';': t = new Semicolon(); break;
            }

            code = code.Skip(1);

            t.Value        = firstTokenChar.Value.ToString();
            t.LineNumber   = firstTokenChar.LineNumber;
            t.LinePosition = firstTokenChar.LinePosition;
            return(new NextToken(t, () => ReadToken(code)));
        }
예제 #14
0
        public double Execute(Operation operation, IFunctionRegistry functionRegistry,
                              Dictionary <string, double> variables)
        {
            if (operation == null)
            {
                throw new ArgumentNullException("operation");
            }

            if (operation.GetType() == typeof(IntegerConstant))
            {
                IntegerConstant constant = (IntegerConstant)operation;
                return(constant.Value);
            }
            else if (operation.GetType() == typeof(FloatingPointConstant))
            {
                FloatingPointConstant constant = (FloatingPointConstant)operation;
                return(constant.Value);
            }
            else if (operation.GetType() == typeof(Variable))
            {
                Variable variable = (Variable)operation;
                if (variables.ContainsKey(variable.Name))
                {
                    return(variables[variable.Name]);
                }
                else
                {
                    throw new VariableNotDefinedException(string.Format("The variable \"{0}\" used is not defined.", variable.Name));
                }
            }
            else if (operation.GetType() == typeof(Multiplication))
            {
                Multiplication multiplication = (Multiplication)operation;
                return(Execute(multiplication.Argument1, functionRegistry, variables) * Execute(multiplication.Argument2, functionRegistry, variables));
            }
            else if (operation.GetType() == typeof(Addition))
            {
                Addition addition = (Addition)operation;
                return(Execute(addition.Argument1, functionRegistry, variables) + Execute(addition.Argument2, functionRegistry, variables));
            }
            else if (operation.GetType() == typeof(Subtraction))
            {
                Subtraction addition = (Subtraction)operation;
                return(Execute(addition.Argument1, functionRegistry, variables) - Execute(addition.Argument2, functionRegistry, variables));
            }
            else if (operation.GetType() == typeof(Division))
            {
                Division division = (Division)operation;
                return(Execute(division.Dividend, functionRegistry, variables) / Execute(division.Divisor, functionRegistry, variables));
            }
            else if (operation.GetType() == typeof(Modulo))
            {
                Modulo division = (Modulo)operation;
                return(Execute(division.Dividend, functionRegistry, variables) % Execute(division.Divisor, functionRegistry, variables));
            }
            else if (operation.GetType() == typeof(Exponentiation))
            {
                Exponentiation exponentiation = (Exponentiation)operation;
                return(Math.Pow(Execute(exponentiation.Base, functionRegistry, variables), Execute(exponentiation.Exponent, functionRegistry, variables)));
            }
            else if (operation.GetType() == typeof(UnaryMinus))
            {
                UnaryMinus unaryMinus = (UnaryMinus)operation;
                return(-Execute(unaryMinus.Argument, functionRegistry, variables));
            }
            else if (operation.GetType() == typeof(Function))
            {
                Function function = (Function)operation;

                FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName);

                double[] arguments = new double[functionInfo.NumberOfParameters];
                for (int i = 0; i < arguments.Length; i++)
                {
                    arguments[i] = Execute(function.Arguments[i], functionRegistry, variables);
                }

                return(Invoke(functionInfo.Function, arguments));
            }
            else
            {
                throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation");
            }
        }
예제 #15
0
            public override BlockFlow Emit(
                FlowGraphBuilder graph,
                ValueTag value)
            {
                // Create the following blocks:
                //
                // bitswitch.entry():
                //   minvalue = const <MinValue>
                //   switchval.adjusted = switchval - minvalue
                //   switchval.unsigned = (uintX)switchval.adjusted
                //   valrange = const <ValueRange>
                //   switch (switchval.unsigned > valrange)
                //     0 -> bitswitch.header()
                //     default -> <defaultBranch>
                //
                // bitswitch.header():
                //   one = const 1
                //   shifted = one << switchval.unsigned
                //   bitmask1 = const <bitmask1>
                //   switch (shifted & bitmask1)
                //     0 -> bitswitch.case2()
                //     default -> <case1Branch>
                //
                // bitswitch.case2():
                //   bitmask2 = const <bitmask2>
                //   switch (shifted & bitmask1)
                //     0 -> bitswitch.case3()
                //     default -> <case2Branch>
                //
                // ...

                var entryBlock  = graph.AddBasicBlock("bitswitch.entry");
                var headerBlock = graph.AddBasicBlock("bitswitch.header");

                var valueType = graph.GetValueType(value);
                var valueSpec = valueType.GetIntegerSpecOrNull();

                var defaultBranch = Flow.DefaultBranch;

                // Subtract the min value from the switch value if necessary.
                if (!MinValue.IsZero)
                {
                    value = entryBlock.AppendInstruction(
                        Instruction.CreateBinaryArithmeticIntrinsic(
                            ArithmeticIntrinsics.Operators.Subtract,
                            false,
                            valueType,
                            value,
                            entryBlock.AppendInstruction(
                                Instruction.CreateConstant(MinValue, valueType),
                                "minvalue")),
                        "switchval.adjusted");
                }

                // Make the switch value unsigned if it wasn't already.
                if (valueSpec.IsSigned)
                {
                    var uintType = TypeEnvironment.MakeUnsignedIntegerType(valueSpec.Size);
                    value = entryBlock.AppendInstruction(
                        Instruction.CreateConvertIntrinsic(
                            false,
                            uintType,
                            valueType,
                            value),
                        "switchval.unsigned");
                    valueType = uintType;
                    valueSpec = uintType.GetIntegerSpecOrNull();
                }

                // Check that the value is within range.
                entryBlock.Flow = SwitchFlow.CreateIfElse(
                    Instruction.CreateRelationalIntrinsic(
                        ArithmeticIntrinsics.Operators.IsGreaterThan,
                        TypeEnvironment.Boolean,
                        valueType,
                        value,
                        entryBlock.AppendInstruction(
                            Instruction.CreateConstant(
                                ValueRange.CastSignedness(false),
                                valueType),
                            "valrange")),
                    defaultBranch,
                    new Branch(headerBlock));

                // Pick an appropriate type for the bitmasks.
                var bitmaskType = valueType;

                if (valueSpec.Size < 32)
                {
                    bitmaskType = TypeEnvironment.UInt32;
                }
                if (ValueRange.IsGreaterThan(new IntegerConstant(valueSpec.Size, ValueRange.Spec)))
                {
                    bitmaskType = TypeEnvironment.UInt64;
                }

                // Set up first part of the header block.
                if (bitmaskType != valueType)
                {
                    valueSpec = bitmaskType.GetIntegerSpecOrNull();
                }

                var zero = headerBlock.AppendInstruction(
                    Instruction.CreateConstant(
                        new IntegerConstant(0, valueSpec),
                        valueType),
                    "zero");

                var one = headerBlock.AppendInstruction(
                    Instruction.CreateConstant(
                        new IntegerConstant(1, valueSpec),
                        valueType),
                    "one");

                value = headerBlock.AppendInstruction(
                    Instruction.CreateArithmeticIntrinsic(
                        ArithmeticIntrinsics.Operators.LeftShift,
                        false,
                        bitmaskType,
                        new[] { bitmaskType, valueType },
                        new[] { one, value }),
                    "shifted");

                valueType = bitmaskType;

                // Start emitting cases.
                var caseBlock = headerBlock;
                var nextCase  = graph.AddBasicBlock("bitswitch.case1");

                for (int i = 0; i < Flow.Cases.Count; i++)
                {
                    // Construct a mask for the case.
                    var switchCase  = Flow.Cases[i];
                    var oneConstant = new IntegerConstant(1, valueSpec);
                    var mask        = new IntegerConstant(0, valueSpec);
                    foreach (var pattern in switchCase.Values)
                    {
                        mask = mask.BitwiseOr(oneConstant.ShiftLeft(((IntegerConstant)pattern).Subtract(MinValue)));
                    }

                    // Switch on the bitwise 'and' of the mask and
                    // the shifted value.
                    caseBlock.Flow = SwitchFlow.CreateIfElse(
                        Instruction.CreateBinaryArithmeticIntrinsic(
                            ArithmeticIntrinsics.Operators.And,
                            false,
                            valueType,
                            value,
                            caseBlock.AppendInstruction(
                                Instruction.CreateConstant(mask, valueType),
                                "bitmask" + i)),
                        switchCase.Branch,
                        new Branch(nextCase));

                    caseBlock = nextCase;
                    nextCase  = graph.AddBasicBlock("bitswitch.case" + (i + 2));
                }

                // Jump to the default branch if nothing matches.
                caseBlock.Flow = new JumpFlow(defaultBranch);

                // Jump to the header block and let it do all of the heavy
                // lifting.
                return(new JumpFlow(entryBlock));
            }
예제 #16
0
        private static BlockFlow SimplifySwitchFlow(SwitchFlow flow, FlowGraph graph)
        {
            var value = SimplifyInstruction(flow.SwitchValue, graph);

            if (value.Prototype is ConstantPrototype)
            {
                // Turn the switch into a jump.
                var constant         = ((ConstantPrototype)value.Prototype).Value;
                var valuesToBranches = flow.ValueToBranchMap;
                return(new JumpFlow(
                           valuesToBranches.ContainsKey(constant)
                    ? valuesToBranches[constant]
                    : flow.DefaultBranch));
            }
            else if (ArithmeticIntrinsics.IsArithmeticIntrinsicPrototype(value.Prototype))
            {
                var proto         = (IntrinsicPrototype)value.Prototype;
                var intrinsicName = ArithmeticIntrinsics.ParseArithmeticIntrinsicName(proto.Name);
                if (intrinsicName == ArithmeticIntrinsics.Operators.Convert &&
                    proto.ParameterCount == 1 &&
                    flow.IsIntegerSwitch)
                {
                    // We can eliminate instructions that extend integers
                    // by changing the values in the list of cases.
                    var operand     = proto.GetArgumentList(value).Single();
                    var operandType = graph.GetValueType(operand);
                    var convType    = proto.ResultType;
                    var operandSpec = operandType.GetIntegerSpecOrNull();

                    if (operandSpec == null)
                    {
                        // The operand of the conversion intrinsic is not an
                        // integer.
                        return(flow);
                    }

                    var convSpec = convType.GetIntegerSpecOrNull();

                    if (operandSpec.Size > convSpec.Size)
                    {
                        // We can't handle this case. To handle it anyway
                        // would require us to introduce additional cases
                        // and that's costly.
                        return(flow);
                    }

                    var caseList = new List <SwitchCase>();
                    foreach (var switchCase in flow.Cases)
                    {
                        // Retain only those switch cases that have values
                        // that are in the range of the conversion function.
                        var values = ImmutableHashSet.CreateBuilder <Constant>();
                        foreach (var val in switchCase.Values.Cast <IntegerConstant>())
                        {
                            var opVal = val.Cast(operandSpec);
                            if (opVal.Cast(convSpec).Equals(val))
                            {
                                values.Add(opVal);
                            }
                        }
                        if (values.Count > 0)
                        {
                            caseList.Add(new SwitchCase(values.ToImmutableHashSet(), switchCase.Branch));
                        }
                    }
                    return(SimplifySwitchFlow(
                               new SwitchFlow(
                                   Instruction.CreateCopy(
                                       operandType,
                                       operand),
                                   caseList,
                                   flow.DefaultBranch),
                               graph));
                }
                else if (intrinsicName == ArithmeticIntrinsics.Operators.IsEqualTo &&
                         proto.ParameterCount == 2 &&
                         proto.ResultType.IsIntegerType())
                {
                    var      args = proto.GetArgumentList(value);
                    var      lhs  = args[0];
                    var      rhs  = args[1];
                    Constant constant;
                    ValueTag operand;
                    if (TryExtractConstantAndValue(lhs, rhs, graph, out constant, out operand))
                    {
                        // The 'arith.eq' intrinsic always either produces '0' or '1'.
                        // Because of that property, we can safely rewrite switches
                        // like so:
                        //
                        // switch arith.eq(value, constant)
                        //   0 -> zeroBranch
                        //   1 -> oneBranch
                        //   default -> defaultBranch
                        //
                        // -->
                        //
                        // switch value
                        //   constant -> oneBranch ?? defaultBranch
                        //   default -> zeroBranch ?? defaultBranch
                        //
                        var resultSpec = proto.ResultType.GetIntegerSpecOrNull();
                        var zeroVal    = new IntegerConstant(0, resultSpec);
                        var oneVal     = new IntegerConstant(1, resultSpec);

                        var valuesToBranches = flow.ValueToBranchMap;
                        var zeroBranch       = valuesToBranches.ContainsKey(zeroVal)
                            ? valuesToBranches[zeroVal]
                            : flow.DefaultBranch;
                        var oneBranch = valuesToBranches.ContainsKey(oneVal)
                            ? valuesToBranches[oneVal]
                            : flow.DefaultBranch;

                        return(SimplifySwitchFlow(
                                   new SwitchFlow(
                                       Instruction.CreateCopy(
                                           graph.GetValueType(operand),
                                           operand),
                                       new[] { new SwitchCase(ImmutableHashSet.Create(constant), oneBranch) },
                                       zeroBranch),
                                   graph));
                    }
                }
            }
            return(flow);
        }
예제 #17
0
 /// <summary>
 /// Constructs a new floating constant
 /// </summary>
 /// <param name="token">The parser token</param>
 /// <param name="major">The major component</param>
 /// <param name="minor">The minor component</param>
 public FloatingConstant(ParseToken token, IntegerConstant major, IntegerConstant minor)
     : base(token)
 {
     Major = major ?? throw new ArgumentNullException(nameof(major));
     Minor = minor ?? throw new ArgumentNullException(nameof(minor));
 }
예제 #18
0
        private Expression GenerateMethodBody(Operation operation, ParameterExpression contextParameter,
                                              IFunctionRegistry functionRegistry)
        {
            if (operation == null)
            {
                throw new ArgumentNullException("operation");
            }

            if (operation.GetType() == typeof(IntegerConstant))
            {
                IntegerConstant constant = (IntegerConstant)operation;

                return(Expression.Convert(Expression.Constant(constant.Value, typeof(int)), typeof(double)));
            }
            else if (operation.GetType() == typeof(FloatingPointConstant))
            {
                FloatingPointConstant constant = (FloatingPointConstant)operation;

                return(Expression.Constant(constant.Value, typeof(double)));
            }
            else if (operation.GetType() == typeof(Variable))
            {
                Type contextType    = typeof(FormulaContext);
                Type dictionaryType = typeof(IDictionary <string, double>);

                Variable variable = (Variable)operation;

                Expression          getVariables = Expression.Property(contextParameter, "Variables");
                ParameterExpression value        = Expression.Variable(typeof(double), "value");

                Expression variableFound = Expression.Call(getVariables,
                                                           dictionaryType.GetRuntimeMethod("TryGetValue", new Type[] { typeof(string), typeof(double).MakeByRefType() }),
                                                           Expression.Constant(variable.Name),
                                                           value);

                Expression throwException = Expression.Throw(
                    Expression.New(typeof(VariableNotDefinedException).GetConstructor(new Type[] { typeof(string) }),
                                   Expression.Constant(string.Format("The variable \"{0}\" used is not defined.", variable.Name))));

                LabelTarget returnLabel = Expression.Label(typeof(double));

                return(Expression.Block(
                           new[] { value },
                           Expression.IfThenElse(
                               variableFound,
                               Expression.Return(returnLabel, value),
                               throwException
                               ),
                           Expression.Label(returnLabel, Expression.Constant(0.0))
                           ));
            }
            else if (operation.GetType() == typeof(Multiplication))
            {
                Multiplication multiplication = (Multiplication)operation;
                Expression     argument1      = GenerateMethodBody(multiplication.Argument1, contextParameter, functionRegistry);
                Expression     argument2      = GenerateMethodBody(multiplication.Argument2, contextParameter, functionRegistry);

                return(Expression.Multiply(argument1, argument2));
            }
            else if (operation.GetType() == typeof(Addition))
            {
                Addition   addition  = (Addition)operation;
                Expression argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry);
                Expression argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry);

                return(Expression.Add(argument1, argument2));
            }
            else if (operation.GetType() == typeof(Subtraction))
            {
                Subtraction addition  = (Subtraction)operation;
                Expression  argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry);
                Expression  argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry);

                return(Expression.Subtract(argument1, argument2));
            }
            else if (operation.GetType() == typeof(Division))
            {
                Division   division = (Division)operation;
                Expression dividend = GenerateMethodBody(division.Dividend, contextParameter, functionRegistry);
                Expression divisor  = GenerateMethodBody(division.Divisor, contextParameter, functionRegistry);

                return(Expression.Divide(dividend, divisor));
            }
            else if (operation.GetType() == typeof(Modulo))
            {
                Modulo     modulo   = (Modulo)operation;
                Expression dividend = GenerateMethodBody(modulo.Dividend, contextParameter, functionRegistry);
                Expression divisor  = GenerateMethodBody(modulo.Divisor, contextParameter, functionRegistry);

                return(Expression.Modulo(dividend, divisor));
            }
            else if (operation.GetType() == typeof(Exponentiation))
            {
                Exponentiation exponentation = (Exponentiation)operation;
                Expression     @base         = GenerateMethodBody(exponentation.Base, contextParameter, functionRegistry);
                Expression     exponent      = GenerateMethodBody(exponentation.Exponent, contextParameter, functionRegistry);

                return(Expression.Call(null, typeof(Math).GetRuntimeMethod("Pow", new Type[] { typeof(double), typeof(double) }), @base, exponent));
            }
            else if (operation.GetType() == typeof(UnaryMinus))
            {
                UnaryMinus unaryMinus = (UnaryMinus)operation;
                Expression argument   = GenerateMethodBody(unaryMinus.Argument, contextParameter, functionRegistry);
                return(Expression.Negate(argument));
            }
            else if (operation.GetType() == typeof(And))
            {
                And        and       = (And)operation;
                Expression argument1 = Expression.NotEqual(GenerateMethodBody(and.Argument1, contextParameter, functionRegistry), Expression.Constant(0.0));
                Expression argument2 = Expression.NotEqual(GenerateMethodBody(and.Argument2, contextParameter, functionRegistry), Expression.Constant(0.0));

                return(Expression.Condition(Expression.And(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(Or))
            {
                Or         and       = (Or)operation;
                Expression argument1 = Expression.NotEqual(GenerateMethodBody(and.Argument1, contextParameter, functionRegistry), Expression.Constant(0.0));
                Expression argument2 = Expression.NotEqual(GenerateMethodBody(and.Argument2, contextParameter, functionRegistry), Expression.Constant(0.0));

                return(Expression.Condition(Expression.Or(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(LessThan))
            {
                LessThan   lessThan  = (LessThan)operation;
                Expression argument1 = GenerateMethodBody(lessThan.Argument1, contextParameter, functionRegistry);
                Expression argument2 = GenerateMethodBody(lessThan.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.LessThan(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(LessOrEqualThan))
            {
                LessOrEqualThan lessOrEqualThan = (LessOrEqualThan)operation;
                Expression      argument1       = GenerateMethodBody(lessOrEqualThan.Argument1, contextParameter, functionRegistry);
                Expression      argument2       = GenerateMethodBody(lessOrEqualThan.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.LessThanOrEqual(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(GreaterThan))
            {
                GreaterThan greaterThan = (GreaterThan)operation;
                Expression  argument1   = GenerateMethodBody(greaterThan.Argument1, contextParameter, functionRegistry);
                Expression  argument2   = GenerateMethodBody(greaterThan.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.GreaterThan(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(GreaterOrEqualThan))
            {
                GreaterOrEqualThan greaterOrEqualThan = (GreaterOrEqualThan)operation;
                Expression         argument1          = GenerateMethodBody(greaterOrEqualThan.Argument1, contextParameter, functionRegistry);
                Expression         argument2          = GenerateMethodBody(greaterOrEqualThan.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.GreaterThanOrEqual(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(Equal))
            {
                Equal      equal     = (Equal)operation;
                Expression argument1 = GenerateMethodBody(equal.Argument1, contextParameter, functionRegistry);
                Expression argument2 = GenerateMethodBody(equal.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.Equal(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(NotEqual))
            {
                NotEqual   notEqual  = (NotEqual)operation;
                Expression argument1 = GenerateMethodBody(notEqual.Argument1, contextParameter, functionRegistry);
                Expression argument2 = GenerateMethodBody(notEqual.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.NotEqual(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(Function))
            {
                Function function = (Function)operation;

                FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName);
                Type         funcType;
                Type[]       parameterTypes;
                Expression[] arguments;

                if (functionInfo.IsDynamicFunc)
                {
                    funcType       = typeof(DynamicFunc <double, double>);
                    parameterTypes = new Type[] { typeof(double[]) };


                    Expression[] arrayArguments = new Expression[function.Arguments.Count];
                    for (int i = 0; i < function.Arguments.Count; i++)
                    {
                        arrayArguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry);
                    }

                    arguments    = new Expression[1];
                    arguments[0] = NewArrayExpression.NewArrayInit(typeof(double), arrayArguments);
                }
                else
                {
                    funcType       = GetFuncType(functionInfo.NumberOfParameters);
                    parameterTypes = (from i in Enumerable.Range(0, functionInfo.NumberOfParameters)
                                      select typeof(double)).ToArray();

                    arguments = new Expression[functionInfo.NumberOfParameters];
                    for (int i = 0; i < functionInfo.NumberOfParameters; i++)
                    {
                        arguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry);
                    }
                }

                Expression getFunctionRegistry = Expression.Property(contextParameter, "FunctionRegistry");

                ParameterExpression functionInfoVariable = Expression.Variable(typeof(FunctionInfo));

                return(Expression.Block(
                           new[] { functionInfoVariable },
                           Expression.Assign(
                               functionInfoVariable,
                               Expression.Call(getFunctionRegistry, typeof(IFunctionRegistry).GetRuntimeMethod("GetFunctionInfo", new Type[] { typeof(string) }), Expression.Constant(function.FunctionName))
                               ),
                           Expression.Call(
                               Expression.Convert(Expression.Property(functionInfoVariable, "Function"), funcType),
                               funcType.GetRuntimeMethod("Invoke", parameterTypes),
                               arguments)));
            }
            else
            {
                throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation");
            }
        }
예제 #19
0
        private void GenerateMethodBody(ILGenerator generator, Operation operation,
                                        IFunctionRegistry functionRegistry)
        {
            if (operation == null)
            {
                throw new ArgumentNullException("operation");
            }

            if (operation.GetType() == typeof(IntegerConstant))
            {
                IntegerConstant constant = (IntegerConstant)operation;

                generator.Emit(OpCodes.Ldc_I4, constant.Value);
                generator.Emit(OpCodes.Conv_R8);
            }
            else if (operation.GetType() == typeof(FloatingPointConstant))
            {
                FloatingPointConstant constant = (FloatingPointConstant)operation;

                generator.Emit(OpCodes.Ldc_R8, constant.Value);
            }
            else if (operation.GetType() == typeof(Variable))
            {
                Type dictionaryType = typeof(IDictionary <string, double>);

                Variable variable = (Variable)operation;

                Label throwExceptionLabel = generator.DefineLabel();
                Label returnLabel         = generator.DefineLabel();

                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Callvirt, typeof(FormulaContext).GetProperty("Variables").GetGetMethod());
                generator.Emit(OpCodes.Ldstr, variable.Name);
                generator.Emit(OpCodes.Ldloca_S, (byte)0);
                generator.Emit(OpCodes.Callvirt, dictionaryType.GetMethod("TryGetValue", new Type[] { typeof(string), typeof(double).MakeByRefType() }));
                generator.Emit(OpCodes.Ldc_I4_0);
                generator.Emit(OpCodes.Ceq);
                generator.Emit(OpCodes.Brtrue_S, throwExceptionLabel);

                generator.Emit(OpCodes.Ldloc_0);
                generator.Emit(OpCodes.Br_S, returnLabel);

                generator.MarkLabel(throwExceptionLabel);
                generator.Emit(OpCodes.Ldstr, string.Format("The variable \"{0}\" used is not defined.", variable.Name));
                generator.Emit(OpCodes.Newobj, typeof(VariableNotDefinedException).GetConstructor(new Type[] { typeof(string) }));
                generator.Emit(OpCodes.Throw);

                generator.MarkLabel(returnLabel);
            }
            else if (operation.GetType() == typeof(Multiplication))
            {
                Multiplication multiplication = (Multiplication)operation;
                GenerateMethodBody(generator, multiplication.Argument1, functionRegistry);
                GenerateMethodBody(generator, multiplication.Argument2, functionRegistry);

                generator.Emit(OpCodes.Mul);
            }
            else if (operation.GetType() == typeof(Addition))
            {
                Addition addition = (Addition)operation;
                GenerateMethodBody(generator, addition.Argument1, functionRegistry);
                GenerateMethodBody(generator, addition.Argument2, functionRegistry);

                generator.Emit(OpCodes.Add);
            }
            else if (operation.GetType() == typeof(Subtraction))
            {
                Subtraction addition = (Subtraction)operation;
                GenerateMethodBody(generator, addition.Argument1, functionRegistry);
                GenerateMethodBody(generator, addition.Argument2, functionRegistry);

                generator.Emit(OpCodes.Sub);
            }
            else if (operation.GetType() == typeof(Division))
            {
                Division division = (Division)operation;
                GenerateMethodBody(generator, division.Dividend, functionRegistry);
                GenerateMethodBody(generator, division.Divisor, functionRegistry);

                generator.Emit(OpCodes.Div);
            }
            else if (operation.GetType() == typeof(Modulo))
            {
                Modulo modulo = (Modulo)operation;
                GenerateMethodBody(generator, modulo.Dividend, functionRegistry);
                GenerateMethodBody(generator, modulo.Divisor, functionRegistry);

                generator.Emit(OpCodes.Rem);
            }
            else if (operation.GetType() == typeof(Exponentiation))
            {
                Exponentiation exponentation = (Exponentiation)operation;
                GenerateMethodBody(generator, exponentation.Base, functionRegistry);
                GenerateMethodBody(generator, exponentation.Exponent, functionRegistry);

                generator.Emit(OpCodes.Call, typeof(Math).GetMethod("Pow"));
            }
            else if (operation.GetType() == typeof(UnaryMinus))
            {
                UnaryMinus unaryMinus = (UnaryMinus)operation;
                GenerateMethodBody(generator, unaryMinus.Argument, functionRegistry);

                generator.Emit(OpCodes.Neg);
            }
            else if (operation.GetType() == typeof(LessThan))
            {
                LessThan lessThan = (LessThan)operation;

                Label ifLabel  = generator.DefineLabel();
                Label endLabel = generator.DefineLabel();

                GenerateMethodBody(generator, lessThan.Argument1, functionRegistry);
                GenerateMethodBody(generator, lessThan.Argument2, functionRegistry);

                generator.Emit(OpCodes.Blt_S, ifLabel);
                generator.Emit(OpCodes.Ldc_R8, 0.0);
                generator.Emit(OpCodes.Br_S, endLabel);
                generator.MarkLabel(ifLabel);
                generator.Emit(OpCodes.Ldc_R8, 1.0);
                generator.MarkLabel(endLabel);
            }
            else if (operation.GetType() == typeof(LessOrEqualThan))
            {
                LessOrEqualThan lessOrEqualThan = (LessOrEqualThan)operation;

                Label ifLabel  = generator.DefineLabel();
                Label endLabel = generator.DefineLabel();

                GenerateMethodBody(generator, lessOrEqualThan.Argument1, functionRegistry);
                GenerateMethodBody(generator, lessOrEqualThan.Argument2, functionRegistry);

                generator.Emit(OpCodes.Ble_S, ifLabel);
                generator.Emit(OpCodes.Ldc_R8, 0.0);
                generator.Emit(OpCodes.Br_S, endLabel);
                generator.MarkLabel(ifLabel);
                generator.Emit(OpCodes.Ldc_R8, 1.0);
                generator.MarkLabel(endLabel);
            }
            else if (operation.GetType() == typeof(GreaterThan))
            {
                GreaterThan greaterThan = (GreaterThan)operation;

                Label ifLabel  = generator.DefineLabel();
                Label endLabel = generator.DefineLabel();

                GenerateMethodBody(generator, greaterThan.Argument1, functionRegistry);
                GenerateMethodBody(generator, greaterThan.Argument2, functionRegistry);

                generator.Emit(OpCodes.Bgt_S, ifLabel);
                generator.Emit(OpCodes.Ldc_R8, 0.0);
                generator.Emit(OpCodes.Br_S, endLabel);
                generator.MarkLabel(ifLabel);
                generator.Emit(OpCodes.Ldc_R8, 1.0);
                generator.MarkLabel(endLabel);
            }
            else if (operation.GetType() == typeof(GreaterOrEqualThan))
            {
                GreaterOrEqualThan greaterOrEqualThan = (GreaterOrEqualThan)operation;

                Label ifLabel  = generator.DefineLabel();
                Label endLabel = generator.DefineLabel();

                GenerateMethodBody(generator, greaterOrEqualThan.Argument1, functionRegistry);
                GenerateMethodBody(generator, greaterOrEqualThan.Argument2, functionRegistry);

                generator.Emit(OpCodes.Bge_S, ifLabel);
                generator.Emit(OpCodes.Ldc_R8, 0.0);
                generator.Emit(OpCodes.Br_S, endLabel);
                generator.MarkLabel(ifLabel);
                generator.Emit(OpCodes.Ldc_R8, 1.0);
                generator.MarkLabel(endLabel);
            }
            else if (operation.GetType() == typeof(Equal))
            {
                Equal equal = (Equal)operation;

                Label ifLabel  = generator.DefineLabel();
                Label endLabel = generator.DefineLabel();

                GenerateMethodBody(generator, equal.Argument1, functionRegistry);
                GenerateMethodBody(generator, equal.Argument2, functionRegistry);

                generator.Emit(OpCodes.Beq_S, ifLabel);
                generator.Emit(OpCodes.Ldc_R8, 0.0);
                generator.Emit(OpCodes.Br_S, endLabel);
                generator.MarkLabel(ifLabel);
                generator.Emit(OpCodes.Ldc_R8, 1.0);
                generator.MarkLabel(endLabel);
            }
            else if (operation.GetType() == typeof(NotEqual))
            {
                NotEqual notEqual = (NotEqual)operation;

                Label ifLabel  = generator.DefineLabel();
                Label endLabel = generator.DefineLabel();

                GenerateMethodBody(generator, notEqual.Argument1, functionRegistry);
                GenerateMethodBody(generator, notEqual.Argument2, functionRegistry);

                generator.Emit(OpCodes.Beq, ifLabel);
                generator.Emit(OpCodes.Ldc_R8, 1.0);
                generator.Emit(OpCodes.Br_S, endLabel);
                generator.MarkLabel(ifLabel);
                generator.Emit(OpCodes.Ldc_R8, 0.0);
                generator.MarkLabel(endLabel);
            }
            else if (operation.GetType() == typeof(Function))
            {
                Function function = (Function)operation;

                FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName);
                Type         funcType     = GetFuncType(functionInfo.NumberOfParameters);

                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Callvirt, typeof(FormulaContext).GetProperty("FunctionRegistry").GetGetMethod());
                generator.Emit(OpCodes.Ldstr, function.FunctionName);
                generator.Emit(OpCodes.Callvirt, typeof(IFunctionRegistry).GetMethod("GetFunctionInfo", new Type[] { typeof(string) }));
                generator.Emit(OpCodes.Callvirt, typeof(FunctionInfo).GetProperty("Function").GetGetMethod());
                generator.Emit(OpCodes.Castclass, funcType);

                for (int i = 0; i < functionInfo.NumberOfParameters; i++)
                {
                    GenerateMethodBody(generator, function.Arguments[i], functionRegistry);
                }

                generator.Emit(OpCodes.Call, funcType.GetMethod("Invoke"));
            }
            else
            {
                throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation");
            }
        }
        private Value ConvertToValue(BlockBuilder currentBlock, ExpressionSyntax expression)
        {
            switch (expression)
            {
            case NewObjectExpressionSyntax newObjectExpression:
                var args = newObjectExpression.Arguments.Select(a => ConvertToOperand(currentBlock, a.Value)).ToFixedList();
                return(new ConstructorCall((ObjectType)newObjectExpression.Type, args, newObjectExpression.Span));

            case IdentifierNameSyntax identifier:
            {
                var symbol = identifier.ReferencedSymbol;
                switch (symbol)
                {
                case VariableDeclarationStatementSyntax _:
                case ParameterSyntax _:
                    return(graph.VariableFor(symbol.FullName.UnqualifiedName));

                default:
                    return(new DeclaredValue(symbol.FullName, identifier.Span));
                }
            }

            case UnaryExpressionSyntax unaryExpression:
                return(ConvertUnaryExpressionToValue(currentBlock, unaryExpression));

            case BinaryExpressionSyntax binaryExpression:
                return(ConvertBinaryExpressionToValue(currentBlock, binaryExpression));

            case IntegerLiteralExpressionSyntax _:
                throw new InvalidOperationException("Integer literals should have an implicit conversion around them");

            case StringLiteralExpressionSyntax _:
                throw new InvalidOperationException("String literals should have an implicit conversion around them");

            case BoolLiteralExpressionSyntax boolLiteral:
                return(new BooleanConstant(boolLiteral.Value, boolLiteral.Span));

            case ImplicitNumericConversionExpression implicitNumericConversion:
                if (implicitNumericConversion.Expression.Type.AssertResolved() is IntegerConstantType constantType)
                {
                    return(new IntegerConstant(constantType.Value, implicitNumericConversion.Type.AssertResolved(), implicitNumericConversion.Span));
                }
                else
                {
                    throw new NotImplementedException();
                }

            case IfExpressionSyntax ifExpression:
                // TODO deal with the value of the if expression
                throw new NotImplementedException();

            case UnsafeExpressionSyntax unsafeExpression:
                return(ConvertToValue(currentBlock, unsafeExpression.Expression));

            case ImplicitLiteralConversionExpression implicitLiteralConversion:
            {
                var conversionFunction = implicitLiteralConversion.ConversionFunction.FullName;
                var literal            = (StringLiteralExpressionSyntax)implicitLiteralConversion.Expression;
                var constantLength     = Utf8BytesConstant.Encoding.GetByteCount(literal.Value);
                var sizeArgument       = new IntegerConstant(constantLength, DataType.Size, literal.Span);
                var bytesArgument      = new Utf8BytesConstant(literal.Value, literal.Span);
                return(new FunctionCall(implicitLiteralConversion.Span, conversionFunction, sizeArgument, bytesArgument));
            }

            case InvocationSyntax invocation:
                return(ConvertInvocationToValue(currentBlock, invocation));

            case MemberAccessExpressionSyntax memberAccess:
            {
                var value  = ConvertToOperand(currentBlock, memberAccess.Expression);
                var symbol = memberAccess.ReferencedSymbol;
                if (symbol is IAccessorSymbol accessor)
                {
                    return(new VirtualFunctionCall(memberAccess.Span, accessor.PropertyName.UnqualifiedName, value));
                }

                return(new FieldAccessValue(value,
                                            memberAccess.ReferencedSymbol.FullName, memberAccess.Span));
            }

            case MutableExpressionSyntax mutable:
                // TODO shouldn't borrowing be explicit in the IR and don't we
                // need to be able to check mutability on borrows?
                return(ConvertToValue(currentBlock, mutable.Expression));

            case MoveExpressionSyntax move:
                // TODO should this be explicit in IR?
                return(ConvertToValue(currentBlock, move.Expression));

            default:
                throw NonExhaustiveMatchException.For(expression);
            }
        }
예제 #21
0
        private void GenerateMethodBody(ILGenerator generator, Operation operation)
        {
            if (operation == null)
            {
                throw new ArgumentNullException("operation");
            }

            if (operation.GetType() == typeof(IntegerConstant))
            {
                IntegerConstant constant = (IntegerConstant)operation;

                generator.Emit(OpCodes.Ldc_I4, constant.Value);
                generator.Emit(OpCodes.Conv_R8);
            }
            else if (operation.GetType() == typeof(FloatingPointConstant))
            {
                FloatingPointConstant constant = (FloatingPointConstant)operation;

                generator.Emit(OpCodes.Ldc_R8, constant.Value);
            }
            else if (operation.GetType() == typeof(Variable))
            {
                Type dictionaryType = typeof(Dictionary <string, double>);

                Variable variable = (Variable)operation;

                Label throwExceptionLabel = generator.DefineLabel();
                Label returnLabel         = generator.DefineLabel();

                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldstr, variable.Name);
                generator.Emit(OpCodes.Callvirt, dictionaryType.GetMethod("ContainsKey", new Type[] { typeof(string) }));
                generator.Emit(OpCodes.Ldc_I4_0);
                generator.Emit(OpCodes.Ceq);
                generator.Emit(OpCodes.Brtrue_S, throwExceptionLabel);

                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldstr, variable.Name);
                generator.Emit(OpCodes.Callvirt, dictionaryType.GetMethod("get_Item", new Type[] { typeof(string) }));
                generator.Emit(OpCodes.Br_S, returnLabel);

                generator.MarkLabel(throwExceptionLabel);
                generator.Emit(OpCodes.Ldstr, string.Format("The variable \"{0}\" used is not defined.", variable.Name));
                generator.Emit(OpCodes.Newobj, typeof(VariableNotDefinedException).GetConstructor(new Type[] { typeof(string) }));
                generator.Emit(OpCodes.Throw);

                generator.MarkLabel(returnLabel);
            }
            else if (operation.GetType() == typeof(Multiplication))
            {
                Multiplication multiplication = (Multiplication)operation;
                GenerateMethodBody(generator, multiplication.Argument1);
                GenerateMethodBody(generator, multiplication.Argument2);

                generator.Emit(OpCodes.Mul);
            }
            else if (operation.GetType() == typeof(Addition))
            {
                Addition addition = (Addition)operation;
                GenerateMethodBody(generator, addition.Argument1);
                GenerateMethodBody(generator, addition.Argument2);

                generator.Emit(OpCodes.Add);
            }
            else if (operation.GetType() == typeof(Substraction))
            {
                Substraction addition = (Substraction)operation;
                GenerateMethodBody(generator, addition.Argument1);
                GenerateMethodBody(generator, addition.Argument2);

                generator.Emit(OpCodes.Sub);
            }
            else if (operation.GetType() == typeof(Division))
            {
                Division division = (Division)operation;
                GenerateMethodBody(generator, division.Dividend);
                GenerateMethodBody(generator, division.Divisor);

                generator.Emit(OpCodes.Div);
            }
            else if (operation.GetType() == typeof(Exponentiation))
            {
                Exponentiation exponentation = (Exponentiation)operation;
                GenerateMethodBody(generator, exponentation.Base);
                GenerateMethodBody(generator, exponentation.Exponent);

                generator.Emit(OpCodes.Call, typeof(Math).GetMethod("Pow"));
            }
            else if (operation.GetType() == typeof(Function))
            {
                Function function = (Function)operation;

                switch (function.FunctionType)
                {
                case FunctionType.Sine:
                    GenerateMethodBody(generator, function.Arguments[0]);

                    generator.Emit(OpCodes.Call, typeof(Math).GetMethod("Sin"));
                    break;

                case FunctionType.Cosine:
                    GenerateMethodBody(generator, function.Arguments[0]);

                    generator.Emit(OpCodes.Call, typeof(Math).GetMethod("Cos"));
                    break;

                case FunctionType.Loge:
                    GenerateMethodBody(generator, function.Arguments[0]);

                    generator.Emit(OpCodes.Call, typeof(Math).GetMethod("Log", new Type[] { typeof(double) }));
                    break;

                case FunctionType.Log10:
                    GenerateMethodBody(generator, function.Arguments[0]);

                    generator.Emit(OpCodes.Call, typeof(Math).GetMethod("Log10"));
                    break;

                case FunctionType.Logn:
                    GenerateMethodBody(generator, function.Arguments[0]);
                    GenerateMethodBody(generator, function.Arguments[1]);

                    generator.Emit(OpCodes.Call, typeof(Math).GetMethod("Log", new Type[] { typeof(double), typeof(double) }));
                    break;

                default:
                    throw new ArgumentException(string.Format("Unsupported function \"{0}\".", function.FunctionType), "operation");
                }
            }
            else
            {
                throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation");
            }
        }
예제 #22
0
 public TypedValue Evaluate(IntegerConstant intConst, InterpreterContext context)
 {
     return(new TypedValue(intConst.Value));
 }
예제 #23
0
        private Expression ParseEntityWithoutSuffixChain(TokenStream tokens, Node owner)
        {
            tokens.EnsureNotEof();

            Token  nextToken = tokens.Peek();
            string next      = nextToken.Value;

            if (next == this.parser.Keywords.NULL)
            {
                return(new NullConstant(tokens.Pop(), owner));
            }
            if (next == this.parser.Keywords.TRUE)
            {
                return(new BooleanConstant(tokens.Pop(), true, owner));
            }
            if (next == this.parser.Keywords.FALSE)
            {
                return(new BooleanConstant(tokens.Pop(), false, owner));
            }
            if (next == this.parser.Keywords.THIS)
            {
                return(new ThisKeyword(tokens.Pop(), owner));
            }
            if (next == this.parser.Keywords.BASE)
            {
                return(new BaseKeyword(tokens.Pop(), owner));
            }

            Token peekToken = tokens.Peek();

            if (next.StartsWith("'"))
            {
                return(new StringConstant(tokens.Pop(), StringConstant.ParseOutRawValue(peekToken), owner));
            }
            if (next.StartsWith("\""))
            {
                return(new StringConstant(tokens.Pop(), StringConstant.ParseOutRawValue(peekToken), owner));
            }
            if (next == "@") // Raw strings (no escape sequences, a backslash is a literal backslash)
            {
                Token atToken         = tokens.Pop();
                Token stringToken     = tokens.Pop();
                char  stringTokenChar = stringToken.Value[0];
                if (stringTokenChar != '"' && stringTokenChar != '\'')
                {
                    throw new ParserException(atToken, "Unexpected token: '@'");
                }
                string stringValue = stringToken.Value.Substring(1, stringToken.Value.Length - 2);
                return(new StringConstant(atToken, stringValue, owner));
            }
            if (next == this.parser.Keywords.NEW)
            {
                return(this.ParseInstantiate(tokens, owner));
            }

            char firstChar = next[0];

            if (nextToken.Type == TokenType.WORD)
            {
                Token varToken = tokens.Pop();
                if (tokens.IsNext("=>"))
                {
                    return(this.ParseLambda(
                               tokens,
                               varToken,
                               new AType[] { AType.Any() },
                               new Token[] { varToken },
                               owner));
                }
                else
                {
                    return(new Variable(varToken, varToken.Value, owner));
                }
            }

            if (firstChar == '[' && nextToken.File.CompilationScope.IsCrayon)
            {
                Token             bracketToken = tokens.PopExpected("[");
                List <Expression> elements     = new List <Expression>();
                bool previousHasCommaOrFirst   = true;
                while (!tokens.PopIfPresent("]"))
                {
                    if (!previousHasCommaOrFirst)
                    {
                        tokens.PopExpected("]");                           // throws appropriate error
                    }
                    elements.Add(Parse(tokens, owner));
                    previousHasCommaOrFirst = tokens.PopIfPresent(",");
                }
                return(new ListDefinition(bracketToken, elements, AType.Any(), owner, false, null));
            }

            if (firstChar == '{' && nextToken.File.CompilationScope.IsCrayon)
            {
                Token             braceToken = tokens.PopExpected("{");
                List <Expression> keys       = new List <Expression>();
                List <Expression> values     = new List <Expression>();
                bool previousHasCommaOrFirst = true;
                while (!tokens.PopIfPresent("}"))
                {
                    if (!previousHasCommaOrFirst)
                    {
                        tokens.PopExpected("}");                           // throws appropriate error
                    }
                    keys.Add(Parse(tokens, owner));
                    tokens.PopExpected(":");
                    values.Add(Parse(tokens, owner));
                    previousHasCommaOrFirst = tokens.PopIfPresent(",");
                }
                return(new DictionaryDefinition(braceToken, AType.Any(), AType.Any(), keys, values, owner));
            }

            if (nextToken.Type == TokenType.NUMBER)
            {
                if (next.Contains("."))
                {
                    double floatValue;
                    if (double.TryParse(next, out floatValue))
                    {
                        return(new FloatConstant(tokens.Pop(), floatValue, owner));
                    }
                    throw new ParserException(nextToken, "Invalid float literal.");
                }
                return(new IntegerConstant(
                           tokens.Pop(),
                           IntegerConstant.ParseIntConstant(nextToken, next),
                           owner));
            }

            throw new ParserException(tokens.Peek(), "Encountered unexpected token: '" + tokens.PeekValue() + "'");
        }
예제 #24
0
 /// <summary>
 /// Constructs a new array index literal
 /// </summary>
 /// <param name="token">The token where the literal was found</param>
 /// <param name="index">The index value</param>
 public ArrayIndexLiteral(ParseToken token, IntegerConstant index)
     : base(token)
 {
     Index = index ?? throw new ArgumentNullException(nameof(index));
 }
예제 #25
0
        public double Execute(Operation operation,
                              IFunctionRegistry functionRegistry,
                              IConstantRegistry constantRegistry,
                              IDictionary <string, double> variables)
        {
            if (operation == null)
            {
                throw new ArgumentNullException("operation");
            }

            if (operation.GetType() == typeof(IntegerConstant))
            {
                IntegerConstant constant = (IntegerConstant)operation;
                return(constant.Value);
            }
            else if (operation.GetType() == typeof(FloatingPointConstant))
            {
                FloatingPointConstant constant = (FloatingPointConstant)operation;
                return(constant.Value);
            }
            else if (operation.GetType() == typeof(Variable))
            {
                Variable variable = (Variable)operation;

                double value;
                bool   variableFound = variables.TryGetValue(variable.Name, out value);

                if (variableFound)
                {
                    return(value);
                }
                else
                {
                    throw new VariableNotDefinedException(string.Format("The variable \"{0}\" used is not defined.", variable.Name));
                }
            }
            else if (operation.GetType() == typeof(Multiplication))
            {
                Multiplication multiplication = (Multiplication)operation;
                return(Execute(multiplication.Argument1, functionRegistry, constantRegistry, variables) * Execute(multiplication.Argument2, functionRegistry, constantRegistry, variables));
            }
            else if (operation.GetType() == typeof(Addition))
            {
                Addition addition = (Addition)operation;
                return(Execute(addition.Argument1, functionRegistry, constantRegistry, variables) + Execute(addition.Argument2, functionRegistry, constantRegistry, variables));
            }
            else if (operation.GetType() == typeof(Subtraction))
            {
                Subtraction addition = (Subtraction)operation;
                return(Execute(addition.Argument1, functionRegistry, constantRegistry, variables) - Execute(addition.Argument2, functionRegistry, constantRegistry, variables));
            }
            else if (operation.GetType() == typeof(Division))
            {
                Division division = (Division)operation;
                return(Execute(division.Dividend, functionRegistry, constantRegistry, variables) / Execute(division.Divisor, functionRegistry, constantRegistry, variables));
            }
            else if (operation.GetType() == typeof(Modulo))
            {
                Modulo division = (Modulo)operation;
                return(Execute(division.Dividend, functionRegistry, constantRegistry, variables) % Execute(division.Divisor, functionRegistry, constantRegistry, variables));
            }
            else if (operation.GetType() == typeof(Exponentiation))
            {
                Exponentiation exponentiation = (Exponentiation)operation;
                return(Math.Pow(Execute(exponentiation.Base, functionRegistry, constantRegistry, variables), Execute(exponentiation.Exponent, functionRegistry, constantRegistry, variables)));
            }
            else if (operation.GetType() == typeof(UnaryMinus))
            {
                UnaryMinus unaryMinus = (UnaryMinus)operation;
                return(-Execute(unaryMinus.Argument, functionRegistry, constantRegistry, variables));
            }
            else if (operation.GetType() == typeof(And))
            {
                And and        = (And)operation;
                var operation1 = Execute(and.Argument1, functionRegistry, constantRegistry, variables) != 0;
                var operation2 = Execute(and.Argument2, functionRegistry, constantRegistry, variables) != 0;

                return((operation1 && operation2) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(Or))
            {
                Or  or         = (Or)operation;
                var operation1 = Execute(or.Argument1, functionRegistry, constantRegistry, variables) != 0;
                var operation2 = Execute(or.Argument2, functionRegistry, constantRegistry, variables) != 0;

                return((operation1 || operation2) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(LessThan))
            {
                LessThan lessThan = (LessThan)operation;
                return((Execute(lessThan.Argument1, functionRegistry, constantRegistry, variables) < Execute(lessThan.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(LessOrEqualThan))
            {
                LessOrEqualThan lessOrEqualThan = (LessOrEqualThan)operation;
                return((Execute(lessOrEqualThan.Argument1, functionRegistry, constantRegistry, variables) <= Execute(lessOrEqualThan.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(GreaterThan))
            {
                GreaterThan greaterThan = (GreaterThan)operation;
                return((Execute(greaterThan.Argument1, functionRegistry, constantRegistry, variables) > Execute(greaterThan.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(GreaterOrEqualThan))
            {
                GreaterOrEqualThan greaterOrEqualThan = (GreaterOrEqualThan)operation;
                return((Execute(greaterOrEqualThan.Argument1, functionRegistry, constantRegistry, variables) >= Execute(greaterOrEqualThan.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(Equal))
            {
                Equal equal = (Equal)operation;
                return((Execute(equal.Argument1, functionRegistry, constantRegistry, variables) == Execute(equal.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(NotEqual))
            {
                NotEqual notEqual = (NotEqual)operation;
                return((Execute(notEqual.Argument1, functionRegistry, constantRegistry, variables) != Execute(notEqual.Argument2, functionRegistry, constantRegistry, variables)) ? 1.0 : 0.0);
            }
            else if (operation.GetType() == typeof(Function))
            {
                Function function = (Function)operation;

                FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName);

                double[] arguments = new double[functionInfo.IsDynamicFunc ? function.Arguments.Count : functionInfo.NumberOfParameters];
                for (int i = 0; i < arguments.Length; i++)
                {
                    arguments[i] = Execute(function.Arguments[i], functionRegistry, constantRegistry, variables);
                }

                return(Invoke(functionInfo.Function, arguments));
            }
            else
            {
                throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation");
            }
        }
예제 #26
0
파일: Interpreter.cs 프로젝트: plurby/Jace
        public double Execute(Operation operation, Dictionary <string, double> variables)
        {
            if (operation == null)
            {
                throw new ArgumentNullException("operation");
            }

            if (operation.GetType() == typeof(IntegerConstant))
            {
                IntegerConstant constant = (IntegerConstant)operation;
                return(constant.Value);
            }
            else if (operation.GetType() == typeof(FloatingPointConstant))
            {
                FloatingPointConstant constant = (FloatingPointConstant)operation;
                return(constant.Value);
            }
            else if (operation.GetType() == typeof(Variable))
            {
                Variable variable = (Variable)operation;
                if (variables.ContainsKey(variable.Name))
                {
                    return(variables[variable.Name]);
                }
                else
                {
                    throw new VariableNotDefinedException(string.Format("The variable \"{0}\" used is not defined.", variable.Name));
                }
            }
            else if (operation.GetType() == typeof(Multiplication))
            {
                Multiplication multiplication = (Multiplication)operation;
                return(Execute(multiplication.Argument1, variables) * Execute(multiplication.Argument2, variables));
            }
            else if (operation.GetType() == typeof(Addition))
            {
                Addition addition = (Addition)operation;
                return(Execute(addition.Argument1, variables) + Execute(addition.Argument2, variables));
            }
            else if (operation.GetType() == typeof(Substraction))
            {
                Substraction addition = (Substraction)operation;
                return(Execute(addition.Argument1, variables) - Execute(addition.Argument2, variables));
            }
            else if (operation.GetType() == typeof(Division))
            {
                Division division = (Division)operation;
                return(Execute(division.Dividend, variables) / Execute(division.Divisor, variables));
            }
            else if (operation.GetType() == typeof(Exponentiation))
            {
                Exponentiation exponentiation = (Exponentiation)operation;
                return(Math.Pow(Execute(exponentiation.Base, variables), Execute(exponentiation.Exponent, variables)));
            }
            else if (operation.GetType() == typeof(Function))
            {
                Function function = (Function)operation;

                switch (function.FunctionType)
                {
                case FunctionType.Sine:
                    return(Math.Sin(Execute(function.Arguments[0], variables)));

                case FunctionType.Cosine:
                    return(Math.Cos(Execute(function.Arguments[0], variables)));

                case FunctionType.Loge:
                    return(Math.Log(Execute(function.Arguments[0], variables)));

                case FunctionType.Log10:
                    return(Math.Log10(Execute(function.Arguments[0], variables)));

                case FunctionType.Logn:
                    return(Math.Log(Execute(function.Arguments[0], variables), Execute(function.Arguments[1], variables)));

                default:
                    throw new ArgumentException(string.Format("Unsupported function \"{0}\".", function.FunctionType), "operation");
                }
            }
            else
            {
                throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation");
            }
        }
예제 #27
0
        private Expression GenerateMethodBody(Operation operation, ParameterExpression contextParameter,
                                              IFunctionRegistry functionRegistry)
        {
            if (operation == null)
            {
                throw new ArgumentNullException("operation");
            }

            if (operation.GetType() == typeof(IntegerConstant))
            {
                IntegerConstant constant = (IntegerConstant)operation;

                double value = constant.Value;
                return(Expression.Constant(value, typeof(double)));
            }
            else if (operation.GetType() == typeof(FloatingPointConstant))
            {
                FloatingPointConstant constant = (FloatingPointConstant)operation;

                return(Expression.Constant(constant.Value, typeof(double)));
            }
            else if (operation.GetType() == typeof(Variable))
            {
                Variable variable = (Variable)operation;

                Func <string, FormulaContext, double> getVariableValueOrThrow = PrecompiledMethods.GetVariableValueOrThrow;
                return(Expression.Call(null,
                                       getVariableValueOrThrow.GetMethodInfo(),
                                       Expression.Constant(variable.Name),

                                       contextParameter));
            }
            else if (operation.GetType() == typeof(Multiplication))
            {
                Multiplication multiplication = (Multiplication)operation;
                Expression     argument1      = GenerateMethodBody(multiplication.Argument1, contextParameter, functionRegistry);
                Expression     argument2      = GenerateMethodBody(multiplication.Argument2, contextParameter, functionRegistry);

                return(Expression.Multiply(argument1, argument2));
            }
            else if (operation.GetType() == typeof(Addition))
            {
                Addition   addition  = (Addition)operation;
                Expression argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry);
                Expression argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry);

                return(Expression.Add(argument1, argument2));
            }
            else if (operation.GetType() == typeof(Subtraction))
            {
                Subtraction addition  = (Subtraction)operation;
                Expression  argument1 = GenerateMethodBody(addition.Argument1, contextParameter, functionRegistry);
                Expression  argument2 = GenerateMethodBody(addition.Argument2, contextParameter, functionRegistry);

                return(Expression.Subtract(argument1, argument2));
            }
            else if (operation.GetType() == typeof(Division))
            {
                Division   division = (Division)operation;
                Expression dividend = GenerateMethodBody(division.Dividend, contextParameter, functionRegistry);
                Expression divisor  = GenerateMethodBody(division.Divisor, contextParameter, functionRegistry);

                return(Expression.Divide(dividend, divisor));
            }
            else if (operation.GetType() == typeof(Modulo))
            {
                Modulo     modulo   = (Modulo)operation;
                Expression dividend = GenerateMethodBody(modulo.Dividend, contextParameter, functionRegistry);
                Expression divisor  = GenerateMethodBody(modulo.Divisor, contextParameter, functionRegistry);

                return(Expression.Modulo(dividend, divisor));
            }
            else if (operation.GetType() == typeof(Exponentiation))
            {
                Exponentiation exponentation = (Exponentiation)operation;
                Expression     @base         = GenerateMethodBody(exponentation.Base, contextParameter, functionRegistry);
                Expression     exponent      = GenerateMethodBody(exponentation.Exponent, contextParameter, functionRegistry);

                return(Expression.Call(null, typeof(Math).GetRuntimeMethod("Pow", new Type[] { typeof(double), typeof(double) }), @base, exponent));
            }
            else if (operation.GetType() == typeof(UnaryMinus))
            {
                UnaryMinus unaryMinus = (UnaryMinus)operation;
                Expression argument   = GenerateMethodBody(unaryMinus.Argument, contextParameter, functionRegistry);
                return(Expression.Negate(argument));
            }
            else if (operation.GetType() == typeof(And))
            {
                And        and       = (And)operation;
                Expression argument1 = Expression.NotEqual(GenerateMethodBody(and.Argument1, contextParameter, functionRegistry), Expression.Constant(0.0));
                Expression argument2 = Expression.NotEqual(GenerateMethodBody(and.Argument2, contextParameter, functionRegistry), Expression.Constant(0.0));

                return(Expression.Condition(Expression.And(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(Or))
            {
                Or         and       = (Or)operation;
                Expression argument1 = Expression.NotEqual(GenerateMethodBody(and.Argument1, contextParameter, functionRegistry), Expression.Constant(0.0));
                Expression argument2 = Expression.NotEqual(GenerateMethodBody(and.Argument2, contextParameter, functionRegistry), Expression.Constant(0.0));

                return(Expression.Condition(Expression.Or(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(LessThan))
            {
                LessThan   lessThan  = (LessThan)operation;
                Expression argument1 = GenerateMethodBody(lessThan.Argument1, contextParameter, functionRegistry);
                Expression argument2 = GenerateMethodBody(lessThan.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.LessThan(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(LessOrEqualThan))
            {
                LessOrEqualThan lessOrEqualThan = (LessOrEqualThan)operation;
                Expression      argument1       = GenerateMethodBody(lessOrEqualThan.Argument1, contextParameter, functionRegistry);
                Expression      argument2       = GenerateMethodBody(lessOrEqualThan.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.LessThanOrEqual(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(GreaterThan))
            {
                GreaterThan greaterThan = (GreaterThan)operation;
                Expression  argument1   = GenerateMethodBody(greaterThan.Argument1, contextParameter, functionRegistry);
                Expression  argument2   = GenerateMethodBody(greaterThan.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.GreaterThan(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(GreaterOrEqualThan))
            {
                GreaterOrEqualThan greaterOrEqualThan = (GreaterOrEqualThan)operation;
                Expression         argument1          = GenerateMethodBody(greaterOrEqualThan.Argument1, contextParameter, functionRegistry);
                Expression         argument2          = GenerateMethodBody(greaterOrEqualThan.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.GreaterThanOrEqual(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(Equal))
            {
                Equal      equal     = (Equal)operation;
                Expression argument1 = GenerateMethodBody(equal.Argument1, contextParameter, functionRegistry);
                Expression argument2 = GenerateMethodBody(equal.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.Equal(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(NotEqual))
            {
                NotEqual   notEqual  = (NotEqual)operation;
                Expression argument1 = GenerateMethodBody(notEqual.Argument1, contextParameter, functionRegistry);
                Expression argument2 = GenerateMethodBody(notEqual.Argument2, contextParameter, functionRegistry);

                return(Expression.Condition(Expression.NotEqual(argument1, argument2),
                                            Expression.Constant(1.0),
                                            Expression.Constant(0.0)));
            }
            else if (operation.GetType() == typeof(Function))
            {
                Function function = (Function)operation;

                FunctionInfo functionInfo = functionRegistry.GetFunctionInfo(function.FunctionName);
                Type         funcType;
                Type[]       parameterTypes;
                Expression[] arguments;

                if (functionInfo.IsDynamicFunc)
                {
                    funcType       = typeof(DynamicFunc <double, double>);
                    parameterTypes = new Type[] { typeof(double[]) };


                    Expression[] arrayArguments = new Expression[function.Arguments.Count];
                    for (int i = 0; i < function.Arguments.Count; i++)
                    {
                        arrayArguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry);
                    }

                    arguments    = new Expression[1];
                    arguments[0] = NewArrayExpression.NewArrayInit(typeof(double), arrayArguments);
                }
                else
                {
                    funcType       = GetFuncType(functionInfo.NumberOfParameters);
                    parameterTypes = (from i in Enumerable.Range(0, functionInfo.NumberOfParameters)
                                      select typeof(double)).ToArray();

                    arguments = new Expression[functionInfo.NumberOfParameters];
                    for (int i = 0; i < functionInfo.NumberOfParameters; i++)
                    {
                        arguments[i] = GenerateMethodBody(function.Arguments[i], contextParameter, functionRegistry);
                    }
                }

                Expression getFunctionRegistry = Expression.Property(contextParameter, "FunctionRegistry");

                ParameterExpression functionInfoVariable = Expression.Variable(typeof(FunctionInfo));

                Expression funcInstance;
                if (!functionInfo.IsOverWritable)
                {
                    funcInstance = Expression.Convert(
                        Expression.Property(
                            Expression.Call(
                                getFunctionRegistry,
                                typeof(IFunctionRegistry).GetRuntimeMethod("GetFunctionInfo", new Type[] { typeof(string) }),
                                Expression.Constant(function.FunctionName)),
                            "Function"),
                        funcType);
                }
                else
                {
                    funcInstance = Expression.Constant(functionInfo.Function, funcType);
                }

                return(Expression.Call(
                           funcInstance,
                           funcType.GetRuntimeMethod("Invoke", parameterTypes),
                           arguments));
            }
            else
            {
                throw new ArgumentException(string.Format("Unsupported operation \"{0}\".", operation.GetType().FullName), "operation");
            }
        }
예제 #28
0
        private static Expression ParseEntityWithoutSuffixChain(TokenStream tokens, Executable owner)
        {
            string next = tokens.PeekValue();

            if (next == "null")
            {
                return(new NullConstant(tokens.Pop(), owner));
            }
            if (next == "true")
            {
                return(new BooleanConstant(tokens.Pop(), true, owner));
            }
            if (next == "false")
            {
                return(new BooleanConstant(tokens.Pop(), false, owner));
            }

            Token peekToken = tokens.Peek();

            if (next.StartsWith("'"))
            {
                return(new StringConstant(tokens.Pop(), StringConstant.ParseOutRawValue(peekToken), owner));
            }
            if (next.StartsWith("\""))
            {
                return(new StringConstant(tokens.Pop(), StringConstant.ParseOutRawValue(peekToken), owner));
            }
            if (next == "new")
            {
                return(ParseInstantiate(tokens, owner));
            }

            char firstChar = next[0];

            if (VARIABLE_STARTER.Contains(firstChar))
            {
                Token varToken = tokens.Pop();
                return(new Variable(varToken, varToken.Value, owner));
            }

            if (firstChar == '[')
            {
                Token             bracketToken = tokens.PopExpected("[");
                List <Expression> elements     = new List <Expression>();
                bool previousHasCommaOrFirst   = true;
                while (!tokens.PopIfPresent("]"))
                {
                    if (!previousHasCommaOrFirst)
                    {
                        tokens.PopExpected("]");                           // throws appropriate error
                    }
                    elements.Add(Parse(tokens, owner));
                    previousHasCommaOrFirst = tokens.PopIfPresent(",");
                }
                return(new ListDefinition(bracketToken, elements, owner));
            }

            if (firstChar == '{')
            {
                Token             braceToken = tokens.PopExpected("{");
                List <Expression> keys       = new List <Expression>();
                List <Expression> values     = new List <Expression>();
                bool previousHasCommaOrFirst = true;
                while (!tokens.PopIfPresent("}"))
                {
                    if (!previousHasCommaOrFirst)
                    {
                        tokens.PopExpected("}");                           // throws appropriate error
                    }
                    keys.Add(Parse(tokens, owner));
                    tokens.PopExpected(":");
                    values.Add(Parse(tokens, owner));
                    previousHasCommaOrFirst = tokens.PopIfPresent(",");
                }
                return(new DictionaryDefinition(braceToken, keys, values, owner));
            }

            if (next.Length > 2 && next.Substring(0, 2) == "0x")
            {
                Token intToken = tokens.Pop();
                int   intValue = IntegerConstant.ParseIntConstant(intToken, intToken.Value);
                return(new IntegerConstant(intToken, intValue, owner));
            }

            if (Parser.IsInteger(next))
            {
                Token  numberToken = tokens.Pop();
                string numberValue = numberToken.Value;

                if (tokens.IsNext("."))
                {
                    Token decimalToken = tokens.Pop();
                    if (decimalToken.HasWhitespacePrefix)
                    {
                        throw new ParserException(decimalToken, "Decimals cannot have whitespace before them.");
                    }

                    Token afterDecimal = tokens.Pop();
                    if (afterDecimal.HasWhitespacePrefix)
                    {
                        throw new ParserException(afterDecimal, "Cannot have whitespace after the decimal.");
                    }
                    if (!Parser.IsInteger(afterDecimal.Value))
                    {
                        throw new ParserException(afterDecimal, "Decimal must be followed by an integer.");
                    }

                    numberValue += "." + afterDecimal.Value;

                    double floatValue = FloatConstant.ParseValue(numberToken, numberValue);
                    return(new FloatConstant(numberToken, floatValue, owner));
                }

                int intValue = IntegerConstant.ParseIntConstant(numberToken, numberToken.Value);
                return(new IntegerConstant(numberToken, intValue, owner));
            }

            if (tokens.IsNext("."))
            {
                Token  dotToken    = tokens.PopExpected(".");
                string numberValue = "0.";
                Token  postDecimal = tokens.Pop();
                if (postDecimal.HasWhitespacePrefix || !Parser.IsInteger(postDecimal.Value))
                {
                    throw new ParserException(dotToken, "Unexpected dot.");
                }

                numberValue += postDecimal.Value;

                double floatValue;
                if (double.TryParse(numberValue, out floatValue))
                {
                    return(new FloatConstant(dotToken, floatValue, owner));
                }

                throw new ParserException(dotToken, "Invalid float literal.");
            }

            throw new ParserException(tokens.Peek(), "Encountered unexpected token: '" + tokens.PeekValue() + "'");
        }
예제 #29
0
 protected abstract void TranslateIntegerConstant(List <string> output, IntegerConstant intConstant);
예제 #30
0
 public WhileType TypeExpression(IntegerConstant intConst, CompilerContext context)
 {
     intConst.CompilerScope = context.CurrentScope;
     return(WhileType.INT);
 }