Repository navigation
Scratch to C++ transpiler experiment - #695
Draft
devin-ai-integration[bot] wants to merge 3 commits into
Draft
devin-ai-integration[bot] wants to merge 3 commits into
devin-ai-integration[bot] wants to merge 3 commits into
Conversation
Co-Authored-By: zemanadam893@gmail.com <zemanadam893@gmail.com>
Co-Authored-By: zemanadam893@gmail.com <zemanadam893@gmail.com>
Co-Authored-By: zemanadam893@gmail.com <zemanadam893@gmail.com>
Author
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
adazem009
marked this pull request as draft
October 17, 2026 14:08
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note: This is just an experiment to implement the entire C++ transpiler using LLM - it will never be actually merged.
Summary
Adds a second compiler backend (
src/engine/internal/cpp/) that turns Scratch scripts into C++ source code instead of LLVM IR. It plugs in at the existingICodeBuilderFactoryboundary. The default backend is still LLVM, so nothing changes for current users.Covers backlog items #662–#681, #683–#687 and #689–#691. Not included: #682 (inlining), #693 (type analyzer) and #692 (in progress elsewhere).
How it works
CppCodeBuilderimplements all ofICodeBuilder. Each script, procedure, reporter or predicate becomes a heapFramesubclass with a switch-basedstep()state machine. This is C++17 (no C++20 coroutines needed). All registers live as frame members, so they survive yields.double,bool,cpp::Str(pooledStringPtr),cpp::Val(ValueData) andvoid *. Conversions use the publicvalue_*/string_*functions. Variables and lists are resolved fromvarData/listData(or the stage) inresolve(), which runs again afterinvalidateTarget()and procedure calls.cppprelude.his the runtime header for generated code. It only uses public headers and is embedded into the library as a string at configure time (CppCompilerContext::prelude()).CppCompilerContext::moduleSource()outputs a module whose static initializer callscpp_register_function(moduleKey, name, fn).moduleKeyis an FNV-1a hash of the generated code.CppExecutableCodelooks the function up by(moduleKey, name). So code only runs if the matching generated source was compiled into the binary.CppExecutableCodefollowsLLVMExecutableCode: it waits for unresolved promises,reset()destroys the suspended frame, and the(void *)0x1end-thread sentinel is passed up through procedure calls.listblocks) are emitted as resolved references instead of raw addresses. Other pointer constants are still only valid in the current process.Tests (#687):
test/cpphas acpp_test_generatorexecutable. At build time it runs the shared test-case builders (cases.cpp) throughCppCodeBuilderand writesgenerated_cases.cpp, which is compiled intocpp_test.cpp_testthen rebuilds the same cases and runs the resultingExecutableCode, checking stdout, run counts and return values. It also covers promise/kill/reset and the codebase generator. 24 tests pass locally, with and withoutLIBSCRATCHCPP_ENABLE_SANITIZER.Codebase generation (#683–#686):
CppCodebaseGenerator::generate(sb3, outDir, name)loads the project with a recording C++ factory and writes:project.cpp: the prelude plus all modulesproject_data.cpp: the.sb3as a byte arraymain.cpp: extracts the.sb3to a temp file, callscpp_use_cpp_backend(), then runsProject::load()andrun()CMakeLists.txt: uses eitherLIBSCRATCHCPP_SOURCE_DIRor a prebuiltLIBSCRATCHCPP_INCLUDE_DIR/LIBSCRATCHCPP_LIBRARYThe new
scratchcpp-transpiler <project.sb3> <outdir> [name]tool (optionLIBSCRATCHCPP_BUILD_TRANSPILER, default ON) wraps the generator. I checked this locally ontest/custom_blocks.sb3andtest/bubble_sort.sb3: the generated projects build and run against libscratchcpp.3_threads.sb3never finishes, but it doesn't finish with the LLVM backend either.Known limitations / review focus
ValueData.extern "C"declarations built from theaddFunctionCallarg types. These have to match the real signatures (same requirement as LLVM)..sb3).