Reusable compiler
This commit is contained in:
parent
6408493ea3
commit
2ff3067fad
|
@ -1,4 +1,79 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import { main } from '../lib/compiler/main.js';
|
||||
main(process.argv);
|
||||
const yargs = require('yargs/yargs');
|
||||
const { hideBin } = require('yargs/helpers');
|
||||
const argv =
|
||||
yargs(hideBin(process.argv))
|
||||
.completion()
|
||||
.command('$0 [input]', 'Compile a single file', (yargs) => {
|
||||
yargs
|
||||
.positional('input', {
|
||||
type: 'string',
|
||||
description: 'Input filename',
|
||||
})
|
||||
.option('output', {
|
||||
alias: 'o',
|
||||
type: 'string',
|
||||
description: 'Output filename (stdout if omitted)',
|
||||
default: null,
|
||||
})
|
||||
.option('map', {
|
||||
type: 'boolean',
|
||||
description: 'Generate source maps',
|
||||
default: true,
|
||||
})
|
||||
.option('map-extension', {
|
||||
type: 'string',
|
||||
description: 'Extension (e.g. ".map") to add to source map files; if omitted, source maps are generated inline',
|
||||
default: null,
|
||||
})
|
||||
.option('runtime', {
|
||||
type: 'string',
|
||||
description: 'Path to require or import to get the Syndicate runtime',
|
||||
default: '@syndicate/core',
|
||||
})
|
||||
.option('module', {
|
||||
type: 'string',
|
||||
description: 'es6 | require | global',
|
||||
})
|
||||
})
|
||||
.argv;
|
||||
|
||||
const fs = require('fs');
|
||||
const { compile } = require('../dist/syndicate.js').Compiler;
|
||||
|
||||
// console.log(argv);
|
||||
|
||||
const inputFilename = 'input' in argv ? argv.input : '/dev/stdin';
|
||||
const source = fs.readFileSync(inputFilename, 'utf-8');
|
||||
|
||||
const { text, map } = compile({
|
||||
source,
|
||||
name: inputFilename,
|
||||
runtime: argv.runtime,
|
||||
module: argv.module,
|
||||
});
|
||||
map.sourcesContent = [source];
|
||||
|
||||
function mapDataURL() {
|
||||
const mapData = Buffer.from(JSON.stringify(map)).toString('base64')
|
||||
return `data:application/json;base64,${mapData}`;
|
||||
}
|
||||
|
||||
if (argv.output !== null) {
|
||||
if (!argv.map) {
|
||||
fs.writeFileSync(argv.output, text);
|
||||
} else if (argv.mapExtension) {
|
||||
const mapFilename = argv.output + argv.mapExtension;
|
||||
fs.writeFileSync(argv.output, text + `\n//# sourceMappingURL=${mapFilename}`);
|
||||
fs.writeFileSync(mapFilename, JSON.stringify(map));
|
||||
} else {
|
||||
fs.writeFileSync(argv.output, text + `\n//# sourceMappingURL=${mapDataURL()}`);
|
||||
}
|
||||
} else {
|
||||
if (!argv.map) {
|
||||
console.log(text);
|
||||
} else {
|
||||
console.log(text + `\n//# sourceMappingURL=${mapDataURL()}`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
"types": "lib/index.d.ts",
|
||||
"author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>",
|
||||
"dependencies": {
|
||||
"preserves": "0.4.0"
|
||||
"preserves": "0.4.0",
|
||||
"yargs": "^16.2.0"
|
||||
},
|
||||
"bin": {
|
||||
"syndicatec": "./bin/syndicatec.js"
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import * as fs from 'fs';
|
||||
import * as S from '../syntax/index.js';
|
||||
import { Substitution } from '../syntax/index.js';
|
||||
import * as G from './grammar.js';
|
||||
|
@ -13,17 +12,41 @@ export function stripShebang(items: S.Items): S.Items {
|
|||
return items;
|
||||
}
|
||||
|
||||
export function main(argv: string[]) {
|
||||
let [ inputFilename ] = argv.slice(2);
|
||||
inputFilename = inputFilename ?? '/dev/stdin';
|
||||
const source = fs.readFileSync(inputFilename, 'utf-8');
|
||||
export interface CompileOptions {
|
||||
source: string,
|
||||
name?: string,
|
||||
runtime?: string,
|
||||
module?: 'es6' | 'require' | 'global',
|
||||
global?: string,
|
||||
}
|
||||
|
||||
export interface CompilerOutput {
|
||||
text: string,
|
||||
map: S.SourceMap,
|
||||
}
|
||||
|
||||
export function compile(options: CompileOptions): CompilerOutput {
|
||||
const inputFilename = options.name ?? '/dev/stdin';
|
||||
const source = options.source;
|
||||
const moduleType = options.module ?? 'es6';
|
||||
|
||||
const scanner = new S.StringScanner(S.startPos(inputFilename), source);
|
||||
const reader = new S.LaxReader(scanner);
|
||||
let tree = stripShebang(reader.readToEnd());
|
||||
let macro = new S.Templates();
|
||||
|
||||
tree = macro.template()`import * as __SYNDICATE__ from '@syndicate/core';\n${tree}`;
|
||||
const runtime = options.runtime ?? '@syndicate/core';
|
||||
switch (moduleType) {
|
||||
case 'es6':
|
||||
tree = macro.template()`import * as __SYNDICATE__ from ${JSON.stringify(runtime)};\n${tree}`;
|
||||
break;
|
||||
case 'require':
|
||||
tree = macro.template()`const __SYNDICATE__ = require(${JSON.stringify(runtime)});\n${tree}`;
|
||||
break;
|
||||
case 'global':
|
||||
tree = macro.template()`const __SYNDICATE__ = ${runtime};\n${tree}`;
|
||||
break;
|
||||
}
|
||||
|
||||
let passNumber = 0;
|
||||
let expansionNeeded = true;
|
||||
|
@ -167,19 +190,29 @@ export function main(argv: string[]) {
|
|||
s => macro.template()`addChildFacet(function (thisFacet) {${s.body}});`);
|
||||
expand(
|
||||
G.bootStatement,
|
||||
s => macro.template()`export function ${BootProc}(thisFacet) {${s}}`);
|
||||
s => {
|
||||
switch (moduleType) {
|
||||
case 'es6':
|
||||
return macro.template()`export function ${BootProc}(thisFacet) {${s}}`;
|
||||
case 'global':
|
||||
return macro.template()`module.exports.${BootProc} = function (thisFacet) {${s}};`;
|
||||
case 'require':
|
||||
return macro.template()`function ${BootProc}(thisFacet) {${s}}`;
|
||||
}
|
||||
});
|
||||
expandFacetAction(
|
||||
G.stopStatement,
|
||||
s => macro.template()`_stop(function (thisFacet) {${s.body}});`);
|
||||
}
|
||||
|
||||
// console.log(`\n\n\n======================================== FINAL OUTPUT\n`);
|
||||
console.log(S.itemText(tree));
|
||||
// console.log(S.itemText(tree));
|
||||
|
||||
const cw = new S.CodeWriter(inputFilename);
|
||||
cw.emit(tree);
|
||||
fs.writeFileSync('/tmp/adhoc.syndicate', cw.text);
|
||||
const mm = cw.map;
|
||||
mm.sourcesContent = [source];
|
||||
fs.writeFileSync('/tmp/adhoc.syndicate.map', JSON.stringify(mm));
|
||||
|
||||
return {
|
||||
text: cw.text,
|
||||
map: cw.map,
|
||||
};
|
||||
}
|
|
@ -1 +1,4 @@
|
|||
export * as Grammar from './grammar.js';
|
||||
export * as Internals from './internals.js';
|
||||
export * as Codegen from './codegen.js';
|
||||
export { compile, CompileOptions } from './codegen.js';
|
||||
|
|
Loading…
Reference in New Issue