public int Compile(List <ClassDefinition> classDefinitions)
        {
            if (programAsset.sourceCsScript == null)
            {
                throw new System.ArgumentException($"Asset '{AssetDatabase.GetAssetPath(programAsset)}' does not have a valid program source to compile from");
            }

            Profiler.BeginSample("Compile Module");

            programAsset.compileErrors.Clear();

            sourceCode = File.ReadAllText(AssetDatabase.GetAssetPath(programAsset.sourceCsScript));

            Profiler.BeginSample("Parse AST");
            SyntaxTree tree = CSharpSyntaxTree.ParseText(sourceCode);

            Profiler.EndSample();

            int errorCount = 0;

            string errorString = "";

            foreach (Diagnostic diagnostic in tree.GetDiagnostics())
            {
                if (diagnostic.Severity == DiagnosticSeverity.Error)
                {
                    errorCount++;

                    LinePosition linePosition = diagnostic.Location.GetLineSpan().StartLinePosition;

                    errorString = UdonSharpUtils.LogBuildError($"error {diagnostic.Descriptor.Id}: {diagnostic.GetMessage()}",
                                                               AssetDatabase.GetAssetPath(programAsset.sourceCsScript).Replace("/", "\\"),
                                                               linePosition.Line,
                                                               linePosition.Character);

                    programAsset.compileErrors.Add(errorString);
                }
            }

            if (errorCount > 0)
            {
                ErrorCount = errorCount;
                Profiler.EndSample();
                return(errorCount);
            }

            Profiler.BeginSample("Visit");
            UdonSharpFieldVisitor fieldVisitor = new UdonSharpFieldVisitor(fieldsWithInitializers);

            fieldVisitor.Visit(tree.GetRoot());

            MethodVisitor methodVisitor = new MethodVisitor(resolver, moduleSymbols, moduleLabels);

            methodVisitor.Visit(tree.GetRoot());

            UdonSharpSettings settings = UdonSharpSettings.GetSettings();

            ClassDebugInfo debugInfo = null;

            if (settings == null || settings.buildDebugInfo)
            {
                debugInfo = new ClassDebugInfo(sourceCode, settings == null || settings.includeInlineCode);
            }

            ASTVisitor visitor = new ASTVisitor(resolver, moduleSymbols, moduleLabels, methodVisitor.definedMethods, classDefinitions, debugInfo);

            try
            {
                visitor.Visit(tree.GetRoot());
                visitor.VerifyIntegrity();
            }
            catch (System.Exception e)
            {
                SyntaxNode currentNode = visitor.visitorContext.currentNode;

                string logMessage = "";

                if (currentNode != null)
                {
                    FileLinePositionSpan lineSpan = currentNode.GetLocation().GetLineSpan();

                    logMessage = UdonSharpUtils.LogBuildError($"{e.GetType()}: {e.Message}",
                                                              AssetDatabase.GetAssetPath(programAsset.sourceCsScript).Replace("/", "\\"),
                                                              lineSpan.StartLinePosition.Line,
                                                              lineSpan.StartLinePosition.Character);
                }
                else
                {
                    logMessage = e.ToString();
                    Debug.LogException(e);
                }

                programAsset.compileErrors.Add(logMessage);

                errorCount++;
            }
            Profiler.EndSample();

            if (errorCount == 0)
            {
                Profiler.BeginSample("Build assembly");
                string dataBlock = BuildHeapDataBlock();
                string codeBlock = visitor.GetCompiledUasm();

                programAsset.SetUdonAssembly(dataBlock + codeBlock);
                Profiler.EndSample();

                Profiler.BeginSample("Assemble Program");
                programAsset.AssembleCsProgram((uint)(moduleSymbols.GetAllUniqueChildSymbols().Count + visitor.GetExternStrCount()));
                Profiler.EndSample();
                programAsset.behaviourIDHeapVarName = visitor.GetIDHeapVarName();

                programAsset.fieldDefinitions = visitor.visitorContext.localFieldDefinitions;

                if (debugInfo != null)
                {
                    debugInfo.FinalizeDebugInfo();
                }

                programAsset.debugInfo = debugInfo;
            }

            Profiler.EndSample();

            return(errorCount);
        }
        public CompileTaskResult Compile(List <ClassDefinition> classDefinitions)
        {
            programAsset.compileErrors.Clear();

            SyntaxTree tree = CSharpSyntaxTree.ParseText(sourceCode);

            CompileTaskResult result = new CompileTaskResult();

            result.programAsset = programAsset;

            int errorCount = 0;

            foreach (Diagnostic diagnostic in tree.GetDiagnostics())
            {
                if (diagnostic.Severity == DiagnosticSeverity.Error)
                {
                    errorCount++;

                    LinePosition linePosition = diagnostic.Location.GetLineSpan().StartLinePosition;

                    CompileError error = new CompileError();
                    error.script   = programAsset.sourceCsScript;
                    error.errorStr = $"error {diagnostic.Descriptor.Id}: {diagnostic.GetMessage()}";
                    error.lineIdx  = linePosition.Line;
                    error.charIdx  = linePosition.Character;

                    result.compileErrors.Add(error);
                }
            }

            if (errorCount > 0)
            {
                return(result);
            }

            moduleSymbols.OpenSymbolTable();

            UdonSharpFieldVisitor fieldVisitor = new UdonSharpFieldVisitor(fieldsWithInitializers);

            fieldVisitor.Visit(tree.GetRoot());

            MethodVisitor methodVisitor = new MethodVisitor(resolver, moduleSymbols, moduleLabels);

            methodVisitor.Visit(tree.GetRoot());

            ClassDebugInfo debugInfo = null;

            if (settings == null || settings.buildDebugInfo)
            {
                debugInfo = new ClassDebugInfo(sourceCode, settings == null || settings.includeInlineCode);
            }

            ASTVisitor visitor = new ASTVisitor(resolver, moduleSymbols, moduleLabels, methodVisitor.definedMethods, classDefinitions, debugInfo);

            try
            {
                visitor.Visit(tree.GetRoot());
                visitor.VerifyIntegrity();
            }
            catch (System.Exception e)
            {
                SyntaxNode currentNode = visitor.visitorContext.currentNode;

                string logMessage = "";

                if (currentNode != null)
                {
                    FileLinePositionSpan lineSpan = currentNode.GetLocation().GetLineSpan();

                    CompileError error = new CompileError();
                    error.script   = programAsset.sourceCsScript;
                    error.errorStr = $"{e.GetType()}: {e.Message}";
                    error.lineIdx  = lineSpan.StartLinePosition.Line;
                    error.charIdx  = lineSpan.StartLinePosition.Character;

                    result.compileErrors.Add(error);
                }
                else
                {
                    logMessage = e.ToString();
                    Debug.LogException(e);
                }
#if UDONSHARP_DEBUG
                Debug.LogException(e);
                Debug.LogError(e.StackTrace);
#endif

                programAsset.compileErrors.Add(logMessage);

                errorCount++;
            }

            if (errorCount > 0)
            {
                return(result);
            }

            moduleSymbols.CloseSymbolTable();

            if (errorCount == 0)
            {
                compiledClassDefinition = classDefinitions.Find(e => e.userClassType == visitor.visitorContext.behaviourUserType);

                string dataBlock = BuildHeapDataBlock();
                string codeBlock = visitor.GetCompiledUasm();

                result.compiledAssembly = dataBlock + codeBlock;
                result.symbolCount      = (uint)(moduleSymbols.GetAllUniqueChildSymbols().Count + visitor.GetExternStrCount());

                programAsset.behaviourIDHeapVarName = visitor.GetIDHeapVarName();

                programAsset.fieldDefinitions = visitor.visitorContext.localFieldDefinitions;

                if (debugInfo != null)
                {
                    debugInfo.FinalizeDebugInfo();
                }

                programAsset.debugInfo = debugInfo;
            }

            return(result);
        }