protected override IExpression ConvertAssign(IAssignExpression iae) { foreach (IStatement stmt in context.FindAncestors <IStatement>()) { // an initializer statement may perform a copy, but it is not valid to replace the lhs // in that case. if (context.InputAttributes.Has <Initializer>(stmt)) { return(iae); } } // Look for assignments where the right hand side is a SetTo call if (iae.Expression is IMethodInvokeExpression imie) { bool isCopy = Recognizer.IsStaticGenericMethod(imie, new Func <PlaceHolder, PlaceHolder>(Clone.Copy)); bool isSetTo = Recognizer.IsStaticGenericMethod(imie, typeof(ArrayHelper), "SetTo"); bool isSetAllElementsTo = Recognizer.IsStaticGenericMethod(imie, typeof(ArrayHelper), "SetAllElementsTo"); bool isGetItemsPoint = Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsPointOp <>), "ItemsAverageConditional"); bool isGetJaggedItemsPoint = Recognizer.IsStaticGenericMethod(imie, typeof(GetJaggedItemsPointOp <>), "ItemsAverageConditional"); bool isGetDeepJaggedItemsPoint = Recognizer.IsStaticGenericMethod(imie, typeof(GetDeepJaggedItemsPointOp <>), "ItemsAverageConditional"); bool isGetItemsFromJaggedPoint = Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsFromJaggedPointOp <>), "ItemsAverageConditional"); bool isGetItemsFromDeepJaggedPoint = Recognizer.IsStaticGenericMethod(imie, typeof(GetItemsFromDeepJaggedPointOp <>), "ItemsAverageConditional"); bool isGetJaggedItemsFromJaggedPoint = Recognizer.IsStaticGenericMethod(imie, typeof(GetJaggedItemsFromJaggedPointOp <>), "ItemsAverageConditional"); if (isCopy || isSetTo || isSetAllElementsTo || isGetItemsPoint || isGetJaggedItemsPoint || isGetDeepJaggedItemsPoint || isGetJaggedItemsFromJaggedPoint || isGetItemsFromJaggedPoint || isGetItemsFromDeepJaggedPoint) { IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(iae.Target); // Find the condition context var ifs = context.FindAncestors <IConditionStatement>(); var condContext = new List <IConditionStatement>(); foreach (var ifSt in ifs) { if (!CodeRecognizer.IsStochastic(context, ifSt.Condition)) { condContext.Add(ifSt); } } var copyAttr = context.InputAttributes.GetOrCreate <CopyOfAttribute>(ivd, () => new CopyOfAttribute()); IExpression rhs; if (isSetTo || isSetAllElementsTo) { // Mark as copy of the second argument rhs = imie.Arguments[1]; } else { // Mark as copy of the first argument rhs = imie.Arguments[0]; } InitialiseTo init = context.InputAttributes.Get <InitialiseTo>(ivd); if (init != null) { IVariableDeclaration ivdRhs = Recognizer.GetVariableDeclaration(rhs); InitialiseTo initRhs = (ivdRhs == null) ? null : context.InputAttributes.Get <InitialiseTo>(ivdRhs); if (initRhs == null || !initRhs.initialMessagesExpression.Equals(init.initialMessagesExpression)) { // Do not replace a variable with a unique initialiser return(iae); } } var initBack = context.InputAttributes.Get <InitialiseBackwardTo>(ivd); if (initBack != null && !(initBack.initialMessagesExpression is IArrayCreateExpression)) { IVariableDeclaration ivdRhs = Recognizer.GetVariableDeclaration(rhs); InitialiseBackwardTo initRhs = (ivdRhs == null) ? null : context.InputAttributes.Get <InitialiseBackwardTo>(ivdRhs); if (initRhs == null || !initRhs.initialMessagesExpression.Equals(init.initialMessagesExpression)) { // Do not replace a variable with a unique initialiser return(iae); } } if (isCopy || isSetTo) { RemoveMatchingSuffixes(iae.Target, rhs, condContext, out IExpression lhsPrefix, out IExpression rhsPrefix); copyAttr.copyMap[lhsPrefix] = new CopyOfAttribute.CopyContext { Expression = rhsPrefix, ConditionContext = condContext }; } else if (isSetAllElementsTo) { copyAttr.copiedInEveryElementMap[iae.Target] = new CopyOfAttribute.CopyContext { Expression = rhs, ConditionContext = condContext }; } else if (isGetItemsPoint || isGetJaggedItemsPoint || isGetDeepJaggedItemsPoint || isGetItemsFromJaggedPoint || isGetItemsFromDeepJaggedPoint || isGetJaggedItemsFromJaggedPoint) { var target = ((IArrayIndexerExpression)iae.Target).Target; int inputDepth = imie.Arguments.Count - 3; List <IExpression> indexExprs = new List <IExpression>(); for (int i = 0; i < inputDepth; i++) { indexExprs.Add(imie.Arguments[1 + i]); } int outputDepth; if (isGetDeepJaggedItemsPoint) { outputDepth = 3; } else if (isGetJaggedItemsPoint || isGetJaggedItemsFromJaggedPoint) { outputDepth = 2; } else { outputDepth = 1; } copyAttr.copyAtIndexMap[target] = new CopyOfAttribute.CopyContext2 { Depth = outputDepth, ConditionContext = condContext, ExpressionAtIndex = (lhsIndices) => { return(Builder.JaggedArrayIndex(rhs, indexExprs.ListSelect(indexExpr => new[] { Builder.JaggedArrayIndex(indexExpr, lhsIndices) }))); } }; } else { throw new NotImplementedException(); } } } return(iae); }
protected void ProcessAssign(IExpression target, IExpression rhs, ref bool shouldDelete) { IVariableDeclaration ivd = Recognizer.GetVariableDeclaration(target); if (ivd == null) { return; } if (rhs is IArrayCreateExpression) { IArrayCreateExpression iace = (IArrayCreateExpression)rhs; bool zeroLength = iace.Dimensions.All(dimExpr => (dimExpr is ILiteralExpression) && ((ILiteralExpression)dimExpr).Value.Equals(0)); if (!zeroLength && iace.Initializer == null) { return; // variable will have assignments to elements } } bool firstTime = !variablesAssigned.Contains(ivd); variablesAssigned.Add(ivd); bool isInferred = context.InputAttributes.Has <IsInferred>(ivd); bool isStochastic = CodeRecognizer.IsStochastic(context, ivd); if (!isStochastic) { return; } VariableInformation vi = VariableInformation.GetVariableInformation(context, ivd); Containers defContainers = context.InputAttributes.Get <Containers>(ivd); int ancIndex = defContainers.GetMatchingAncestorIndex(context); Containers missing = defContainers.GetContainersNotInContext(context, ancIndex); // definition of a stochastic variable IExpression lhs = target; if (lhs is IVariableDeclarationExpression) { lhs = Builder.VarRefExpr(ivd); } IExpression defExpr = lhs; if (firstTime && isStochastic) { // Create a ChannelInfo attribute for use by later transforms, e.g. MessageTransform ChannelInfo defChannel = ChannelInfo.DefChannel(vi); defChannel.decl = ivd; context.OutputAttributes.Set(ivd, defChannel); } bool isDerived = context.InputAttributes.Has <DerivedVariable>(ivd); IAlgorithm algorithm = this.algorithmDefault; Algorithm algAttr = context.InputAttributes.Get <Algorithm>(ivd); if (algAttr != null) { algorithm = algAttr.algorithm; } if (algorithm is VariationalMessagePassing && ((VariationalMessagePassing)algorithm).UseDerivMessages && isDerived && firstTime) { vi.DefineAllIndexVars(context); IList <IStatement> stmts = Builder.StmtCollection(); IVariableDeclaration derivDecl = vi.DeriveIndexedVariable(stmts, context, ivd.Name + "_deriv"); context.OutputAttributes.Set(ivd, new DerivMessage(derivDecl)); ChannelInfo derivChannel = ChannelInfo.DefChannel(vi); derivChannel.decl = derivDecl; context.OutputAttributes.Set(derivChannel.decl, derivChannel); context.OutputAttributes.Set(derivChannel.decl, new DescriptionAttribute("deriv of '" + ivd.Name + "'")); // Add the declarations stmts = Containers.WrapWithContainers(stmts, missing.outputs); context.AddStatementsBeforeAncestorIndex(ancIndex, stmts); } bool isPointEstimate = context.InputAttributes.Has <PointEstimate>(ivd); if (this.analysis.variablesExcludingVariableFactor.Contains(ivd)) { this.variablesLackingVariableFactor.Add(ivd); // ivd will get a marginal channel in ConvertMethodInvoke useOfVariable[ivd] = ivd; return; } if (isDerived && !isInferred && !isPointEstimate) { return; } IExpression useExpr2 = null; if (firstTime) { // create marginal and use channels vi.DefineAllIndexVars(context); IList <IStatement> stmts = Builder.StmtCollection(); CreateMarginalChannel(ivd, vi, stmts); if (isStochastic) { CreateUseChannel(ivd, vi, stmts); context.InputAttributes.Set(useOfVariable[ivd], defContainers); } // Add the declarations stmts = Containers.WrapWithContainers(stmts, missing.outputs); context.AddStatementsBeforeAncestorIndex(ancIndex, stmts); } if (isStochastic && !useOfVariable.ContainsKey(ivd)) { Error("cannot find use channel of " + ivd); return; } IExpression marginalExpr = Builder.ReplaceVariable(lhs, ivd, marginalOfVariable[ivd]); IExpression useExpr = isStochastic ? Builder.ReplaceVariable(lhs, ivd, useOfVariable[ivd]) : marginalExpr; InitialiseTo it = context.InputAttributes.Get <InitialiseTo>(ivd); Type[] genArgs = new Type[] { defExpr.GetExpressionType() }; if (rhs is IMethodInvokeExpression) { IMethodInvokeExpression imie = (IMethodInvokeExpression)rhs; if (Recognizer.IsStaticGenericMethod(imie, new Func <PlaceHolder, PlaceHolder>(Clone.Copy)) && ancIndex < context.InputStack.Count - 2) { IExpression arg = imie.Arguments[0]; IVariableDeclaration ivd2 = Recognizer.GetVariableDeclaration(arg); if (ivd2 != null && context.InputAttributes.Get <MarginalPrototype>(ivd) == context.InputAttributes.Get <MarginalPrototype>(ivd2)) { // if a variable is a copy, use the original expression since it will give more precise dependencies. defExpr = arg; shouldDelete = true; bool makeClone = false; if (makeClone) { VariableInformation vi2 = VariableInformation.GetVariableInformation(context, ivd2); IList <IStatement> stmts = Builder.StmtCollection(); List <IList <IExpression> > indices = Recognizer.GetIndices(defExpr); IVariableDeclaration useDecl2 = vi2.DeriveIndexedVariable(stmts, context, ivd2.Name + "_use", indices); useExpr2 = Builder.VarRefExpr(useDecl2); Containers defContainers2 = context.InputAttributes.Get <Containers>(ivd2); int ancIndex2 = defContainers2.GetMatchingAncestorIndex(context); Containers missing2 = defContainers2.GetContainersNotInContext(context, ancIndex2); stmts = Containers.WrapWithContainers(stmts, missing2.outputs); context.AddStatementsBeforeAncestorIndex(ancIndex2, stmts); context.InputAttributes.Set(useDecl2, defContainers2); // TODO: call CreateUseChannel ChannelInfo usageChannel = ChannelInfo.UseChannel(vi2); usageChannel.decl = useDecl2; context.InputAttributes.CopyObjectAttributesTo <InitialiseTo>(vi.declaration, context.OutputAttributes, useDecl2); context.InputAttributes.CopyObjectAttributesTo <DerivMessage>(vi.declaration, context.OutputAttributes, useDecl2); context.OutputAttributes.Set(useDecl2, usageChannel); //context.OutputAttributes.Set(useDecl2, new DescriptionAttribute("use of '" + ivd.Name + "'")); context.OutputAttributes.Remove <InitialiseTo>(vi.declaration); IExpression copyExpr = Builder.StaticGenericMethod( new Func <PlaceHolder, PlaceHolder>(Clone.Copy), genArgs, useExpr2); var copyStmt = Builder.AssignStmt(useExpr, copyExpr); context.AddStatementAfterCurrent(copyStmt); } } } } // Add the variable factor IExpression variableFactorExpr; bool isGateExitRandom = context.InputAttributes.Has <VariationalMessagePassing.GateExitRandomVariable>(ivd); if (isGateExitRandom) { variableFactorExpr = Builder.StaticGenericMethod( new Models.FuncOut <PlaceHolder, PlaceHolder, PlaceHolder>(Gate.ExitingVariable), genArgs, defExpr, marginalExpr); } else { Delegate d = algorithm.GetVariableFactor(isDerived, it != null); if (isPointEstimate) { d = new Models.FuncOut <PlaceHolder, PlaceHolder, PlaceHolder>(Clone.VariablePoint); } if (it == null) { variableFactorExpr = Builder.StaticGenericMethod(d, genArgs, defExpr, marginalExpr); } else { IExpression initExpr = Builder.ReplaceExpression(lhs, Builder.VarRefExpr(ivd), it.initialMessagesExpression); variableFactorExpr = Builder.StaticGenericMethod(d, genArgs, defExpr, initExpr, marginalExpr); } } context.InputAttributes.CopyObjectAttributesTo <GivePriorityTo>(ivd, context.OutputAttributes, variableFactorExpr); context.InputAttributes.CopyObjectAttributesTo <Algorithm>(ivd, context.OutputAttributes, variableFactorExpr); if (isStochastic) { context.OutputAttributes.Set(variableFactorExpr, new IsVariableFactor()); } var assignStmt = Builder.AssignStmt(useExpr2 == null ? useExpr : useExpr2, variableFactorExpr); context.AddStatementAfterCurrent(assignStmt); }
internal IVariableDeclaration DeriveArrayVariable(ICollection <IStatement> addTo, BasicTransformContext context, string name, IList <IExpression[]> arraySize, IList <IVariableDeclaration[]> newIndexVar, IList <IList <IExpression> > indices = null, IList <IList <IExpression> > wildcardVars = null, bool useLiteralIndices = false, bool copyInitializer = false) { List <IExpression[]> newSizes = new List <IExpression[]>(); List <IVariableDeclaration[]> newIndexVars = new List <IVariableDeclaration[]>(); Type innerType = varType; if (indices != null) { // add wildcard variables to newIndexVars for (int i = 0; i < indices.Count; i++) { List <IExpression> sizeBracket = new List <IExpression>(); List <IVariableDeclaration> indexVarsBracket = new List <IVariableDeclaration>(); for (int j = 0; j < indices[i].Count; j++) { IExpression index = indices[i][j]; if (Recognizer.IsStaticMethod(index, new Func <int>(GateAnalysisTransform.AnyIndex))) { int replaceCount = 0; sizeBracket.Add(ReplaceIndexVars(context, sizes[i][j], indices, wildcardVars, ref replaceCount)); IVariableDeclaration v = indexVars[i][j]; if (wildcardVars != null) { v = Recognizer.GetVariableDeclaration(wildcardVars[newIndexVars.Count][indexVarsBracket.Count]); } else if (Recognizer.GetLoopForVariable(context, v) != null) { // v is already used in a parent loop. must generate a new variable. v = GenerateLoopVar(context, "_a"); } indexVarsBracket.Add(v); } } if (sizeBracket.Count > 0) { newSizes.Add(sizeBracket.ToArray()); newIndexVars.Add(indexVarsBracket.ToArray()); } innerType = Util.GetElementType(innerType); } } int literalIndexingDepth = 0; if (arraySize != null) { newSizes.AddRange(arraySize); if (useLiteralIndices) { literalIndexingDepth = newSizes.Count; } newIndexVars.AddRange(newIndexVar); } // innerType may not be an array type, so we create the new array type here instead of descending further. Type arrayType = CodeBuilder.MakeJaggedArrayType(innerType, newSizes); int indexingDepth = (indices == null) ? 0 : indices.Count; List <IList <IExpression> > replacements = new List <IList <IExpression> >(); if (indices != null) { replacements.AddRange(indices); } for (int i = indexingDepth; i < sizes.Count; i++) { if (replacements.Count == 0) { newSizes.Add(sizes[i]); if (indexVars.Count > i) { newIndexVars.Add(indexVars[i]); } } else { // must substitute references to indexVars with indices IExpression[] sizeBracket = new IExpression[sizes[i].Length]; IVariableDeclaration[] indexVarBracket = new IVariableDeclaration[sizes[i].Length]; IList <IExpression> replacementBracket = Builder.ExprCollection(); for (int j = 0; j < sizeBracket.Length; j++) { int replaceCount = 0; sizeBracket[j] = ReplaceIndexVars(context, sizes[i][j], replacements, wildcardVars, ref replaceCount); if (replaceCount > 0) { indexVarBracket[j] = GenerateLoopVar(context, "_a"); } else if (indexVars.Count > i) { indexVarBracket[j] = indexVars[i][j]; } if (indexVarBracket[j] != null) { replacementBracket.Add(Builder.VarRefExpr(indexVarBracket[j])); } } newSizes.Add(sizeBracket); newIndexVars.Add(indexVarBracket); replacements.Add(replacementBracket); } } IVariableDeclaration arrayvd = Builder.VarDecl(CodeBuilder.MakeValid(name), arrayType); Builder.NewJaggedArray(addTo, arrayvd, newIndexVars, newSizes, literalIndexingDepth); context.InputAttributes.CopyObjectAttributesTo(declaration, context.OutputAttributes, arrayvd); // cannot copy the initializer since it will have a different size. context.OutputAttributes.Remove <InitialiseTo>(arrayvd); context.OutputAttributes.Remove <InitialiseBackwardTo>(arrayvd); context.OutputAttributes.Remove <InitialiseBackward>(arrayvd); context.OutputAttributes.Remove <VariableInformation>(arrayvd); context.OutputAttributes.Remove <SuppressVariableFactor>(arrayvd); context.OutputAttributes.Remove <LoopContext>(arrayvd); context.OutputAttributes.Remove <Containers>(arrayvd); context.OutputAttributes.Remove <ChannelInfo>(arrayvd); context.OutputAttributes.Remove <IsInferred>(arrayvd); context.OutputAttributes.Remove <QueryTypeCompilerAttribute>(arrayvd); context.OutputAttributes.Remove <DerivMessage>(arrayvd); context.OutputAttributes.Remove <PointEstimate>(arrayvd); context.OutputAttributes.Remove <DescriptionAttribute>(arrayvd); context.OutputAttributes.Remove <MarginalPrototype>(arrayvd); VariableInformation vi = VariableInformation.GetVariableInformation(context, arrayvd); vi.IsStochastic = IsStochastic; vi.sizes = newSizes; vi.indexVars = newIndexVars; if (useLiteralIndices) { vi.LiteralIndexingDepth = literalIndexingDepth; } if (marginalPrototypeExpression != null) { // substitute indices in the marginal prototype expression vi.marginalPrototypeExpression = GetMarginalPrototypeExpression(context, marginalPrototypeExpression, replacements, wildcardVars); } InitialiseTo it = context.InputAttributes.Get <InitialiseTo>(declaration); if (it != null && copyInitializer) { // if original array is indexed [i,j][k,l][m,n] and indices = [*,*][3,*] then // initExpr2 = new PlaceHolder[wildcard0,wildcard1] { new PlaceHolder[wildcard2] { new PlaceHolder[newIndexVar] { initExpr[wildcard0,wildcard1][3,wildcard2] } } } IExpression initExpr = it.initialMessagesExpression; // add indices to the initialiser expression int wildcardBracket = 0; for (int depth = 0; depth < indexingDepth; depth++) { IList <IExpression> indexCollection = Builder.ExprCollection(); int wildcardCount = 0; for (int i = 0; i < indices[depth].Count; i++) { if (Recognizer.IsStaticMethod(indices[depth][i], new Func <int>(GateAnalysisTransform.AnyIndex))) { indexCollection.Add(wildcardVars[wildcardBracket][wildcardCount]); wildcardCount++; } else { indexCollection.Add(indices[depth][i]); } } if (indexCollection.Count > 0) { if (wildcardCount > 0) { wildcardBracket++; } initExpr = Builder.ArrayIndex(initExpr, indexCollection); } } // add array creates to the initialiser expression if (newIndexVar != null) { initExpr = MakePlaceHolderArrayCreate(initExpr, newIndexVar); } if (wildcardBracket > 0) { while (wildcardBracket > 0) { wildcardBracket--; initExpr = MakePlaceHolderArrayCreate(initExpr, vi.indexVars[wildcardBracket]); } } context.OutputAttributes.Set(arrayvd, new InitialiseTo(initExpr)); } ChannelTransform.setAllGroupRoots(context, arrayvd, false); return(arrayvd); }
/// <summary> /// Add the definition of a random variable to the MSL, inside of the necessary containers. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="variable"></param> /// <remarks> /// A scalar variable is declared and defined in one line such as: <c>int x = factor(...);</c>. /// An array variable is first declared with an initializer such as: <c>int[] array = new int[4];</c>. /// Then it is defined either with a bulk factor such as: <c>array = factor(...);</c>, /// or it is defined via its item variable. /// An item variable is defined by 'for' loop whose body is: <c>array[i] = factor(...);</c>. /// </remarks> protected void BuildRandVar <T>(Variable <T> variable) { if (!variable.IsDefined) { throw new InferCompilerException("Variable '" + variable + "' has no definition"); } if (variable.IsArrayElement) { for (int initType = 0; initType < 2; initType++) { IModelExpression init = (initType == 0) ? variable.initialiseTo : variable.initialiseBackwardTo; if (init != null) { IExpression initExpr = init.GetExpression(); // find the base variable Variable parent = variable; while (parent.ArrayVariable != null) { IVariableDeclaration[] indexVars = new IVariableDeclaration[parent.indices.Count]; for (int i = 0; i < indexVars.Length; i++) { IModelExpression expr = parent.indices[i]; if (!(expr is Range)) { throw new Exception(parent + ".InitializeTo is not allowed since the indices are not ranges"); } indexVars[i] = ((Range)expr).GetIndexDeclaration(); } initExpr = VariableInformation.MakePlaceHolderArrayCreate(initExpr, indexVars); parent = (Variable)parent.ArrayVariable; } IVariableDeclaration parentDecl = (IVariableDeclaration)parent.GetDeclaration(); ICompilerAttribute attr; if (initType == 0) { attr = new InitialiseTo(initExpr); } else { attr = new InitialiseBackwardTo(initExpr); } Attributes.Set(parentDecl, attr); } } return; } IVariableDeclaration ivd = (IVariableDeclaration)variable.GetDeclaration(); if (variable.initialiseTo != null) { Attributes.Set(ivd, new InitialiseTo(variable.initialiseTo.GetExpression())); } if (variable.initialiseBackwardTo != null) { Attributes.Set(ivd, new InitialiseBackwardTo(variable.initialiseBackwardTo.GetExpression())); } List <IStatementBlock> stBlocks = new List <IStatementBlock>(); stBlocks.AddRange(variable.Containers); IVariableDeclarationExpression ivde = Builder.VarDeclExpr(ivd); if (variable is IVariableArray iva) { IList <IStatement> sc = Builder.StmtCollection(); IList <IVariableDeclaration[]> jaggedIndexVars; IList <IExpression[]> jaggedSizes; GetJaggedArrayIndicesAndSizes(iva, out jaggedIndexVars, out jaggedSizes); // check that containers are all unique and distinct from jaggedIndexVars Set <IVariableDeclaration> loopVars = new Set <IVariableDeclaration>(); foreach (IStatementBlock stBlock in stBlocks) { if (stBlock is ForEachBlock fb) { IVariableDeclaration loopVar = fb.Range.GetIndexDeclaration(); if (loopVars.Contains(loopVar)) { throw new InvalidOperationException("Variable '" + ivd.Name + "' uses range '" + loopVar.Name + "' twice. Use a cloned range instead."); } loopVars.Add(loopVar); } } foreach (IVariableDeclaration[] bracket in jaggedIndexVars) { foreach (IVariableDeclaration indexVar in bracket) { if (loopVars.Contains(indexVar)) { throw new InvalidOperationException("Variable '" + ivd.Name + "' uses range '" + indexVar.Name + "' twice. Use a cloned range instead."); } } } Builder.NewJaggedArray(sc, ivd, jaggedIndexVars, jaggedSizes); if (!variable.Inline) { BuildStatementBlocks(stBlocks, true); foreach (IStatement stmt in sc) { AddStatement(stmt); } BuildStatementBlocks(stBlocks, false); } ivde = null; // prevent re-declaration } if (ivde != null) { if (!variable.Inline) { BuildStatementBlocks(stBlocks, true); AddStatement(Builder.ExprStatement(ivde)); BuildStatementBlocks(stBlocks, false); } ivde = null; } if (ivde != null) { throw new InferCompilerException("Variable '" + variable + "' has no definition"); } }