internal static Variable FromContext(SSLParser.VariableDeclarationContext ctx, SSLVisitor vis, VariableScope scope) { var name = ctx.Name.Text; if (name[0] == '$') { vis.Error(ctx, "Cannot start a variable with the character '$', this is reserved for built-in variables."); } if (name.Length > 32) { vis.Error(ctx, "Variable names cannot be longer than 32 characters."); } if (ctx.KW_FLAT() != null && scope != VariableScope.Internal) { vis.Error(ctx, "'flat' qualifier is only valid for internals."); } var type = ReflectionUtils.TranslateTypeContext(ctx.type()); if (!type.HasValue) { vis.Error(ctx, $"Unable to convert variable '{name}' to internal type."); } if (type.Value == ShaderType.Void) { vis.Error(ctx, $"The variable '{name}' cannot be of type 'void'."); } uint?asize = null; if (ctx.arrayIndexer() != null) { if (!vis.TryParseArrayIndexer(ctx.arrayIndexer(), (null, null), out var aidx, out var error)) { vis.Error(ctx.arrayIndexer(), error); } if (aidx.Index2 != null) { vis.Error(ctx.arrayIndexer(), "Cannot declare multi-dimensional arrays."); } if (!aidx.Index1.GetIntegerLiteral().HasValue) // Must be a literal (OR A SPEC CONSTANT TODO) { vis.Error(ctx.arrayIndexer(), "Must use integer literals when declaring arrays."); } asize = (uint)aidx.Index1.GetIntegerLiteral().Value; if (asize.Value > 255) { vis.Error(ctx.arrayIndexer(), "Cannot declare arrays larger than 255."); } } return(new Variable(type.Value, name, scope, false, asize, flat: (ctx.KW_FLAT() != null))); }
// 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); }