UNPKG

tstosc

Version:

A transpiler that convert TypeScript to SuperCollider's SCLang.

55 lines (52 loc) 3.48 kB
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 };