Discuss Scratch
- Discussion Forums
- » Advanced Topics
- » Scratch compiler beta test
- goldfish678
-
1000+ posts
Scratch compiler beta test
Looks amazing. The only complaint I have is the Procd icon and loading screen.
Last edited by goldfish678 (Oct. 12, 2014 00:25:38)
- procd
-
100+ posts
Scratch compiler beta test
The icon can be changed when compiling. What would you suggest for a load screen?
- s_federici
-
500+ posts
Scratch compiler beta test
http://www.gtoal.com/scratch/sb2c/if you're still interested in seeing (roughly) how a scratch parser works, I just put up my prototype scratch to C code at
This is not the full Scratch 2 exe converter, is it? Or, if it is, what is the best (hopefully free) environment to edit, compile and run it? I used to use MS Visual Studio some years ago, but I lost track of the development of C programming environments in the last years :-) Thanks in advance for your help.
- gtoal
-
1000+ posts
Scratch compiler beta test
http://www.gtoal.com/scratch/sb2c/if you're still interested in seeing (roughly) how a scratch parser works, I just put up my prototype scratch to C code at
This is not the full Scratch 2 exe converter, is it? Or, if it is, what is the best (hopefully free) environment to edit, compile and run it? I used to use MS Visual Studio some years ago, but I lost track of the development of C programming environments in the last years :-) Thanks in advance for your help.
No, this won't create anything that you can run. It was a quick proof of concept for me to see how much work might be involved in writing a scratch converter, but that was before I was aware of the work that procd had done which is almost complete, so I'm unlikely to take this any farther. But I thought I might leave it online so that if anyone wanted to play around with this stuff, they could use it for some ideas to get started.
It's just C and should run on any environment, but if you don't have linux you'll need to modify it to read the json file into an array, because I took a unix shortcut and loaded the file by connecting it directly in the virtual memory using mmap. (The bits you would have to modify are all in main() near the end of the file - open/lseek/mmap should be replaced with stdio calls.)
Graham
PS “cc”, a text editor, and possibly “make” are the only IDE you need. These ridiculous GUIs just slow you down and obfuscate what you're actually doing. (A bit like C++ itself)
Last edited by gtoal (Oct. 14, 2014 22:06:02)
- procd
-
100+ posts
Scratch compiler beta test
The following text are my thoughts before I started to write the compiler. Most of the ideas are still present in the compiler. NOt sure ow much sense it will make 

ScratchBlock -> Returns ScratchBlock when Invoked to allow chaining
ScratchBlock is a function or ScratchBlock is a Value
abstract ScratchBlock
Concrete ScratchFunction
Concrete ScratchValue = String,Int?,Float?,Bool?, (void/null?)
Selector -
ScratchFunction LeftArg RighArg -> ScratchValue
ScratchFuntion will Evaluate each Arg until it becomes a ScratchValue perform the function and return the ScratchValue
ScratchFunction => delegate ScratchBlock fn(ScratchObject this, ScratchBlock Args) // Type called fn with this function pattern
public ScratchBlock Subtract(ScratchObject this, ScratchBlock Args)
{
Assert Args.Count = 2;
ScratchValue leftARg = Eval Args 0
ScratchValue RightARg = Eval Arg 1
return new ScratchValue (leftArg - RightArg)
}
ScratchFunction
{
fn Invoke = Subtract;
}
BlockRunner to call SCratchBlocks => ScratchBlock only ever returns ScratchBlock or End?
ScratchValue
1/0 = (String)Infinity
Numeric operation on a string then take value of string as 0
boolean to string is true or false
Want a ScratchBlockFactory to make ScratchBlocks from Selector Names (Block Names)
Runner
Passed the first block in the script so has a ScratchBlock
(Note: Compiler check/optimisation only compile scripts that start with an event and are followed by at least one block.)
SCratchBlock needs to know the next block.
BlockRunner
{
ScratchBlock currentBlock;
ScratchObject this;
public void LoadScript(ScratchObject this, ScratchBlock start)
{
currentBlock = start;
this.this = this !
}
public ScratchBlock RunOneBlock()
{
if currentBlock is a ScratchFunction
return currentBlock = currentBlock.Invoke(this)
else
return currentBlock
}
public bool IsFinished()
{
return (currentBlock is a ScratchValue);
}
}
Let's have the this object as an interface call IScratchObject. This can the be implemented by the Stage, Sprites, clones etc.
Because we need to chain blocks then we need a script builder to go through the script and call block factory but remember the last block to then fix up the next block property of the previous block, do that in ScratchBlock
Which blocks wait for something to finish?
wait
glide
say for
think for
play sound until done
play drum for
rest for
play note for
broadcast and wait
ask and wait
Each IScratchObject will have a scheduler to schedule all its scripts. Wait type blocks need to remove their scripts from the scheduler until the event is complete then add back in.
What type of scripts are there (events)?
when green flag clicked
when key pressed
when sprite clicked
when backdrop switches
when loudness|timer|video motion >
when I receive
- gtoal
-
1000+ posts
Scratch compiler beta test
Are you actually turning the Scratch statements into C# source code which you then compile, or are you just embedding a data structure representing the Scratch code in a program which interprets the Scratch statements from a C# executable? I thought I understood what you were doing but now I'm completely baffled :-)
If the former, I don't suppose you could show us a snippet of some translated Scratch code to let us see what it looks like in C#?
I'm interested in how you handle some of the major underlying translation issues, eg dynamic typing. Unless you do a very complex flow analysis (which *is* possible, because unlike other languages, with a Scratch program you're always guaranteed to have the complete source code available), you can't convert to int/float/string at compile time.
I guess with a language like C++ (and I presume C#?) where you have overloaded operators, you can *write* expressions like A = A - B but they'll always be implemented behind the scenes by a mess of code rather than a simple arithmetic operation.
G
If the former, I don't suppose you could show us a snippet of some translated Scratch code to let us see what it looks like in C#?
I'm interested in how you handle some of the major underlying translation issues, eg dynamic typing. Unless you do a very complex flow analysis (which *is* possible, because unlike other languages, with a Scratch program you're always guaranteed to have the complete source code available), you can't convert to int/float/string at compile time.
I guess with a language like C++ (and I presume C#?) where you have overloaded operators, you can *write* expressions like A = A - B but they'll always be implemented behind the scenes by a mess of code rather than a simple arithmetic operation.
G
Last edited by gtoal (Oct. 14, 2014 22:02:12)
- procd
-
100+ posts
Scratch compiler beta test
When I started I wasn't sure how Scratch ran it's scripts. I thought it was a round robin approach taking a block from a script executing it then take the block from another script. I was also looking at F# at the time and liked the idea of a Scratchblock being a “value” or “function”. So the compiller is not converting to C# direct, so a forever block does not become for(;
{ } as it does in your C compiler. In this a script is effectively a linked list of ScratchBlocks. A ScratchBlock is an abstract class with 2 concrete types
1) A ScratchValue which is my solution for Scratch's dynamic typing and this represents, floats, int, string, bool, null and converts between the types as needed
2) ScratchFn which is a function call to do some work.

1) A ScratchValue which is my solution for Scratch's dynamic typing and this represents, floats, int, string, bool, null and converts between the types as needed
2) ScratchFn which is a function call to do some work.
- gtoal
-
1000+ posts
Scratch compiler beta test
When I started I wasn't sure how Scratch ran it's scripts. I thought it was a round robin approach taking a block from a script executing it then take the block from another script. I was also looking at F# at the time and liked the idea of a Scratchblock being a “value” or “function”. So the compiler is not converting to C# direct, so a forever block does not become for ( ; ; ) { } as it does in your C compiler. In this a script is effectively a linked list of ScratchBlocks. A ScratchBlock is an abstract class with 2 concrete types
Gotcha. I would call that an interpreter or VM rather than a compiler, but the name is not really important. The end result is similar. So are you saying that your multitasking is done by coroutines that you're explicitly manually scheduling yourself, rather than using C's pthreads or whatever C#'s lightweight threads are called?
G
- procd
-
100+ posts
Scratch compiler beta test
Correct. Yes compiler is potentially misleading, but for want of a better name ;-) besides it still has to compile everything to CIL and package everything into an exe.
Yes I use my own scheduler as that seemed the best way at the time. Because I thought the blocks were run round robin then if separate threads had to yield after each statement then it would be horribly inefficient. Now I know that not to be the case then perhaps I would've done things differently. It was all an exploration of what was possible at the time. I based the graphics side on monogame and the audio on naudio, both of which I'd never used before so that was an adventure too. Certainly learnt a lot about Scratch and although not perfect, pleased with the end result.
Yes I use my own scheduler as that seemed the best way at the time. Because I thought the blocks were run round robin then if separate threads had to yield after each statement then it would be horribly inefficient. Now I know that not to be the case then perhaps I would've done things differently. It was all an exploration of what was possible at the time. I based the graphics side on monogame and the audio on naudio, both of which I'd never used before so that was an adventure too. Certainly learnt a lot about Scratch and although not perfect, pleased with the end result.
- procd
-
100+ posts
Scratch compiler beta test
So
(() + ())becomes
public static ScratchBlock AddFn(IScratchThread st, ScratchBlock[] args)
{
ScratchValue l, r;
if (args[0] is ScratchFunction)
{
l = (new BlockRunner(st, args[0])).EvaluateBlock();
}
else
{
l = (ScratchValue)args[0];
}
if (args[1] is ScratchFunction)
{
r = (new BlockRunner(st, args[1])).EvaluateBlock();
}
else
{
r = (ScratchValue)args[1];
}
l = l.BestNumberFormat(l);
r = l.CastToCompatibleBlock(r);
if (l.GetScratchValueType() != r.GetScratchValueType())
{
// probably need to upconvert an int to a double to avoid overflows
l = r.CastToCompatibleBlock(l);
}
switch (l.GetScratchValueType())
{
case ScratchValue.ScratchValueType.ValueInt:
try
{
checked
{
return new ScratchValue(l.ToInt() + r.ToInt());
}
}
catch (OverflowException)
{
return new ScratchValue(l.ToDouble() + r.ToDouble());
}
case ScratchValue.ScratchValueType.ValueDouble:
return new ScratchValue(l.ToDouble() + r.ToDouble());
default:
throw new BlockException("Unexpected non-numeric Block Type");
}
}
Last edited by procd (Oct. 15, 2014 08:56:40)
- s_federici
-
500+ posts
Scratch compiler beta test
Hi, any news about when the source code will be released? 

- __init__
-
1000+ posts
Scratch compiler beta test
Well, not exactly… So(() + ())becomespublic static ScratchBlock AddFn(IScratchThread st, ScratchBlock[] args)
{
ScratchValue l, r;
if (args[0] is ScratchFunction)
{
l = (new BlockRunner(st, args[0])).EvaluateBlock();
}
else
{
l = (ScratchValue)args[0];
}
if (args[1] is ScratchFunction)
{
r = (new BlockRunner(st, args[1])).EvaluateBlock();
}
else
{
r = (ScratchValue)args[1];
}
l = l.BestNumberFormat(l);
r = l.CastToCompatibleBlock(r);
if (l.GetScratchValueType() != r.GetScratchValueType())
{
// probably need to upconvert an int to a double to avoid overflows
l = r.CastToCompatibleBlock(l);
}
switch (l.GetScratchValueType())
{
case ScratchValue.ScratchValueType.ValueInt:
try
{
checked
{
return new ScratchValue(l.ToInt() + r.ToInt());
}
}
catch (OverflowException)
{
return new ScratchValue(l.ToDouble() + r.ToDouble());
}
case ScratchValue.ScratchValueType.ValueDouble:
return new ScratchValue(l.ToDouble() + r.ToDouble());
default:
throw new BlockException("Unexpected non-numeric Block Type");
}
}
function(b:*):* { return interp.numarg(b, 0) + interp.numarg(b, 1) };

Edit: Oh wait, interp.numarg() is
public function numarg(b:Block, i:int):Number { var args:Array = b.args; if (b.rightToLeft) { i = args.length - i - 1; } var n:Number = (args[i] is BlockArg) ? Number(BlockArg(args[i]).argValue) : Number(evalCmd(Block(args[i]))); if (n != n) return 0; // return 0 if NaN (uses fast, inline test for NaN) return n; }
Last edited by __init__ (Nov. 7, 2014 22:15:29)
thisandagain pls explain
- procd
-
100+ posts
Scratch compiler beta test
Thanks. FYI The compiler also supports http extensions. Brilliant - worked first time
Simon
- __init__
-
1000+ posts
Scratch compiler beta test
Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.
C:\Users\David\Documents\procd>procd -o=test.exe "F:\FOLDER03 [scratch]\Invisible.sb2"
Procd version 1.0.0.0
2014-11-25 19:03:22.0656 procd.ScratchCompiler.Compile Error *** 50 Parsing Problems encountered. ***
2014-11-25 19:03:31.3346 procd.ScratchCompiler.Compile Error Line number 8, Error Number: CS1009, 'Unrecognized escape sequence;
2014-11-25 19:03:31.3346 procd.ScratchCompiler.Compile Error Line number 8, Error Number: CS1009, 'Unrecognized escape sequence;
2014-11-25 19:03:31.8578 procd.Program.Main Fatal Compiler Errors Compiler Errors
C:\Users\David\Documents\procd>
thisandagain pls explain
- procd
-
100+ posts
Scratch compiler beta test
If you send a link to the project then I'll taka look. Guess that there's some odd characters in your project. Possibly as a variable name or in a custom block?Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.
C:\Users\David\Documents\procd>procd -o=test.exe "F:\FOLDER03 [scratch]\Invisible.sb2"
Procd version 1.0.0.0
2014-11-25 19:03:22.0656 procd.ScratchCompiler.Compile Error *** 50 Parsing Problems encountered. ***
2014-11-25 19:03:31.3346 procd.ScratchCompiler.Compile Error Line number 8, Error Number: CS1009, 'Unrecognized escape sequence;
2014-11-25 19:03:31.3346 procd.ScratchCompiler.Compile Error Line number 8, Error Number: CS1009, 'Unrecognized escape sequence;
2014-11-25 19:03:31.8578 procd.Program.Main Fatal Compiler Errors Compiler Errors
C:\Users\David\Documents\procd>
- goldfish678
-
1000+ posts
Scratch compiler beta test
How do you copy that? I have an error code I've been wanting to report to Procd, but I can't figure out how to copy it. IgnoreMicrosoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.
C:\Users\David\Documents\procd>procd -o=test.exe "F:\FOLDER03 [scratch]\Invisible.sb2"
Procd version 1.0.0.0
2014-11-25 19:03:22.0656 procd.ScratchCompiler.Compile Error *** 50 Parsing Problems encountered. ***
2014-11-25 19:03:31.3346 procd.ScratchCompiler.Compile Error Line number 8, Error Number: CS1009, 'Unrecognized escape sequence;
2014-11-25 19:03:31.3346 procd.ScratchCompiler.Compile Error Line number 8, Error Number: CS1009, 'Unrecognized escape sequence;
2014-11-25 19:03:31.8578 procd.Program.Main Fatal Compiler Errors Compiler Errors
C:\Users\David\Documents\procd>
Last edited by goldfish678 (Nov. 26, 2014 13:45:53)
- goldfish678
-
1000+ posts
Scratch compiler beta test
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Users\NAMEEDITEDOUT>cd Documents\Scratch 2.0 Projects
C:\Users\NAMEEDITEDOUT\Documents\Scratch 2.0 Projects>procd -o="It's June!.exe" "It's J
une!.sb2"
Unhandled Exception: System.TypeInitializationException: The type initializer fo
r 'procd.Program' threw an exception. ---> System.IO.FileNotFoundException: Coul
d not load file or assembly 'NLog, Version=2.0.1.0, Culture=neutral, PublicKeyTo
ken=5120e14c03d0593c' or one of its dependencies. The system cannot find the fil
e specified.
at procd.Program..cctor()
--- End of inner exception stack trace ---
at procd.Program.Main(String[] args)
Last edited by goldfish678 (Nov. 26, 2014 13:48:31)
- procd
-
100+ posts
Scratch compiler beta test
Have you extracted the nlog.dll from the zip file to the same folder as procd.exe? (Extract all the files from the zip file to the same directory)Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Users\NAMEEDITEDOUT>cd Documents\Scratch 2.0 Projects
C:\Users\NAMEEDITEDOUT\Documents\Scratch 2.0 Projects>procd -o="It's June!.exe" "It's J
une!.sb2"
Unhandled Exception: System.TypeInitializationException: The type initializer fo
r 'procd.Program' threw an exception. ---> System.IO.FileNotFoundException: Coul
d not load file or assembly 'NLog, Version=2.0.1.0, Culture=neutral, PublicKeyTo
ken=5120e14c03d0593c' or one of its dependencies. The system cannot find the fil
e specified.
at procd.Program..cctor()
--- End of inner exception stack trace ---
at procd.Program.Main(String[] args)
- Discussion Forums
- » Advanced Topics
-
» Scratch compiler beta test