aboutsummaryrefslogtreecommitdiff
path: root/static/compiler.js
blob: 021992ceb6c96c523396579cf99d14b7a15d18ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
let compiler;

export default async function initGleamCompiler() {
  const wasm = await import("/compiler/gleam_wasm.js");
  await wasm.default();
  wasm.initialise_panic_hook();
  if (!compiler) {
    compiler = new Compiler(wasm);
  }
  return compiler;
}

class Compiler {
  #wasm;
  #nextId = 0;
  #projects = new Map();

  constructor(wasm) {
    this.#wasm = wasm;
  }

  get wasm() {
    return this.#wasm;
  }

  newProject() {
    const id = this.#nextId++;
    const project = new Project(id);
    this.#projects.set(id, new WeakRef(project));
    return project;
  }

  garbageCollectProjects() {
    const gone = [];
    for (const [id, project] of this.#projects) {
      if (!project.deref()) gone.push(id);
    }
    for (const id of gone) {
      this.#projects.delete(id);
      this.#wasm.delete_project(id);
    }
  }
}

class Project {
  #id;

  constructor(id) {
    this.#id = id;
  }

  get projectId() {
    return this.#id;
  }

  writeModule(moduleName, code) {
    compiler.wasm.write_module(this.#id, moduleName, code);
  }

  compilePackage(target) {
    compiler.garbageCollectProjects();
    compiler.wasm.reset_warnings(this.#id);
    compiler.wasm.compile_package(this.#id, target);
  }

  readCompiledJavaScript(moduleName) {
    return compiler.wasm.read_compiled_javascript(this.#id, moduleName);
  }

  readCompiledErlang(moduleName) {
    return compiler.wasm.read_compiled_erlang(this.#id, moduleName);
  }

  resetFilesystem() {
    compiler.wasm.reset_filesystem(this.#id);
  }

  delete() {
    compiler.wasm.delete_project(this.#id);
  }

  takeWarnings() {
    const warnings = [];
    while (true) {
      const warning = compiler.wasm.pop_warning(this.#id);
      if (!warning) return warnings;
      warnings.push(warning.trimStart());
    }
  }
}