tstosc
Version:
A transpiler that convert TypeScript to SuperCollider's SCLang.
55 lines (52 loc) • 3.48 kB
JavaScript
import ts from 'typescript';
import { generateVarConstDeclarationAndDefinition } from '../name_decl_def_hoist.js';
import { convertTSStatementToSC } from './stmt_conv.js';
import { default_generator_context } from '../context.js';
function convertTSCodeBlockToSC(block, generator_context = default_generator_context) {
const { indent_level, is_standalone_statement, statement_label } = generator_context;
const generator_context_new = generator_context.clearedStatementLabel();
const name_decl_def_hoist = generateVarConstDeclarationAndDefinition(
block,
generator_context_new
).indent(is_standalone_statement ? indent_level : 0);
const sep = name_decl_def_hoist.length > 0 ? "\n" : "";
const stmts_without_decl_def = block.statements.filter(
(s) => !ts.isDeclarationStatement(s)
);
const is_early_return = generator_context_new.with_early_return || !generator_context_new.is_generating_method && hasEarlyReturnIn(block.statements);
const stmts_in_sc = [
...stmts_without_decl_def.map(
(s) => convertTSStatementToSC(s, generator_context_new.withEarlyReturn(is_early_return))
)
].filter((s) => s.trim().length > 0).join("\n");
let result = `${name_decl_def_hoist}${sep}${stmts_in_sc}`;
if (statement_label != "") {
result = `block { |tstosc__label__${statement_label}|
${result.indent(1)}
} ;`;
}
return result;
}
function hasEarlyReturnIn(stmts, at_outest_level = true) {
function hasEarlyReturnInBlockOrOfStatement(s, at_outest_level2 = true) {
return ts.isBlock(s) ? hasEarlyReturnIn(s.statements, at_outest_level2) : ts.isReturnStatement(s);
}
const early_return_alike__index = stmts.findIndex(
(s, index) => (
// If is flow-control, need to check all types of them:
// `if` statement.
ts.isIfStatement(s) && // If `then` part only contains one return statement, or a block.
(hasEarlyReturnInBlockOrOfStatement(s.thenStatement, index == stmts.length - 1) || s.elseStatement != void 0 && hasEarlyReturnInBlockOrOfStatement(s.elseStatement, index == stmts.length - 1)) || (ts.isForStatement(s) || ts.isWhileStatement(s)) && hasEarlyReturnInBlockOrOfStatement(s.statement, index == stmts.length - 1) || ts.isSwitchStatement(s) && s.caseBlock.clauses.some((c) => c.statements.some((n) => ts.isReturnStatement(n))) || ts.isTryStatement(s) && (hasEarlyReturnIn(s.tryBlock.statements, index == stmts.length - 1) || s.catchClause != void 0 && hasEarlyReturnIn(s.catchClause.block.statements, index == stmts.length - 1) || s.finallyBlock != void 0 && hasEarlyReturnIn(s.finallyBlock.statements, index == stmts.length - 1)) || ts.isReturnStatement(s)
)
);
return at_outest_level ? early_return_alike__index >= 0 && early_return_alike__index < stmts.length - 1 : early_return_alike__index >= 0;
}
function convertTSCodeBlockWithEarlyReturnToSC(stmts, generator_context = default_generator_context) {
return "block { |return_with|\n".indent(generator_context.indent_level) + stmts.map(
(s) => convertTSStatementToSC(s, generator_context.indent().isStandalongStatement().withEarlyReturn())
).filter((s) => s.length > 0).join(" ;\n") + "\n" + "} ;".indent(generator_context.indent_level);
}
function isTSFlowControlStatement(stmt) {
return ts.isIfStatement(stmt) || ts.isSwitchStatement(stmt) || ts.isIterationStatement(stmt, true) || ts.isTryStatement(stmt);
}
export { convertTSCodeBlockToSC, convertTSCodeBlockWithEarlyReturnToSC, hasEarlyReturnIn, isTSFlowControlStatement };