Skip to content

Local Module Import & Export

Ian Yong edited this page Jan 15, 2023 · 14 revisions

Overview

The importing & exporting of local modules (not to be confused with Source modules) is available in Source 2+. It is done as a preprocessing step where the Abstract Syntax Trees (ASTs) that are parsed from the various files/modules involved are transformed in such a way that outputs a single AST that handles all imports & exports.

Local Modules vs Source Modules

In Source, we make the distinction between the following modules:

  1. Source modules, which can be thought of as libraries which can be imported from. There is a separate system for handling these in js-slang. The modules that are available can be found in the modules repository.
  2. Local modules, which are essentially user-written files to allow for multi-file Source programs.

More details on how this distinction is made can be found below.

Example Program

How the AST transformation works is best described by the equivalent code.

Say we have a Source 2+ program consisting of 4 files where /a.js is the entrypoint file (i.e., the file containing the code that is the entrypoint of the program - because evaluation of any program needs to have a defined starting point):

  • /a.js
    import { a as x, b as y } from "./b.js";
    
    x + y;
  • /b.js
    import y, { square } from "./c.js";
    
    const a = square(y);
    const b = 3;
    export { a, b };
  • /c.js
    import { mysteryFunction } from "./d.js";
    
    const x = mysteryFunction(5);
    export function square(x) {
      return x * x;
    }
    export default x;
  • /d.js
    const addTwo = x => x + 2;
    export { addTwo as mysteryFunction };

The resulting AST after transformation will be equivalent to the following Source code:

function __$b$dot$js__(___$c$dot$js___) {
  const y = __access_export__(___$c$dot$js___, "default");
  const square = __access_export__(___$c$dot$js___, "square");

  const a = square(y);
  const b = 3;

  return pair(null, list(pair("a", a), pair("b", b)));
}

function __$c$dot$js__(___$d$dot$js___) {
  const mysteryFunction = __access_export__(___$d$dot$js___, "mysteryFunction");

  const x = mysteryFunction(5);
  function square(x) {
    return x * x;
  }

  return pair(x, list(pair("square", square)));
}

function __$d$dot$js__() {
  const addTwo = x => x + 2;

  return pair(null, list(pair("mysteryFunction", addTwo)));
}

const ___$d$dot$js___ = __$d$dot$js__();
const ___$c$dot$js___ = __$c$dot$js__(___$d$dot$js___);
const ___$b$dot$js___ = __$b$dot$js__(___$c$dot$js___);

const x = __access_export__(___$b$dot$js___, "a");
const y = __access_export__(___$b$dot$js___, "b");

x + y;