Home

GlitterIDE

Language Features

The current langauge used for scripting in Glitter is meant to roughly be "c like", and is mainly inspired by Java (Java being the language Glitter is developed in), with thought given to similar languages such as Javascript. Internally, this language is referred to as "guava". It is hoped that one day that a Python like language will also be available (being functionally similar, but having syntax similar to Python.

Basics

Code in guava/Glitter is written similar to Java/C. In particular:

The actually substance of the code mimics, in general, the form of a Scratch script. In particular:

Differences from Scratch include the following:

Writing a Flag block

Flag blocks are started whenever the "flag" button is pushed (and/or when the progject is run). An example is as follows:

      
        flag {
          print("Hello, I am in a flag block");
          repeat(10) {
            turnLeft(10);
            move(10);
          }
          repeat(10) {
            turnRight(10);
            move(10);
          }
        }
      
    

Note the use of the curly brackets "{ ... }" to mark out blocks. For each opening bracket, there should be a closing one.

Declaring Variables

Variables are declared similar to if they were being used in Java or C. In particular, the type is given first followed by the variable name, followed by an initial assignment. For example:


        int x = 4; //declare x
        string y = "cat";
        int z = 3;
        
        flag {
          print("X is:",x);
          print("Y is:",y);
          z = x+15;
          print("Z is:",z);
        }
  

The above code declares three variables (x, y, and z), where x and z have the type "int", but y is of type "string" (text). The variable z is reassigned (set in Scratch) to the value of x+15 before being used, so the output of the above would be:


      X is:4
      Y is:cat
      Z is:19
  

Typing means that a variable has a certain type of thing it can contain. The type "int" means that variable can only contain numbers (with no fractional component), and "string", means only text (though the text of numbers can be store in that variable. Thus the following code would produce an error:


      int x = 4; //declare x
      string y = "cat";
      flag {
      
        x = "dog"; //An error because x cannot be a string
        y = 4; //Not an error, because the 4 will be turned into a string for y
      }
  

Variable types

The in-built types are as follows:

Note, the type may not relate to the actual way the data is stored in the final app, for example if it is exported to Scratch or HTML, then the variables themselves will be the general untyped variables of those languages, but the typing exists to manage consistent usage of a variable (and the compiled code will try to preserve the behaviour of variables for those types). There are also some other built-in types for the C64 target environment (such as byte, and short) not covered here.

Variables can also be declared without a type using "let", which uses a general type (any), or with "var" (which gets the type from the initial value) or "app" (which by itself uses the "any" type) as follows:


    let x = 4; //x is anything
    let y = 4.2; //y is anything
    var x2 = 4; //x2 is int
    var y2 = 4.2; //y2 is float
    app z = "cat"; //z is untyped
    let z2:string = "cat"; //z is string. Don't use this syntax...
  

Note: the exact symantics of variable declaration might change. The basic Java style is fixed.

The use of app refers to the execution space of variable, and forces it to "app" space. This will be covered elsewhere.

Lists and Arrays

Coming soon...

General Control Statements

The current general control statements are similar to the ones in Scratch. In particular there are looping controls in the form of repeat count, forever, and repeat until. In addition there is a while loop form. There are started if/else constructs too. For example:


    flag {
      if(a==4) {
        print("A is 4");
      }
      
      if(b<3) {
        print("B is less than 3");
      } else {
        print("B is greater than or equal to 3");
      }
      
      repeat(10) {
        print("Doing this 10 times");
      }
      a = 0;
      repeat until (a==10) {
        print("A is :",a);
        a = a+1;
      }
      while(a>0) {
        print("A is :",a);
        a -= 1;
      }
      forever {
        print("Round and round!!!");
      }
      //Could also do
      while(true) {
        print("Round and round and round!!!");      
      }
    }
  

Declaring and using blocks

Blocks are declared roughly like functions in other languages. A type is required for any parameter, but the type "any" may be used. For exmaple:


	block cat(int count) {
		repeat(count) {
			print('Cat!!");
		}
	}
	
	flag {
		cat(4);
	}
  

Messages

The message system has three parts. The first is the message declaration, which must currently be in the Stage script. (Later versions will allow messages to be declared via the GUI). This is simply a declaration of the name of the message using the message keyword. For example:


	message doStuff; //Must be in the Stage scripts
	
	message doOtherStuff;
  

The second part is the message handlers. These are declared similar to a Flag block, but using the 'on' keyword. They occur in either the Stage or in a sprite. For example:


	on doStuff {
		turnLeft(10);
		move(20);
	}
	on doOtherStuff {
		repeat(10) {
			turnRight(10);
		}
	}
	flag {
		print("Not an message handler");
	}
  

The third and final part is the broadcasting of messages. Broadcasts can occur in either Stage or sprites. They are invoked with the 'broadcast' keyword. For example:


		flag {
			waitTime(3); //Wait three seconds
			broadcast doStuff;
			waitTime(3); //Wait three more seconds
			broadcast doOtherStuff;
		}
  

It is possible to "broadcast and wait". This means to broadcast the message, and then wait for all event handlers, that were started as a result of that broadcast, to finsih. This is done by append "..." to the broadcast command. For example:


		flag {
			broadcast doOtherStuff...
			//This script will pause while other event handlers for doOtherStuff messages execute
			broadcast doStuff;
		}
  

In the current version of GlitterIDE broadcast will restart all message event handlers (once per update frame), roughly inline with Scratch, but future versions will allow broadcasting that does not restart event handlers if already running, and event handlers that cannot be restarted.

Declaring Blocks

Blocks are chunks of reusable code, one to one with blocks in Scratch, and like simple procedures in other languages. They do not return a value.

Blocks are declared similar to event blocks, but with the block keyword followed by a (bracket, comma seperated) list of parameters. For example:


			block doStuff(int x, string text) {
				repeat(x) {
					print("Text:",text);
				}
			}
	  

In the above example the block is given the name "doStuff", and takes two parameters: "x" an integer, and "text", a string.

Calling Blocks

To use a block, the syntax is similar to using built-in functions (and similar to other languages like C or Java). For example, given "doStuff" has been defined as previously, the following may be used:


			flag {
				print("Testing doStuff");
				doStuff(2,"Two times");
				doStuff(3,"Three times");
			}
	  

Supplied parameters values can be named, but this is not recommended for now (unpolished feature). But you could do the following:


			flag {
				print("Testing doStuff");
				doStuff(x: 2, text: "Two times");
				doStuff(text: "Three times", x: 3);
			}
	  

Turbo Blocks

In Scratch blocks can be set to "run without screen refresh", which will run the block at maximum speed. A similar feature is in GlitterIDE where a block can be set to be "turbo" (internally a "strong" thread), which does not yeild to the next frame when the display has been updated. Such blocks are defined exactly like with normal blocks but after the block a "*" or "!" is written to indicate turbo running. For example:


			int count = 0;
			//Older syntax, probably to be avoided as "*" means other things in other languages
			block* fastStuff1(int x) {
				repeat(x) {
					count = count+1;
				}
			}
			//Possible new syntax, may be better to use
			block! fastStuff2(int x) {
				repeat(x) {
					count = count-11;
				}
			}
	  

Local Variables in Blocks

The current version of GlitterIDE does not, in general, support local variables in blocks (or anywhere), as Scratch does not support this. This is planned to change in the near future (as well as functions that return values some time after). Local variables can be used, but not if they are modified in a runtime dependent way. So, for example the following is possible:


			block doStuff2(string text) {
				 int x = 4;
				int total = 0;
				while(x>0) {
					total+=x;
					x-=1;
				}
				print(text, total);
			}
	  

This works because the while loop is done at the generating stage, and so the generated code is just a single statement:


		  //Actual generated code
			block doStuff2(string text) {
				print(text, 10);
			}
	  

Note, the actual rules around when things can and can't be used this way are complex. In general though, a local variable can be declared if its value is not changed, or is changed within a scope not dependent on runtime factors (beyond the scope of this quick intro). Also, there are bugs in the compilier, so it fails if "x = x-1" is used in the example instead (this will be fixed!) Note though, that poor code can get the compilation stage stuck in an infinite loop.

Constructors

A feature of GlitterIDE not in Scratch (but is compiled to Scratch output) is the use of sprite "constructors". A constructor is declared in the same way as a block, but with the constructor keyword instead (and without a name). So, for example:


		costructor(float startX, float startY) {
			goXY(startX, startY);
		}
	  

The above constructor takes two parameters which are used to set the current position of the sprite. Constructors can only be declared within sprites, not within the stage. A sprite can only have one constructor.

Creating a New Sprite Instance

The purpose of the constructor is enable the use of sprite instantiating by other sprites, or the stage. This is essentially a suped up version of sprite cloning (but conceptionally more useful). Creating a new instance requires the use of the "new" keyword, and is similar to calling a function. For example, given a sprite with the class name "Ball", that has a constructor define as in the previous constructor example, a new Ball can be created as follows:


		flag {
		  new Ball(100,100);
		  new Ball(-100,100);
		  new Ball(-100,-100);
		  new Ball(100,-100);
		}
	  

The above will create four new clones of the Ball sprite, and call the constructor on each clone. The constructor will then move the new clone to the new position. Note, that since the underlying mechanism is still cloning, by default the aspects of the new Sprite will be copied from the current state of the original sprite.

Advanced Constructors

Constructors start in a new thread, so can do multi-frame actions like any other event code. For example:


		costructor(int arc) {
			repeat(arc) {
				turnLeft(10);
				move(10);
			}
		}
	
Like blocks they can normal or turbo. To declare constructor as a turbo one, use a "*" or "!" after the constructor keyword. For example:


		int total = 0;
		costructor*(int count,int arc) {
			repeat(arc) {
				turnLeft(10);
				move(10);
				repeat(count) {
					total+=1
				}
			}
		}