public IExpression GetExpression(IExpression[] expressions) { if (Members != expressions.Count()) { throw new ArgumentException(); } var powers = new IExpression[Members, Exponent + 1]; for (int i = 0; i < Members; i++) { for (int j = 0; j < Exponent + 1; j++) { powers[i, j] = expressions[Members - i - 1].Power(new NumberExpression(new NumberDecimal(j, 0))).Format().Expand(); } } IExpression result = NumberExpression.Zero; foreach (var item in this) { IExpression term = new NumberExpression(new NumberDecimal(item.Coefficient, 0)); for (int i = 0; i < item.Exponents.Count(); i++) { term = term.Multiply(powers[i, item.Exponents[i]]).Format().Expand(); } result = result.Add(term); } return(result.Format().Expand()); }
public IExpression Expand(int PowerLevel = int.MaxValue) { var items = ExpandLevel(GetMembers().Select(a => a.Expand()).ToArray(), 0); IExpression result = NumberExpression.Zero; foreach (var item in items) { result = result.Add(item); } return(result); }
public IExpression Expand(int PowerLevel = int.MaxValue) { IExpression result = NumberExpression.Zero; var Lefts = Helper.SplitAddition(this.Left.Expand()).Select(a => a.Expand()).ToArray(); var Rights = Helper.SplitAddition(this.Right.Expand()).Select(a => a.Expand()).ToArray(); foreach (var item1 in Lefts) { foreach (var item2 in Rights) { result = result.Add(item1.Multiply(item2)); } } return(result); }
public BatsmanStatisticsViewModel(IDataSeedService <PlayerInning> playerInningService, string filter) { _playerInningService = playerInningService ?? throw new ArgumentNullException($"playerService is null, cannot get match."); IExpression condition = Expression.Property("type").EqualTo(Expression.String("PlayerInning")); if (filter == "only tournament matches") { condition.Add(Expression.Property("tournamentId").IsNot(Expression.String(string.Empty))); } List <PlayerInning> playerinnings = _playerInningService.GetFilteredList(condition).ToList(); BatsmanStatistics = playerinnings.GroupBy(pi => pi.PlayerId).Select(p => new PlayerStatistics(p.ToList())).ToList(); }
public static IExpression ExpandLevel(IExpression[] expressions, int currentLevel, IExpression current = null) { current = current ?? NumberExpression.One; IExpression result = NumberExpression.Zero; if (currentLevel == 0) { return(current); } foreach (var item in expressions) { var test = ExpandLevel(expressions, currentLevel - 1, current.Multiply(item)); //Console.WriteLine($"{ currentLevel } {current} ({current}) * ({item}) = ({current.Multiply(item)}) { test } {result } {result.GetType() } { test.GetType() }"); result = result.Add(test); } return(result); }
private IExpression ParseExpression() { IExpression x = ParseTerm(); while (true) { if (Eat('+')) { x = x.Add(ParseTerm()); } else if (Eat('-')) { x = x.Sub(ParseTerm()); } else { return(x); } } }
public static IExpression Parse(string exp, out string[] parsedVariables) { // set up stacks Stack <char> opts = new Stack <char>(); Stack <string> vars = new Stack <string>(); Stack <IExpression> expres = new Stack <IExpression>(); // getting the stacks to use string[] variables = GetVariableNames(exp); parsedVariables = variables; vars = GetVarStack(variables); char[] operations = GetOperators(exp); opts = GetOperatorStack(operations); expres.Push(null); IExpression expression = null; // expception handling if (opts.Count == 0 && vars.Count != 1) { throw new Exception(String.Format("An expression with multiple variables requires an operation: {0}", exp)); } // whlie we still have operations to use while (opts.Count > 0) { char opt = opts.Pop(); if (opt != '(' && opt != ')') // opt is actually an operator // later on i will need to implement Not { if (expression == null) { expression = GetOperationExpression(opt); } expression.Add(new Variable(vars.Pop())); // shortcircuiting so that i dont check an empty stack if ((opts.Count == 0 && vars.Count > 0) || (opts.Count > 0 && opts.Peek() == ')')) { //TODO errors here when there is something like (x|y)&z expression.Add(new Variable(vars.Pop())); } } // opening a paren // push paren here, push null if it directly follows another open paren else if (opt == '(') { expres.Push(expression); expression = null; } // this will be for close paren else { // close paren, pop expres IExpression temp; do { // TODO error here when there are more than 1 paren paris (()) temp = expres.Pop(); // only need to check for this because // )( is not allowed and the preprocessor checks for it if ((opts.Count > 0 && opts.Peek() != ')') && temp == null) { // make sure i don't have to pop it here temp = GetOperationExpression(opts.Peek()); } if (temp != null) { temp.Add(expression); expression = temp; } }while(temp == null && expres.Count > 0); } } // yay for hotfix! if (expression == null && vars.Count == 1) { expression = new Variable(vars.Pop()); } return(expression); }
static void Process <T>(ILReader il, IExpression <T> exp, Stack <T> eval, T[] args, T[] locals) { var tailcall = false; while (il.MoveNext()) { var x = il.Current;//.Simplify(); T rhs; switch (x.OpCode.Type()) { //--------------- arithmetic instructions -------------- case OpType.Add_ovf: case OpType.Add_ovf_un: rhs = eval.Pop(); eval.Push(exp.AddOverflow(eval.Pop(), rhs)); break; case OpType.Add: rhs = eval.Pop(); eval.Push(exp.Add(eval.Pop(), rhs)); break; case OpType.Sub: rhs = eval.Pop(); eval.Push(exp.Subtract(eval.Pop(), rhs)); break; case OpType.Sub_ovf: case OpType.Sub_ovf_un: rhs = eval.Pop(); eval.Push(exp.SubtractOverflow(eval.Pop(), rhs)); break; case OpType.Mul: rhs = eval.Pop(); eval.Push(exp.Multiply(eval.Pop(), rhs)); break; case OpType.Mul_ovf: case OpType.Mul_ovf_un: rhs = eval.Pop(); eval.Push(exp.MultiplyOverflow(eval.Pop(), rhs)); break; case OpType.Div: case OpType.Div_un: rhs = eval.Pop(); eval.Push(exp.Divide(eval.Pop(), rhs)); break; case OpType.Neg: eval.Push(exp.Negate(eval.Pop())); break; case OpType.Rem: case OpType.Rem_un: rhs = eval.Pop(); eval.Push(exp.Modulo(eval.Pop(), rhs)); break; //------------ logical/bitwise operations -------------- case OpType.And: rhs = eval.Pop(); eval.Push(exp.And(eval.Pop(), rhs)); break; case OpType.Or: rhs = eval.Pop(); eval.Push(exp.Or(eval.Pop(), rhs)); break; case OpType.Not: eval.Push(exp.Not(eval.Pop())); break; case OpType.Box: eval.Push(exp.Box(eval.Pop())); break; case OpType.Shl: rhs = eval.Pop(); eval.Push(exp.LeftShift(eval.Pop(), rhs)); break; case OpType.Shr: case OpType.Shr_un: rhs = eval.Pop(); eval.Push(exp.RightShift(eval.Pop(), rhs)); break; //----------- Branching instructions --------- case OpType.Br: case OpType.Br_s: il.Seek(x.Operand.Label); // seek to branch label eval.Push(exp.Goto(eval.Pop())); break; case OpType.Beq: case OpType.Beq_s: rhs = eval.Pop(); eval.Push(exp.Equal(eval.Pop(), rhs)); goto case OpType.Brtrue; case OpType.Bge: case OpType.Bge_un: case OpType.Bge_un_s: rhs = eval.Pop(); eval.Push(exp.GreaterThanOrEqual(eval.Pop(), rhs)); goto case OpType.Brtrue; case OpType.Ble: case OpType.Ble_un: case OpType.Ble_un_s: rhs = eval.Pop(); eval.Push(exp.LessThanOrEqual(eval.Pop(), rhs)); goto case OpType.Brtrue; case OpType.Blt: case OpType.Blt_un: case OpType.Blt_un_s: rhs = eval.Pop(); eval.Push(exp.LessThan(eval.Pop(), rhs)); goto case OpType.Brtrue; case OpType.Bne_un: case OpType.Bne_un_s: rhs = eval.Pop(); eval.Push(exp.NotEqual(eval.Pop(), rhs)); goto case OpType.Brtrue; case OpType.Brfalse: case OpType.Brfalse_s: eval.Push(exp.Negate(eval.Pop())); goto case OpType.Brtrue; case OpType.Brtrue: case OpType.Brtrue_s: //FIXME: this duplicates expressions for every branch instead of unifying them. Need //to track a Dictionary<Label, T>, and should skip Process() calls if the Label //already exists (and patch it in with a goto). var cond = eval.Pop(); if (!il.MoveNext()) { throw new InvalidOperationException("Expected an instruction after branch!"); } var elseStart = il.Mark(); // save current position var thenStart = x.Operand.Label; il.Seek(thenStart); // seek to _then when branch condition true Process(il, exp, eval, args, locals); var _then = eval.Pop(); // extract _then expression il.Seek(elseStart); // seek to _else when branch condition false Process(il, exp, eval, args, locals); var _else = eval.Pop(); // extract _else expression eval.Push(exp.If(cond, _then, _else)); break; case OpType.Switch: var val = eval.Pop(); if (!il.MoveNext()) { throw new InvalidOperationException("Expected an instruction after switch!"); } var swt = il.Mark(); var cases = x.ResolveBranches().Select(kv => { il.Seek(kv.Value); Process(il, exp, eval, args, locals); return(new KeyValuePair <object, T>(kv.Key, eval.Pop())); }); eval.Push(exp.Switch(val, cases)); il.Seek(swt); break; #if DEBUG //FIXME: extend ILReader to support consulting exception handling blocks: // method.GetMethodBody().ExceptionHandlingClauses[0].TryOffset/TryLength/HandlerOffset // case OpType.Leave: case OpType.Leave_s: //FIXME: should leave be treated differently from br? //Process(il, exp, eval, args, locals); // process the .try block il.Seek(x.Operand.Label); // seek to branch label eval.Push(exp.Goto(eval.Pop())); return; case OpType.Endfilter: // return to try context? //eval.Push() return; //eval.Push(exp.EndFilter(eval.Pop())); //break; case OpType.Endfinally: return; //case OpType.Try: // Process(il, exp, eval, args, locals); // var leaveTry = eval.Pop(); // if (il.Current.OpCode.Type() != OpType.Leave || il.Current.OpCode.Type() != OpType.Leave_s || !il.MoveNext()) // throw new InvalidOperationException("Try-catch-finally requires .try block to end with a leave instruction."); // if (!il.MoveNext()) //FIXME: maybe shouldn't call this? // return; // var handlers = new Dictionary<Type, T>(); // do // { // Process(il, exp, eval, args, locals); // if (il.Current.OpCode.Type() != OpType.Endfilter) // } while (il.Current.OpCode.Type() == OpType.Endfilter); // Process(il, exp, eval, args, locals); // if (il.Current.OpCode.Type() != OpType.Leave || il.Current.OpCode.Type() != OpType.Leave_s) // throw new InvalidOperationException("Try-catch-finally requires .try block to end with a leave instruction."); // while (il.Current.OpCode.Type() == OpType.Endfinally); // //eval.Push(exp.TryCatchFinally(leaveTry, )); // break; #endif //------------ Method call instructions --------------- #if DEBUG //FIXME: indirect calls and method pointers require decoding method signatures. //See incomplete CallSignature type. case OpType.Ldftn: eval.Push(exp.GetPointer(x.ResolveMethod(), default(T))); break; case OpType.Ldvirtftn: eval.Push(exp.GetPointer(x.ResolveMethod(), eval.Pop())); break; case OpType.Calli: var sig = x.ResolveSignature(); //var args = var entry = eval.Pop(); eval.Push(exp.CallIndirect(sig, entry, tailcall, args)); tailcall = false; break; #endif case OpType.Call: case OpType.Callvirt: var method = x.ResolveMethod(); var mparams = method.GetParameters(); var margs = mparams.Select((a, i) => Cast(eval.Pop(), mparams[i].ParameterType, exp)) .Reverse() .ToArray(); var minstance = method.IsStatic ? default(T) : eval.Pop(); eval.Push(exp.Call(method, tailcall, minstance, margs)); tailcall = false; break; case OpType.Jmp: eval.Push(exp.Jump(x.ResolveMethod())); break; case OpType.Cpblk: rhs = eval.Pop(); var src = eval.Pop(); eval.Push(exp.BlockCopy(eval.Pop(), src, rhs)); break; case OpType.Cpobj: rhs = eval.Pop(); eval.Push(exp.StructCopy(eval.Pop(), rhs, x.ResolveType())); break; case OpType.Initblk: rhs = eval.Pop(); var value = eval.Pop(); eval.Push(exp.BlockInit(eval.Pop(), value, rhs)); break; case OpType.Initobj: eval.Push(exp.ObjectInit(eval.Pop(), x.ResolveType())); break; //---------------- Load/store instructions ------------- case OpType.Sizeof: eval.Push(exp.SizeOf(x.ResolveType())); break; case OpType.Localloc: eval.Push(exp.LocalAlloc(eval.Pop())); break; case OpType.Ldsflda: case OpType.Ldflda: var afield = x.ResolveField(); eval.Push(exp.AddressOf(exp.Field(afield, afield.IsStatic ? default(T) : eval.Pop()))); break; case OpType.Ldarga: case OpType.Ldarga_s: eval.Push(exp.AddressOf(args[x.Operand.Int16])); break; case OpType.Ldloca: case OpType.Ldloca_s: eval.Push(exp.AddressOf(locals[x.Operand.Int16])); break; case OpType.Ldarg: case OpType.Ldarg_s: eval.Push(args[x.Operand.Int16]); break; case OpType.Ldarg_0: eval.Push(args[0]); break; case OpType.Ldarg_1: eval.Push(args[1]); break; case OpType.Ldarg_2: eval.Push(args[2]); break; case OpType.Ldarg_3: eval.Push(args[3]); break; case OpType.Ldc_i4_m1: eval.Push(exp.Constant(-1)); break; case OpType.Ldc_i4_0: eval.Push(exp.Constant(0)); break; case OpType.Ldc_i4_1: eval.Push(exp.Constant(1)); break; case OpType.Ldc_i4_2: eval.Push(exp.Constant(2)); break; case OpType.Ldc_i4_3: eval.Push(exp.Constant(3)); break; case OpType.Ldc_i4_4: eval.Push(exp.Constant(4)); break; case OpType.Ldc_i4_5: eval.Push(exp.Constant(5)); break; case OpType.Ldc_i4_6: eval.Push(exp.Constant(6)); break; case OpType.Ldc_i4_7: eval.Push(exp.Constant(7)); break; case OpType.Ldc_i4_8: eval.Push(exp.Constant(8)); break; case OpType.Ldc_i4: case OpType.Ldc_i4_s: var i4 = x.Operand.Int32; eval.Push(exp.Constant(i4)); break; case OpType.Ldc_i8: var i8 = x.Operand.Int64; eval.Push(exp.Constant(i8)); break; case OpType.Ldc_r8: var r8 = x.Operand.Float64; eval.Push(exp.Constant(r8)); break; case OpType.Ldc_r4: var r4 = x.Operand.Float32; eval.Push(exp.Constant(r4)); break; case OpType.Ldfld: case OpType.Ldsfld: var lfield = x.ResolveField(); eval.Push(exp.Field(lfield, lfield.IsStatic ? default(T) : eval.Pop())); return; case OpType.Ldlen: eval.Push(exp.ArrayLength(eval.Pop())); break; case OpType.Ldloc_0: eval.Push(locals[0]); break; case OpType.Ldloc_1: eval.Push(locals[1]); break; case OpType.Ldloc_2: eval.Push(locals[2]); break; case OpType.Ldloc_3: eval.Push(locals[3]); break; case OpType.Ldloc: case OpType.Ldloc_s: eval.Push(locals[x.Operand.Int32]); break; case OpType.Stloc_0: eval.Push(exp.Assign(locals[0], eval.Pop())); break; case OpType.Stloc_1: eval.Push(exp.Assign(locals[1], eval.Pop())); break; case OpType.Stloc_2: eval.Push(exp.Assign(locals[2], eval.Pop())); break; case OpType.Stloc_3: eval.Push(exp.Assign(locals[3], eval.Pop())); break; case OpType.Stloc: case OpType.Stloc_s: eval.Push(exp.Assign(locals[x.Operand.Int16], eval.Pop())); break; case OpType.Starg: case OpType.Starg_s: eval.Push(exp.Assign(args[x.Operand.Int16], eval.Pop())); break; case OpType.Stobj: rhs = eval.Pop(); eval.Push(exp.Assign(eval.Pop(), rhs)); break; case OpType.Stsfld: case OpType.Stfld: var sfield = x.ResolveField(); rhs = eval.Pop(); eval.Push(exp.Assign(exp.Field(sfield, sfield.IsStatic ? default(T) : eval.Pop()), rhs)); break; case OpType.Ldnull: eval.Push(exp.Constant <object>(null)); break; case OpType.Ldstr: eval.Push(exp.Constant(x.ResolveString())); break; case OpType.Ldtoken: eval.Push(exp.Constant(x.Resolve())); break; case OpType.Nop: break; case OpType.Pop: eval.Pop(); break; case OpType.Ret: Debug.Assert(eval.Count == 1); eval.Push(exp.Return(eval.Pop())); break; case OpType.Ldelem: case OpType.Ldelem_ref: case OpType.Ldelem_i: case OpType.Ldelem_i1: case OpType.Ldelem_i2: case OpType.Ldelem_i4: case OpType.Ldelem_i8: case OpType.Ldelem_r4: case OpType.Ldelem_r8: case OpType.Ldelem_u1: case OpType.Ldelem_u2: case OpType.Ldelem_u4: rhs = eval.Pop(); eval.Push(exp.ArrayGet(eval.Pop(), rhs)); break; case OpType.Stelem: case OpType.Stelem_i: case OpType.Stelem_i1: case OpType.Stelem_i2: case OpType.Stelem_i4: case OpType.Stelem_i8: case OpType.Stelem_r4: case OpType.Stelem_r8: case OpType.Stelem_ref: rhs = eval.Pop(); var idx = eval.Pop(); eval.Push(exp.ArraySet(eval.Pop(), idx, rhs)); break; case OpType.Ldind_ref: case OpType.Ldind_i: case OpType.Ldind_i1: case OpType.Ldind_i2: case OpType.Ldind_i4: case OpType.Ldind_i8: case OpType.Ldind_r4: case OpType.Ldind_r8: case OpType.Ldind_u1: case OpType.Ldind_u2: case OpType.Ldind_u4: eval.Push(exp.AddressGet(eval.Pop())); break; case OpType.Stind_ref: case OpType.Stind_i: case OpType.Stind_i1: case OpType.Stind_i2: case OpType.Stind_i4: case OpType.Stind_i8: case OpType.Stind_r4: case OpType.Stind_r8: rhs = eval.Pop(); eval.Push(exp.AddressSet(eval.Pop(), rhs)); break; case OpType.Arglist: eval.Push(exp.ArgumentList()); break; //-------------- Comparison instructions -------------- case OpType.Isinst: eval.Push(exp.TypeAs(eval.Pop(), x.ResolveType())); break; case OpType.Ceq: // a bool is a native int in CIL, and != is a comparison against 0 rhs = eval.Pop(); var lhs = eval.Pop(); var tyleft = exp.TypeOf(lhs); var tyright = exp.TypeOf(rhs); if (tyleft != typeof(bool) || tyleft == tyright) { eval.Push(exp.Equal(lhs, rhs)); } else if (tyleft != typeof(bool) && tyright == typeof(bool)) { eval.Push(exp.Equal(exp.Cast(lhs, tyright), rhs)); } else if (tyright != typeof(bool) && tyleft == typeof(bool)) { eval.Push(exp.Equal(lhs, exp.Cast(rhs, tyleft))); } else { throw new InvalidOperationException("Unknown bool comparison!"); } break; case OpType.Cgt: case OpType.Cgt_un: rhs = eval.Pop(); eval.Push(exp.GreaterThan(eval.Pop(), rhs)); break; case OpType.Clt: case OpType.Clt_un: rhs = eval.Pop(); eval.Push(exp.LessThan(eval.Pop(), rhs)); break; case OpType.Ckfinite: var isInfinity = exp.TypeOf(eval.Peek()) == typeof(float) ? r4IsInfinity : r8IsInfinity; var ethrow = exp.Throw(exp.New(arithError, new[] { exp.Constant("Value is not a finite number.") })); var evalue = eval.Pop(); eval.Push(exp.If(exp.Call(isInfinity, false, default(T), new[] { evalue }), ethrow, evalue)); break; case OpType.Constrained_: break; //------------ Conversion instructions ------------- case OpType.Castclass: eval.Push(exp.Cast(eval.Pop(), x.ResolveType())); break; case OpType.Conv_i: eval.Push(exp.Cast(eval.Pop(), nativeInt)); break; case OpType.Conv_i1: eval.Push(exp.Cast(eval.Pop(), typeof(sbyte))); break; case OpType.Conv_i2: eval.Push(exp.Cast(eval.Pop(), typeof(short))); break; case OpType.Conv_i4: eval.Push(exp.Cast(eval.Pop(), typeof(int))); break; case OpType.Conv_i8: eval.Push(exp.Cast(eval.Pop(), typeof(long))); break; case OpType.Conv_ovf_i: case OpType.Conv_ovf_i_un: eval.Push(exp.CastOverflow(eval.Pop(), nativeInt)); break; case OpType.Conv_ovf_i1: case OpType.Conv_ovf_i1_un: eval.Push(exp.CastOverflow(eval.Pop(), typeof(sbyte))); break; case OpType.Conv_ovf_i2: case OpType.Conv_ovf_i2_un: eval.Push(exp.CastOverflow(eval.Pop(), typeof(short))); break; case OpType.Conv_ovf_i4: case OpType.Conv_ovf_i4_un: eval.Push(exp.CastOverflow(eval.Pop(), typeof(int))); break; case OpType.Conv_ovf_i8: case OpType.Conv_ovf_i8_un: eval.Push(exp.CastOverflow(eval.Pop(), typeof(long))); break; case OpType.Conv_r4: case OpType.Conv_r_un: eval.Push(exp.Cast(eval.Pop(), typeof(float))); break; case OpType.Conv_r8: eval.Push(exp.Cast(eval.Pop(), typeof(double))); break; case OpType.Conv_u: eval.Push(exp.Cast(eval.Pop(), typeof(UIntPtr))); break; case OpType.Conv_u1: eval.Push(exp.Cast(eval.Pop(), typeof(byte))); break; case OpType.Conv_u2: eval.Push(exp.Cast(eval.Pop(), typeof(ushort))); break; case OpType.Conv_u4: eval.Push(exp.Cast(eval.Pop(), typeof(uint))); break; case OpType.Conv_u8: eval.Push(exp.Cast(eval.Pop(), typeof(ulong))); break; case OpType.Dup: eval.Push(exp.Duplicate(eval.Pop())); break; case OpType.Newarr: var atype = x.ResolveType(); eval.Push(exp.Array(atype, new[] { eval.Pop() })); break; case OpType.Newobj: var ctor = (ConstructorInfo)x.ResolveMethod(); var cparams = ctor.GetParameters(); var cargs = cparams.Select(a => eval.Pop()).Reverse(); eval.Push(exp.New(ctor, cargs)); break; case OpType.Rethrow: eval.Push(exp.Rethrow()); break; case OpType.Tail_: tailcall = true; break; case OpType.Unaligned_: eval.Push(exp.Unaligned(eval.Pop())); break; case OpType.Unbox: case OpType.Unbox_any: eval.Push(exp.Unbox(eval.Pop(), x.ResolveType())); break; //case OpType.Break: // break; //case OpType.Volatile_: // break; //case OpType.Refanytype: //case OpType.Refanyval: //case OpType.Mkrefany: //case OpType.Localloc: //case OpType.Readonly_: default: throw new NotSupportedException("Instruction not supported: " + x); } } }