// This tutorial is part of a series that explains the basic concepts of the APRON simulation system.
// Please ensure you have read and understood any previous tutorial examples.
//
// © David R W Barr 2009
//
// Name: 		USING VARIABLES, NUMBERS AND DEFINES
// Description:	This tutorial will introduce variables and their manipulation
//				and usage with registers and numbers. Defines are also covered
//				and emphasis is placed on how these should be used with care
// Usage:		Please STEP-THROUGH this algorithm in the simulator.


// Always include this line for an APRON simulation. This file includes many pre-defined
// types and functions that are used in a standard APRON simulation.
!include('apron.aps')

// DEFINES
// ~~~~~~~

// First, we shall create some 'DEFINES'. Defines are string placeholders for other strings.
// For example, suppose I had a definition that said the string 'cat' was actually 'dog', and
// the compiler was given this sentence to compile 'the cat sat on the mat'. Before the compiler
// attempts to assemble code, it performs all the necessary string substitutions or 'swaps'. Thus
// the compiler will actually see the sentence 'the dog sat on the mat'.
//
// What if the definition was to swap the string 'at' with 'ow'? The string swapping takes place at
// the token level. This means you would NOT see 'the cow sow on the mow'. In fact, the sentence would 
// remain unchanged. Tokens are defined as unique strings that are seperated by spaces and these symbols:
// '!=', '==', '>', '<', ',', '>=', '<=', '(', ')', '=', '+', '/', '-', '*', '%'
//
// This means we can use defines as convenient methods of changing algorithms. The extent to which you
// can do this is quite an advanced topic and is covered in a later tutorial. For now though, we will use it
// to make our algorithm more scaleable.

// We will define the width and height of the registers. Note that the strings RW and RH are not APRON specific
// It is an un-written convention to use all CAPTIAL LETTERS for defined tokens, although this is not enforced.
// By sticking to this convention, it is easier to distinguish 'defines' from 'variables'. They are NOT the same!
!define(RW, 128)
!define(RH, 128)

// We now want to define some registers. By using RW and RH, we only need to change the defines 
// if we want to scale the algorithm later
!create_reg('a', RW, RH) 
!create_reg('b', RW, RH) 
!create_reg('c', RW, RH)


// VARIABLES
// ~~~~~~~~~
//
// Variables are created at compile time. APRON does not require any explicit decalration, and all variables
// are the same type - floating point. Variables are 'implicitly created'. This means that a variable is
// created when it is first assigned something. If you use a variable that has not been created as an argument
// the compile will produce errors. Thus the simplest form of variable creation is:
n = 1

// Equally valid is:
m = n + 7 // as n has already been created before it is used.
p = m * n // as both m and n have been created 

// This however will fail compilation p = m * k, as k has not been created yet.

// We can also create variables with function returns. The get function retrieves an individual element
// from the specified register r[a], at (x, y) = (0, 0)
q = get(r[a], 0, 0)

// Q: What does this mean?
width = RW

// A: We are creating a variable called width, and it is being assigned the value 128. The compiler
// will see this line as 'width = 128'. The 'RW' token is completely removed at the substitution stage.
height = RH




// This is the end of the tutorial. We can stop the simulation by...
end