public LambdaExpression CreateLambda(Type from, Type to) { var fromParameters = from.GetTypeInfo().GenericTypeArguments; var toParameters = to.GetTypeInfo().GenericTypeArguments; var converters = fromParameters .Zip(toParameters, (f, t) => Ref.GetLambda(f, t)) .ToArray(); var input = Ex.Parameter(from, "input"); var res = toParameters.Select(t => Ex.Parameter(typeof(ConversionResult <>).MakeGenericType(t))).ToArray(); var conversion = res.Select((r, i) => Ex.Assign(res[i], converters[i].ApplyTo(Ex.PropertyOrField(input, $"Item{i + 1}")))).ToArray(); var conversionSuccesful = Enumerable.Aggregate(res, (Ex)Ex.Constant(true), (c, p) => Ex.MakeBinary(Et.AndAlso, c, Ex.Property(p, nameof(IConversionResult.IsSuccessful)))); var block = Ex.Block(res, Ex.Block(conversion), Ex.Condition(conversionSuccesful, Result(to, Ex.Call(Creator(to), Enumerable.Select(res, p => Ex.Property(p, nameof(IConversionResult.Result))))), NoResult(to))); var lambda = Ex.Lambda(block, input); return(lambda); }
public static BlockExpression RotateLerp(Ex target, Ex source, TExArgCtx bpi, bool isRate, bool isTrue, Ex rate) { if (isRate) { rate = rate.Mul(M.degRad); } if (isTrue) { rate = rate.Mul(ETime.FRAME_TIME); } TExV2 v = TExV2.Variable(); TEx <float> ang = ExUtils.VFloat(); Expression[] exprs = new Expression[3]; exprs[1] = ang.Is(RadDiff(target, v)); if (isTrue) { var key = bpi.Ctx.NameWithSuffix("_RotateLerpKey"); exprs[0] = v.Is( Ex.Condition(FiringCtx.Contains <Vector2>(bpi, key), FiringCtx.GetValue <Vector2>(bpi, key), FiringCtx.SetValue <Vector2>(bpi, key, source) )); exprs[2] = FiringCtx.SetValue <Vector2>(bpi, key, RotateRad(isRate ? (Ex)Limit(rate, ang) : ang.Mul(rate), v)); } else { exprs[0] = v.Is(source); exprs[2] = RotateRad(isRate ? (Ex)Limit(bpi.t.Mul(rate), ang) : ang.Mul(Min(bpi.t.Mul(rate), E1)), v); } return(Ex.Block(new ParameterExpression[] { v, ang }, exprs)); }
public void TestAssign() { var x = VF("x"); var yi = VF("y"); var zi = VF("z"); var ex = x.Is(Ex.Block(new[] { yi }, yi.Is(ExC(5f)), yi.Add(x) )); DebugsTo(ex, "(x=((y=5);\n(y+x);))"); LinDebugsTo(ex, "((y=5);\n(x=(y+x));)"); AreEqual(11f, Compile1(ex.Linearize(), x)(6)); var ex2 = Ex.Block( x.Is(Ex.Block(new[] { yi }, yi.Is(ExC(5f)), yi.Add(x) ).Add(Ex.Block(new[] { zi }, zi.Is(x), zi.Mul(2f) ))), x.Add(2f) ); DebugsTo(ex2, "((x=(((y=5);\n(y+x);)+((z=x);\n(z*2);)));\n(x+2);)"); LinDebugsTo(ex2, @"((y=5); (z=x); (x=((y+x)+(z*2))); (x+2);)"); }
internal MetaObject /*!*/ CreateMetaObject(MetaObjectBinder /*!*/ action, MetaObject /*!*/[] /*!*/ siteArgs) { var expr = _error ? Ast.Throw(_result) : _result; Restrictions restrictions; if (_condition != null) { var deferral = action.Defer(siteArgs); expr = Ast.Condition(_condition, AstUtils.Convert(expr, typeof(object)), deferral.Expression); restrictions = deferral.Restrictions; } else { restrictions = Restrictions.Empty; } if (_temps != null) { expr = Ast.Block(_temps, expr); } if (_restriction != null) { restrictions = restrictions.Merge(Restrictions.GetExpressionRestriction(_restriction)); } return(new MetaObject(expr, restrictions)); }
// Generate expression to swap a and b, using t as a temporary. private static LinqExpr Swap(LinqExpr a, LinqExpr b, LinqExpr t) { return(LinqExpr.Block( LinqExpr.Assign(t, a), LinqExpr.Assign(a, b), LinqExpr.Assign(b, t))); }
public void Factorial() { var value = LinqExpression.Parameter(typeof(int), "value"); var result = LinqExpression.Parameter(typeof(int), "result"); var label = LinqExpression.Label(typeof(int), "label"); var one = LinqExpression.Constant(1); var expression = LinqExpression.Block( new[] { result }, LinqExpression.Assign( result, one), LinqExpression.Loop( LinqExpression.Condition( LinqExpression.GreaterThan( value, one), LinqExpression.MultiplyAssign( result, LinqExpression.PostDecrementAssign( value)), LinqExpression.Break( label, result), typeof(void)), label)); ShouldRoundrip(expression); }
/// <summary> /// Generates the method's body /// </summary> /// <returns></returns> protected Expr GenerateDeserializationMethodBody() { // Generate a tree of BodyExpression. // We just populate the type token, the member info, and the access expressions var bodyParts = MakeRootNode(); foreach (var member in Root.Members) { if (member.MemberType != MemberType || member.IsReadOnly) continue; var node = new TreeNode() { AccessExpression = MakeRootMemberAccess(member), TypeToken = member.TypeToken, MemberToken = member, }; GenerateTreeNode(node); bodyParts.Children.Add(node); } // Emit candidate read calls. bodyParts.GenerateReadCalls(this); var expr = bodyParts.TryUnroll().ToExpression(); var returnType = MakeReturnExpression(); if (returnType != null) expr = Expr.Block(expr, returnType); // TODO: See if trying to optimize iterator usages in the generated code outweighs the cost of optimizing // (It probably doesn't) (except for large files question mark?) return expr; }
public static Func <TExArgCtx, TEx <float> > PivotShift <S>(Func <EEx <float>, TEx <float>[], TEx <float> > shifter, Func <TExArgCtx, TEx <float> > sharpness, Func <TExArgCtx, TEx <float> > pivot, Func <TExArgCtx, TEx <float> > f1, Func <TExArgCtx, TEx <float> > f2, string pivotVar) where S : TEx, new() { if (pivotVar == "t" || pivotVar == "p" || pivotVar == "x") { return(t => { var pivotT = t.MakeCopyForType <S>(out var currEx, out var pivotEx); return Ex.Block(new ParameterExpression[] { pivotEx }, Ex.Assign(pivotEx, currEx), Ex.Assign(pivotVar.Into <Func <TExArgCtx, TEx <float> > >()(pivotT), pivot(t)), shifter(sharpness(t), new TEx <float>[] { f1(t), f1(pivotT).Add(f2(t).Sub(f2(pivotT))) }) ); }); } else if (pivotVar[0] == Parser.SM_REF_KEY_C) { var let = pivotVar.Substring(1); return(t => shifter(sharpness(t), new TEx <float>[] { f1(t), f2(t).Add( ReflectEx.Let <float, float>(let, pivot, () => f1(t).Sub(f2(t)), t) ) })); } else { throw new Exception($"{pivotVar} is not a valid pivoting target."); } }
public LambdaExpression CreateLambda(Type from, Type to) { var toParameters = to.GetTypeInfo().GenericTypeArguments; var tupa = toParameters.Length; var input = Ex.Parameter(from, "input"); var converters = toParameters.Select(p => Ref.GetLambda(typeof(string), p)).ToArray(); var res = toParameters.Select(p => Ex.Parameter(typeof(ConversionResult <>).MakeGenericType(p))).ToArray(); var end = Ex.Label(typeof(ConversionResult <>).MakeGenericType(to), "end"); var indexer = typeof(string[]).GetTypeInfo().GetDeclaredProperty("Item"); var split = Ex.Parameter(typeof(string[]), "split"); var conversion = Ex.Block(converters.Select((c, i) => Ex.Block( Ex.Assign(res[i], c.ApplyTo(Ex.MakeIndex(split, indexer, new[] { Ex.MakeBinary(Et.Add, Ex.Constant(i), Ex.MakeBinary(Et.Subtract, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa))) }))), Ex.IfThen(Ex.Not(Ex.Property(res[i], nameof(IConversionResult.IsSuccessful))), Ex.Goto(end, NoResult(to)))))); var block = Ex.Block(new[] { split }, Ex.Assign(split, Ex.Call(input, nameof(string.Split), Type.EmptyTypes, _separator)), Ex.Condition(Ex.MakeBinary(Et.LessThan, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa)), NoResult(to), Ex.Block(res, Ex.IfThen(Ex.MakeBinary(Et.GreaterThan, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa)), Ex.Assign(Ex.ArrayAccess(split, Ex.MakeBinary(Et.Subtract, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa))), Ex.Call(typeof(string), nameof(string.Join), Type.EmptyTypes, _separatorString, Ex.Call(typeof(Enumerable), nameof(Enumerable.Take), new[] { typeof(string) }, split, Ex.MakeBinary(Et.Add, Ex.Constant(1), Ex.MakeBinary(Et.Subtract, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa))))))), conversion, Ex.Label(end, Result(to, Ex.Call(Creator(to), res.Select(r => Ex.Property(r, nameof(IConversionResult.Result))))))))); var lambda = Ex.Lambda(block, input); return(lambda); }
/// <summary> /// Takes current result and wraps it into try-filter(MethodUnwinder)-finally block that ensures correct "break" behavior for /// Ruby method calls with a block given in arguments. /// /// Sets up a RFC frame similarly to MethodDeclaration. /// </summary> internal static void ApplyBlockFlowHandlingInternal(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { // TODO (improvement): // We don't special case null block here, although we could (we would need a test for that then). // We could also statically know (via call-site flag) that the current method is not a proc-converter (passed by ref), // which would make such calls faster. if (metaBuilder.Error || !args.Signature.HasBlock) { return; } Expression rfcVariable = metaBuilder.GetTemporary(typeof(RuntimeFlowControl), "#rfc"); ParameterExpression methodUnwinder = metaBuilder.GetTemporary(typeof(MethodUnwinder), "#unwinder"); Expression resultVariable = metaBuilder.GetTemporary(typeof(object), "#result"); metaBuilder.Result = Ast.Block( // initialize frame (RFC): Ast.Assign(rfcVariable, Methods.CreateRfcForMethod.OpCall(AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)))), AstUtils.Try( Ast.Assign(resultVariable, metaBuilder.Result) ).Filter(methodUnwinder, Ast.Equal(Ast.Field(methodUnwinder, MethodUnwinder.TargetFrameField), rfcVariable), // return unwinder.ReturnValue; Ast.Assign(resultVariable, Ast.Field(methodUnwinder, MethodUnwinder.ReturnValueField)) ).Finally( // we need to mark the RFC dead snce the block might escape and break later: Ast.Assign(Ast.Field(rfcVariable, RuntimeFlowControl.IsActiveMethodField), Ast.Constant(false)) ), resultVariable ); }
private Exp CheckIfZero(CompilerState state, Exp expression) { if (state == null) { throw new Exception(); } if (expression == null) { throw new Exception(); } if (expression.Type == typeof(int)) { var constructor = typeof(Exception).GetConstructor(new Type[] { typeof(string) }); return(Exp.Block( Exp.IfThen(Exp.Equal(expression, Exp.Constant(0)), Exp.Throw(Exp.New(constructor, Exp.Constant("Division by zero")))), expression)); } if (expression.Type == typeof(float)) { var constructor = typeof(Exception).GetConstructor(new Type[] { typeof(string) }); return(Exp.Block( Exp.IfThen(Exp.Equal(expression, Exp.Constant(0.0f)), Exp.Throw(Exp.New(constructor, Exp.Constant("Division by zero")))), expression)); } return(expression); }
/// <summary> /// For each expression provided, linearize it if necessary, and then linearize the process of combining /// the expressions by assigning all block results to temporary variables and then using those temporary /// variables instead of the blocks. /// </summary> private Expression Linearize(Func <Expression[], Expression> combiner, params Expression[] pieces) { var linearized = pieces.Select(Visit).ToArray(); //Best case! if (!linearized.Any(ex => ex is BlockExpression)) { return(combiner(linearized)); } var prms = new List <ParameterExpression>(); var stmts = new List <Expression>(); var reduced_args = new Expression[linearized.Length]; linearized.ForEachI((i, ex) => { if (ex is BlockExpression bex) { prms.AddRange(bex.Variables); stmts.AddRange(bex.Expressions.Take(bex.Expressions.Count - 1)); reduced_args[i] = bex.Expressions[bex.Expressions.Count - 1]; } else { reduced_args[i] = ex; } }); stmts.Add(combiner(reduced_args)); return(Ex.Block(prms, stmts)); }
private LambdaExpression toDictLambda(Type from, Type to) { var valueType = recordCreator.GetValueType(to); var recType = typeof(IRecord <>).MakeGenericType(valueType); var set = recType.GetTypeInfo().GetDeclaredMethod(nameof(IRecord <object> .SetValue)); var input = Ex.Parameter(from, "input"); var tmp = Ex.Parameter(typeof(ConversionResult <>).MakeGenericType(valueType), "tmp"); var res = Ex.Parameter(typeof(IDictionary <,>).MakeGenericType(typeof(string), valueType), "res"); var rec = Ex.Parameter(recType, "rec"); var getters = GetReadablePropertiesForType(from); var converters = getters.Select(g => Ref.GetLambda(g.PropertyType, valueType)); var end = Ex.Label(typeof(ConversionResult <>).MakeGenericType(to)); var block = Ex.Block(new[] { tmp, res, rec }, Ex.Assign(res, Ex.New(GetParameterlessConstructor(to))), Ex.Assign(rec, recordCreator.Creator(to).ApplyTo(res)), Ex.IfThen(Ex.MakeBinary(ExpressionType.Equal, rec, Ex.Default(rec.Type)), Ex.Goto(end, NoResult(to))), Ex.Block(getters.Zip(converters, (g, c) => new { g, c }) .Select(x => Ex.Block( Ex.Assign(tmp, x.c.ApplyTo(Ex.Property(input, x.g))), Ex.IfThenElse(Ex.Property(tmp, nameof(IConversionResult.IsSuccessful)), Ex.Call(rec, set, Ex.Constant(x.g.Name), Ex.Property(tmp, nameof(IConversionResult.Result))), Ex.Goto(end, NoResult(to)))))), Ex.Label(end, Result(to, Ex.Convert(res, to)))); return(Ex.Lambda(block, input)); }
/// <summary> /// Invariant: bex is linearized. /// </summary> private BlockExpression AssignBlockResultToTemp(BlockExpression bex, ParameterExpression pex) { var exprs = bex.Expressions.ToArray(); exprs[exprs.Length - 1] = Ex.Assign(pex, exprs[exprs.Length - 1]); return(Ex.Block(bex.Variables, exprs)); }
protected override Expression VisitBlock(BlockExpression node) { if (node.Expressions.Count == 1 && node.Variables.Count == 0) { return(Visit(node.Expressions[0])); } var prms = new List <ParameterExpression>(); var stmts = new List <Expression>(); prms.AddRange(node.Variables); foreach (var ex in node.Expressions) { var linearized = Visit(ex); if (linearized is BlockExpression bex) { prms.AddRange(bex.Variables); stmts.AddRange(bex.Expressions); } else { stmts.Add(linearized); } } return(Ex.Block(prms, stmts)); }
public Expr ToExpression() { var exitLabel = Expr.Label(); var loopBody = Expr.Block(Body.ToExpression(), Expr.PreIncrementAssign(Iterator.ToExpression())); return(Expr.Loop(Expr.IfThenElse(Expr.LessThan(Iterator.ToExpression(), UpperBound.ToExpression()), loopBody, Expr.Break(exitLabel)), exitLabel)); }
/// <summary> /// Wrap a position equation around a cylinder. /// </summary> /// <param name="radius">Radius of the cylinder</param> /// <param name="ang0">Starting angle offset (radians) on the cylinder. 0 = z-axis</param> /// <param name="maxWrap">Maximum angle value (radians) of the wrap. After this, the function will continue along the tangent. Starting offset not included. Absolute value tested.</param> /// <param name="axisOff">Offset angle (radians) of the axis of the cylinder from the y-axis</param> /// <param name="position">Position equation</param> /// <returns></returns> public static tv3 CylinderWrap(efloat radius, efloat ang0, efloat maxWrap, efloat axisOff, ev2 position) => EEx.Resolve(radius, ang0, axisOff, position, (r, a0, axis, _v2) => { var cs = new TExV2(); var xyd = new TExV2(); var v2 = new TExV2(_v2); var v3 = new TExV3(); var a = ExUtils.VFloat(); var aRem = ExUtils.VFloat(); var aMax = ExUtils.VFloat(); var a_cs = new TExV2(); var a0_cs = new TExV2(); return(Ex.Block(new[] { v3, cs, xyd, a, aRem, aMax, a_cs, a0_cs }, aMax.Is(maxWrap), cs.Is(CosSin(axis)), xyd.Is(ConvertBasis(v2, cs)), a.Is(xyd.x.Div(r)), aRem.Is(E0), Ex.IfThen(Abs(a).GT(aMax), Ex.Block( Ex.IfThen(a.LT0(), MulAssign(aMax, EN1)), aRem.Is(a.Sub(aMax)), a.Is(aMax) )), a0_cs.Is(CosSin(a0)), a_cs.Is(CosSin(a.Add(a0))), xyd.x.Is(r.Mul(a_cs.y.Sub(a0_cs.y).Add(aRem.Mul(a_cs.x)))), v3.Is(TP3(DeconvertBasis(xyd, cs))), v3.z.Is(r.Mul(a_cs.x.Sub(a0_cs.x).Sub(aRem.Mul(a_cs.y)))), v3 )); });
private static Func <int[], int[]> GenerateCopyExpression() { var ctor = typeof(int[]).GetConstructor(new[] { typeof(int) }); var get = typeof(int[]).GetMethod("Get", new[] { typeof(int) }); var set = typeof(int[]).GetMethod("Set", new[] { typeof(int), typeof(int) }); var p1 = Exp.Parameter(typeof(int[])); var v1 = Exp.Variable(typeof(int[])); var v2 = Exp.Variable(typeof(int)); var @break = Exp.Label(); var block = Exp.Block( new[] { v1, v2 }, Exp.Assign(v1, Exp.New(ctor, Exp.Property(p1, "Length"))), Exp.Assign(v2, Exp.Constant(0)), Exp.Loop( Exp.IfThenElse( Exp.LessThan(v2, Exp.Property(p1, "Length")), Exp.Block( Exp.Call(v1, set, v2, Exp.Call(p1, get, v2)), Exp.AddAssign(v2, Exp.Constant(1)) ), Exp.Break(@break) ), @break), v1 ); return(Exp.Lambda <Func <int[], int[]> >(block, new ParameterExpression[] { p1 }).Compile()); }
private LambdaExpression fromEnumerableLambda(Type from) { var input = Ex.Parameter(from, "input"); var eType = from.GetTypeInfo().ImplementedInterfaces .Where(i => i.GenericTypeArguments.Length == 1 && i.GetGenericTypeDefinition() == typeof(IEnumerable <>)) .Select(i => i.GenericTypeArguments[0]).SingleOrDefault() ?? from.GetTypeInfo().GenericTypeArguments[0]; var res = Ex.Parameter(typeof(string), "res"); var result = Ex.Block(new[] { res }, Ex.Assign(res, Ex.Call((from mi in typeof(string).GetTypeInfo().GetDeclaredMethods(nameof(string.Join)) where mi.GetGenericArguments().Length == 1 let par = mi.GetParameters() where par.Length == 2 && par[0].ParameterType == typeof(string) && par[1].ParameterType == typeof(IEnumerable <>).MakeGenericType(mi.GetGenericArguments()[0]) select mi).Single().MakeGenericMethod(eType), Ex.Constant(Separators[0].ToString()), input)), Ex.Condition(Ex.MakeBinary(Et.Equal, Ex.Property(res, nameof(string.Length)), Ex.Constant(0)), NoResult(typeof(string)), Result(typeof(string), res))); var block = Ex.Condition(Ex.MakeBinary(Et.Equal, input, Ex.Default(from)), NoResult(typeof(string)), result); var lambda = Ex.Lambda(block, input); return(lambda); }
public void TestAssign() { var x = VF("x"); var y = VF("y"); AreEqual("((y=((2*x)+2));\n(y+(x*2));)", DerivDebug(x, Ex.Block(new[] { y }, Ex.Assign(y, E2.Mul(x).Add(E2)), x.Mul(y)))); }
// Pseudocode: //string input => //{ // R result = 0; // for (int i = input.Length - 1; i >= 0; i--) // { // result <<= 6; // var m = _invMap[input[i]]; // if (m == 0xff) // return default(ConversionResult<R>); // result += m; // } // return new ConversionResult<R>(result); //} private LambdaExpression fromLambda(Type to) { var stringthis = typeof(string).GetTypeInfo().DeclaredProperties.First(p => p.GetIndexParameters().Length == 1 && p.GetIndexParameters()[0].ParameterType == typeof(int)); var input = Ex.Parameter(typeof(string), "input"); var result = Ex.Parameter(to, "result"); var i = Ex.Parameter(typeof(int), "i"); var m = Ex.Parameter(typeof(byte), "m"); var loopstart = Ex.Label("loopstart"); var end = Ex.Label(typeof(ConversionResult <>).MakeGenericType(to), "end"); var loop = Ex.Block( Ex.Label(loopstart), Ex.IfThen(Ex.MakeBinary(ExpressionType.LessThan, i, Ex.Constant(0)), Ex.Goto(end, Result(to, result))), Ex.LeftShiftAssign(result, Ex.Constant(6)), Ex.Assign(m, Ex.ArrayIndex(Ex.Constant(_invMap), Ex.Convert(Ex.MakeIndex(input, stringthis, new[] { i }), typeof(int)))), Ex.IfThen(Ex.MakeBinary(ExpressionType.Equal, m, Ex.Constant((byte)0xff)), Ex.Goto(end, NoResult(to))), Ex.AddAssign(result, Ex.Convert(m, result.Type)), Ex.PostDecrementAssign(i), Ex.Goto(loopstart)); var block = Ex.Block(new[] { result, i, m }, Ex.Assign(result, Ex.Convert(Ex.Constant(0), to)), Ex.Assign(i, Ex.MakeBinary(ExpressionType.Subtract, Ex.Property(input, nameof(string.Length)), Ex.Constant(1))), loop, Ex.Label(end, NoResult(to))); return(Ex.Lambda(block, input)); }
public EvaluationCallback Create(Node node) { var compilerstate = new CompilerState { FunctionState = Exp.Parameter(typeof(Character), "state"), ErrorVariable = Exp.Parameter(typeof(bool), "error") }; var result = Make(compilerstate, node); if (result.Type == typeof(bool)) { result = ToInteger(result); } if (result.Type == typeof(int) || result.Type == typeof(float)) { // int or float convert to number var constructor = typeof(Number).GetConstructor(new[] { result.Type }); result = Exp.New(constructor, new[] { result }); // wrap the evaluation in a try..catch var exceptionParameter = Exp.Parameter(typeof(Exception), "e"); var writeLineMethod = typeof(Console).GetMethod(nameof(Console.WriteLine), new Type[] { typeof(string) }); var toStringMethod = typeof(Exception).GetMethod(nameof(Exception.ToString)); var catchBody = Exp.Block( Exp.Call(null, writeLineMethod, Exp.Call(exceptionParameter, toStringMethod)), Exp.Constant(new Number(0))); result = Exp.TryCatch(result, Exp.Catch(exceptionParameter, catchBody)); // create lambda var func = Exp.Lambda <Func <Character, bool, Number> >(result, compilerstate.FunctionState, compilerstate.ErrorVariable).Compile(); return(new EvaluationCallback(o => func(o, false))); } throw new Exception(); }
public static BlockExpression LaserRotateLerp(Ex target, Ex source, TExArgCtx bpi, Ex rate) { var r1 = rate.Mul(ExC(ETime.FRAME_TIME)); TExV2 v = TExV2.Variable(); TEx <float> ang = ExUtils.VFloat(); var dirKey = bpi.Ctx.NameWithSuffix("_LaserRotateLerpDirKey"); var sideKey = bpi.Ctx.NameWithSuffix("_LaserRotateLerpSideKey"); var inter_ang = HighPass(ExC(0.01f), RadDiff(target, v)); return(Ex.Block(new ParameterExpression[] { v, ang }, Ex.Condition( bpi.FCtxHas <Vector2>(dirKey).And(bpi.t.GT0()), Ex.Block( v.Is(bpi.FCtxGet <Vector2>(dirKey)), ang.Is(Ex.Condition(bpi.FCtxGet <float>(sideKey).LT0(), RadToNeg(inter_ang), RadToPos(inter_ang) )), bpi.FCtxSet <Vector2>(dirKey, RotateRad(Limit(r1, ang), v)) ), Ex.Block( v.Is(source), ang.Is(RadDiff(target, v)), bpi.FCtxSet <float>(sideKey, Sign(ang)), bpi.FCtxSet <Vector2>(dirKey, RotateRad(Limit(r1, ang), v)) ) ) )); }
/// <summary> /// Lerp between two functions. The controller is not clamped. /// </summary> /// <param name="zeroBound">Lower bound for lerp controller</param> /// <param name="oneBound">Upper bound for lerp controller</param> /// <param name="controller">Lerp controller</param> /// <param name="f1">First function</param> /// <param name="f2">Second function</param> /// <returns></returns> public static TEx <T> LerpU <T>(efloat zeroBound, efloat oneBound, efloat controller, TEx <T> f1, TEx <T> f2) => EEx.Resolve(zeroBound, oneBound, controller, (z, o, c) => { var rc = VFloat(); return(Ex.Block(new[] { rc }, rc.Is(c.Sub(z).Div(o.Sub(z))), rc.Mul(f2).Add(rc.Complement().Mul(f1)) )); });
public void ZeroOneRemoval() { var x = VF("x"); var ex = Ex.Block(Ex.Add(x, E1), Ex.Add(x, E0), E1.Mul(x), x.Mul(E0), x.Sub(E0), E0.Sub(x)); AreEqual("((x+1);\n(x+0);\n(1*x);\n(x*0);\n(x-0);\n(0-x);)", ex.Debug()); AreEqual("((x+1);\nx;\nx;\n0;\nx;\n(0-x);)", ex.FlatDebug()); }
public void Block_Expressions() { var expression = LinqExpression.Block( LinqExpression.Default(typeof(string))); ShouldRoundrip(expression); }
public void MiscellaneousExpression_Block() { var variable = Expr.Variable(typeof(bool)); var block = Expr.Block(Expr.Assign(variable, Expr.Constant(true)), variable); UnsupportedExpr(Property.Active, active => Expr.Equal(active, block), ExpressionType.Block); }
/// <summary> /// Home towards a target location at a fixed speed. /// </summary> /// <remarks> /// Use with StopSampling to home for only a few seconds. /// <para>This is primarily for use with non-rotational velocity. /// Rotational use creates: contracting spirals (0,90), circle around player [90], expanding spiral (90,180).</para> /// </remarks> /// <param name="speed">Speed</param> /// <param name="location">Target location</param> /// <returns></returns> public static ExTP VHome(ExBPY speed, ExTP location) { TExV2 l = new TExV2(); return(bpi => Ex.Block(new ParameterExpression[] { l }, Ex.Assign(l, location(bpi).Sub(bpi.loc)), l.Mul(Ex.Divide(speed(bpi), Sqrt(Ex.Add(SqrMag(l), EPS)))) )); }
/// <summary> /// Lerp between two functions with smoothing applied to the controller. /// </summary> public static TEx <T> LerpSmooth <T>([LookupMethod] Func <tfloat, tfloat> smoother, efloat zeroBound, efloat oneBound, efloat controller, TEx <T> f1, TEx <T> f2) => EEx.Resolve(zeroBound, oneBound, controller, (z, o, c) => { var rc = VFloat(); return(Ex.Block(new[] { rc }, rc.Is(smoother(Clamp(z, o, c).Sub(z).Div(o.Sub(z)))), rc.Mul(f2).Add(rc.Complement().Mul(f1)) )); });
/// <summary> /// Derive a Vector2 from a Vector3 by dropping the Z-component. /// </summary> public static ExTP TP(ExTP3 xyz) { var v3 = TExV3.Variable(); return(bpi => Ex.Block(new ParameterExpression[] { v3 }, Ex.Assign(v3, xyz(bpi)), ExUtils.V2(v3.x, v3.y) )); }