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); }
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); } }
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."); } }
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)); }
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"); }
public BitTestLowering( SwitchFlow flow, IntegerConstant minValue, IntegerConstant valueRange, TypeEnvironment typeEnvironment) { this.Flow = flow; this.MinValue = minValue; this.ValueRange = valueRange; this.TypeEnvironment = typeEnvironment; }
/// <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); }
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(); }
protected override void TranslateIntegerConstant(List <string> output, IntegerConstant intConstant) { int value = intConstant.Value; if (value >= 0) { output.Add("" + value); } else { output.Add("(" + value + ")"); } }
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); }
/// <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)); }
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)); }
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))); }
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"); } }
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)); }
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); }
/// <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)); }
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"); } }
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); } }
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"); } }
public TypedValue Evaluate(IntegerConstant intConst, InterpreterContext context) { return(new TypedValue(intConst.Value)); }
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() + "'"); }
/// <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)); }
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"); } }
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"); } }
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"); } }
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() + "'"); }
protected abstract void TranslateIntegerConstant(List <string> output, IntegerConstant intConstant);
public WhileType TypeExpression(IntegerConstant intConst, CompilerContext context) { intConst.CompilerScope = context.CurrentScope; return(WhileType.INT); }