Beispiel #1
0
 public static NodeBinder BindNotInList(NodeBinder left, IEnumerable <NodeBinder> rest)
 {
     return(new NodeBinder(ctx =>
     {
         var equalExprs = rest.Select(
             n =>
             Expression.NotEqual(left(ctx), n(ctx)));
         return equalExprs.ToOrElseExpression();
     }));
 }
Beispiel #2
0
            public override void VisitMvApplyOperator(MvApplyOperator node)
            {
                base.VisitMvApplyOperator(node);

                if (_position >= node.OnKeyword.TextStart)
                {
                    var info = new NodeBinder(_binder).VisitMvApplyOperator(node);
                    _binder._rowScope = info?.ResultType as TableSymbol;
                }
            }
Beispiel #3
0
 public static NodeBinder Bind(ModelBuilder builder, GeoModel node)
 {
     if (null != (object)builder)
     {
         var nb = new NodeBinder
         {
             builder = builder,
             Restore = System.Threading.Interlocked.Exchange(ref builder.geoModel, node),
             Replace = node,
         };
         nb.NeedDispose = nb.Restore != nb.Replace;
         if (nb.NeedDispose)
         {
             return(nb);
         }
     }
     return(default(NodeBinder));
 }
Beispiel #4
0
 public static NodeBinder BindUserOperator(string opr, NodeBinder left, NodeBinder right)
 {
     return(new NodeBinder(ctx =>
     {
         if (!ctx.UserFunctions.ContainsKey(opr))
         {
             throw new BindingException($"Undefined user function: '{opr}'");
         }
         var func = ctx.UserFunctions[opr];
         var leftExpr = left(ctx);
         var rightExpr = right(ctx);
         if (func.GetMethodInfo().IsStatic)
         {
             return Expression.Call(func.GetMethodInfo(), leftExpr, rightExpr);
         }
         else
         {
             return Expression.Call(Expression.Constant(func.Target), func.GetMethodInfo(), leftExpr, rightExpr);
         }
     }));
 }
Beispiel #5
0
        private ArrayType GetArrayType(PapyrusType elementType)
        {
            var objectIdentifier = elementType.Name;

            lock (_arrayTypes)
            {
                if (!_arrayTypes.ContainsKey(objectIdentifier))
                {
                    var source = CreateArrayTypeSource(objectIdentifier);
                    var stream = new CaseInsensitiveStringStream(source);
                    var lexer  = new PapyrusLexer(stream);
                    var parser = new PapyrusParser(new CommonTokenStream(lexer));
                    parser.AsDynamic().KnownUserFlags = _program.FlagsFile.NativeFlagsDict;
                    parser.script();

                    var compilerType = parser.ParsedObject;

                    var nodeBinder = new NodeBinder();

                    var node = nodeBinder.Bind(null, _program,
                                               new ScriptText(null, source, "0"), compilerType.GetTokenStream(), compilerType.GetAst());

                    var scopeBinder = new ScopeBinder();
                    var scopeResult = scopeBinder.Bind(compilerType, node.Value);

                    node.Diagnostics.AddRange(scopeResult.Diagnostics);

                    var symbolBinder = new SymbolBinder();
                    var symbolResult = symbolBinder.Bind(node.Value);

                    var type = new ArrayType(_program, symbolResult.Value, compilerType, elementType.Name);
                    _arrayTypes.Add(objectIdentifier, type);
                }

                return(_arrayTypes[objectIdentifier]);
            }
        }
 public TreeBinder(Binder binder)
 {
     _binder     = binder;
     _nodeBinder = new NodeBinder(binder);
 }
Beispiel #7
0
        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);
        }