|
| 1 | +// @ts-check |
| 2 | + |
| 3 | +import { promises as fsPromises, createWriteStream } from 'fs' |
| 4 | +import { join, extname } from 'path' |
| 5 | +import { parse } from 'acorn' |
| 6 | +import createContext from '../dist/createContext.js' |
| 7 | +import { ACORN_PARSE_OPTIONS } from '../dist/constants.js' |
| 8 | +import { Chapter } from '../dist/types.js' |
| 9 | + |
| 10 | +async function recursiveDirCopy(fromPath, dstPath) { |
| 11 | + // Copy and keep only necessary files |
| 12 | + const files = await fsPromises.readdir(fromPath) |
| 13 | + |
| 14 | + return Promise.all(files.map(async fileName => { |
| 15 | + const fullFromPath = join(fromPath, fileName) |
| 16 | + const fullToPath = join(dstPath, fileName) |
| 17 | + |
| 18 | + const stats = await fsPromises.stat(fullFromPath) |
| 19 | + |
| 20 | + if (stats.isFile()) { |
| 21 | + const extension = extname(fileName) |
| 22 | + if (extension !== '.js') return; |
| 23 | + await fsPromises.copyFile(fullFromPath, fullToPath) |
| 24 | + } else if (stats.isDirectory()) { |
| 25 | + await fsPromises.mkdir(fullToPath) |
| 26 | + await recursiveDirCopy(fullFromPath, fullToPath) |
| 27 | + } |
| 28 | + })) |
| 29 | +} |
| 30 | + |
| 31 | +async function prepare() { |
| 32 | + await fsPromises.rm('sicp_publish/dist', { recursive: true, force: true }) |
| 33 | + await fsPromises.mkdir('sicp_publish/dist', { recursive: true }) |
| 34 | + await recursiveDirCopy('dist', 'sicp_publish/dist') |
| 35 | + |
| 36 | + // Remove unnecessary dependencies |
| 37 | + await Promise.all([ |
| 38 | + 'finder.js', 'index.js', 'scope-refactoring.js', 'sicp-prepare.js' |
| 39 | + ].map(fileName => fsPromises.rm(`sicp_publish/dist/${fileName}`))) |
| 40 | +} |
| 41 | + |
| 42 | +function main() { |
| 43 | + const writeStream = createWriteStream('sicp_publish/dist/sicp.js', { |
| 44 | + encoding: 'utf-8', |
| 45 | + flags: 'w' |
| 46 | + }) |
| 47 | + writeStream.write('"use strict";\n') |
| 48 | + writeStream.write('Object.defineProperty(exports, "__esModule", { value: true });\n') |
| 49 | + writeStream.write('const createContext_1 = require("./createContext");\n') |
| 50 | + writeStream.write('const dict = createContext_1.default(4).nativeStorage.builtins;') |
| 51 | + writeStream.write('\n// Declare functions for prelude\n') |
| 52 | + |
| 53 | + // @ts-expect-error Something to do with weird stuff going on between cjs and esm |
| 54 | + const context = createContext.default(Chapter.SOURCE_4) |
| 55 | + const builtins = context.nativeStorage.builtins |
| 56 | + |
| 57 | + for (const builtin of builtins.keys()) { |
| 58 | + if (builtin !== 'undefined' && builtin !== 'NaN' && builtin !== 'Infinity') { |
| 59 | + writeStream.write(`const ${builtin} = dict.get("${builtin}");\n`) |
| 60 | + } |
| 61 | + } |
| 62 | + |
| 63 | + if (context.prelude !== null) { |
| 64 | + writeStream.write('\n// Prelude\n') |
| 65 | + writeStream.write(context.prelude) |
| 66 | + |
| 67 | + const prelude = parse(context.prelude, ACORN_PARSE_OPTIONS) |
| 68 | + |
| 69 | + writeStream.write('\n // Export prelude functions\n') |
| 70 | + for (const func of prelude.body) { |
| 71 | + if (func.type !== 'FunctionDeclaration') { |
| 72 | + throw new Error(`Expected FunctionDeclarations, got '${func.type}' instead`) |
| 73 | + } |
| 74 | + |
| 75 | + const funcName = func.id.name; |
| 76 | + writeStream.write(`exports.${funcName} = ${funcName};\n`) |
| 77 | + } |
| 78 | + } |
| 79 | + |
| 80 | + writeStream.write('\n// Export builtin functions\n') |
| 81 | + for (const builtin of builtins.keys()) { |
| 82 | + if (builtin !== 'undefined' && builtin !== 'NaN' && builtin !== 'Infinity') { |
| 83 | + writeStream.write(`exports.${builtin} = ${builtin};\n`) |
| 84 | + } |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | +await prepare().then(main) |
0 commit comments