typeof-keyword.azsl 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. class getter
  2. {
  3. float2x2 fval();
  4. };
  5. class intermediate
  6. {
  7. getter getgetter();
  8. };
  9. class top
  10. {
  11. intermediate many[3];
  12. struct inner {};
  13. void innerfunc() {}
  14. };
  15. top gettop();
  16. class A
  17. {
  18. int a;
  19. };
  20. class B : A
  21. {
  22. };
  23. struct Half{};
  24. struct Double{};
  25. half returnThings(Half);
  26. double returnThings(Double);
  27. struct UniformFoo{};
  28. UniformFoo returnSame(int);
  29. UniformFoo returnSame(float1x1);
  30. struct S { int i; };
  31. ShaderResourceGroupSemantic freq
  32. { FrequencyId = 1; }
  33. ShaderResourceGroup MySRG : freq
  34. {
  35. // Buffer-views are chameleons mimicking "T[]" (collapsed to T in azslc)
  36. Buffer<float> m_buf;
  37. RasterizerOrderedBuffer<float> m_rob_f;
  38. RasterizerOrderedStructuredBuffer<struct R { int i; float f; }> m_rosb_R;
  39. struct Ext { R r; };
  40. RWStructuredBuffer<Ext> m_rwsb_E;
  41. RWBuffer<int4x2> m_rwb_i42;
  42. // CB is chameleon to "(one element of) type S"
  43. ConstantBuffer<S> m_cb_S;
  44. StructuredBuffer<S> m_sb_S;
  45. // SRG Constants
  46. int m_i; // scalar
  47. vector<float,2> m_vec_f2; // generic vector
  48. matrix<half,2,2> m_mat_h22; // generic matrix
  49. // other view types
  50. Sampler m_samp {};
  51. Texture2D m_tex;
  52. Texture2D<float4> m_tex_f4;
  53. };
  54. void h()
  55. {
  56. // typeof exists to support the seenat feature.
  57. // therefore the only accepted parameters are dependencies of idExpressions: idExpressions and MemberAccessExpression.
  58. // at level 2, MemberAccessExpression depends on 'expression' but only a subset can return UserDefinedType.
  59. //
  60. // supported:
  61. // idExpressions stuff::name
  62. // MemberAccessExpression stuff.name
  63. // FunctionCallExpression stuff()
  64. // ArrayIndexExpression stuff[i]
  65. // ParenthesizedExpression (stuff)
  66. // CastExpression (stuff)thing
  67. // ConditionalExpression stuff ? thenthat : otherwisethat
  68. // AssignmentExpression stuff = thing
  69. // NumericConstructorExpression float2(0,0)
  70. // LiteralExpression 42
  71. // CommaExpression X, Y
  72. // PostfixUnaryExpression i++
  73. // PrefixUnaryExpression ++i
  74. // BinaryExpression i + j
  75. // mathematics
  76. __azslc_print_message("@check predicate ");
  77. __azslc_print_symbol(typeof(1 + 3), __azslc_prtsym_least_qualified);
  78. __azslc_print_message(" == 'int'\n");
  79. // literals
  80. __azslc_print_message("@check predicate ");
  81. __azslc_print_symbol(typeof(1), __azslc_prtsym_least_qualified);
  82. __azslc_print_message(" == 'int'\n");
  83. __azslc_print_message("@check predicate ");
  84. __azslc_print_symbol(typeof(1u), __azslc_prtsym_least_qualified);
  85. __azslc_print_message(" == 'uint'\n");
  86. __azslc_print_message("@check predicate ");
  87. __azslc_print_symbol(typeof(1l), __azslc_prtsym_least_qualified);
  88. __azslc_print_message(" == 'int'\n");
  89. __azslc_print_message("@check predicate ");
  90. __azslc_print_symbol(typeof(1ul), __azslc_prtsym_least_qualified);
  91. __azslc_print_message(" == 'uint'\n");
  92. __azslc_print_message("@check predicate ");
  93. __azslc_print_symbol(typeof(1lu), __azslc_prtsym_least_qualified);
  94. __azslc_print_message(" == 'uint'\n");
  95. __azslc_print_message("@check predicate ");
  96. __azslc_print_symbol(typeof(1.0), __azslc_prtsym_least_qualified);
  97. __azslc_print_message(" == 'float'\n");
  98. __azslc_print_message("@check predicate ");
  99. __azslc_print_symbol(typeof(1.0f), __azslc_prtsym_least_qualified);
  100. __azslc_print_message(" == 'float'\n");
  101. __azslc_print_message("@check predicate ");
  102. __azslc_print_symbol(typeof(1.h), __azslc_prtsym_least_qualified);
  103. __azslc_print_message(" == 'half'\n");
  104. __azslc_print_message("@check predicate ");
  105. __azslc_print_symbol(typeof(1.H), __azslc_prtsym_least_qualified);
  106. __azslc_print_message(" == 'half'\n");
  107. __azslc_print_message("@check predicate ");
  108. __azslc_print_symbol(typeof(1.0L), __azslc_prtsym_least_qualified);
  109. __azslc_print_message(" == 'double'\n");
  110. __azslc_print_message("@check predicate ");
  111. __azslc_print_symbol(typeof(true), __azslc_prtsym_least_qualified);
  112. __azslc_print_message(" == 'bool'\n");
  113. __azslc_print_message("@check predicate ");
  114. __azslc_print_symbol(typeof(false), __azslc_prtsym_least_qualified);
  115. __azslc_print_message(" == 'bool'\n");
  116. __azslc_print_message("@check predicate ");
  117. __azslc_print_symbol(typeof("stuff"), __azslc_prtsym_least_qualified);
  118. __azslc_print_message(" == '<fail>'\n");
  119. // direct type (identity)
  120. __azslc_print_message("@check predicate ");
  121. __azslc_print_symbol(typeof(top), __azslc_prtsym_least_qualified);
  122. __azslc_print_message(" == 'top'\n");
  123. // same, as fully qualified
  124. __azslc_print_message("@check predicate ");
  125. __azslc_print_symbol(typeof(top), __azslc_prtsym_fully_qualified);
  126. __azslc_print_message(" == '/top'\n");
  127. float f;
  128. // local symbol
  129. __azslc_print_message("@check predicate ");
  130. __azslc_print_symbol(typeof(f), __azslc_prtsym_least_qualified);
  131. __azslc_print_message(" == 'float'\n");
  132. // same as fully qualified
  133. __azslc_print_message("@check predicate ");
  134. __azslc_print_symbol(typeof(f), __azslc_prtsym_fully_qualified);
  135. __azslc_print_message(" == '?float'\n");
  136. S s;
  137. // member access
  138. __azslc_print_message("@check predicate ");
  139. __azslc_print_symbol(typeof(s.i), __azslc_prtsym_least_qualified);
  140. __azslc_print_message(" == 'int'\n");
  141. // the qualified unevaluated-expression access can probably also be supported as a bonus:
  142. __azslc_print_message("@check predicate ");
  143. __azslc_print_symbol(typeof(S::i), __azslc_prtsym_least_qualified);
  144. __azslc_print_message(" == 'int'\n");
  145. // legit qualified id (just names a type directly):
  146. __azslc_print_message("@check predicate ");
  147. __azslc_print_symbol(typeof(top::inner), __azslc_prtsym_fully_qualified);
  148. __azslc_print_message(" == '/top/inner'\n");
  149. // class inheritance: parent member access using scope resolution operator
  150. __azslc_print_message("@check predicate ");
  151. __azslc_print_symbol(typeof(B::a), __azslc_prtsym_least_qualified);
  152. __azslc_print_message(" == 'int'\n");
  153. // function call, the return type is returned
  154. __azslc_print_message("@check predicate ");
  155. __azslc_print_symbol(typeof(gettop()), __azslc_prtsym_least_qualified);
  156. __azslc_print_message(" == 'top'\n");
  157. // function type is not a citizen in HLSL nor AZSL.
  158. // the typeof keyword thus simply returns the function symbol itself.
  159. __azslc_print_message("@check predicate ");
  160. __azslc_print_symbol(typeof(gettop), __azslc_prtsym_fully_qualified);
  161. __azslc_print_message(" == '/gettop()'\n"); // resolved to the unique concrete function candidate if no overloads
  162. __azslc_print_message("@check predicate ");
  163. __azslc_print_symbol(typeof(returnThings), __azslc_prtsym_fully_qualified);
  164. __azslc_print_message(" == '/returnThings'\n"); // but remains undetermined in case of the presence of overloads
  165. __azslc_print_message("@check predicate ");
  166. __azslc_print_symbol(typeof(top::innerfunc), __azslc_prtsym_least_qualified);
  167. __azslc_print_message(" == 'top/innerfunc'\n"); // least qualification removes the argument mangling.
  168. __azslc_print_message("@check predicate ");
  169. __azslc_print_symbol(typeof(top::innerfunc), __azslc_prtsym_fully_qualified);
  170. __azslc_print_message(" == '/top/innerfunc()'\n"); // full qualification preserves them
  171. // though call expression should work (this is not a compound because that function reference is an idExpression, be it qualified or not)
  172. __azslc_print_message("@check predicate ");
  173. __azslc_print_symbol(typeof(top::innerfunc()), __azslc_prtsym_least_qualified);
  174. __azslc_print_message(" == 'void'\n");
  175. // overloaded calls also work as long as the resolve of arguments is possible, or the overloadSet has a uniform return type
  176. // resolved arguments
  177. __azslc_print_message("@check predicate ");
  178. __azslc_print_symbol(typeof(returnThings((Half)0)), __azslc_prtsym_least_qualified);
  179. __azslc_print_message(" == 'half'\n");
  180. __azslc_print_message("@check predicate ");
  181. __azslc_print_symbol(typeof(returnThings((Double)0)), __azslc_prtsym_least_qualified);
  182. __azslc_print_message(" == 'double'\n");
  183. // unresolved arguments
  184. __azslc_print_message("@check predicate ");
  185. __azslc_print_symbol(typeof(returnSame(0+0)), __azslc_prtsym_least_qualified);
  186. __azslc_print_message(" == 'UniformFoo'\n");
  187. __azslc_print_message("@check predicate ");
  188. __azslc_print_symbol(typeof(returnSame((float1x1)0+(float1x1)0)), __azslc_prtsym_least_qualified);
  189. __azslc_print_message(" == 'UniformFoo'\n");
  190. // array index
  191. __azslc_print_message("@check predicate ");
  192. __azslc_print_symbol(typeof(top::many[1]), __azslc_prtsym_least_qualified);
  193. __azslc_print_message(" == 'intermediate'\n");
  194. // compound: member access + (function call & array index)
  195. __azslc_print_message("@check predicate ");
  196. __azslc_print_symbol(typeof(gettop().many[1]), __azslc_prtsym_least_qualified);
  197. __azslc_print_message(" == 'intermediate'\n");
  198. // for now array-types are coalesced to their underlying type
  199. __azslc_print_message("@check predicate ");
  200. __azslc_print_symbol(typeof(top::many), __azslc_prtsym_least_qualified);
  201. __azslc_print_message(" == 'intermediate'\n");
  202. // ultimate compound
  203. __azslc_print_message("@check predicate ");
  204. __azslc_print_symbol(typeof(gettop().many[1].getgetter().fval()), __azslc_prtsym_least_qualified);
  205. __azslc_print_message(" == 'float2x2'\n");
  206. // ultimate compound with over-qualification in the middle
  207. __azslc_print_message("@check predicate ");
  208. __azslc_print_symbol(typeof(gettop().top::many[1].getgetter().fval()), __azslc_prtsym_least_qualified);
  209. __azslc_print_message(" == 'float2x2'\n");
  210. // ultimate compound with full qualification in the middle
  211. __azslc_print_message("@check predicate ");
  212. __azslc_print_symbol(typeof(gettop().::top::many[1].getgetter().fval()), __azslc_prtsym_least_qualified);
  213. __azslc_print_message(" == 'float2x2'\n");
  214. // check what's going on with generic predefineds
  215. // SRG Constants
  216. // == check chameleon types ==
  217. // chameleon= have a generic type as parameter, but end up being a forward for its behavior. (like typedef)
  218. // typeof can't see the non-canonicalized type. So we lose the original chameleon type, and all we "see" is its mimicked type: the canonical type.
  219. // from SRG references
  220. // plain Buffer<>
  221. __azslc_print_message("@check predicate ");
  222. __azslc_print_symbol(typeof(MySRG::m_buf), __azslc_prtsym_least_qualified);
  223. __azslc_print_message(" == 'float'\n"); // this is really a Buffer<float> but we see float.
  224. // ROB in SRG
  225. __azslc_print_message("@check predicate ");
  226. __azslc_print_symbol(typeof(MySRG::m_rob_f), __azslc_prtsym_least_qualified);
  227. __azslc_print_message(" == 'float'\n");
  228. // ROSB in SRG
  229. __azslc_print_message("@check predicate ");
  230. __azslc_print_symbol(typeof(MySRG::m_rosb_R), __azslc_prtsym_least_qualified);
  231. __azslc_print_message(" == 'MySRG/R'\n");
  232. // RWB in SRG
  233. __azslc_print_message("@check predicate ");
  234. __azslc_print_symbol(typeof(MySRG::m_rwb_i42), __azslc_prtsym_least_qualified);
  235. __azslc_print_message(" == 'int4x2'\n");
  236. // RWSB in SRG
  237. __azslc_print_message("@check predicate ");
  238. __azslc_print_symbol(typeof(MySRG::m_rwsb_E), __azslc_prtsym_least_qualified);
  239. __azslc_print_message(" == 'MySRG/Ext'\n"); // this is really a RWStructuredBuffer<Ext> but we see Ext.
  240. // SB in SRG
  241. __azslc_print_message("@check predicate ");
  242. __azslc_print_symbol(typeof(MySRG::m_sb_S), __azslc_prtsym_least_qualified);
  243. __azslc_print_message(" == 'S'\n");
  244. // CB
  245. __azslc_print_message("@check predicate ");
  246. __azslc_print_symbol(typeof(MySRG::m_cb_S), __azslc_prtsym_least_qualified);
  247. __azslc_print_message(" == 'S'\n");
  248. // int
  249. __azslc_print_message("@check predicate ");
  250. __azslc_print_symbol(typeof(MySRG::m_i), __azslc_prtsym_least_qualified);
  251. __azslc_print_message(" == 'int'\n");
  252. // vector<float,2> m_vec_f2;
  253. __azslc_print_message("@check predicate ");
  254. __azslc_print_symbol(typeof(MySRG::m_vec_f2), __azslc_prtsym_least_qualified);
  255. //__azslc_print_message(" == 'float2'\n"); // canonicalized form // WIP
  256. __azslc_print_message(" == 'vector'\n");
  257. // matrix<half,2,2> m_mat_h22;
  258. __azslc_print_message("@check predicate ");
  259. __azslc_print_symbol(typeof(MySRG::m_mat_h22), __azslc_prtsym_least_qualified);
  260. //__azslc_print_message(" == 'half2x2'\n"); // WIP
  261. __azslc_print_message(" == 'matrix'\n"); // for now it returns the core type since I didn't create the canonicalization system for GenericArithmetic
  262. // other view types
  263. // Sampler m_samp;
  264. __azslc_print_message("@check predicate ");
  265. __azslc_print_symbol(typeof(MySRG::m_samp), __azslc_prtsym_least_qualified);
  266. __azslc_print_message(" == 'Sampler'\n");
  267. // Texture2D m_tex;
  268. __azslc_print_message("@check predicate ");
  269. __azslc_print_symbol(typeof(MySRG::m_tex), __azslc_prtsym_least_qualified);
  270. __azslc_print_message(" == 'Texture2D'\n");
  271. // Texture2D<float4> m_tex_f4;
  272. __azslc_print_message("@check predicate ");
  273. __azslc_print_symbol(typeof(MySRG::m_tex_f4), __azslc_prtsym_least_qualified);
  274. __azslc_print_message(" == 'Texture2D'\n"); // texture generic types are ignored
  275. // fail get test
  276. __azslc_print_message("@check predicate ");
  277. __azslc_print_symbol(typeof(MySRG::inexistent), __azslc_prtsym_least_qualified);
  278. __azslc_print_message(" == '<fail>'\n");
  279. // from local references (local view-data-types don't have extern binding. they are pure aliases.)
  280. RasterizerOrderedBuffer<float> rob_f;
  281. RasterizerOrderedStructuredBuffer<struct R { int i; float f; }> rosb_R;
  282. struct Ext { R r; }; // using R here is possible in azsl; because above generic clause is not hygienic in the Kohlbecker sense.
  283. RWStructuredBuffer<Ext> rwsb_E;
  284. RWBuffer<int4x2> rwb_i42;
  285. StructuredBuffer<S> sb_S;
  286. vector<float,2> vec_f2;
  287. matrix<half,2,2> mat_h22;
  288. // ROB
  289. __azslc_print_message("@check predicate ");
  290. __azslc_print_symbol(typeof(rob_f), __azslc_prtsym_least_qualified);
  291. __azslc_print_message(" == 'float'\n");
  292. // ROSB
  293. __azslc_print_message("@check predicate ");
  294. __azslc_print_symbol(typeof(rosb_R), __azslc_prtsym_least_qualified);
  295. __azslc_print_message(" == 'R'\n"); // R refers to the 'struct R' passed in rosb_R generic parameter.
  296. // RWB
  297. __azslc_print_message("@check predicate ");
  298. __azslc_print_symbol(typeof(rwb_i42), __azslc_prtsym_least_qualified);
  299. __azslc_print_message(" == 'int4x2'\n");
  300. // RWSB
  301. __azslc_print_message("@check predicate ");
  302. __azslc_print_symbol(typeof(rwsb_E), __azslc_prtsym_least_qualified);
  303. __azslc_print_message(" == 'Ext'\n");
  304. // SB
  305. __azslc_print_message("@check predicate ");
  306. __azslc_print_symbol(typeof(sb_S), __azslc_prtsym_least_qualified);
  307. __azslc_print_message(" == 'S'\n");
  308. // generic vector
  309. __azslc_print_message("@check predicate ");
  310. __azslc_print_symbol(typeof(vec_f2), __azslc_prtsym_least_qualified);
  311. //__azslc_print_message(" == 'float2'\n"); // canonicalized form // WIP
  312. __azslc_print_message(" == 'vector'\n");
  313. // generic matrix
  314. __azslc_print_message("@check predicate ");
  315. __azslc_print_symbol(typeof(mat_h22), __azslc_prtsym_least_qualified);
  316. //__azslc_print_message(" == 'half2x2'\n"); // WIP
  317. __azslc_print_message(" == 'matrix'\n");
  318. // == end check chameleon types ==
  319. // simple (already canonical) vector
  320. half3 h3;
  321. __azslc_print_message("@check predicate ");
  322. __azslc_print_symbol(typeof(h3), __azslc_prtsym_least_qualified);
  323. __azslc_print_message(" == 'half3'\n");
  324. // cast
  325. __azslc_print_message("@check predicate ");
  326. __azslc_print_symbol(typeof((top)0), __azslc_prtsym_fully_qualified);
  327. __azslc_print_message(" == '/top'\n");
  328. // conditional
  329. __azslc_print_message("@check predicate ");
  330. __azslc_print_symbol(typeof(true ? (int)1 : (int)2), __azslc_prtsym_least_qualified);
  331. __azslc_print_message(" == 'int'\n");
  332. // parenthesis
  333. __azslc_print_message("@check predicate ");
  334. __azslc_print_symbol(typeof((s.i)), __azslc_prtsym_least_qualified);
  335. __azslc_print_message(" == 'int'\n");
  336. // cast compounded with typeof
  337. __azslc_print_message("@check predicate ");
  338. __azslc_print_symbol(typeof( (typeof(s.i))0 ), __azslc_prtsym_least_qualified);
  339. __azslc_print_message(" == 'int'\n");
  340. // numeric constructor expression
  341. __azslc_print_message("@check predicate ");
  342. __azslc_print_symbol(typeof(float2(0,0)), __azslc_prtsym_least_qualified);
  343. __azslc_print_message(" == 'float2'\n");
  344. __azslc_print_message("@check predicate ");
  345. __azslc_print_symbol(typeof(uint(0)), __azslc_prtsym_least_qualified);
  346. __azslc_print_message(" == 'uint'\n");
  347. __azslc_print_message("@check predicate ");
  348. __azslc_print_symbol(typeof(uint()), __azslc_prtsym_least_qualified);
  349. __azslc_print_message(" == 'uint'\n");
  350. // comma expression:
  351. int INTVAR;
  352. double DOUBLEVAR;
  353. __azslc_print_message("@check predicate ");
  354. __azslc_print_symbol(typeof(INTVAR, INTVAR, DOUBLEVAR), __azslc_prtsym_least_qualified);
  355. __azslc_print_message(" == 'double'\n");
  356. // binary arithmetic expression
  357. __azslc_print_message("@check predicate ");
  358. __azslc_print_symbol(typeof(1 + 1), __azslc_prtsym_least_qualified);
  359. __azslc_print_message(" == 'int'\n");
  360. // with float promotion
  361. __azslc_print_message("@check predicate ");
  362. __azslc_print_symbol(typeof(1 + 1.f), __azslc_prtsym_least_qualified);
  363. __azslc_print_message(" == 'float'\n");
  364. // with half promotion
  365. __azslc_print_message("@check predicate ");
  366. __azslc_print_symbol(typeof(1 + 1.h), __azslc_prtsym_least_qualified);
  367. __azslc_print_message(" == 'half'\n");
  368. // half and float to float promotion
  369. __azslc_print_message("@check predicate ");
  370. __azslc_print_symbol(typeof(1.f + 1.h), __azslc_prtsym_least_qualified);
  371. __azslc_print_message(" == 'float'\n");
  372. // int16_t to double promotion
  373. __azslc_print_message("@check predicate ");
  374. __azslc_print_symbol(typeof(1.l + int16_t(1)), __azslc_prtsym_least_qualified);
  375. __azslc_print_message(" == 'double'\n");
  376. // bool binary
  377. __azslc_print_message("@check predicate ");
  378. __azslc_print_symbol(typeof(1.l && int16_t(1)), __azslc_prtsym_least_qualified);
  379. __azslc_print_message(" == 'bool'\n");
  380. // lookedup
  381. double d;
  382. int64_t i64;
  383. __azslc_print_message("@check predicate ");
  384. __azslc_print_symbol(typeof(d || i64), __azslc_prtsym_least_qualified);
  385. __azslc_print_message(" == 'bool'\n");
  386. __azslc_print_message("@check predicate ");
  387. __azslc_print_symbol(typeof(d - i64), __azslc_prtsym_least_qualified);
  388. __azslc_print_message(" == 'double'\n");
  389. // vector scalar
  390. float4 f4;
  391. __azslc_print_message("@check predicate ");
  392. __azslc_print_symbol(typeof(2.f * f4), __azslc_prtsym_least_qualified);
  393. __azslc_print_message(" == 'float4'\n");
  394. __azslc_print_message("@check predicate ");
  395. __azslc_print_symbol(typeof(f4 * 2.f), __azslc_prtsym_least_qualified);
  396. __azslc_print_message(" == 'float4'\n");
  397. __azslc_print_message("@check predicate ");
  398. __azslc_print_symbol(typeof(d * f4), __azslc_prtsym_least_qualified);
  399. __azslc_print_message(" == 'double4'\n");
  400. __azslc_print_message("@check predicate ");
  401. __azslc_print_symbol(typeof(f4 * d), __azslc_prtsym_least_qualified);
  402. __azslc_print_message(" == 'double4'\n");
  403. // matrix scalar
  404. __azslc_print_message("@check predicate ");
  405. __azslc_print_symbol(typeof(float() * float3x2()), __azslc_prtsym_least_qualified);
  406. __azslc_print_message(" == 'float3x2'\n");
  407. // matrix scalar with base type promotion
  408. __azslc_print_message("@check predicate ");
  409. __azslc_print_symbol(typeof(half3x2() * double()), __azslc_prtsym_least_qualified);
  410. __azslc_print_message(" == 'double3x2'\n");
  411. // truncations
  412. __azslc_print_message("@check predicate ");
  413. __azslc_print_symbol(typeof(float3() * float2()), __azslc_prtsym_least_qualified);
  414. __azslc_print_message(" == 'float2'\n");
  415. __azslc_print_message("@check predicate ");
  416. __azslc_print_symbol(typeof(float4x4() * float2x2()), __azslc_prtsym_least_qualified);
  417. __azslc_print_message(" == 'float2x2'\n");
  418. // truncate & upcast
  419. __azslc_print_message("@check predicate ");
  420. __azslc_print_symbol(typeof(float4x4() * double2x2()), __azslc_prtsym_least_qualified);
  421. __azslc_print_message(" == 'double2x2'\n");
  422. // through alias
  423. typealias d34m = double3x4;
  424. typealias real = half;
  425. __azslc_print_message("@check predicate ");
  426. __azslc_print_symbol(typeof((d34m)0 * (real)0), __azslc_prtsym_least_qualified);
  427. __azslc_print_message(" == 'double3x4'\n");
  428. // note: the parser takes d32m() as a function call, this is the "most verxing parse" problem
  429. // float() is understood by the parser as a NumericConstructorExpression because it
  430. // has a list of the tokens representing all fundamental types.
  431. // but, with user defined identifiers, it can't branch into the "intended" context,
  432. // because ALL(*) Antlr4 parsers recognizes context free grammar only.
  433. // We could adopt a universal construction syntax Obj{} a la C++ for AZSL but it's not
  434. // compliant with the philosophy of not deviating from HLSL, which on its side doesn't really
  435. // accept constructor-type constructs. DXC just does it better here because clang parser is Turing complete.
  436. d34m d34var;
  437. real rVar;
  438. __azslc_print_message("@check predicate ");
  439. __azslc_print_symbol(typeof(rVar - d34var ), __azslc_prtsym_least_qualified);
  440. __azslc_print_message(" == 'double3x4'\n");
  441. }