protected void ProcessDefinition(IExpression expr, IVariableDeclaration targetVar, bool isLhs) { bool targetIsPointMass = false; IMethodInvokeExpression imie = expr as IMethodInvokeExpression; if (imie != null) { // TODO: consider using a method attribute for this if (Recognizer.IsStaticGenericMethod(imie, new Models.FuncOut <PlaceHolder, PlaceHolder, PlaceHolder>(Clone.VariablePoint)) ) { targetIsPointMass = true; } else { FactorManager.FactorInfo info = CodeRecognizer.GetFactorInfo(context, imie); targetIsPointMass = info.IsDeterministicFactor && ( (info.ReturnedInAllElementsParameterIndex != -1 && ArgumentIsPointMass(imie.Arguments[info.ReturnedInAllElementsParameterIndex])) || imie.Arguments.All(ArgumentIsPointMass) ); } if (targetIsPointMass) { // do this immediately so all uses are updated if (!context.InputAttributes.Has <ForwardPointMass>(targetVar)) { context.OutputAttributes.Set(targetVar, new ForwardPointMass()); } // the rest is done later List <IMethodInvokeExpression> list; if (!variablesDefinedPointMass.TryGetValue(targetVar, out list)) { list = new List <IMethodInvokeExpression>(); variablesDefinedPointMass.Add(targetVar, list); } // this code needs to be synchronized with MessageTransform.ConvertMethodInvoke if (Recognizer.IsStaticGenericMethod(imie, new Func <PlaceHolder, int, PlaceHolder[]>(Clone.Replicate)) || Recognizer.IsStaticGenericMethod(imie, new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <int>, PlaceHolder[]>(Collection.GetItems)) || Recognizer.IsStaticGenericMethod(imie, new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <IReadOnlyList <int> >, PlaceHolder[][]>(Collection.GetJaggedItems)) || Recognizer.IsStaticGenericMethod(imie, new Func <IReadOnlyList <PlaceHolder>, IReadOnlyList <IReadOnlyList <IReadOnlyList <int> > >, PlaceHolder[][][]>(Collection.GetDeepJaggedItems)) || Recognizer.IsStaticGenericMethod(imie, new Func <IReadOnlyList <IReadOnlyList <PlaceHolder> >, IReadOnlyList <int>, IReadOnlyList <int>, PlaceHolder[]>(Collection.GetItemsFromJagged)) || Recognizer.IsStaticGenericMethod(imie, new Func <IReadOnlyList <IReadOnlyList <IReadOnlyList <PlaceHolder> > >, IReadOnlyList <int>, IReadOnlyList <int>, IReadOnlyList <int>, PlaceHolder[]>(Collection.GetItemsFromDeepJagged)) || Recognizer.IsStaticGenericMethod(imie, new Func <IReadOnlyList <IReadOnlyList <PlaceHolder> >, IReadOnlyList <IReadOnlyList <int> >, IReadOnlyList <IReadOnlyList <int> >, PlaceHolder[][]>(Collection.GetJaggedItemsFromJagged)) ) { list.Add(imie); } } } if (!targetIsPointMass && !(expr is IArrayCreateExpression)) { variablesDefinedNonPointMass.Add(targetVar); if (variablesDefinedPointMass.ContainsKey(targetVar)) { variablesDefinedPointMass.Remove(targetVar); context.OutputAttributes.Remove <ForwardPointMass>(targetVar); } } }
/// <summary> /// Convert random assignments to derived variables /// </summary> /// <param name="iae"></param> /// <returns></returns> protected override IExpression ConvertAssign(IAssignExpression iae) { iae = (IAssignExpression)base.ConvertAssign(iae); IStatement ist = context.FindAncestor <IStatement>(); if (!context.InputAttributes.Has <Models.Constraint>(ist) && (iae.Expression is IMethodInvokeExpression)) { IMethodInvokeExpression imie = (IMethodInvokeExpression)iae.Expression; IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(iae.Target); if (ivd != null) { bool isDerived = context.InputAttributes.Has <DerivedVariable>(ivd); if (isDerived) { FactorManager.FactorInfo info = CodeRecognizer.GetFactorInfo(context, imie); if (!info.IsDeterministicFactor) { // The variable is derived, but this definition is not derived. // Thus we must convert // y = sample() // into // y_random = sample() // y = Copy(y_random) // where y_random is not derived. VariableInformation varInfo = VariableInformation.GetVariableInformation(context, ivd); IList <IStatement> stmts = Builder.StmtCollection(); string name = ivd.Name + "_random" + (Count++); List <IList <IExpression> > indices = Recognizer.GetIndices(iae.Target); IVariableDeclaration cloneVar = varInfo.DeriveIndexedVariable(stmts, context, name, indices, copyInitializer: true); context.OutputAttributes.Remove <DerivedVariable>(cloneVar); stmts.Add(Builder.AssignStmt(Builder.VarRefExpr(cloneVar), iae.Expression)); int ancIndex = context.FindAncestorIndex <IStatement>(); context.AddStatementsBeforeAncestorIndex(ancIndex, stmts); Type tp = iae.Target.GetExpressionType(); if (tp == null) { Error("Could not determine type of expression: " + iae.Target); return(iae); } IExpression copy = Builder.StaticGenericMethod(new Func <PlaceHolder, PlaceHolder>(Clone.Copy), new Type[] { tp }, Builder.VarRefExpr(cloneVar)); iae = Builder.AssignExpr(iae.Target, copy); } } } } return(iae); }
private NodeInfo GetNodeInfo(IExpression factor) { IExpression target = null; IMethodInvokeExpression imie; if (factor is IAssignExpression iae) { target = iae.Target; if (target is IVariableDeclarationExpression) { IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target); target = Builder.VarRefExpr(ivd); } imie = (IMethodInvokeExpression)iae.Expression; } else { imie = (IMethodInvokeExpression)factor; } NodeInfo info = new NodeInfo(imie) { info = CodeRecognizer.GetFactorInfo(context, imie) }; if (target != null) { info.isReturnOrOut.Add(true); info.arguments.Add(target); } if (!info.info.Method.IsStatic) { info.isReturnOrOut.Add(false); info.arguments.Add(imie.Method.Target); } foreach (IExpression arg in imie.Arguments) { bool isOut = (arg is IAddressOutExpression); info.isReturnOrOut.Add(isOut); info.arguments.Add(isOut ? ((IAddressOutExpression)arg).Expression : arg); } return(info); }
protected override IExpression ConvertMethodInvoke(IMethodInvokeExpression imie) { CheckMethodArgumentCount(imie); if (CodeRecognizer.IsInfer(imie)) { inferCount++; object decl = Recognizer.GetDeclaration(imie.Arguments[0]); if (decl != null && !context.InputAttributes.Has <IsInferred>(decl)) { context.InputAttributes.Set(decl, new IsInferred()); } // the arguments must not be substituted for their values, so we don't call ConvertExpression var newArgs = imie.Arguments.Select(CodeRecognizer.RemoveCast); IMethodInvokeExpression infer = Builder.MethodInvkExpr(); infer.Method = imie.Method; infer.Arguments.AddRange(newArgs); context.InputAttributes.CopyObjectAttributesTo(imie, context.OutputAttributes, infer); return(infer); } IExpression converted = base.ConvertMethodInvoke(imie); if (converted is IMethodInvokeExpression mie) { foreach (IExpression arg in mie.Arguments) { if (arg is IAddressOutExpression iaoe) { IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(iaoe.Expression); if (ivd != null) { FactorManager.FactorInfo info = CodeRecognizer.GetFactorInfo(context, mie); if (info != null && info.IsDeterministicFactor && !context.InputAttributes.Has <DerivedVariable>(ivd)) { context.InputAttributes.Set(ivd, new DerivedVariable()); } } } } } return(converted); }
/// <summary> /// Attach DerivedVariable attributes to newly created variables /// </summary> /// <param name="iae"></param> /// <returns></returns> protected override IExpression ConvertAssign(IAssignExpression iae) { iae = (IAssignExpression)base.ConvertAssign(iae); if (iae.Expression is IMethodInvokeExpression imie) { IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(iae.Target); if (ivd != null) { bool isDerived = context.InputAttributes.Has <DerivedVariable>(ivd); if (!isDerived) { FactorManager.FactorInfo info = CodeRecognizer.GetFactorInfo(context, imie); if (info.IsDeterministicFactor) { context.InputAttributes.Set(ivd, new DerivedVariable()); } } } } return(iae); }
protected override IExpression ConvertMethodInvoke(IMethodInvokeExpression imie) { if (Recognizer.IsStaticGenericMethod(imie, new Func <PlaceHolder, ICompilerAttribute, PlaceHolder>(Attrib.Var))) { IVariableReferenceExpression ivre = imie.Arguments[0] as IVariableReferenceExpression; IVariableDeclaration target = ivre.Variable.Resolve(); IExpression expr = CodeRecognizer.RemoveCast(imie.Arguments[1]); AddAttribute(target, expr); return(null); } else if (Recognizer.IsStaticMethod(imie, new Action <object, object>(Attrib.InitialiseTo))) { IVariableReferenceExpression ivre = CodeRecognizer.RemoveCast(imie.Arguments[0]) as IVariableReferenceExpression; IVariableDeclaration target = ivre.Variable.Resolve(); context.OutputAttributes.Set(target, new InitialiseTo(imie.Arguments[1])); return(null); } else if (CodeRecognizer.IsInfer(imie)) { inferCount++; object decl = Recognizer.GetDeclaration(imie.Arguments[0]); if (decl != null && !context.InputAttributes.Has <IsInferred>(decl)) { context.InputAttributes.Set(decl, new IsInferred()); } // the arguments must not be substituted for their values, so we don't call ConvertExpression List <IExpression> newArgs = new List <IExpression>(); foreach (var arg in imie.Arguments) { newArgs.Add(CodeRecognizer.RemoveCast(arg)); } IMethodInvokeExpression mie = Builder.MethodInvkExpr(); mie.Method = imie.Method; mie.Arguments.AddRange(newArgs); context.InputAttributes.CopyObjectAttributesTo(imie, context.OutputAttributes, mie); return(mie); } IExpression converted = base.ConvertMethodInvoke(imie); if (converted is IMethodInvokeExpression) { var mie = (IMethodInvokeExpression)converted; bool isAnd = Recognizer.IsStaticMethod(converted, new Func <bool, bool, bool>(Factors.Factor.And)); bool isOr = Recognizer.IsStaticMethod(converted, new Func <bool, bool, bool>(Factors.Factor.Or)); bool anyArgumentIsLiteral = mie.Arguments.Any(arg => arg is ILiteralExpression); if (anyArgumentIsLiteral) { if (isAnd) { if (mie.Arguments.Any(arg => arg is ILiteralExpression && ((ILiteralExpression)arg).Value.Equals(false))) { return(Builder.LiteralExpr(false)); } // any remaining literals must be true, and therefore can be ignored. var reducedArguments = mie.Arguments.Where(arg => !(arg is ILiteralExpression)); if (reducedArguments.Count() == 1) { return(reducedArguments.First()); } else { return(Builder.LiteralExpr(true)); } } else if (isOr) { if (mie.Arguments.Any(arg => arg is ILiteralExpression && ((ILiteralExpression)arg).Value.Equals(true))) { return(Builder.LiteralExpr(true)); } // any remaining literals must be false, and therefore can be ignored. var reducedArguments = mie.Arguments.Where(arg => !(arg is ILiteralExpression)); if (reducedArguments.Count() == 1) { return(reducedArguments.First()); } else { return(Builder.LiteralExpr(false)); } } else if (Recognizer.IsStaticMethod(converted, new Func <bool, bool>(Factors.Factor.Not))) { bool allArgumentsAreLiteral = mie.Arguments.All(arg => arg is ILiteralExpression); if (allArgumentsAreLiteral) { return(Builder.LiteralExpr(evaluator.Evaluate(mie))); } } } foreach (IExpression arg in mie.Arguments) { if (arg is IAddressOutExpression) { IAddressOutExpression iaoe = (IAddressOutExpression)arg; IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(iaoe.Expression); if (ivd != null) { FactorManager.FactorInfo info = CodeRecognizer.GetFactorInfo(context, mie); if (info != null && info.IsDeterministicFactor && !context.InputAttributes.Has <DerivedVariable>(ivd)) { context.InputAttributes.Set(ivd, new DerivedVariable()); } } } } } return(converted); }
protected override IExpression ConvertAssign(IAssignExpression iae) { IParameterDeclaration ipd = null; IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(iae.Target); object decl = ivd; if (ivd == null) { ipd = Recognizer.GetParameterDeclaration(iae.Target); if (ipd == null) { return(base.ConvertAssign(iae)); } decl = ipd; } if (iae.Target is IArrayIndexerExpression) { // Gather index variables from the left-hand side of the assignment VariableInformation vi = VariableInformation.GetVariableInformation(context, decl); try { List <IVariableDeclaration[]> indVars = new List <IVariableDeclaration[]>(); Recognizer.AddIndexers(context, indVars, iae.Target); int depth = Recognizer.GetIndexingDepth(iae.Target); // if this statement is actually a constraint, then we don't need to enforce matching of index variables bool isConstraint = context.InputAttributes.Has <Models.Constraint>(context.FindAncestor <IStatement>()); for (int i = 0; i < depth; i++) { vi.SetIndexVariablesAtDepth(i, indVars[i], allowMismatch: isConstraint); } } catch (Exception ex) { Error(ex.Message, ex); } } IAssignExpression ae = (IAssignExpression)base.ConvertAssign(iae); if (ipd == null) { // assignment to a local variable if (ae.Expression is IMethodInvokeExpression) { IMethodInvokeExpression imie = (IMethodInvokeExpression)ae.Expression; // this unfortunately duplicates some of the work done by SetStoch and IsStoch. FactorManager.FactorInfo info = CodeRecognizer.GetFactorInfo(context, imie); if (info != null && info.IsDeterministicFactor && !context.InputAttributes.Has <DerivedVariable>(ivd)) { context.InputAttributes.Set(ivd, new DerivedVariable()); } } if (ae.Expression is ILiteralExpression) { bool isLoopInitializer = (Recognizer.GetAncestorIndexOfLoopBeingInitialized(context) != -1); if (!isLoopInitializer) { Type valueType = ae.Expression.GetExpressionType(); if (Quoter.ShouldInlineType(valueType)) { // inline all future occurrences of this variable with the rhs expression conditionContext.Add(new ConditionBinding(ae.Target, ae.Expression)); } } } } else { // assignment to a method parameter IStatement ist = context.FindAncestor <IStatement>(); if (!context.InputAttributes.Has <Models.Constraint>(ist)) { // mark this statement as a constraint context.OutputAttributes.Set(ist, new Models.Constraint()); } } // a FactorAlgorithm attribute on a variable turns into an Algorithm attribute on its right hand side. var attr = context.InputAttributes.Get <FactorAlgorithm>(decl); if (attr != null) { context.OutputAttributes.Set(ae.Expression, new Algorithm(attr.algorithm)); } context.InputAttributes.CopyObjectAttributesTo <GivePriorityTo>(decl, context.OutputAttributes, ae.Expression); return(ae); }