Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
ShaderVirtualTable.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System.Collections.Generic;
4 using System.Linq;
5 
6 using SiliconStudio.Paradox.Shaders.Parser.Ast;
7 using SiliconStudio.Paradox.Shaders.Parser.Utility;
8 using SiliconStudio.Shaders.Ast;
9 using SiliconStudio.Shaders.Utility;
10 
11 namespace SiliconStudio.Paradox.Shaders.Parser.Mixins
12 {
13  internal class ShaderVirtualTable
14  {
15  #region Public member
16 
17  public Dictionary<string, MethodDeclaration[]> VirtualTableGroup = new Dictionary<string, MethodDeclaration[]>();
18 
19  #endregion
20 
21  #region Constructor
22 
23  public ShaderVirtualTable() {}
24 
25  #endregion
26 
27  #region Public methods
28 
29  /// <summary>
30  /// Adds the virtual table of the mixin
31  /// </summary>
32  /// <param name="shaderVirtualTable"></param>
33  /// <param name="className"></param>
34  /// <param name="errorLogger"></param>
35  public void AddVirtualTable(ShaderVirtualTable shaderVirtualTable, string className, LoggerResult errorLogger)
36  {
37  var newVT = shaderVirtualTable.VirtualTableGroup[className].ToArray();
38  VirtualTableGroup.Add(className, newVT);
39 
40  foreach (var methodDecl in newVT)
41  ReplaceVirtualMethod(methodDecl, errorLogger);
42  }
43 
44  /// <summary>
45  /// Replace the method occurence with its last definition
46  /// </summary>
47  /// <param name="methodDeclaration">the overriding method</param>
48  /// <param name="errorLogger"></param>
49  public void ReplaceVirtualMethod(MethodDeclaration methodDeclaration, LoggerResult errorLogger)
50  {
51  var baseDeclarationMixin = (string)methodDeclaration.GetTag(ParadoxTags.BaseDeclarationMixin);
52  foreach (var dict in VirtualTableGroup.Select(x => x.Value))
53  {
54  for (int i = 0; i < dict.Length; ++i)
55  {
56  var method = dict[i];
57  var originalDecl = (string)method.GetTag(ParadoxTags.BaseDeclarationMixin);
58 
59  // TODO: take typedefs into account...
60  if (originalDecl == baseDeclarationMixin && method.IsSameSignature(methodDeclaration))
61  {
62  if (method.Qualifiers.Contains(ParadoxStorageQualifier.Stage) && !methodDeclaration.Qualifiers.Contains(ParadoxStorageQualifier.Stage))
63  {
64  errorLogger.Warning(ParadoxMessageCode.WarningMissingStageKeyword, methodDeclaration.Span, methodDeclaration, (methodDeclaration.GetTag(ParadoxTags.ShaderScope) as ModuleMixin).MixinName);
65  methodDeclaration.Qualifiers |= ParadoxStorageQualifier.Stage;
66  }
67  else if (!method.Qualifiers.Contains(ParadoxStorageQualifier.Stage) && methodDeclaration.Qualifiers.Contains(ParadoxStorageQualifier.Stage))
68  {
69  errorLogger.Error(ParadoxMessageCode.ErrorExtraStageKeyword, methodDeclaration.Span, methodDeclaration, method, (methodDeclaration.GetTag(ParadoxTags.ShaderScope) as ModuleMixin).MixinName);
70  methodDeclaration.Qualifiers.Values.Remove(ParadoxStorageQualifier.Stage);
71  }
72 
73  dict[i] = methodDeclaration;
74  }
75  }
76  }
77  }
78 
79  /// <summary>
80  /// Adds the methods defined in the final mixin
81  /// </summary>
82  /// <param name="methodDeclarations">a list of MethodDeclaration</param>
83  /// <param name="className">the name of the class</param>
84  /// <param name="errorLogger">the logger for errors and warnings</param>
85  public void AddFinalDeclarations(List<MethodDeclaration> methodDeclarations, string className, LoggerResult errorLogger)
86  {
87  var finalDict = new MethodDeclaration[methodDeclarations.Count];
88  foreach (var methodDecl in methodDeclarations)
89  {
90  var vtableReference = (VTableReference)methodDecl.GetTag(ParadoxTags.VirtualTableReference);
91  finalDict[vtableReference.Slot] = methodDecl;
92 
93  // TODO: override/abstract behavior
94  //if (methodDecl.Qualifiers.Contains(ParadoxStorageQualifier.Override))
95  LookForBaseDeclarationMixin(methodDecl, errorLogger);
96  }
97 
98  VirtualTableGroup.Add(className, finalDict);
99  }
100 
101  /// <summary>
102  /// Finds the location of the method in the virtual table of its definition mixin
103  /// </summary>
104  /// <param name="methodDeclaration"></param>
105  /// <returns></returns>
106  public VTableReference GetBaseDeclaration(MethodDeclaration methodDeclaration)
107  {
108  var baseMethodDeclMixin = methodDeclaration.GetTag(ParadoxTags.BaseDeclarationMixin) as string;
109  var slot = -1;
110  var vt = VirtualTableGroup[baseMethodDeclMixin];
111  for (int i = 0; i < vt.Length; ++i)
112  {
113  if (methodDeclaration.IsSameSignature(vt[i]))
114  {
115  slot = i;
116  break;
117  }
118  }
119  return new VTableReference { Shader = baseMethodDeclMixin, Slot = slot };
120  }
121 
122  /// <summary>
123  /// Returns the method at the specified location
124  /// </summary>
125  /// <param name="mixinName">the sub virtual table</param>
126  /// <param name="slot">the slot index</param>
127  /// <returns>the method in the specified location</returns>
128  public MethodDeclaration GetMethod(string mixinName, int slot)
129  {
130  MethodDeclaration[] decls;
131  if (VirtualTableGroup.TryGetValue(mixinName, out decls))
132  {
133  if (decls.Length > slot)
134  return VirtualTableGroup[mixinName][slot];
135  }
136  return null;
137  }
138 
139  #endregion
140 
141  #region Private methods
142 
143  /// <summary>
144  /// Find the base definition of the method and override its occurence
145  /// </summary>
146  /// <param name="methodDeclaration"></param>
147  /// <param name="errorLogger"></param>
148  private void LookForBaseDeclarationMixin(MethodDeclaration methodDeclaration, LoggerResult errorLogger)
149  {
150  foreach (var dict in VirtualTableGroup.Select(x => x.Value))
151  {
152  for (int i = 0; i < dict.Length; ++i)
153  {
154  var method = dict[i];
155  var baseDeclarationMixin = (string)method.GetTag(ParadoxTags.BaseDeclarationMixin);
156 
157  // TODO: take typedefs into account...
158  if (method.IsSameSignature(methodDeclaration))
159  {
160  var sourceShader = ((ModuleMixin)methodDeclaration.GetTag(ParadoxTags.ShaderScope)).MixinName;
161 
162  // test override
163  if (methodDeclaration is MethodDefinition && method is MethodDefinition && !methodDeclaration.Qualifiers.Contains(ParadoxStorageQualifier.Override))
164  errorLogger.Error(ParadoxMessageCode.ErrorMissingOverride, method.Span, methodDeclaration, sourceShader);
165  if (!(methodDeclaration is MethodDefinition))
166  errorLogger.Error(ParadoxMessageCode.ErrorOverrindingDeclaration, method.Span, methodDeclaration, sourceShader);
167 
168  if (method.Qualifiers.Contains(ParadoxStorageQualifier.Stage) && !methodDeclaration.Qualifiers.Contains(ParadoxStorageQualifier.Stage))
169  {
170  errorLogger.Warning(ParadoxMessageCode.WarningMissingStageKeyword, methodDeclaration.Span, methodDeclaration, (methodDeclaration.GetTag(ParadoxTags.ShaderScope) as ModuleMixin).MixinName);
171  methodDeclaration.Qualifiers |= ParadoxStorageQualifier.Stage;
172  }
173  else if (!method.Qualifiers.Contains(ParadoxStorageQualifier.Stage) && methodDeclaration.Qualifiers.Contains(ParadoxStorageQualifier.Stage))
174  {
175  errorLogger.Error(ParadoxMessageCode.ErrorExtraStageKeyword, methodDeclaration.Span, methodDeclaration, method, (methodDeclaration.GetTag(ParadoxTags.ShaderScope) as ModuleMixin).MixinName);
176  methodDeclaration.Qualifiers.Values.Remove(ParadoxStorageQualifier.Stage);
177  }
178 
179  dict[i] = methodDeclaration;
180  methodDeclaration.SetTag(ParadoxTags.BaseDeclarationMixin, baseDeclarationMixin);
181  }
182  }
183  }
184  }
185 
186  #endregion
187  }
188 }
void Error(MessageCode message, SourceSpan span)
Logs an Error with the specified message.
Definition: LoggerResult.cs:75
A class to collect parsing/expression messages.
Definition: LoggerResult.cs:13
static readonly SiliconStudio.Shaders.Ast.StorageQualifier Override
Override keyword (override).
A method definition with a body of statements.
bool IsSameSignature(MethodDeclaration methodDeclaration)
Test if a method declaration has the same signature.
static readonly SiliconStudio.Shaders.Ast.StorageQualifier Stage
Stage keyword (stage).
Toplevel container of a shader parsing result.
Definition: Shader.cs:12
bool Contains(CompositeEnum enumValue)
Determines whether [contains] [the specified enum value].
Qualifier Qualifiers
Gets or sets the storage class.
object GetTag(object tagKey)
Gets a tag value associated to this node..
Definition: Node.cs:78