From addb74deb38785698a9ed23d3e3b5d589e10f5fe Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 19 Jul 2022 13:34:07 +0800 Subject: [PATCH 1/2] Update README.md --- README.md | 336 +----------------------------------------------------- 1 file changed, 1 insertion(+), 335 deletions(-) diff --git a/README.md b/README.md index dda6bd6c..80e2d5e1 100644 --- a/README.md +++ b/README.md @@ -1,339 +1,5 @@ -## TurboWarp/scratch-vm +##### this are fork from [LLK/scratch-vm](https://github.com/LLK/scratch-vm/) and merged with [TurboWarp/scratch-vm ](https://github.com/TurboWarp/scratch-vm) -Modified Scratch VM with a JIT compiler and more features. -The public API of TurboWarp/scratch-vm should be compatible with LLK/scratch-vm. See "Public API" section below for more information. -## Setup -See https://github.com/TurboWarp/scratch-gui/wiki/Getting-Started to setup the complete TurboWarp environment. - -If you just want to play with the VM then it's the same process as upstream scratch-vm. - -## Public API - -Any public-facing API in LLK/scratch-vm *should* work just fine in TurboWarp/scratch-vm. Anything that doesn't is a bug. TurboWarp adds some new methods to the public API. - -### Runtime.setFramerate / VirtualMachine.setFramerate - -setCompatibilityMode is deprecated (but still works) in favor of a generic setFramerate method. - -```js -runtime.setFramerate(60); -``` - -There is an event for framerate changes on Runtime and VirtualMachine: FRAMERATE_CHANGED (emitted with new framerate as only argument) - -### Runtime.setInterpolation / VirtualMachine.setInterpolation - -Toggles frame interpolation, an experimental feature that tries to make project motion smoother without changing the script tick rate. - -There is an event for changes on Runtime and VirtualMachine: INTERPOLATION_CHANGED - -### Runtime.setCompilerOptions / VirtualMachine.setCompilerOptions - -This lets you change the behavior of the compiler. This method takes an object with the following arguments: - - - enabled (boolean; default true) - controls whether the JIT compiler is enabled - - warpTimer (boolean; default false) - controls whether to use a warp timer to limit how long warp scripts can run. Can have significant performance impact - -```js -runtime.setCompilerOptions({ - enabled: true, - warpTimer: true -}); -// Partial updates are also supported -- this will only change `enabled` and not any other properties -runtime.setCompilerOptions({ enabled: false }); -``` - -There is an event for compiler option changes on Runtime and VirtualMachine: COMPILER_OPTIONS_CHANGED (called with current options) - -### Runtime.setRuntimeOptions / VirtualMachine.setRuntimeOptions - -Similar to setCompilerOption. This lets you control some behavior of the runtime. - - - maxClones (number; default 300) - controls the clone limit; Infinity to disable - - miscLimits (boolean; default true) - controls various limits such as pitch, pan, etc. - - fencing (number; default true) - controls whether sprite fencing should be enabled - -There is an event for runtime option changes on Runtime and VirtualMachine: RUNTIME_OPTIONS_CHANGED (called with current options) - -### Runtime.stop / VirtualMachine.stop - -Stops the tick loop. This does not touch the active thread list. Anything currently active will be resumed when start is called again. - -There is an event for stop on Runtime and VirtualMachine: RUNTIME_STOPPED (similar to RUNTIME_STARTED) - -### Runtime.stageWidth / Runtime.stageHeight - -These control the width and height of the stage. Set them to values other than 480 and 360 respectively to get custom stage sizes. Keep in mind that you need to manually resize the renderer as well. - -### COMPILE_ERROR event - -A COMPILE_ERROR is fired on Runtime and VirtualMachine when a script couldn't be compiled. - -## Extension authors - -If you only use the standard reporter, boolean, and command block types, everything should just work without any changes. - -## Compiler Overview - -The source code for the compiler is in src/compiler. Script compilation happens "Just In Time" when a thread is started. - -I'm going to try to explain some of the high-level details of the compiler below. If you have any questions, just ask. Open an issue or something, I'm very easy to get ahold of. - -### Intermediate representation - -Source: src/compiler/irgen.js - -The first stage of the compiler is to generate an intermediate representation (IR). This is really just a more abstract version of Scratch's AST. Some analysis and optimizations happen at this stage. - -In the future there may also be multiple different code generators, and having this abstraction will be even more useful then. - -### JavaScript generation - -Source: src/compiler/jsgen.js - -The IR is passed into the JavaScript generator which descends the IR and generates optimized JavaScript. This JavaScript has some idiosyncrasies. I'll try to explain some of them using a simple project with a bouncing cat (https://scratch.mit.edu/projects/437419376) as an example. - -This is an example result of compiling a project. - -```js -function factory0 (target) { - // Note: manually formatted to be more readable. The actual code has no indentation or other formatting. - const runtime = target.runtime; - const stage = runtime.getTargetForStage(); - - const b0 = stage.variables["`jEk@4|i[#Fk?(8x)AV.-my variable"]; - - return function* gen0 () { - b0.value = 0; - target.setXY(0, 0); - - for (var a0 = 100; a0 >= 0.5; a0--) { - b0.value = ((+b0.value || 0) + 1); - runtime.ext_scratch3_motion._moveSteps(b0.value, target); - runtime.ext_scratch3_motion._ifOnEdgeBounce(target); - - if (thread.warp === 0) yield; - } - - retire(); - }; -} -``` - -There's a lot to unpack here, so let's start from the top. - -#### Factory function - -The factory function is the function that the JavaScript generator returns. This is run once when a thread is started. This function takes the current target as an argument, sets up any required variables, and returns another function (keep reading). There is also an implied `thread` variable that represents the current thread. - -#### Factory variables - -The factory function sets up various pieces of data that the script needs to run. For example, every script gets access to the `runtime` and `stage` objects. These variables will be shared amongst all instances of the generator function returned by the factory function (described below). - -#### Generator function - -The factory function returns a generator function. When a script is run, this is the code that runs. If a procedure runs 20 times, this script runs 20 times. If a procedure never runs, this function is never run. - -This function is usually a [generator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*). The interesting thing about generator functions is that they can yield at arbitrary points and resume later, which is necessary to support control flow used by Scratch. - -#### The actual script - -Let's break this down line-by-line. - -`b0.value = 0;` - -Sets the `value` property of `b0` (a factory variable) to 0. This is where variable values are stored. - -`target.setXY(0, 0)` - -Sets the target's position to (0, 0). - -`for (var a0 = 100; a0 >= 0.5; a0--) {` - -This is really just a regular for loop that will repeat 100 times. The loop index, `a0`, is called a local variable. These are variables that are local to each invocation of the generator function. In this case, it's being used as a loop index to iterate 100 times. - -`b0.value = ((+b0.value || 0) + 1);` - -Changes `b0.value` by 1. `(+b0.value || 0)` converts the value of `b0.value` to a number (in Scratch, NaN becomes 0). This is necessary because the compiler can't statically determine that `b0.value` will always evaluate to a number. Why can't it, even when `b0.value` was just set to the number 0 earlier? Because the script may have yielded control and another script may have changed the type of the variable, as you'll see later. If the variable changes to the string "10" and the script does not perform this conversion, then you would get `"10" + 1` which evaluates to the string "101", not the number 11. - -`runtime.ext_scratch3_motion._moveSteps(b0.value, target);` - -Accesses the `scratch3_motion` extension through the runtime factory variable and calls `_moveSteps` with `b0.value` (distance to move) and `target` (the target to operate on). - -`runtime.ext_scratch3_motion._ifOnEdgeBounce(target);` - -Similar to the above, it runs the "if on edge, bounce" block on the current target. - -`if (thread.warp === 0) yield;` - -This is what makes JavaScript generator functions powerful: they can yield and resume later. This particular expression says "if not running in warp mode (run without screen refresh), then yield and let another script run." - -`retire();` - -This runs the runtime function `retire`. This function marks the current thread as finished so that it will not run again. There are many other runtime functions for lots of operations such as list replacements, insertions, gets, etc. These are defined in src/compiler/jsexecute.js - -#### Procedures - -One factory function exists for each procedure used by a thread. These work the same as described above: factory function runs once, generator functions run as needed. The only difference is that generator functions for procedures accepts arguments and can be called. - -#### Compatibility layer - -Not every block needs to be compiled to optimized JavaScript. For example, will anyone notice if the "play sound until done" block runs slightly slower than it could? Probably not. Would people notice if there was a subtle bug that broke 1 in 10 sounds? Definitely. This is why the compiler also has a "compatibility layer" that allows it to use the Scratch implementation of blocks rather than writing a second "compiled" version. - -For example, an addition in TurboWarp is compiled down to the JavaScript `+` operator: `firstThing + secondThing`. If the `+` operator instead ran in the compatibility layer, it would look like: `yield* executeInCompatibilityLayer({"OPERAND1":firstThing,"OPERAND2":secondThing}, runtime.getOpcodeFunction("operator_add"))` and the actual addition would happen in Scratch's definition of the operator_add block. - -The opcodes that this is used for are in src/engine/compat-blocks.js - -#### Errors - -When scripts can't be compiled, they run in the standard (slow) scratch-vm interpreter. This is used for some edge cases: monitor threads, unknown opcodes, edge-activated hats, other errors. - -## License - -TurboWarp's modifications to Scratch are licensed under the GNU Lesser General Public License version 3. See COPYING and COPYING.LESSER for more information. - -Original license for scratch-vm: - -``` -Copyright (c) 2016, Massachusetts Institute of Technology -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -``` - - From eb77c9f8ef12713664c070e88c3154062c8ad51d Mon Sep 17 00:00:00 2001 From: Nick Date: Tue, 19 Jul 2022 13:34:34 +0800 Subject: [PATCH 2/2] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 80e2d5e1..d78b6b51 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -##### this are fork from [LLK/scratch-vm](https://github.com/LLK/scratch-vm/) and merged with [TurboWarp/scratch-vm ](https://github.com/TurboWarp/scratch-vm) +##### This repo is forked from [LLK/scratch-vm](https://github.com/LLK/scratch-vm/) and merged with [TurboWarp/scratch-vm ](https://github.com/TurboWarp/scratch-vm)