public override void Visit(VariableReferenceExpression variableReferenceExpression) { base.Visit(variableReferenceExpression); if (sourceManager.IsClassExists(variableReferenceExpression.Name.Text)) FoundClasses.Add(variableReferenceExpression.Name.Text); }
private void Visit(VariableReferenceExpression variableReferenceExpression) { Visit((Node)variableReferenceExpression); if (sourceManager.IsClassExists(variableReferenceExpression.Name.Text)) FoundClasses.Add(variableReferenceExpression.Name.Text); }
public XenkoReplaceAppend(HashSet<MethodInvocationExpression> appendList, List<Statement> output, VariableReferenceExpression vre) : base(false, false) { appendMethodsList = appendList; outputStatements = output; outputVre = vre; }
public override Node Visit(VariableReferenceExpression expression) { base.Visit(expression); if (expression.Name.Text == VariableToReplace.Name.Text) return IndexerReplacement; return expression; }
protected Node Visit(VariableReferenceExpression expression) { Visit((Node)expression); if (expression.Name.Text == VariableToReplace.Name.Text) return IndexerReplacement; return expression; }
protected void Visit(VariableReferenceExpression variableRef) { var variable = GetUniform(variableRef); // If the variable is a global uniform, non static/const and is not already in the list used then if (variable != null && !uniformReadList.Contains(variable)) { uniformReadList.Add(variable); } }
public override Node Visit(VariableReferenceExpression variableRef) { var variable = GetUniform(variableRef); // If the variable is a global uniform, non static/const and is not already in the list used then if (variable != null && !uniformReadList.Contains(variable)) { uniformReadList.Add(variable); } return variableRef; }
/// <summary> /// Replace a MemberReferenceExpression by a VariableReferenceExpression in the AST /// </summary> /// <param name="memberReferenceExpression">the member reference expression.</param> /// <param name="variableReferenceExpression">the variable reference expression.</param> /// <param name="parentNode">the parent node.</param> private static void ReplaceMemberReferenceExpressionByVariableReferenceExpression(MemberReferenceExpression memberReferenceExpression, VariableReferenceExpression variableReferenceExpression, Node parentNode) { var replacor = new XenkoReplaceVisitor(memberReferenceExpression, variableReferenceExpression); replacor.Run(parentNode); }
/// <summary> /// Creates a ForStatement with the same behavior /// </summary> /// <param name="forEachStatement">the ForEachStatement</param> /// <returns>the ForStatement</returns> private static ForStatement ExpandForEachStatement(ForEachStatement forEachStatement) { if (forEachStatement != null) { var collec = forEachStatement.Collection.TypeInference.Declaration as Variable; LiteralExpression dimLit = null; if (collec.Type is ArrayType) { if ((collec.Type as ArrayType).Dimensions.Count == 1) { dimLit = (collec.Type as ArrayType).Dimensions[0] as LiteralExpression; } } if (dimLit != null) { var initializer = new Variable(ScalarType.Int, forEachStatement.Variable.Name.Text + "Iter", new LiteralExpression(0)); var vre = new VariableReferenceExpression(initializer.Name); var condition = new BinaryExpression(BinaryOperator.Less, vre, dimLit); var next = new UnaryExpression(UnaryOperator.PreIncrement, vre); ForStatement forStatement = new ForStatement(new DeclarationStatement(initializer), condition, next); var body = new BlockStatement(); var variable = forEachStatement.Variable; variable.InitialValue = new IndexerExpression(forEachStatement.Collection, new VariableReferenceExpression(initializer)); body.Statements.Add(new DeclarationStatement(variable)); if (forEachStatement.Body is BlockStatement) body.Statements.AddRange((forEachStatement.Body as BlockStatement).Statements); else body.Statements.Add(forEachStatement.Body); forStatement.Body = body; return forStatement; } // TODO: multidimension-array? // TODO: unroll? // TODO: multiple foreach? } return null; }
/// <summary> /// Rename the methods and their references /// </summary> /// <param name="references">the pool to rename</param> /// <param name="id">the id used to build the new name</param> private void RenameAllMethods(ReferencesPool references, HashSet<MethodDefinition> renameFreeMethods, ref int id) { foreach (var method in references.MethodsReferences) { if (renameFreeMethods.Contains(method.Key) || !(method.Key is MethodDefinition)) continue; foreach (var methodRef in method.Value) { var targetMre = methodRef.Target as MemberReferenceExpression; if (targetMre != null) { var vre = new VariableReferenceExpression(); methodRef.Target = vre; vre.TypeInference.Declaration = targetMre.TypeInference.Declaration; vre.TypeInference.TargetType = targetMre.TypeInference.TargetType; } var targetVre = methodRef.Target as VariableReferenceExpression; targetVre.Name = method.Key.Name; } method.Key.Name.Text += "_id" + id; ++id; } references.RegenKeys(); }
/// <summary> /// Rename all the variables and their references based on the id /// </summary> /// <param name="references">the pool to rename</param> /// <param name="id">the id used to build the new name</param> private void RenameAllVariables(ReferencesPool references, ref int id) { foreach (var variable in references.VariablesReferences) { if (variable.Key.Name.Text == FlipRendertargetVariableName) // DO NOT RENAME THIS SPECIFIC VARIABLE continue; foreach (var varRef in variable.Value) { if (varRef.Expression is MemberReferenceExpression) { if (variable.Key.Qualifiers.Contains(XenkoStorageQualifier.Stream)) // TODO: change test { (varRef.Expression as MemberReferenceExpression).Member = variable.Key.Name; var type = (varRef.Expression as MemberReferenceExpression).Target.TypeInference.TargetType as StreamsType; if (type == null || !type.IsInputOutput) (varRef.Expression as MemberReferenceExpression).Target = new VariableReferenceExpression(StreamsType.ThisStreams); } else if (variable.Key.Qualifiers.Contains(XenkoStorageQualifier.PatchStream)) { (varRef.Expression as MemberReferenceExpression).Member = variable.Key.Name; } else { var vre = new VariableReferenceExpression(variable.Key.Name); vre.TypeInference.Declaration = variable.Key; vre.TypeInference.TargetType = variable.Key.Type.ResolveType(); ReplaceMemberReferenceExpressionByVariableReferenceExpression(varRef.Expression as MemberReferenceExpression, vre, varRef.Node); varRef.Expression = vre; } } else (varRef.Expression as VariableReferenceExpression).Name = variable.Key.Name; } variable.Key.Name.Text += "_id" + id; ++id; } }
/// <summary> /// Checks if a function needs to have a stream strucutre added in its declaration /// </summary> /// <param name="methodDefinition">the method definition</param> /// <param name="inputStream">The stage input structure stream.</param> /// <param name="intermediateStream">the stream structure</param> /// <param name="outputStream">The stage output stream structure.</param> /// <param name="visitedMethods">the list of already visited methods</param> /// <param name="methodsWithStreams">The list of methods that have a streams argument.</param> /// <returns>true if needed, false otherwise</returns> private bool PropagateStreamsParameter(MethodDefinition methodDefinition, StructType inputStream, StructType intermediateStream, StructType outputStream, HashSet<MethodDeclaration> visitedMethods, List<MethodDeclaration> methodsWithStreams) { var needStream = false; if (methodDefinition != null) { if (visitedMethods.Contains(methodDefinition)) return methodDefinition.Parameters.Count > 0 && methodDefinition.Parameters[0].Type == intermediateStream; List<StreamUsageInfo> streamUsageInfos; if (streamsUsages.TryGetValue(methodDefinition, out streamUsageInfos)) { needStream = streamUsageInfos.Any(x => x.CallType == StreamCallType.Member || x.CallType == StreamCallType.Direct); visitedMethods.Add(methodDefinition); List<MethodDeclaration> calls; if (TryGetMethodCalls(methodDefinition, out calls)) needStream = calls.Aggregate(needStream, (res, calledmethod) => res | PropagateStreamsParameter(calledmethod as MethodDefinition, inputStream, intermediateStream, outputStream, visitedMethods, methodsWithStreams)); if (needStream && !entryPointMethods.Contains(methodDefinition)) { var param = new Parameter(new TypeName(intermediateStream.Name), "streams"); foreach (var methodRef in mainModuleMixin.ClassReferences.MethodsReferences[methodDefinition]) { var vre = new VariableReferenceExpression(param.Name) { TypeInference = { Declaration = param, TargetType = param.Type } }; methodRef.Arguments.Insert(0, vre); } param.Qualifiers |= ParameterQualifier.InOut; methodDefinition.Parameters.Insert(0, param); // If any parameters in the method are streams, then replace by using the intermediate stream foreach (var parameter in methodDefinition.Parameters) { if (parameter.Type == StreamsType.Streams) { parameter.Type = new TypeName(intermediateStream.Name); } } methodsWithStreams.Add(methodDefinition); } } TransformStreamsAssignments(methodDefinition, inputStream, intermediateStream, outputStream); } return needStream; }
protected void Visit(VariableReferenceExpression variableRef) { ((ScopeDeclarationWithRef)ScopeStack.Peek()).VariableReferences.Add(variableRef); }
private static VariableReferenceExpression Clone(VariableReferenceExpression expression) { var vre = new VariableReferenceExpression(expression.Name); if (expression.TypeInference.TargetType is StreamsType) vre.TypeInference.TargetType = expression.TypeInference.TargetType; return vre; }
/// <summary> /// Checks that the name does not bear many meanings /// </summary> /// <param name="variableReferenceExpression">the variable reference expression to check to check</param> private void CheckNameConflict(VariableReferenceExpression variableReferenceExpression) { var name = variableReferenceExpression.Name.Text; // NOTE: a VariableReferenceExpression means that we are in the context of the currently analyzed mixin // we need to check that a variable does not appear twice var varCount = analyzedModuleMixin.VirtualTable.Variables.Count(x => x.Variable.Name.Text == name); if (varCount > 1) Error(XenkoMessageCode.ErrorVariableNameAmbiguity, variableReferenceExpression.Span, variableReferenceExpression, analyzedModuleMixin.MixinName); }
public void Visit(VariableReferenceExpression variableReferenceExpression) { Visit((Node)variableReferenceExpression); AddReference(GetDeclarationContainer(), (Node)variableReferenceExpression.TypeInference.Declaration); }
public override void Visit(VariableReferenceExpression variableReferenceExpression) { base.Visit(variableReferenceExpression); AddReference(GetDeclarationContainer(), (Node)variableReferenceExpression.TypeInference.Declaration); }
private void ExtractGenericParameters(Expression expression, out Expression mixinName, List<Expression> genericParametersOut) { if (genericParametersOut == null) { throw new ArgumentNullException("genericParametersOut"); } mixinName = expression; genericParametersOut.Clear(); var varExp = expression as VariableReferenceExpression; if (varExp != null) { Identifier identifier = varExp.Name; var identifierGeneric = identifier as IdentifierGeneric; if (identifierGeneric != null) { mixinName = new VariableReferenceExpression(identifierGeneric.Text); foreach (Identifier subIdentifier in identifierGeneric.Identifiers) { var identifierDot = subIdentifier as IdentifierDot; if (identifierDot != null) { if (identifierDot.Identifiers.Count == 2) { genericParametersOut.Add(new MemberReferenceExpression(new VariableReferenceExpression(identifierDot.Identifiers[0]), identifierDot.Identifiers[1])); } else { logging.Error("Unsupported identifier in generic used for mixin", identifierDot.Span); } } else if (subIdentifier is LiteralIdentifier) { var literalIdentifier = (LiteralIdentifier)subIdentifier; genericParametersOut.Add(new LiteralExpression(literalIdentifier.Value)); } else if (subIdentifier.GetType() == typeof(Identifier)) { genericParametersOut.Add(new VariableReferenceExpression(subIdentifier)); } else { logging.Error("Unsupported identifier in generic used for mixin", subIdentifier.Span); } } } } }
/// <inheritdoc/> public override void Visit(VariableReferenceExpression variableReferenceExpression) { base.Visit(variableReferenceExpression); var variableDeclaration = variableReferenceExpression.TypeInference.Declaration as Variable; if (variableDeclaration == null) { result.Error("Unable to find variable [{0}]", variableReferenceExpression.Span, variableReferenceExpression); } else if (variableDeclaration.InitialValue == null || !variableDeclaration.Qualifiers.Contains(StorageQualifier.Const)) { result.Error("Variable [{0}] used in expression is not constant", variableReferenceExpression.Span, variableDeclaration); } else { var evaluator = new ExpressionEvaluator(); var subResult = evaluator.Evaluate(variableDeclaration.InitialValue); subResult.CopyTo(result); if (subResult.HasErrors) { values.Push(0.0); } else { values.Push(subResult.Value); } } }
protected virtual void Visit(VariableReferenceExpression variableReferenceExpression) { Visit((Node)variableReferenceExpression); var typeReference = variableReferenceExpression.TypeInference; typeReference.Declaration = FindDeclaration(variableReferenceExpression.Name); typeReference.TargetType = ResolveTypeFromDeclaration(typeReference.Declaration); }
/// <summary> /// Rename all the variables and their references based on the id /// </summary> /// <param name="references">the pool to rename</param> /// <param name="id">the id used to build the new name</param> private void RenameAllVariables(ReferencesPool references, ref int id) { foreach (var variable in references.VariablesReferences) { foreach (var varRef in variable.Value) { var memberReferenceExpression = varRef.Expression as MemberReferenceExpression; if (memberReferenceExpression != null) { if (variable.Key.Qualifiers.Contains(XenkoStorageQualifier.Stream)) // TODO: change test { memberReferenceExpression.Member = variable.Key.Name; var type = memberReferenceExpression.Target.TypeInference.TargetType; if (type == null || !type.IsStreamsType() || !type.IsStreamsMutable()) memberReferenceExpression.Target = new VariableReferenceExpression(StreamsType.ThisStreams); } else if (variable.Key.Qualifiers.Contains(XenkoStorageQualifier.PatchStream)) { memberReferenceExpression.Member = variable.Key.Name; } else { var vre = new VariableReferenceExpression(variable.Key.Name); vre.TypeInference.Declaration = variable.Key; vre.TypeInference.TargetType = variable.Key.Type.ResolveType(); ReplaceMemberReferenceExpressionByVariableReferenceExpression(memberReferenceExpression, vre, varRef.Node); varRef.Expression = vre; } } else ((VariableReferenceExpression)varRef.Expression).Name = variable.Key.Name; } variable.Key.Name.Text += "_id" + id; ++id; } }
public override Node Visit(VariableReferenceExpression variableRef) { ((ScopeDeclarationWithRef)ScopeStack.Peek()).VariableReferences.Add(variableRef); return variableRef; }
/// <summary> /// Visits the specified variable reference expression. /// </summary> /// <param name="variableReferenceExpression">The variable reference expression.</param> public override Node Visit(VariableReferenceExpression variableReferenceExpression) { base.Visit(variableReferenceExpression); var typeReference = variableReferenceExpression.TypeInference; typeReference.Declaration = FindDeclaration(variableReferenceExpression.Name); typeReference.TargetType = ResolveTypeFromDeclaration(typeReference.Declaration); return variableReferenceExpression; }
/// <summary> /// Analyse the VariableReferenceExpression, detects streams, propagate type inference, get stored in the correct list for later analysis /// </summary> /// <param name="variableReferenceExpression">the VariableReferenceExpression</param> public override void Visit(VariableReferenceExpression variableReferenceExpression) { base.Visit(variableReferenceExpression); // HACK: force types on base, this and stream keyword to eliminate errors in the log an use the standard type inference if (variableReferenceExpression.Name == StreamsType.ThisStreams.Name) { if (!(ParentNode is MemberReferenceExpression)) // streams is alone currentStreamUsageList.Add(new StreamUsageInfo { CallType = StreamCallType.Direct, Variable = StreamsType.ThisStreams, Expression = variableReferenceExpression, Usage = currentStreamUsage }); } }
protected override void ProcessMethodInvocation(MethodInvocationExpression invoke, MethodDefinition method) { var textureParameters = new List<Parameter>(); var parameterValues = new List<Expression>(); var parameterGlobalValues = new List<Variable>(); var samplerTypes = new List<int>(); for (int i = 0; i < method.Parameters.Count; i++) { var parameter = method.Parameters[i]; if (parameter.Type is TextureType || parameter.Type is StateType) { textureParameters.Add(parameter); // Find global variable var parameterValue = this.FindGlobalVariable(invoke.Arguments[i]); // Set the tag ScopeValue for the current parameter parameter.SetTag(ScopeValueKey, parameterValue); // Add only new variable if (!parameterGlobalValues.Contains(parameterValue)) parameterGlobalValues.Add(parameterValue); } else if ( i < invoke.Arguments.Count) { parameterValues.Add(invoke.Arguments[i]); if (parameter.Type is SamplerType) { samplerTypes.Add(i); } } } // We have texture/sampler parameters. We need to generate a new specialized method if (textureParameters.Count > 0) { // Order parameter values by name parameterGlobalValues.Sort((left, right) => left.Name.Text.CompareTo(right.Name.Text)); var methodKey = new TextureSamplerMethodKey(method); int indexOf = textureSamplerMethods.IndexOf(methodKey); if (indexOf < 0) { methodKey.Initialize(cloneContext); textureSamplerMethods.Add(methodKey); } else { // If a key is found again, add it as it was reused in order to keep usage in order methodKey = textureSamplerMethods[indexOf]; textureSamplerMethods.RemoveAt(indexOf); textureSamplerMethods.Add(methodKey); } methodKey.Invokers.Add(invoke); var newTarget = new VariableReferenceExpression(methodKey.NewMethod.Name) { TypeInference = { Declaration = methodKey.NewMethod, TargetType = invoke.TypeInference.TargetType } }; invoke.Target = newTarget; invoke.Arguments = parameterValues; invoke.TypeInference.Declaration = methodKey.NewMethod; invoke.TypeInference.TargetType = invoke.TypeInference.TargetType; this.VisitDynamic(methodKey.NewMethod); } else { // Visit the method callstack this.VisitDynamic(method); // There is an anonymous sampler type // We need to resolve its types after the method definition was processed if (samplerTypes.Count > 0) { foreach (var samplerTypeIndex in samplerTypes) { var samplerRef = invoke.Arguments[samplerTypeIndex] as VariableReferenceExpression; if (samplerRef != null) { var samplerDecl = samplerRef.TypeInference.Declaration as Variable; ChangeVariableType(samplerDecl, method.Parameters[samplerTypeIndex].Type); } } } } // Remove temporary parameters if (textureParameters.Count > 0) { foreach (var textureParameter in textureParameters) { textureParameter.RemoveTag(ScopeValueKey); } } }
public override Node Visit(VariableReferenceExpression variableReferenceExpression) { var expression = (Expression)base.Visit(variableReferenceExpression); return ProcessExpression(expression); }
/// <summary> /// Analyse the MethodInvocationExpression, link to the base calls, remove "this" from virtual calls, store in the correct list for later analysis /// </summary> /// <param name="expression">the method expression</param> /// <param name="methodName">the method name</param> /// <param name="declarations">the special declarations</param> protected override void ProcessMethodInvocation(MethodInvocationExpression expression, string methodName, List<IDeclaration> declarations) { bool callBaseProcessMethodInvocation = true; bool isNotBaseCall = true; // check if it is a base/this invocation var memberReferenceExpression = expression.Target as MemberReferenceExpression; if (memberReferenceExpression != null) { var variableReferenceExpression = memberReferenceExpression.Target as VariableReferenceExpression; if (variableReferenceExpression != null) { switch (variableReferenceExpression.Name.Text) { case "base": { parsingInfo.BaseMethodCalls.Add(expression); isNotBaseCall = false; callBaseProcessMethodInvocation = false; // get a base method declaration MethodDeclaration baseMethod = null; foreach (var mixin in analyzedModuleMixin.InheritanceList) { baseMethod = mixin.LocalVirtualTable.Methods.Select(x => x.Method).FirstOrDefault(x => x.IsSameSignature(expression)); if (baseMethod != null) break; } if (baseMethod == null) baseMethod = analyzedModuleMixin.LocalVirtualTable.Methods.Select(x => x.Method).FirstOrDefault(x => x.IsSameSignature(expression)); if (baseMethod != null) { expression.TypeInference.TargetType = baseMethod.ReturnType.ResolveType(); expression.Target.TypeInference.Declaration = baseMethod; } else Error(XenkoMessageCode.ErrorImpossibleBaseCall, memberReferenceExpression.Span, expression, analyzedModuleMixin.MixinName); break; } case "this": { // remove "this" keyword var vre = new VariableReferenceExpression(memberReferenceExpression.Member); expression.Target = vre; callBaseProcessMethodInvocation = false; // get top method declaration var topMethod = analyzedModuleMixin.VirtualTable.Methods.Select(x => x.Method).FirstOrDefault(x => x.IsSameSignature(expression)); if (topMethod != null) { expression.TypeInference.TargetType = topMethod.ReturnType.ResolveType(); expression.Target.TypeInference.Declaration = topMethod; } else Error(XenkoMessageCode.ErrorImpossibleVirtualCall, memberReferenceExpression.Span, expression, analyzedModuleMixin.MixinName, analyzedModuleMixin.MixinName); memberReferenceExpression = null; break; } } } if (expression.Target is MemberReferenceExpression) { var typeCall = (expression.Target as MemberReferenceExpression).Target.TypeInference.TargetType; if (typeCall is ShaderClassType) declarations.AddRange(FindDeclarationsFromObject(typeCall, memberReferenceExpression.Member)); } } // call base if (callBaseProcessMethodInvocation) base.ProcessMethodInvocation(expression, methodName, declarations); var methodDecl = expression.Target.TypeInference.Declaration as MethodDeclaration; var isBuiltIn = true; if (methodDecl != null) { // check if it is a recursive call if (ReferenceEquals(currentVisitedMethod, expression.Target.TypeInference.Declaration)) // How to handle "this" keyword? Error(XenkoMessageCode.ErrorCyclicMethod, currentVisitedMethod.Span, currentVisitedMethod, analyzedModuleMixin.MixinName); // check if it is a build-in method isBuiltIn = !methodDecl.ContainsTag(XenkoTags.ShaderScope); if (memberReferenceExpression != null) { var varDecl = memberReferenceExpression.Target.TypeInference.Declaration as Variable; if (memberReferenceExpression.Target is IndexerExpression) varDecl = (memberReferenceExpression.Target as IndexerExpression).Target.TypeInference.Declaration as Variable; if (varDecl != null && varDecl.Qualifiers.Contains(StorageQualifier.Extern)) { if (IsStageInitMember(memberReferenceExpression)) expression.SetTag(XenkoTags.StageInitRef, null); else expression.SetTag(XenkoTags.ExternRef, null); } var shaderDecl = memberReferenceExpression.Target.TypeInference.Declaration as ShaderClassType; if (shaderDecl != null && shaderDecl != analyzedModuleMixin.Shader && analyzedModuleMixin.InheritanceList.All(x => x.Shader != shaderDecl)) expression.SetTag(XenkoTags.StaticRef, null); } if (!isBuiltIn) { // store if not a base call if (isNotBaseCall && !expression.ContainsTag(XenkoTags.ExternRef) && !expression.ContainsTag(XenkoTags.StageInitRef) && !expression.ContainsTag(XenkoTags.StaticRef)) parsingInfo.ThisMethodCalls.Add(expression); if (methodDecl.Qualifiers.Contains(XenkoStorageQualifier.Stage)) parsingInfo.StageMethodCalls.Add(expression); } } }
/// <summary> /// Generates a stream structure and add them to the Ast - for the geometry shader /// </summary> /// <param name="entryPoint">the entrypoint function</param> /// <param name="streamStageUsage">the stream usage in this stage</param> /// <param name="stageName">the name of the stage</param> /// <param name="prevOuputStructure">the output structutre from the previous stage</param> /// <returns>the new output structure</returns> private StructType GenerateStreamsWithSpecialDataInput(MethodDefinition entryPoint, StreamStageUsage streamStageUsage, string stageName, StructType prevOuputStructure) { if (entryPoint != null) { var inStreamStruct = prevOuputStructure ?? CreateStreamStructure(streamStageUsage.InStreamList, stageName + "_INPUT"); var outStreamStruct = CreateStreamStructure(streamStageUsage.OutStreamList, stageName + "_OUTPUT"); var mixin = entryPoint.GetTag(ParadoxTags.ShaderScope) as ModuleMixin; var intermediateStreamStruct = CreateIntermediateStructType(streamStageUsage, stageName); // put the streams declaration at the beginning of the method body var streamsDeclaration = new DeclarationStatement(new Variable(new TypeName(intermediateStreamStruct.Name), "streams") { InitialValue = new CastExpression { From = new LiteralExpression(0), Target = new TypeName(intermediateStreamStruct.Name) } }); entryPoint.Body.Insert(0, streamsDeclaration); // add the declaration statements to the entrypoint and fill with the values var outputStatements = CreateOutputFromStream(outStreamStruct, "output", intermediateStreamStruct, "streams").ToList(); var outputVre = new VariableReferenceExpression(((outputStatements.First() as DeclarationStatement).Content as Variable).Name); var replacor = new ParadoxReplaceAppend(streamAnalyzer.AppendMethodCalls, outputStatements, outputVre); ReplaceAppendMethod(entryPoint, replacor); var visitedMethods = new Stack<MethodDeclaration>(); var inStructType = new TypeName(inStreamStruct.Name); var outStructType = new TypeName(outStreamStruct.Name); RecursiveRename(entryPoint, inStructType, null, outStructType, null, visitedMethods); // explore all the called functions var streamsVisitedMethods = new HashSet<MethodDeclaration>(); var methodsWithStreams = new List<MethodDeclaration>(); PropagateStreamsParameter(entryPoint, inStreamStruct, intermediateStreamStruct, outStreamStruct, streamsVisitedMethods, methodsWithStreams); CheckCrossStageMethodCall(streamStageUsage.ShaderStage, methodsWithStreams); if (prevOuputStructure == null) shader.Members.Insert(0, inStreamStruct); shader.Members.Insert(0, outStreamStruct); shader.Members.Insert(0, intermediateStreamStruct); return outStreamStruct; } return prevOuputStructure; }
/// <summary> /// Analyse the VariableReferenceExpression, detects streams, propagate type inference, get stored in the correct list for later analysis /// </summary> /// <param name="variableReferenceExpression">the VariableReferenceExpression</param> public override Node Visit(VariableReferenceExpression variableReferenceExpression) { // HACK: force types on base, this and stream keyword to eliminate errors in the log and use the standard type inference var name = variableReferenceExpression.Name.Text; if (name == "base") { variableReferenceExpression.TypeInference.Declaration = analyzedModuleMixin.Shader; variableReferenceExpression.TypeInference.TargetType = analyzedModuleMixin.Shader; return variableReferenceExpression; } if (name == "this") { variableReferenceExpression.TypeInference.Declaration = analyzedModuleMixin.Shader; variableReferenceExpression.TypeInference.TargetType = analyzedModuleMixin.Shader; return variableReferenceExpression; } if (name == "stage") { if (!(ParentNode is Variable && (ParentNode as Variable).InitialValue == variableReferenceExpression)) Error(XenkoMessageCode.ErrorStageOutsideVariable, ParentNode.Span, ParentNode, analyzedModuleMixin.MixinName); return variableReferenceExpression; } if (name == StreamsType.ThisStreams.Name.Text) { variableReferenceExpression.TypeInference.Declaration = StreamsType.ThisStreams; variableReferenceExpression.TypeInference.TargetType = StreamsType.ThisStreams.Type; } // check if the variable is double-defined if (!XenkoKeywords.Contains(variableReferenceExpression.Name.Text)) CheckNameConflict(variableReferenceExpression); base.Visit(variableReferenceExpression); var varDecl = variableReferenceExpression.TypeInference.Declaration as Variable; if (varDecl != null) { // because the parent classes do not do this all the time if (variableReferenceExpression.TypeInference.TargetType == null) variableReferenceExpression.TypeInference.TargetType = (variableReferenceExpression.TypeInference.Declaration as Variable).Type.ResolveType(); if (varDecl.ContainsTag(XenkoTags.ShaderScope)) { // stream variable should be called within the streams scope if (varDecl.Qualifiers.Contains(XenkoStorageQualifier.Stream) || varDecl.Qualifiers.Contains(XenkoStorageQualifier.PatchStream)) Error(XenkoMessageCode.ErrorMissingStreamsStruct, variableReferenceExpression.Span, variableReferenceExpression, analyzedModuleMixin.MixinName); } } var isMethodName = defaultDeclarations.Any(x => x.Name.Text == variableReferenceExpression.Name.Text); if (!XenkoKeywords.Contains(variableReferenceExpression.Name.Text) && variableReferenceExpression.TypeInference.Declaration == null && !inSampler && !isMethodName) Error(XenkoMessageCode.ErrorMissingVariable, variableReferenceExpression.Span, variableReferenceExpression, analyzedModuleMixin.MixinName); // update function static status if (!inSampler && !isMethodName && variableReferenceExpression.TypeInference.Declaration == null) Error(XenkoMessageCode.ErrorNoTypeInference, variableReferenceExpression.Span, variableReferenceExpression, analyzedModuleMixin.MixinName); if (currentVisitedMethod != null && currentVisitedMethod.Qualifiers.Contains(StorageQualifier.Static) && varDecl != null && varDecl.GetTag(XenkoTags.BaseDeclarationMixin) != null) Error(XenkoMessageCode.ErrorNonStaticReferenceInStaticMethod, variableReferenceExpression.Span, currentVisitedMethod, varDecl, analyzedModuleMixin.MixinName); // Add to the variables references list AddToVariablesReference(variableReferenceExpression); return variableReferenceExpression; }
private void Visit(VariableReferenceExpression variableReferenceExpression) { Visit((Node)variableReferenceExpression); CheckUsage(variableReferenceExpression.TypeInference.Declaration as Variable); }