FUSE is a low-level programming language that compiles to Scratch. It is designed to be similar to Rust and TypeScript, making it easier for developers familiar with those languages to learn and use. FUSE aims to provide a more structured and powerful way to create Scratch projects, while still being accessible to beginners.
fn main() once -> void {
looks.say("Hello, World!")
}
event.start {
main()
}
- Familiar syntax for developers with experience in Rust and TypeScript
- Compiles to Scratch, allowing for easy sharing and execution of projects
- Supports variables, lists, and custom blocks
- Event-driven programming with Scratch hat blocks
- Type annotations for better code clarity
- Decorators for exporting blocks and variables
- Can be used as Intermediate Representation (IR) for other languages, or as a component for Scratch Addons
fn main() once -> void {
looks.say("Hello, World!")
}
event.start {
main()
}
global score = 0
global playerName = "Player"
fn checkScore() once -> void {
if (score >= 100) {
looks.say(playerName .. " wins!")
} else {
looks.say("Keep trying!")
}
}
event.start {
checkScore()
}
global numbers = [1, 2, 3, 4, 5]
global sum = 0
global i = 0
fn calculateSum() once -> void {
for (i = 0; i < numbers.length; i++) {
sum += numbers[i]
}
looks.say("Sum: " .. sum)
}
event.start {
calculateSum()
}
fn greet(name: any, times: any) once -> void {
let counter = 1
while (counter <= times) {
looks.say("Hello, " .. name .. "!")
counter++
}
}
event.start {
greet("Scratch", 3)
}
global speed = 10
fn moveCharacter() once -> void {
motion.moveSteps(speed)
if (sensing.touchingObject("_edge_")) {
motion.ifOnEdgeBounce()
}
}
event.start {
loop {
moveCharacter()
}
}
event.keyPressed("space") {
speed += 5
}
// Export Scratch blocks using @export decorator
@export("wait 1 frame") fn yield() once -> void {
}
@export("current timestamp") fn currentTimestamp() once -> any {
return sensing.daysSince2000() * 86400 * 1000
}
fn main() once -> void {
let startTime = currentTimestamp()
yield()
let endTime = currentTimestamp()
looks.say("Frame time: " .. (endTime - startTime) .. "ms")
}
event.start {
main()
}
@export("// [value]") fn description(value: any) once -> void {
// This function is a no-op, used for adding comments in the generated Scratch blocks
}
@export("drop [value]") fn drop(value: any) once -> void {
description(value)
}
@export("last timestamp") let lastTimestamp = 0
@export("current timestamp") fn currentTimestamp() once -> any {
return sensing.daysSince2000() * 86400 * 1000
}
@export("wait 1 frame") fn yield() once -> void {
drop(translate.getTranslate(1, ""))
}
fn calculateFps() once -> any {
lastTimestamp = currentTimestamp()
yield()
return 1000 / (currentTimestamp() - lastTimestamp)
}
global fps = 0
fn main() once -> void {
loop {
fps = calculateFps()
looks.say("FPS: " .. fps)
}
}
event.start {
main()
}
- Badger: FUSE works as secondary IR for Badger, a language with complex features (temporary variables, OOP, etc.).
- FSE (FUSE-based Script Editing, aka Fluent Script Editing): FUSE works as the language for FSE, a Scratch Addon that provides users a single-line input box to insert scripts immediately with autocomplete, syntax highlighting, and even AI assistance.
- Educational Tools: Create structured programming lessons for Scratch users transitioning to text-based languages.
- Code Generation: Use FUSE as a target language for visual programming tools or domain-specific languages.
For detailed language specification, see specification.md.
- Implement basic syntax and semantics
- Implement compiler to convert FUSE code to Scratch blocks
- Create documentation and examples
- Decompiler from Scratch blocks to FUSE code
- Develop LSP with syntax highlighting and autocomplete
- This project is inspired by SteveXMH's scratch-script, which provides a similar functionality for Scratch. This project is a successor to it, with a focus on a more fancy syntax and better structure.
This project is licensed under the MPL-2.0 License. See the LICENSE file for details.