A simple compiler to compile FUSE language to intermediate representation (IR). You will need it for many applications (LSP, FUSE to Scratch, etc.).
This repository contains the core of a compiler/tooling library written in TypeScript. It includes built-in modules under src/builtins/ and the compiler implementation under src/compiler/. The project uses tsup for bundling and build tasks and is intended to be used as a Node.js library or integrated into a larger toolchain.
- Written in TypeScript with type definitions
- Built-in modules (see
src/builtins/) - Simple build configuration using
tsup(tsup.config.ts) - Decompiler - Convert IR back to AST for analysis and transformation
The decompiler allows you to convert compiled IR (Intermediate Representation) back into FUSE AST nodes. This is useful for:
- Code analysis and transformation
- Round-trip compilation testing
- IR optimization and refactoring
- Creating code generation tools
-
Smart Variable Naming: Automatically handles variable name conflicts and generates valid identifiers
- Prefers original variable names when valid
- Handles conflicts between global and local variables
- Generates
var1,var2, etc. for invalid or conflicting names
-
Function Format Detection: Automatically detects compiler-generated vs export formats
- Parses
functionName(param1 = %s, param2 = %b)format - Handles parameter name conflicts
- Generates
arg1,arg2, etc. for invalid parameter names
- Parses
-
Operator Reconstruction: Reconstructs complex operators from IR
- Detects
!=,<=,>=fromoperator_notpatterns - Preserves operator precedence
- Handles nested expressions
- Detects
-
Namespace Matching: Attempts to match unknown blocks to namespace entries
- Matches opcode, fields, and inputs
- Generates namespace member calls (
namespace.member()) - Falls back gracefully for unmatched blocks
import {
createDecompiler,
Scope,
Namespace,
Variable
} from '@scratch-fuse/compiler'
// Setup variables
const globalVariables = new Map<string, Variable>()
globalVariables.set('score', {
name: 'score',
exportName: null,
type: 'scalar',
isGlobal: true
})
// Create scope and decompiler
const globalScope = new Scope(globalVariables)
const namespaces = new Map<string, Namespace>()
const decompiler = createDecompiler(globalScope, namespaces)
// Decompile a variable
const variable: Variable = {
name: 'myVar',
exportName: null,
type: 'scalar',
isGlobal: false
}
const varDecl = decompiler.decompileVariable(variable, 0)
// Result: { type: 'VariableDeclaration', name: 'myVar', ... }
// Decompile blocks
const block: Block = {
opcode: 'data_setvariableto',
fields: { VARIABLE: 'score' },
inputs: { VALUE: { type: 'any', value: '10' } }
}
const stmt = decompiler.decompileBlock(block)
// Result: { type: 'AssignmentStatement', left: ..., operator: '=', right: ... }
// Decompile a function
const proccode = 'moveBy(x = %s, y = %s)'
const impl: Block[] = [
/* function blocks */
]
const funcDecl = decompiler.decompileFunction(proccode, impl)
// Result: { type: 'FunctionDeclaration', name: { name: 'moveBy' }, ... }- All generated tokens have
line: 0andcolumn: 0 - The
exportNamefield is set tonullwhen it matches the generated name - For variables, global variables have priority in name resolution
- For functions, parameter names are resolved to avoid conflicts with function-scoped variables
-
Clone the repository and open the project folder.
-
Install dependencies:
npm install- Build the project (if a build script is present):
npm run buildNote: The repository includes a tsup.config.ts file. If you use a custom build flow or tooling, consult that file for configuration details.
src/— TypeScript source filesbuiltins/— built-in features and sb3-related implementationcompiler/— compiler core implementationindex.ts,global.d.ts— package entry point and global type declarations
tsup.config.ts— bundler/build configurationpackage.json— npm configuration and scriptsLICENSE— license file
See the files under src/ for more implementation details.
Contributions are welcome via issues and pull requests. Please ensure code formatting and tests (if any) pass before opening a PR and describe the purpose of changes in the PR description.
MPL-2.0. See the LICENSE file for details.