public static bool Prefix( ScriptCompiler __instance, ref ScriptObjectType __result, string asObjectName, Dictionary <string, ScriptComplexType> apKnownTypes, Stack <string> apChildren, bool abErrorOnNoObject, ScriptObjectType apImmediateChild) {
public static bool Prefix( ScriptCompiler __instance, ITokenStream apTokenStream, out ScriptObjectType apParsedObj, out IToken arpParentName, out Dictionary <string, IToken> apImports) {
// Skyrim's LoadObject method calls TypeCheck internally, which mutates the AST and prevents a subsequent type check from succeeding. // So, this patch is just to replace it with a no-op. public static bool Prefix(ScriptCompiler __instance, ScriptObjectType akObj, Dictionary <string, ScriptObjectType> akKnownTypes, Stack <string> akChildren) { return(false); }
public ScriptFile(ObjectIdentifier id, string filePath, PapyrusProgram program, IScriptTextProvider textProvider, ILogger <ScriptFile> logger) { _id = id; _filePath = filePath; _program = program; _textProvider = textProvider; _logger = logger; var initialVersion = _textProvider.GetTextVersion(_filePath).WaitForResult(); _scriptText = new TokenEqualityCachedValue <ScriptText, string>( () => _textProvider.GetText(_filePath).WaitForResult(), (_) => { var currentVersion = _scriptText.CurrentToken; var version = _textProvider.GetTextVersion(_filePath).WaitForResult(); if (currentVersion != version) { _logger.LogTrace($"{_id} file version changed from '{currentVersion}' to '{version}'. (Thread: {Thread.CurrentThread.ManagedThreadId})"); } return(version); }, initialVersion); _textProvider.OnScriptTextChanged += HandleScriptTextChanged; _compiler = new TokenEqualityCachedValue <ScriptCompiler, string>(() => { var compiler = new ScriptCompiler(this, _logger); compiler.CompilerNotifyHandler += (s, e) => { _logger.LogTrace($"Compiler: {e.sMessage}"); }; return(compiler); }, (_) => _scriptText.Value.Version, initialVersion); _compilationResult = new TokenEqualityCachedValue <DiagnosticResult <CompilationResult>, ScriptCompiler>(() => { DiagnosticResult <CompilationResult> compileFunc() { return(DiagnosticResult <CompilationResult> .TryWithDiagnostics((diagnostics) => { return UseCompiler((compiler, types) => { var compilationResult = new CompilationResult(); _logger.LogTrace($"Compiling {_id}... (Thread: {Thread.CurrentThread.ManagedThreadId})"); var type = compiler.Load(types); compilationResult.CompilerType = type; compilationResult.CompilerNode = type?.GetAst(); _logger.LogTrace($"Type checking {_id}... (Thread: {Thread.CurrentThread.ManagedThreadId})"); var typeWalker = new TypeWalker(this, type, _logger); typeWalker.OnError((s, e) => { if (!e.ErrorText.StartsWith("mismatched tree node")) { diagnostics.Add(e.ToDiagnostic()); } }); try { #if FALLOUT4 typeWalker.script(type, compiler, types); #elif SKYRIM lock (types) { if (types.ContainsKey("int")) { types.Remove("int"); types.Remove("float"); types.Remove("string"); types.Remove("bool"); } } typeWalker.script(type, compiler, types, new Stack <string>()); #endif } catch (Exception e) { _logger.LogWarning(e, $"Thrown during type checking of {_id}"); } return compilationResult; }, (s, e) => { diagnostics.Add(e.ToDiagnostic()); }); })); } // If there are diagnostic errors, we re-run the compile once in case anything was missing, // but couldn't be resolved at the time. var result = compileFunc(); if (result.Diagnostics.Count > 0) { return(compileFunc()); } return(result); }, (_) => _compiler.Value); _node = new TokenEqualityCachedValue <DiagnosticResult <ScriptNode>, CompilationResult>(() => { if (CompilerType == null) { return(null); } _logger.LogTrace($"Transforming {_id} syntax tree... (Thread: {Thread.CurrentThread.ManagedThreadId})"); var nodeBinder = new NodeBinder(); var node = nodeBinder.Bind(this, _program, Text, CompilerType.GetTokenStream(), CompilerNode); _logger.LogTrace($"Binding script scopes to {_id} syntax tree... (Thread: {Thread.CurrentThread.ManagedThreadId})"); var scopeBinder = new ScopeBinder(); var scopeResult = scopeBinder.Bind(CompilerType, node.Value); node.Diagnostics.AddRange(scopeResult.Diagnostics); _logger.LogTrace($"Binding {_id} symbols... (Thread: {Thread.CurrentThread.ManagedThreadId})"); var symbolBinder = new SymbolBinder(); var symbolResult = symbolBinder.Bind(node.Value); node.Diagnostics.AddRange(symbolResult.Diagnostics); return(node); }, (_) => _compilationResult.Value?.Value); _type = new TokenEqualityCachedValue <ScriptType, ScriptSymbol>(() => { if (Symbol == null) { return(null); } _logger.LogTrace($"Creating {_id} type... (Thread: {Thread.CurrentThread.ManagedThreadId})"); return(new ScriptType(Program, Symbol, CompilerType)); }, (_) => Symbol); }