At least *propagate* unhandlable-binder-guard errors

This commit is contained in:
Tony Garnock-Jones 2021-12-08 14:29:28 +01:00
parent 4ad2dd69a6
commit 7b137bea06
4 changed files with 31 additions and 7 deletions

View File

@ -29,6 +29,8 @@ export function stripShebang(items: Items): Items {
export type ModuleType ='es6' | 'require' | 'global'; export type ModuleType ='es6' | 'require' | 'global';
export type ErrorSink = (message: string) => void;
export interface CompileOptions { export interface CompileOptions {
source: string, source: string,
name?: string, name?: string,
@ -36,6 +38,7 @@ export interface CompileOptions {
module?: ModuleType, module?: ModuleType,
global?: string, global?: string,
typescript?: boolean, typescript?: boolean,
emitError: ErrorSink,
} }
export interface CompilerOutput { export interface CompilerOutput {
@ -49,14 +52,17 @@ export class ExpansionContext {
readonly parser: SyndicateParser; readonly parser: SyndicateParser;
readonly moduleType: ModuleType; readonly moduleType: ModuleType;
readonly typescript: boolean; readonly typescript: boolean;
readonly emitError: (message: string) => void;
nextIdNumber = 0; nextIdNumber = 0;
constructor(moduleType: ModuleType, constructor(moduleType: ModuleType,
typescript: boolean) typescript: boolean,
emitError: ErrorSink)
{ {
this.parser = typescript ? new SyndicateTypedParser : new SyndicateParser(); this.parser = typescript ? new SyndicateTypedParser : new SyndicateParser();
this.moduleType = moduleType; this.moduleType = moduleType;
this.typescript = typescript; this.typescript = typescript;
this.emitError = emitError;
} }
quasiRandomId(): string { quasiRandomId(): string {
@ -72,7 +78,7 @@ function stringifyId(i: Identifier): Items {
return [ { ... i, type: TokenType.STRING, text: JSON.stringify(i.text) } ]; return [ { ... i, type: TokenType.STRING, text: JSON.stringify(i.text) } ];
} }
function binderTypeGuard(t: TemplateFunction): (binder: Binder, index: number) => Items { function binderTypeGuard(ctx: ExpansionContext, t: TemplateFunction): (binder: Binder, index: number) => Items {
return (binder, index) => { return (binder, index) => {
if (binder.id.text[0] === '_') { if (binder.id.text[0] === '_') {
return t`${`/* Ignoring underscore-prefixed binder ${binder.id.text} */`}`; return t`${`/* Ignoring underscore-prefixed binder ${binder.id.text} */`}`;
@ -93,8 +99,8 @@ function binderTypeGuard(t: TemplateFunction): (binder: Binder, index: number) =
case 'any': case 'any':
return bind; return bind;
default: default:
// TODO: something better than this!! ctx.emitError(`Cannot emit guard for binding of type: ${JSON.stringify(typeText)}`);
throw new Error(`Unhandled binding type: ${JSON.stringify(typeText)}`); return bind; /* act as if "any", for now */
} }
} }
}; };
@ -136,7 +142,7 @@ export function expand(tree: Items, ctx: ExpansionContext): Items {
observer: __SYNDICATE__.Turn.ref(__SYNDICATE__.assertionFacetObserver( observer: __SYNDICATE__.Turn.ref(__SYNDICATE__.assertionFacetObserver(
(${ctx.argDecl(t, '__vs', '__SYNDICATE__.AnyValue')}) => { (${ctx.argDecl(t, '__vs', '__SYNDICATE__.AnyValue')}) => {
if (Array.isArray(__vs)) { if (Array.isArray(__vs)) {
${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} ${joinItems(sa.captureBinders.map(binderTypeGuard(ctx, t)), '\n')}
${walk(s.body)} ${walk(s.body)}
} }
} }
@ -202,7 +208,7 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')}
const sa = compilePattern(s.pattern); const sa = compilePattern(s.pattern);
const guardBody = (body: Statement) => t`if (Array.isArray(__vs)) { const guardBody = (body: Statement) => t`if (Array.isArray(__vs)) {
${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} ${joinItems(sa.captureBinders.map(binderTypeGuard(ctx, t)), '\n')}
${body} ${body}
}`; }`;
@ -281,7 +287,7 @@ export function compile(options: CompileOptions): CompilerOutput {
const macro = new Templates(undefined, { extraDelimiters: ':' }); const macro = new Templates(undefined, { extraDelimiters: ':' });
const ctx = new ExpansionContext(moduleType, typescript); const ctx = new ExpansionContext(moduleType, typescript, options.emitError);
tree = expand(tree, ctx); tree = expand(tree, ctx);

View File

@ -117,6 +117,8 @@ export function main(argv: string[]) {
argv => argv) argv => argv)
.argv); .argv);
const collectedErrors: Array<string> = [];
const rename = makeRenamer(options.outputDirectory ?? '', const rename = makeRenamer(options.outputDirectory ?? '',
options.rootDirectory ?? '.', options.rootDirectory ?? '.',
options.rename); options.rename);
@ -144,6 +146,10 @@ export function main(argv: string[]) {
runtime: options.runtime, runtime: options.runtime,
module: options.module, module: options.module,
typescript: options.typed, typescript: options.typed,
emitError: m => {
console.error(m);
collectedErrors.push(m);
}
}); });
map.sourcesContent = [source]; map.sourcesContent = [source];
@ -161,4 +167,8 @@ export function main(argv: string[]) {
fs.writeFileSync(outputFilename, text + sourceMappingComment(dataURL(JSON.stringify(map)))); fs.writeFileSync(outputFilename, text + sourceMappingComment(dataURL(JSON.stringify(map))));
} }
} }
if (collectedErrors.length > 0) {
throw new Error(`Compilation failed with ${collectedErrors.length} error(s).`);
}
} }

View File

@ -164,6 +164,10 @@ const boot: tslib.server.PluginModuleFactory = ({ typescript: ts }) => {
source: inputText, source: inputText,
name: fileName, name: fileName,
typescript: true, typescript: true,
emitError: m => {
console.error(m);
onError?.(m);
},
}); });
const sf = ts.createSourceFile(fileName, expandedText, languageVersion, true); const sf = ts.createSourceFile(fileName, expandedText, languageVersion, true);
syndicateInfo.set(fileName, { syndicateInfo.set(fileName, {

View File

@ -150,6 +150,10 @@ function runBuildOnce(options: CommandLineArguments, toWatch = new ToWatch()) {
source: inputText, source: inputText,
name: fileName, name: fileName,
typescript: true, typescript: true,
emitError: m => {
console.error(m);
onError?.(m);
},
}); });
writeIntermediate(fileName, expandedText); writeIntermediate(fileName, expandedText);
syndicateInfo.set(fileName, { syndicateInfo.set(fileName, {