goldfish678
Looks amazing. The only complaint I have is the Procd icon and loading screen.
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
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.
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
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
(() + ())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");
}
}
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) };
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; }
Thanks. FYI The compiler also supports http extensions. Brilliant - worked first time
Simon
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>
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>
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>
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)
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)