EcmaTurtle Manual

Welcome to EcmaTurtle. There is no real manual yet, but I wrote this quick introduction for you.

Except for this first section, the contents of the manual can be accessed from within the program via the context help. When you place the cursor over a known command in the source code editor, the related section is shown.

Purpose of the Program

EcmaTurtle is an educational tool and a toy. Its main focus is centered around turtle graphics. Commands similar to those found in the Logo Programming Language are provided, but JavaScript is used as the programming language instead. Because JavaScript is very flexible, you can use most programming paradigms in your programs.

As an Educational Tool

Although I tried to include a set of useful example programs, EcmaTurtle was not made for autodidact study. It is a tool for teachers, that will guide their students through the learning process.

If you are on your own, I recommend you take a look at the Learning Area of the MDN web site. You can also get help from real people on the IRC Network. You will probably want to join ##javascript on Freenode.

User Interface

Hopefully, the UI of EcmaTurtle is self-explanatory, but a few aspects may not be as intuitive:

If you run into problems, be it my software not working right or you having questions, feel free to contact me.

Context Help Pages

The following sections are used in the program as context specific help.
The links will only work on this very page, if JavaScript is enabled in your browser:

EcmaTurtle

Set the cursor on a command in the source code above to get help on it.

TurtleScript

JavaScript functions provided by EcmaTurtle:

Drawing

Control

Math

JavaScript

Predefined Objects

Supplementary Articles

Introductions on MDN

Supplementary Articles

Scope

The scope of an object (or variable, function) is the region in the program, where it is "visible"and this can be accessed. The top level is the "global scope", where your program and its functions live in. Code within curly braces gets its own new scope. While objects outside the local scope can be accessed from the inside, code outside of the scope cannot access local objects.

var myGlobalVariable = 1;

function func( myArgument ) {
	var myLocalVariable = myArgument;
	myGlobalVariable = myLocalVariable;
}

console.log(myGlobalVariable);   // Output: "1"
func(2);
console.log(myGlobalVariable);   // Output: "2"
console.log(myLocalVariable);    // Uncaught ReferenceError: myLocalVariable is not defined
console.log(myArgument);         // Uncaught ReferenceError: myArgument is not defined

It is possible to re-use a name, that already exists outside of the current scope. This makes access to the outside object impossible. It is also quesionable, if this is a good idea:

function x() {
	const y = 1;
	console.log(y);

	function z() {
		const y = 2;
		console.log(y);
	}

	z();
}

x();   // Output: "1", "2"

See also:

Hoisting

Variables declared with var are put into memory during the compile phase, before the program is started. Therfore, those variables are available, before they seemingly have been declared, as if they were automagically moved to the top of the scope. This can be prevented by never using the outdated var instruction, but instead using let (which was added to JavaScript at a later time), thus preventing nasty surprises:

function func() {
	console.log(my_var);
	console.log(my_let);

	var my_var = "This will be logged to the console.";
	let my_let = "Will trigger a Reference Error.";
}

See also:

Code Security

JavaScript is a very powerful language. Unfortunately, it has some really strange quirks, that can easily trip unexpirienced programmers, sometimes even experts are scratching their heads. It also allows you to do things, that are not always smart to do. Simpler code is safer in general, and easier to understand, when you come back to it a long time later.

Therefore, I recommend, you stick to certain coding styles and refrain from writing clever constructs. Here are a few hints, that will make your code easier to debug and will prevent certain mistakes from happenening in the first place:

See also:

Comments

are inactive parts of a source code, helping the reader to understand, what's going on.

/* This is a
multi-line comment */

const y = 1;   // The rest of this line is a comment.

/* This type of comment, can wrap around
   // this type of comment
*/

See also:

Arrays

are lists of values, which can be accessed by their index.

const myArray = [ 1, 2, "three", {"four": 4} ];

for( let i=0 ; i<myArray.length ; ++i ) {
	console.log( myArray[i] );
}

// Output:
// 1
// 2
// three
// {four: 4}

See also:

Curly Braces

can either group a set commands (scope) or be a list of key/value pairs (objects).

The if statement will always execute the next command, if the condition evaluates to true:

if (condition == true) doSomething();

In order to have it execute several commands, one can combine them into a "block", that behaves like it was one single command:

if (condition == true) {
	doSomething();
	doAnotherThing();
}

Objects

const myObject = {
	"key1": "value1",
	"key2": "value2",
};

console.log( myObject.key1    );   // Output: value1
console.log( myObject["key2"] );   // Output: value2

myObject["key3"] = "value3";
console.log(myObject.key3);        // Output: value3

const key_name = "key4";
myObject[key_name] = "value4";
console.log(myObject.key4);        // Output: value4

The variable myObject contains a reference to the data within the object and will usually not change throughout the lifetime of the variable. Therefore it should be declared const. The contents (properties) of an object are always variable.

See also:

Parentheses

Used for functions and their arguments or in mathematical expressions.

function myFunc( someArgument ) {
	console.log(someArgument);
}

myFunc("Text");   // Output: Text
const someValue = (1 + 2) / 3;

See also:

Comparisons

Comparison operators return Boolean values (true/false).

if (var1 == var2) { do_something(); }
const true_or_not = (1 < 2);   // Result: true

true also represents the value (+1), while false equals to zero:

const add_offset = true;
const offset     = 3;
const value      = 10 + (add_offset * offset);   // Result: 13

See also:

Operators

Operators combine one, two or three values. Most of the time you will see arithmetical operators (const x = a + b;) or assignments (const x = 1;).

Like in mathematics, operators have different priorities, called "operator precedence". See the MDN link below for a list of all operators and their order of precedence.

const x = 1 + 2 * 3;         // Result: 7
const x = (1 + 2) * 3;       // Result: 9
const remainder = 7 % 3;     // Modulo, remainder of division. Result: 1
const is_equal = (a == b);   // Boolean operator (equality). Result: true/false

See also:

Turtle Commands

FD(units)

moves the turtle forward. If the turtle is "down", this will draw a line.

FD(10);

See also:

BK(units)

moves the turtle backwards. If the turtle is "down", this will draw a line.

BK(10);

See also:

LT(degrees)

turns the turtle to the left.

LT(90)

See also:

RT(degrees)

turns the turtle to the right.

RT(90)

See also:

UP()

lifts the turtle, so it will not draw a line, when moving.

UP()

See also:

DN()

Lowers the turtle, so it will draw a line, while moving.

DN()

See also:

HOME()

Sets the pen to the home position (0|0) and the direction 0° (to the right).

DN()

See also:

PUSH()

Pushes position, direction, color, line width and pen up/down status to the stack.

PUSH()

See also:

POP()

Retreives position, direction, color, line width and pen up/down status from the stack.

POP()

See also:

SHOW()

Shows the pen.

SHOW()

See also:

HIDE()

Hides the pen

HIDE()

See also:

WIDTH(1/SCALE_FACTOR units)

sets the line width. At 100% zoom, a unit is SCALE_FACTOR pixels on the screen.

WIDTH(1)

COLOR("color code")

sets the drawing color. CSS color codes and names are allowed.

COLOR("red")
COLOR("#f00")
COLOR("#ff0000")
COLOR("rgb(255,0,0)")
COLOR("rgba(100%,0,0, 0.5)")
COLOR("hsl(0,1,0.5)")
COLOR("hsla(0,100%,50%, 0.5)")

See also:

BACKGROUND("color code")

sets the background color. CSS color codes and names are allowed

BACKGROUND("red")
BACKGROUND("#f00")
BACKGROUND("#ff0000")
BACKGROUND("rgb(255,0,0)")
BACKGROUND("rgba(100%,0,0, 0.5)")
BACKGROUND("hsl(0,1,0.5)")
BACKGROUND("hsla(0,100%,50%, 0.5)")

See also:

REPEAT

Repeats a block of commands a given number of times.

REPEAT 12 BEGIN
	do_this_12_times();
END

See also:

BEGIN

Starts a block of repeated commands.

REPEAT 12 BEGIN
	do_this_12_times();
END

See also:

END

Ends a block of repeated commands.

REPEAT 12 BEGIN
	do_this_12_times();
END

See also:

SLEEP(milliseconds)

upadets the screen and pauses program execution.

SLEEP(1000)

See also:

UPDATE()

shows, what has been drawn so far. Useful, when speed is set to "No animation".

UPDATE()

See also:

RESET(options)

Clears the drawing, sets options.

RESET()
RESET(NO_GRID)
RESET(NO_GRID | NO_TURTLE)
RESET(NO_GRID | NO_TURTLE | FULL_SPEED)
RESET(NO_GRID | NO_TURTLE | NO_ANIMATION | NO_TRACE | NO_LOG)

RESET will enable all options, unless one or more flags prohibiting the option(s) are set.

Options

NO_GRID
Same effect as GRID(OFF)
NO_TURTLE
Same effect as HIDE()
NO_ANIMATION
Same effect as SPEED(-1) (Single turtle operations are not shown), sets maximum execution speed, no automatic screen updates, see UPDATE()
NO_TRACE
Don't follow the code in the debugger
NO_LOG
Don't add turtle commands to the log. Slightly improves speed, but redrawing is impossible. FULL_SPEED
const FULL_SPEED = (NO_ANIMATION | NO_TRACE | NO_LOG);

See also:

SPEED(milliseconds)

Set execution speed as a delay between every command.

SPEED(33)
SPEED(NO_ANIMATION)   // No automatic update of the screen while running.
                      // See RESET() and UPDATE()

See also:

GRID([on|off])

toggles the grid on or off. The grid will never be saved when downloading the image.

GRID()       // Turns the grid on
GRID(ON)
GRID(1)
GRID(true)

GRID(OFF)    // Turns the grid off
GRID(0)
GRID(false)

See also:

Math

RND([min, max])

returns a random value from 0..1 or min..max

let random_float = RND()      // Returns values from 0 to 0.999...
let random_integer = (2, 9)   // Returns values from 2 to 9

See also:

SIN(degrees)

returns the sinus of a value.

let y = SIN(45)

While JavaScript Math functions take angles in radians, Turtle functions use degrees:

const x = COS(45);
const y = Math.sin(45 / 180 * Math.PI);

See also:

COS(degrees)

returns the cosinus of a value.

let x = COS(45)

While JavaScript Math functions take angles in radians, Turtle functions use degrees:

const x = COS(45);
const y = Math.sin(45 / 180 * Math.PI);

See also:

TAN(degrees)

returns the tangens of a value.

let y = TAN(45);

While JavaScript Math functions take angles in radians, Turtle functions use degrees:

const x = COS(45);
const y = Math.sin(45 / 180 * Math.PI);

See also:

COT(degrees)

returns the cotangens of a value.

let x = COT(90);

While JavaScript Math functions take angles in radians, Turtle functions use degrees:

const x = COS(45);
const y = Math.sin(45 / 180 * Math.PI);

See also:

SQRT(n)

returns the square root of a value.

let r = SQRT(4);   // r will be 2

See also:

PI

- the mathematical constant π.

let radians = degrees / 180 * PI;
let degrees = radians * 180 / π;    // The unicode charcter is allowed, too.

See also:

TAU

- the mathematical constant τ = 2π.

let radians = degrees / 360 * TAU;
let degrees = radians * 360 / τ;     // The unicode charcter is allowed, too.

See also:

JavaScript

const

defines a constant and assigns a value to it.

const my_string = "String";
const my_array  = ["with", 1, 3, "mixed", "content"];
const my_object = { name:"My PC", type:"Notebook", GB_ram:8 };

It is a good idea to define all variables as const, if you don't intend to change their contents later. This prevents you from accidentially assigning values to it.

See also:

var

defines a variable for the current function. Initial values can also be set:

var π;
var my_string = "String";
var my_array  = ["with", 1, 3, "mixed", "content", my_string];
var my_object = { name:"My PC", type:"Notebook", GB_ram:8 };

See also:

let

defines a variable for the current scope.

Initial values can also be set:

let my_string = "String";
let my_array  = ["with", 1, 3, "mixed", "content"];
let my_object = { name:"My PC", type:"Notebook", GB_ram:8 };
for( let i=0 ; i<MAX ; ++i ) { console.log(i); }

See also:

if

executes a command, if a given condition evaluates to true.

if (myVariable == 1) {
	console.log("Yay. It is 1.");
} else {
	console.log("Nay. It isn't 1.");
}

See also:

else

Executes the commands in the else branch, if the given condition evaluates to false.

if (myVariable == 1) {
	console.log("Yay. It is 1.");
} else {
	console.log("Nay. It isn't 1.");
}

See also:

switch

will execute a block of commands, if the given variable equals to the case:

switch (command) {
	case "do_something":
		do_something();
		break;

	case "do_another_thing":
		do_another_thing();
		break;

	default:
		do_a_default_action();
}

In fact, a switch statement is similar to a combination of if and goto; The first case with a label equal to the switch variable will be jumped to, like in the following example:

if (command == "do_something")     goto DO_SOMETHING;
if (command == "do_another_thing") goto DO_ANOTHER_THING;
goto DEFAULT;

DO_SOMETHING:
	do_something();
	goto SWITCH_END;   // break; will jump to the end of a switch

DO_ANOTHER_THING:
	do_another_thing();
	goto SWITCH_END;   // break; will jump to the end of a switch

DEFAULT:
	do_a_default_action();

SWITCH_END:
	// Done.

Therefore, if the break; instruction is omitted, the next case block will be executed, too. This is called "fall through" and might be intended. It is a good idea, to place a comment explaining, that the fall through is intended and not a case of a forgotten break;

switch (command) {
	case "do_a":
		// Doing nothing here means, that do_a is effectively the same as do_b.
		// fall through

	case "do_b":
		do_something_only_if_a_or_b();
		// fall through

	case "do_c":
		do_in_all_three_cases();
		break;   // Make sure, no other case blocks after this are executed.
}

See also:

case

part of a switch statement, that is executed, when the switch variable is equal to the case label:

switch (command) {
	case "do_something":
		do_something();
		break;

	case "do_another_thing":
		do_another_thing();
		break;

	default:
		do_a_default_action();
}

See also:

default

part of a switch statement, that is executed, when no case applied:

switch (command) {
	case "do_something":
		do_something();
		break;

	case "do_another_thing":
		do_another_thing();
		break;

	default:
		do_a_default_action();
}

See also:

break

exits the current loop or switch and jumps to the next command after the loop/switch.

switch (command) {
	case "do_something":
		do_something();
		break;   // Do NOT execute the commands in the next case section

	case "do_another_thing":
		do_another_thing();
		break;   // Do NOT execute the commands in the default section

	default:
		do_a_default_action();
}

jump_here_when_break_is_called();
let text = "";
for( let i=1 ; i<=10 ; ++i ) {
	if (i == 5) {
		break;   // Exit the for loop alltogether
	}
	text = text + i;
}

console.log(text);   // Expected output: "1234"

See also:

continue

terminates execution of the statements in the current iteration of the current or labeled loop, and continues execution of the loop with the next iteration.

var text = "";

for( let i=0 ; i<10 ; ++i ) {
	if (i == 3) {
		continue;   // Skip the rest of this iteration
	}
	text = text + i;
}

console.log(text);   // Expected output: "012456789"

See also:

for

repeats a block of commands as long as a given condition evaluates to true.

for( initialization ; condition ; command list );
for(
	var i=0, text="" ;
	text.length<4    ;
	++i, text+=i
);

console.log(text);   // Expected output: "1234"

Note, that commands in each section are separated by commas, not semicolons.

The above example is a bit unwieldy. Furthermore, the instruction or block after the for can also be executed in each iteration. The block will be executed before the instructions in the "command list" section.

It is common to use the sections in the for statement for counting the numbers of iterations and put the actual work in the block after the for:

let text = "";
for( let i=1 ; i<=4 ; ++i ) {
	text += i;
}
console.log(text);   // Expected output: "1234"

for is pretty flexible. You can create an endless loop like so:

for(;;) {
	repeat_me_endlessly();
}

which is equal to:

while (true) {
	repeat_me_endlessly();
}

See also:

while

executes a block of commands as long as the condition evaluates to true

let we_are_running = true;
while (we_are_running) {
	we_are_running = decide_if_we_keep_running();
}

One can use while to do the same as a for loop:

let counter = 1;
let text    = "";

while (counter <= 4) {
	text = text + counter;
	counter = counter + 1;
}

console.log(text);   // Expected output: "1234"

Take care not to create unterminated (endless) loops in EcmaTurtle. It is not designed for this and may crash.

See also:

function

introduces a new "sub-program", which can be called from elsewhere.

function do_something() {
	console.log("Hello, world!");
}

do_something();
console.log("Test");
do_something();        // Prints three lines: "Hello World!", "Test", "Hello, World!"

As in mathematics, functions can return values to the caller:

function add_numbers( n1, n2 ) {
	return n1 + n2;
}
const sum = add_numbers(1, 2);
console.log(sum);   // Expected output: 3

See also:

return

terminates the execution of a function and may return a value.

function compare( value1, value2 ) {
	if (value1 < value2) {
		return -1;
	}

	if (value1 > value2) {
		return +1;
	}

	return 0;
}

If no return statement is used, the return value is undefined:

function do_something() {
	// Calculate things
}
const value = do_something();
console.log( typeof value );   // Expected output: "undefined"

See also:

this

short description

Example code

See also:

true

- Boolean flag. Equal to ON and +1

if (true) always_do_this();
GRID(true)
GRID(ON)
GRID(1)

See also:

false

- Boolean flag, equal to OFF and 0

if (false) never_do_this();
GRID(false)
GRID(OFF)
GRID(0)

See also:

Pre-defined Objects

Array

short description

Example code

See also:

Object

short description

Example code

See also:

Math

short description

Example code

See also: