// Creates an expression result by applying array indexers and swizzles, if present public static ExprResult ApplyModifiers(SSLVisitor vis, ExprResult res, SSLParser.ArrayIndexerContext actx, ITerminalNode swizzle) { bool hasa = (actx != null); bool hass = (swizzle != null); // This prevents duplication in the event that there is an ssa already, and there is no array indexer or swizzle if (res.HasSSA) { res = new ExprResult(res.Type, null, res.SSA.Name); } if (hasa) { var lim = res.IsArray ? res.ArraySize : res.Type.IsVectorType() ? res.Type.GetComponentCount() : ((res.Type == ShaderType.Mat2) ? 2u : (res.Type == ShaderType.Mat3) ? 3u : 4u); if (!vis.TryParseArrayIndexer(actx, (lim - 1, res.Type.IsMatrixType() ? lim - 1 : (uint?)null), out var aidx, out var error)) { vis.Error(actx, error); } if (res.IsArray) { if (aidx.Index2 != null) { vis.Error(actx, "Multi-dimensional arrays are not supported."); } res = new ExprResult(res.Type, null, $"{res.RefText}[{aidx.Index1.RefText}]"); } else if (res.Type.IsVectorType()) { if (aidx.Index2 != null) { vis.Error(actx, "Vectors cannot have more than one array indexer."); } res = new ExprResult(res.Type.GetComponentType(), null, $"{res.RefText}[{aidx.Index1.RefText}]"); } else if (res.Type.IsMatrixType()) { if (aidx.Index2 == null) { vis.Error(actx, "Matrices must have two array indexers to access their members."); } res = new ExprResult(ShaderType.Float, null, $"{res.RefText}[{aidx.Index1.RefText}][{aidx.Index2.RefText}]"); } else { vis.Error(actx, "The preceeding expression cannot have array indexers applied to it."); } } if (hass) { if (!res.Type.IsVectorType()) { vis.Error(swizzle.Symbol, "Cannot apply a swizzle to a non-vector type."); } var stxt = swizzle.Symbol.Text.Substring(1); if (stxt.Length > 4) { vis.Error(swizzle.Symbol, "A swizzle cannot have more than four components."); } foreach (var swc in stxt) { if (!ReflectionUtils.IsSwizzleValid(res.Type, swc)) { vis.Error(swizzle.Symbol, $"The swizzle character '{swc}' is not valid for this type."); } } res = new ExprResult(res.Type.ToVectorType((uint)stxt.Length).Value, null, $"{res.RefText}.{stxt}"); } return(res); }