コード例 #1
0
        // 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);
        }