private static void EnsureSizeIfNotScalar(SSLVisitor vis, IToken token, string name, ShaderType vtype, ShaderType ctype, int vp, int cp)
 {
     if (!ctype.IsScalarType() && (ctype.GetComponentCount() != vtype.GetComponentCount()))
     {
         vis.Error(token, $"The built-in function '{name}' requires argument {cp} to be a scalar, or a matching vector size to argument {vp}.");
     }
 }
 private static void EnsureMatchingComponents(SSLVisitor vis, IToken token, string name, ShaderType a1c, ShaderType a2c, ShaderType a3c)
 {
     if (!a2c.CanPromoteTo(a1c))
     {
         vis.Error(token, $"The built-in function '{name}' requires a '{a1c}' compatible type for argument 2 (actual is '{a2c}').");
     }
     if ((a3c != ShaderType.Void) && !a3c.CanPromoteTo(a1c))
     {
         vis.Error(token, $"The built-in function '{name}' requires a '{a1c}' compatible type for argument 3 (actual is '{a3c}').");
     }
 }
Esempio n. 3
0
        public StandardFunction AddFunction(SSLParser.StandardFunctionContext ctx, SSLVisitor vis)
        {
            var func = StandardFunction.FromContext(ctx, vis);

            var pre = FindFunction(func.Name);

            if (pre != null)
            {
                vis.Error(ctx, $"A function with the name '{func.Name}' already exists in the shader.");
            }

            _functions.Add(func.Name, func);
            return(func);
        }
Esempio n. 4
0
        public Variable AddConstant(SSLParser.ConstantStatementContext ctx, SSLVisitor vis)
        {
            var v = Variable.FromConstant(ctx, vis);

            var pre = FindGlobal(v.Name);

            if (pre != null)
            {
                vis.Error(ctx, $"A variable with the name '{v.Name}' already exists in the global {v.Scope} context.");
            }

            _constants.Add(v.Name, v);
            return(v);
        }
Esempio n. 5
0
        private bool compile(CompileOptions options, SSLVisitor visitor, out CompileError error)
        {
            var finalPath = options.OutputPath ?? CompileOptions.MakeDefaultOutputPath(SourceFile) ?? Path.Combine(Directory.GetCurrentDirectory(), "shader.spv");

            bool hasVert = (ShaderInfo.Stages & ShaderStages.Vertex) > 0,
                 hasTesc = (ShaderInfo.Stages & ShaderStages.TessControl) > 0,
                 hasTese = (ShaderInfo.Stages & ShaderStages.TessEval) > 0,
                 hasGeom = (ShaderInfo.Stages & ShaderStages.Geometry) > 0,
                 hasFrag = (ShaderInfo.Stages & ShaderStages.Fragment) > 0;

            string vertPath = null, tescPath = null, tesePath = null, geomPath = null, fragPath = null;

            if (hasVert && !GLSLV.Compile(options, visitor.GLSL.GetGLSLOutput(ShaderStages.Vertex), ShaderStages.Vertex, out vertPath, out error))
            {
                return(false);
            }
            if (hasTesc && !GLSLV.Compile(options, visitor.GLSL.GetGLSLOutput(ShaderStages.TessControl), ShaderStages.TessControl, out tescPath, out error))
            {
                return(false);
            }
            if (hasTese && !GLSLV.Compile(options, visitor.GLSL.GetGLSLOutput(ShaderStages.TessEval), ShaderStages.TessEval, out tesePath, out error))
            {
                return(false);
            }
            if (hasGeom && !GLSLV.Compile(options, visitor.GLSL.GetGLSLOutput(ShaderStages.Geometry), ShaderStages.Geometry, out geomPath, out error))
            {
                return(false);
            }
            if (hasFrag && !GLSLV.Compile(options, visitor.GLSL.GetGLSLOutput(ShaderStages.Fragment), ShaderStages.Fragment, out fragPath, out error))
            {
                return(false);
            }

            // Link the files
            var linkOut = options.OptimizeBytecode ? Path.GetTempFileName() : finalPath;

            if (!SPIRVLink.Link(options, new[] { vertPath, tescPath, tesePath, geomPath, fragPath }, linkOut, out error))
            {
                return(false);
            }

            // Optimize the files
            if (options.OptimizeBytecode && !SPIRVOpt.Optimize(options, linkOut, finalPath, out error))
            {
                return(false);
            }

            error = null;
            return(true);
        }
 private static void EnsureVectorSizes(SSLVisitor vis, IToken token, string name, ShaderType a1t, ShaderType a2t, ShaderType a3t)
 {
     if ((a1t != ShaderType.Void) && (a2t != ShaderType.Void) && (a2t.GetComponentCount() != a1t.GetComponentCount()))
     {
         vis.Error(token, $"The built-in function '{name}' requires matching vector sizes for arguments 1 and 2.");
     }
     if ((a1t != ShaderType.Void) && (a3t != ShaderType.Void) && (a3t.GetComponentCount() != a1t.GetComponentCount()))
     {
         vis.Error(token, $"The built-in function '{name}' requires matching vector sizes for arguments 1 and 3.");
     }
     if ((a2t != ShaderType.Void) && (a3t != ShaderType.Void) && (a3t.GetComponentCount() != a2t.GetComponentCount()))
     {
         vis.Error(token, $"The built-in function '{name}' requires matching vector sizes for arguments 2 and 3.");
     }
 }
Esempio n. 7
0
        private bool outputRefl(CompileOptions options, SSLVisitor vis, out CompileError error)
        {
            error = null;
            var rPath = options.ReflectionPath ?? CompileOptions.MakeDefaultReflectionPath(SourceFile) ?? Path.Combine(Directory.GetCurrentDirectory(), "shader.refl");

            try
            {
                vis.Info.SaveToFile(rPath, options.UseBinaryReflection);
            }
            catch (Exception e)
            {
                error = new CompileError(ErrorSource.Output, 0, 0, $"Unable to generate reflection info: {e.Message}.");
            }

            return(error == null);
        }
        // Checks the arugments and return types for built in functions
        // Note: the visitor ensures that the correct number of args are present, we dont need to check that in this function
        public static ShaderType CheckBuiltinCall(SSLVisitor vis, IToken token, string name, int type, ExprResult[] args)
        {
            var btidx = Array.FindIndex(args, a => a.IsArray);

            if (btidx != -1)
            {
                vis.Error(token, $"Arguments to built-in functions cannot be arrays (arg {btidx+1}).");
            }

            ShaderType a1t = args[0].Type,
                       a2t = (args.Length > 1) ? args[1].Type : ShaderType.Void,
                       a3t = (args.Length > 2) ? args[2].Type : ShaderType.Void;
            ShaderType a1c = a1t.GetComponentType(),
                       a2c = a2t.GetComponentType(),
                       a3c = a3t.GetComponentType();

            if (type >= SSLParser.BIF_TEXSIZE && type <= SSLParser.BIF_TEXFETCH)             // Functions that deal with texture handles
            {
                if (!a1t.IsTextureType())
                {
                    vis.Error(token, $"The built-in function '{name}' requires a texture handle as argument 1.");
                }
                var tdim = a1t.GetTexelDim();

                if (type == SSLParser.BIF_TEXSIZE)
                {
                    return(ShaderType.Int.ToVectorType(tdim).Value);
                }
                else if (type == SSLParser.BIF_TEXTURE)
                {
                    if (!a2c.CanPromoteTo(ShaderType.Float))
                    {
                        vis.Error(token, $"The built-in function '{name}' requires a floating-point vector or scalar as argument 2.");
                    }
                    if (a2t.GetComponentCount() != tdim)
                    {
                        vis.Error(token, "The size of the texture access coordinates does not match the size of the texture.");
                    }
                }
                else
                {
                    if (a2c != ShaderType.Int)
                    {
                        vis.Error(token, $"The built-in function '{name}' requires integer texture coordinates.");
                    }
                    if (a2t.GetComponentCount() != tdim)
                    {
                        vis.Error(token, "The size of the texture access coordinates does not match the size of the texture.");
                    }
                }
                return(ShaderType.Float4);
            }
            else if (type >= SSLParser.BIF_IMAGESIZE && type <= SSLParser.BIF_IMAGESTORE)             // Functions that deal with image handles
            {
                if (!a1t.IsImageType())
                {
                    vis.Error(token, $"The built-in function '{name}' requires an image handle as argument 1.");
                }
                var tdim = a1t.GetTexelDim();

                if (type == SSLParser.BIF_IMAGESIZE)
                {
                    return(ShaderType.Int.ToVectorType(tdim).Value);
                }

                if (a2c != ShaderType.Int)
                {
                    vis.Error(token, $"The built-in function '{name}' requires integer texture coordinates.");
                }
                if (a2t.GetComponentCount() != tdim)
                {
                    vis.Error(token, "The size of the texture access coordinates does not match the size of the texture.");
                }

                var ttype = args[0].ImageFormat.Value;
                if ((type == SSLParser.BIF_IMAGESTORE) && !a3t.CanPromoteTo(ttype.GetTexelType()))
                {
                    vis.Error(token, $"The built-in function '{name}' requires the type {ttype.GetTexelType()} for argument 3.");
                }
                return((type == SSLParser.BIF_IMAGESTORE) ? ShaderType.Void : ttype.GetTexelType());
            }
            else if (type >= SSLParser.BIF_MATCOMPMUL && type <= SSLParser.BIF_DETERMINANT)             // Functions that deal with matrices
            {
                btidx = Array.FindIndex(args, a => !a.Type.IsMatrixType());
                if (btidx != -1)
                {
                    vis.Error(token, $"The built-in function '{name}' does not support non-matrix arguments (arg {btidx+1}).");
                }

                if (type == SSLParser.BIF_MATCOMPMUL)                 // 'matCompMul' function
                {
                    if (a1t != a2t)
                    {
                        vis.Error(token, $"The built-in function '{name}' expects two identically sized matrix types for both arguments.");
                    }
                    return(a1t);
                }
                else if (type == SSLParser.BIF_TRANSPOSE || type == SSLParser.BIF_INVERSE)                 // 'transpose' and 'inverse' functions
                {
                    return(a1t);
                }
                else if (type == SSLParser.BIF_DETERMINANT)                 // 'determinant' function
                {
                    return(ShaderType.Float);
                }
            }
            else if (type == SSLParser.BIF_SUBPASSLOAD)             // 'subpassLoad' function
            {
                if (!a1t.IsSubpassInput())
                {
                    vis.Error(token, "The 'subpassLoad' function requires a subpass input as an argument.");
                }
                return(ShaderType.Float4);
            }
            else             // Functions that deal with scalar and vector types
            {
                btidx = Array.FindIndex(args, a => !(a.Type.IsScalarType() || a.Type.IsVectorType()));
                if (btidx != -1)
                {
                    vis.Error(token, $"The built-in function '{name}' does not support handle or matrix arguments (arg {btidx+1}).");
                }

                if (type >= SSLParser.BIF_DEG2RAD && type <= SSLParser.BIF_FRACT)                 // trig, exponential, and 1-arg common functions
                {
                    EnsureCastableComponents(vis, token, name, a1c, a2c, a3c, ShaderType.Float);
                    EnsureVectorSizes(vis, token, name, a1t, a2t, a3t);
                    return(ShaderType.Float.ToVectorType(a1t.GetComponentCount()).Value);
                }
                else if (type == SSLParser.BIF_MOD)                 // 'mod' function
                {
                    EnsureCastableComponents(vis, token, name, a1c, a2c, a3c, ShaderType.Float);
                    EnsureSizeIfNotScalar(vis, token, name, a1t, a2t, 1, 2);
                    return(ShaderType.Float.ToVectorType(a1t.GetComponentCount()).Value);
                }
                else if (type == SSLParser.BIF_MIN || type == SSLParser.BIF_MAX)                 // 'min' and 'max' functions
                {
                    EnsureCastableComponents(vis, token, name, a1c, ShaderType.Void, ShaderType.Void, ShaderType.Float);
                    EnsureMatchingComponents(vis, token, name, a1c, a2c, a3c);
                    EnsureSizeIfNotScalar(vis, token, name, a1t, a2t, 1, 2);
                    return(a1t);
                }
                else if (type == SSLParser.BIF_CLAMP)                 // 'clamp' function
                {
                    EnsureCastableComponents(vis, token, name, a1c, ShaderType.Void, ShaderType.Void, ShaderType.Float);
                    EnsureMatchingComponents(vis, token, name, a1c, a2c, a3c);
                    EnsureVectorSizes(vis, token, name, ShaderType.Void, a2t, a3t);
                    EnsureSizeIfNotScalar(vis, token, name, a1t, a2t, 1, 2);
                    return(a1t);
                }
                else if (type == SSLParser.BIF_MIX)                 // 'mix' function, unlike GLSL this only supports floating points
                {
                    EnsureCastableComponents(vis, token, name, a1c, a2c, a3c, ShaderType.Float);
                    EnsureVectorSizes(vis, token, name, a1t, a2t, ShaderType.Void);
                    EnsureSizeIfNotScalar(vis, token, name, a1t, a3t, 1, 3);
                    return(ShaderType.Float.ToVectorType(a1t.GetComponentCount()).Value);
                }
                else if (type == SSLParser.BIF_STEP)                 // 'step' function
                {
                    EnsureCastableComponents(vis, token, name, a1c, a2c, a3c, ShaderType.Float);
                    EnsureSizeIfNotScalar(vis, token, name, a2t, a1t, 2, 1);
                    return(ShaderType.Float.ToVectorType(a1t.GetComponentCount()).Value);
                }
                else if (type == SSLParser.BIF_SSTEP)                 // 'smoothstep' function
                {
                    EnsureCastableComponents(vis, token, name, a1c, a2c, a3c, ShaderType.Float);
                    EnsureVectorSizes(vis, token, name, a1t, a2t, a3t);
                    EnsureSizeIfNotScalar(vis, token, name, a2t, a1t, 2, 1);
                    return(ShaderType.Float.ToVectorType(a3t.GetComponentCount()).Value);
                }
                else if (type == SSLParser.BIF_LENGTH)                 // 'length' function
                {
                    EnsureCastableComponents(vis, token, name, a1c, a2c, a3c, ShaderType.Float);
                    return(ShaderType.Float);
                }
                else if (type == SSLParser.BIF_DISTANCE || type == SSLParser.BIF_DOT)                 // 'distance' and 'dot' functions
                {
                    EnsureCastableComponents(vis, token, name, a1c, a2c, a3c, ShaderType.Float);
                    EnsureVectorSizes(vis, token, name, a1t, a2t, a3t);
                    return(ShaderType.Float);
                }
                else if (type == SSLParser.BIF_CROSS)                 // 'cross' function
                {
                    EnsureCastableComponents(vis, token, name, a1c, a2c, a3c, ShaderType.Float);
                    if (a1t.GetComponentCount() != 3 || a2t.GetComponentCount() != 3)
                    {
                        vis.Error(token, $"The built-in function '{name}' expects 3-component floating-point vector arguments.");
                    }
                    return(ShaderType.Float3);
                }
                else if (type == SSLParser.BIF_NORMALIZE)                 // 'normalize' function
                {
                    EnsureCastableComponents(vis, token, name, a1c, a2c, a3c, ShaderType.Float);
                    return(ShaderType.Float.ToVectorType(a1t.GetComponentCount()).Value);
                }
                else if (type == SSLParser.BIF_FFORWARD)                 // 'faceforward' function
                {
                    EnsureCastableComponents(vis, token, name, a1c, a2c, a3c, ShaderType.Float);
                    EnsureVectorSizes(vis, token, name, a1t, a2t, a3t);
                    return(ShaderType.Float.ToVectorType(a1t.GetComponentCount()).Value);
                }
                else if (type == SSLParser.BIF_REFLECT)                 // 'reflect' function
                {
                    EnsureCastableComponents(vis, token, name, a1c, a2c, a3c, ShaderType.Float);
                    EnsureVectorSizes(vis, token, name, a1t, a2t, a3t);
                    return(ShaderType.Float.ToVectorType(a1t.GetComponentCount()).Value);
                }
                else if (type == SSLParser.BIF_REFRACT)                 // 'refract' function
                {
                    EnsureCastableComponents(vis, token, name, a1c, a2c, a3c, ShaderType.Float);
                    EnsureVectorSizes(vis, token, name, a1t, a2t, ShaderType.Void);
                    if (!a3t.CanPromoteTo(ShaderType.Float))
                    {
                        vis.Error(token, $"The built-in function '{name}' expects a floating-point scalar for argument 3.");
                    }
                    return(ShaderType.Float.ToVectorType(a1t.GetComponentCount()).Value);
                }
                else if (type >= SSLParser.BIF_VECLT && type <= SSLParser.BIF_VECGE)                 // 2-arg relational vector functions
                {
                    EnsureCastableComponents(vis, token, name, a1c, a2c, a3c, ShaderType.Float);
                    EnsureVectorSizes(vis, token, name, a1t, a2t, a3t);
                    return(ShaderType.Bool.ToVectorType(a1t.GetComponentCount()).Value);
                }
                else if (type == SSLParser.BIF_VECEQ || type == SSLParser.BIF_VECNE)                 // 2-arg logical vector functions
                {
                    if ((a1c == ShaderType.Bool) || a1c.CanPromoteTo(ShaderType.Float))
                    {
                        EnsureMatchingComponents(vis, token, name, a1c, a2c, a3c);
                    }
                    else
                    {
                        vis.Error(token, $"The built-in function '{name}' expects floating-point or boolean vectors for all arguments.");
                    }
                    EnsureVectorSizes(vis, token, name, a1t, a2t, a3t);
                    return(ShaderType.Bool.ToVectorType(a1t.GetComponentCount()).Value);
                }
                else if (type >= SSLParser.BIF_VECANY && type <= SSLParser.BIF_VECNOT)                 // 1-arg logical vector functions
                {
                    EnsureCastableComponents(vis, token, name, a1c, a2c, a3c, ShaderType.Bool);
                    return(ShaderType.Bool);
                }
            }

            // Error
            vis.Error(token, $"The built-in function '{name}' was not understood.");
            return(ShaderType.Void);
        }
Esempio n. 9
0
        public static StandardFunction FromContext(SSLParser.StandardFunctionContext ctx, SSLVisitor vis)
        {
            var rtype = ReflectionUtils.TranslateTypeContext(ctx.type());
            var fname = ctx.Name.Text;

            List <Param> pars = new List <Param>();

            if (ctx.Params != null)
            {
                foreach (var pctx in ctx.Params._PList)
                {
                    var pname = pctx.Name.Text;
                    var aidx  = pctx.Access?.Type ?? SSLParser.KW_IN;
                    var acs   = (aidx == SSLParser.KW_OUT) ? Access.Out : (aidx == SSLParser.KW_INOUT) ? Access.InOut : Access.In;
                    var ptype = ReflectionUtils.TranslateTypeContext(pctx.type());
                    if (ptype == ShaderType.Void)
                    {
                        vis.Error(ctx, $"The parameter '{pname}' cannot have type 'void'.");
                    }
                    var fidx = pars.FindIndex(ep => ep.Name == pname);
                    if (fidx != -1)
                    {
                        vis.Error(ctx, $"Duplicate parameter name '{pname}' in the function parameter list.");
                    }
                    pars.Add(new Param {
                        Name = pname, Type = ptype.Value, Access = acs
                    });
                }
            }

            return(new StandardFunction(fname, rtype.Value, pars.ToArray()));
        }
Esempio n. 10
0
        private bool outputGLSL(CompileOptions options, SSLVisitor visitor, out CompileError error)
        {
            var outDir  = options.GLSLPath ?? CompileOptions.MakeDefaultGLSLPath(SourceFile) ?? Directory.GetCurrentDirectory();
            var outName = (SourceFile != null) ? Path.GetFileNameWithoutExtension(SourceFile) : "shader";

            if ((ShaderInfo.Stages & ShaderStages.Vertex) > 0)
            {
                try
                {
                    var path = Path.Combine(outDir, outName + ".vert");
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                    File.WriteAllText(path, visitor.GLSL.GetGLSLOutput(ShaderStages.Vertex));
                }
                catch (Exception e)
                {
                    error = new CompileError(ErrorSource.Output, 0, 0,
                                             $"Unable to write vertex source file, reason: '{e.Message.Substring(0, e.Message.Length - 1)}'.");
                    return(false);
                }
            }
            if ((ShaderInfo.Stages & ShaderStages.TessControl) > 0)
            {
                try
                {
                    var path = Path.Combine(outDir, outName + ".tesc");
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                    File.WriteAllText(path, visitor.GLSL.GetGLSLOutput(ShaderStages.TessControl));
                }
                catch (Exception e)
                {
                    error = new CompileError(ErrorSource.Output, 0, 0,
                                             $"Unable to write tess control source file, reason: '{e.Message.Substring(0, e.Message.Length - 1)}'.");
                    return(false);
                }
            }
            if ((ShaderInfo.Stages & ShaderStages.TessEval) > 0)
            {
                try
                {
                    var path = Path.Combine(outDir, outName + ".tese");
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                    File.WriteAllText(path, visitor.GLSL.GetGLSLOutput(ShaderStages.TessEval));
                }
                catch (Exception e)
                {
                    error = new CompileError(ErrorSource.Output, 0, 0,
                                             $"Unable to write tess eval source file, reason: '{e.Message.Substring(0, e.Message.Length - 1)}'.");
                    return(false);
                }
            }
            if ((ShaderInfo.Stages & ShaderStages.Geometry) > 0)
            {
                try
                {
                    var path = Path.Combine(outDir, outName + ".geom");
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                    File.WriteAllText(path, visitor.GLSL.GetGLSLOutput(ShaderStages.Geometry));
                }
                catch (Exception e)
                {
                    error = new CompileError(ErrorSource.Output, 0, 0,
                                             $"Unable to write geometry source file, reason: '{e.Message.Substring(0, e.Message.Length - 1)}'.");
                    return(false);
                }
            }
            if ((ShaderInfo.Stages & ShaderStages.Fragment) > 0)
            {
                try
                {
                    var path = Path.Combine(outDir, outName + ".frag");
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                    File.WriteAllText(path, visitor.GLSL.GetGLSLOutput(ShaderStages.Fragment));
                }
                catch (Exception e)
                {
                    error = new CompileError(ErrorSource.Output, 0, 0,
                                             $"Unable to write fragment source file, reason: '{e.Message.Substring(0, e.Message.Length - 1)}'.");
                    return(false);
                }
            }

            error = null;
            return(true);
        }
Esempio n. 11
0
        /// <summary>
        /// Performs the compilation of the input file, using the given options.
        /// </summary>
        /// <param name="options">The options to use when compiling the shader file.</param>
        /// <param name="error">The error generated by the compiler, if any. Will be <c>null</c> on success.</param>
        /// <returns><c>true</c> if the compilation completes successfully, <c>false</c> otherwise.</returns>
        public bool Compile(CompileOptions options, out CompileError error)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }
            error = null;

            // Validate the build options
            options.Validate();

            // Create the lexer and parser
            AntlrInputStream  inStream    = new AntlrInputStream(Source);
            SSLLexer          lexer       = new SSLLexer(inStream);
            CommonTokenStream tokenStream = new CommonTokenStream(lexer);
            SSLParser         parser      = new SSLParser(tokenStream);

            // Register our custom error listener
            lexer.RemoveErrorListeners();
            parser.RemoveErrorListeners();
            var err = new SSLErrorListener();

            lexer.AddErrorListener(err);
            parser.AddErrorListener(err);

            // Check for the version statement first
            var versionCtx = parser.versionMetaStatement();

            if (err.Error != null)
            {
                error = err.Error;
                return(false);
            }
            if (versionCtx != null && !checkVersion(versionCtx, out error))
            {
                return(false);
            }

            // Perform the parsing, and report the error if there is one
            parser.Reset();
            var fileCtx = parser.file();

            if (err.Error != null)
            {
                error = err.Error;
                return(false);
            }

            // Visit the tree (this step actually generates the GLSL)
            SSLVisitor visitor = new SSLVisitor(tokenStream, this, options);

            try
            {
                visitor.Visit(fileCtx);
                ShaderInfo = visitor.Info;
            }
            catch (VisitException e)
            {
                error = e.Error;
                return(false);
            }

            // Output the reflection if requested
            if (options.OutputReflection && !outputRefl(options, visitor, out error))
            {
                return(false);
            }

            // Output the GLSL if requested
            if (options.OutputGLSL && !outputGLSL(options, visitor, out error))
            {
                return(false);
            }

            // Compile if requested
            if (options.Compile && !compile(options, visitor, out error))
            {
                return(false);
            }

            return(true);
        }