time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

ProjectItem.js (4624B)


      1 import { parse } from "../../ast/parse.js";
      2 import { ICompileError, IRuntimeError } from "../../errors/IError.js";
      3 import { compileAst } from "../../expression/compile.js";
      4 import { evaluate } from "../../reducer/index.js";
      5 import * as Result from "../../utility/result.js";
      6 import { Ok } from "../../utility/result.js";
      7 import { SqCompileError, SqRuntimeError } from "../SqError.js";
      8 export class ProjectItem {
      9     constructor(props) {
     10         this.sourceId = props.sourceId;
     11         this.source = props.source;
     12         this.continues = [];
     13     }
     14     touchSource() {
     15         this.ast = undefined;
     16         this.imports = undefined;
     17         this.output = undefined;
     18     }
     19     setSource(source) {
     20         this.source = source;
     21         this.touchSource();
     22     }
     23     setAst(ast) {
     24         this.ast = ast;
     25         this.imports = undefined;
     26         this.output = undefined;
     27     }
     28     setImports(imports) {
     29         this.imports = imports;
     30         this.output = undefined;
     31     }
     32     clean() {
     33         this.output = undefined;
     34     }
     35     getDependencies() {
     36         if (!this.imports?.ok) {
     37             return this.continues;
     38         }
     39         return [...this.continues, ...this.imports.value.map((i) => i.sourceId)];
     40     }
     41     getImplicitImports() {
     42         const implicitImports = [];
     43         for (const continueId of this.continues) {
     44             implicitImports.push({
     45                 type: "flat",
     46                 sourceId: continueId,
     47             });
     48         }
     49         return implicitImports;
     50     }
     51     setContinues(continues) {
     52         this.continues = continues;
     53         this.clean();
     54     }
     55     parseImports(linker) {
     56         if (this.imports) {
     57             return;
     58         }
     59         this.buildAst();
     60         if (!this.ast) {
     61             throw new Error("Internal logic error");
     62         }
     63         if (!this.ast.ok) {
     64             this.setImports(this.ast);
     65             return;
     66         }
     67         const program = this.ast.value;
     68         const resolvedImports = [];
     69         for (const [file, variable] of program.imports) {
     70             const location = file.location;
     71             if (!linker) {
     72                 this.setImports(Result.Err(new SqCompileError(new ICompileError("Can't use imports when linker is not configured", location))));
     73                 return;
     74             }
     75             try {
     76                 const sourceId = linker.resolve(file.value, this.sourceId);
     77                 resolvedImports.push({
     78                     type: "named",
     79                     variable: variable.value,
     80                     sourceId,
     81                 });
     82             }
     83             catch (e) {
     84                 this.setImports(Result.Err(new SqCompileError(new ICompileError(`SqLinker.resolve has failed to resolve ${file.value}`, location))));
     85                 return;
     86             }
     87         }
     88         this.setImports(Ok(resolvedImports));
     89     }
     90     buildAst() {
     91         if (this.ast) {
     92             return;
     93         }
     94         const ast = Result.errMap(parse(this.source, this.sourceId), (e) => new SqCompileError(e));
     95         this.setAst(ast);
     96     }
     97     failRun(e) {
     98         this.output = Result.Err(e);
     99     }
    100     async run(context, externals) {
    101         if (this.output) {
    102             return;
    103         }
    104         this.buildAst();
    105         if (!this.ast) {
    106             throw new Error("Internal logic error");
    107         }
    108         if (!this.ast.ok) {
    109             this.failRun(this.ast.value);
    110             return;
    111         }
    112         const expression = Result.errMap(compileAst(this.ast.value, externals), (e) => new SqCompileError(e));
    113         if (!expression.ok) {
    114             this.failRun(expression.value);
    115             return;
    116         }
    117         try {
    118             const wrappedEvaluate = context.evaluate;
    119             const asyncEvaluate = (expression, context) => {
    120                 return wrappedEvaluate(expression, context);
    121             };
    122             if (expression.value.type !== "Program") {
    123                 throw new Error("Expected Program expression");
    124             }
    125             const [result, contextAfterEvaluation] = evaluate(expression.value, {
    126                 ...context,
    127                 evaluate: asyncEvaluate,
    128             });
    129             const bindings = contextAfterEvaluation.stack.asBindings();
    130             const exportNames = new Set(expression.value.value.exports);
    131             const exports = bindings.filter((_, key) => exportNames.has(key));
    132             this.output = Ok({
    133                 result,
    134                 bindings,
    135                 exports,
    136             });
    137         }
    138         catch (e) {
    139             this.failRun(new SqRuntimeError(IRuntimeError.fromException(e)));
    140         }
    141     }
    142 }
    143 //# sourceMappingURL=ProjectItem.js.map