2020-02-25 17:55:17 +01:00
|
|
|
|
2020-05-10 15:56:34 +02:00
|
|
|
import { Syntax, SyntaxKind, kindToString } from "./ast"
|
2020-02-25 17:55:17 +01:00
|
|
|
|
|
|
|
export class Emitter {
|
|
|
|
|
|
|
|
emit(node: Syntax) {
|
|
|
|
|
2020-05-10 23:50:42 +02:00
|
|
|
let out = '';
|
2020-05-10 18:21:44 +02:00
|
|
|
|
2020-02-25 17:55:17 +01:00
|
|
|
switch (node.kind) {
|
|
|
|
|
2020-05-10 18:21:44 +02:00
|
|
|
case SyntaxKind.JSReferenceExpression:
|
2020-05-10 23:50:42 +02:00
|
|
|
out += node.name;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SyntaxKind.JSConstantExpression:
|
|
|
|
if (typeof node.value === 'string') {
|
|
|
|
out += '"' + node.value + '"';
|
|
|
|
} else if (typeof node.value === 'bigint') {
|
|
|
|
out += node.value.toString();
|
|
|
|
} else {
|
|
|
|
throw new Error(`Could not emit the value of a specific JSConstantExpression.`);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SyntaxKind.JSFunctionDeclaration:
|
|
|
|
out += 'function ' + node.name.text + '(';
|
|
|
|
//out += node.params.map(p => this.emit(p)).join(', ');
|
|
|
|
out += ') {\n';
|
|
|
|
out += '}\n\n'
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SyntaxKind.JSCallExpression:
|
|
|
|
out += this.emit(node.operator) + '(';
|
|
|
|
out += node.operands.map(op => this.emit(op)).join(', ');
|
|
|
|
out += ')'
|
|
|
|
break;
|
2020-05-10 18:21:44 +02:00
|
|
|
|
2020-05-10 15:56:34 +02:00
|
|
|
case SyntaxKind.JSSourceFile:
|
2020-02-25 17:55:17 +01:00
|
|
|
for (const element of node.elements) {
|
|
|
|
out += this.emit(element);
|
|
|
|
}
|
2020-05-10 23:50:42 +02:00
|
|
|
break;
|
2020-02-25 17:55:17 +01:00
|
|
|
|
|
|
|
default:
|
2020-05-10 15:56:34 +02:00
|
|
|
throw new Error(`Could not emit source code for ${kindToString(node.kind)}`)
|
2020-02-25 17:55:17 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-05-10 23:50:42 +02:00
|
|
|
return out;
|
|
|
|
|
2020-02-25 17:55:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-10 11:58:07 +02:00
|
|
|
/**
|
|
|
|
* A wrapper around `Emitter` for quick emission of AST nodes with sane defaults.
|
|
|
|
*/
|
|
|
|
export function emit(node: Syntax) {
|
|
|
|
const emitter = new Emitter();
|
|
|
|
return emitter.emit(node);
|
|
|
|
}
|
|
|
|
|