Lape is an interpreter for a subset of the Pascal language. This guide contains a compact introduction to programming and more specifically programming with Lape. It is by no means a complete guide on learning how to program. There are awesome books and more comprehensive articles on becoming a programmer.
This guide serves as reference and compact introduction to lape.
Lape features a language very similar to the programming language Pascal. Writing a programming language is called programming:
The purpose of programming is to create a program that exhibits a certain desired behavior.
To learn programming you have to - as with all things - start with the very basics. Let us start a very basic but important question: What is a Program? Simply put, a program is a set of logical statements and instructions. A logical statement is as the name implies - logical. An instruction is simply an operation the computer will execute - the results of the instruction can vary - you can make the computer add two numbers, have it draw a line on the screen, download a file and much more.
Say we have the follow sentence in English:
If it is raining I will have to put on my raincoat.
This roughly translates into the following code:
if (it_is_raining) then put_on_raincoat();
Now, if you're new to programming, this probably looks very weird. There are lots of programming language and they all look different - this particular language is called Pascal.
Basically, the line below is a logical construct:
Whereas the following line is an instruction, in this case an instruction that tells us to perform other instructions define in the procedure put_on_raincoat.
When combining other logical statements (there are a lot more statements than just if) with instructions, it is possible to construct a program.
Now we've gone through a little background, let's start by writing our first Pascal program.
Observe the following program:
begin writeln('hi'); end.
Immediately we see something new - begin and end. Every program needs a begin and end, it defines where the program starts and where it stops - that is when the last instruction has been reached. Lape will execute instructions as directed by the logical statements until the end of the program is reached.
So what does the line below really do?
To find out, we have to run or execute the program.
TODO: COVER HOW TO EXECUTE A PROGRAM. (IN SIMBA??)
After running the program, you should see something like this:
Compiled successfully in 70 ms. hi Successfully executed.
So, the function writeln prints something out. Try changing 'hi' to something else, if you do it properly, it should print something else. If it fails after you've changed something - don't worry, just keep on reading.
Now you're thinking, what is a procedure? If we look at the example in Hello, Lape!, writeln is a procedure.
A procedure can be seen as a small program on its own, containing instructions and logical statements. When a procedure is invoked, the program executes the instructions and logical statements in the procedure, which also has a begin and end. Once the procedure ends, the program continues as usual.
A simple example:
procedure I_am_a_procedure; begin writeln('Hello from the procedure'); end; begin writeln('Hello from the program'); I_am_a_procedure(); writeln('And we are back in the program'); end.
Here, I_am_a_procedure is a procedure, identified by having the word procedure in front of it. Then follows a usual begin, followed by some instructions and terminated with an end.
Running this program writes the following:
Compiled succesfully in 71 ms. Hello from the program Hello from the procedure And we are back in the program Successfully executed.
As you can see, Lape first executes:
writeln('Hello from the program');
And then invokes or calls the procedure I_am_a_procedure, which on its turn tells Lape to execute the following:
writeln('Hello from the procedure');
And finally, Lape executes:
writeln('And we are back in the program');
As you can see, the execution of a program is perfectly logical and follows very strict steps. A procedure can be used to divide code into smaller pieces, to prevent writing the same instructions and logical constructs over and over.
Now that we have a general idea on how Lape executes your code, we'll move onto variables.
What is a variable? Let us consult Wikipedia [*]
In computer programming, a variable is a symbolic name given to some known or unknown quantity or information, for the purpose of allowing the name to be used independently of the information it represents. A variable name in computer source code is usually associated with a data storage location and thus also its contents, and these may change during the course of program execution.
In layman terms: We use variables in programming to store values for reuse of the value. There are different types of values: Variables are always of a specific type.
Consider the following code:
var sum: integer; begin sum := 0; writeln(sum); sum := sum + 42; writeln(sum); sum := sum + 43; writeln(sum); end.
Here, sum is a variable. The type of sum is Integer and var indicates that we are about to declare one or more variables.
First of all, a variable of type Integer can store whole numbers. Both positive and negative. There is a limit on the maximum (and minimum) value of the number, but that is not relevant yet.
So, let us start with:
sum := 0;
This instructions makes the value of sum equal 0, zero.
sum := sum + 42; sum := sum + 43;
These two statement successively add 42 and 43 to the value of sum, by setting the value of sum to the value of sum plus a number.
Output of the program is as follows:
Compiled succesfully in 71 ms. 0 42 85 Successfully executed.
So far we've covered how your program is run, what a procedure is, how you can make simple use of variables and how to comment your code to make it more readable. Note that we've previously spoken of logical statements, but have not yet thoroughly discussed them.
The if statement consists of a condition and one of more instructions that follow the condition:
if condition then instruction;
Obviously condition must be either True or False, there is no maybe. Apart from the Integer type introduced in Variables and Types, Lape also supports a Bollean type - which can in contrast to an Integer, only hold two kind of values: True and False.
Thus, the following code is perfectly valid:
var a_condition: Boolean; begin a_condition := True; if a_condition then writeln('a_condition was true!'); if a_condition = false then writeln('a condition was false!'); end;
And it will write:
a_condition was true!
Lape will try evaluate your condition to either True or False. If it cannot do this, your code is invalid. As a result, you can combine logical constructs if then evaluate to either True or False. See Not, And, Or, Xor on combining logical constructs.
For example, the following code is invalid:
if 42 then writeln('The answer to life, the universe and everything!');
The if statement can optionally make use of an else clause, simplifying our previous code:
var a_condition: Boolean; begin a_condition := True; if a_condition then writeln('a_condition was true!') // Note that there is no semicolon here now else writeln('a condition was false!'); end;
If you wish to perform more than one operation in you if statement, use the begin and end keywords:
var a_condition: Boolean begin a_condition := True; if a_condition then begin writeln('a_condition is true'); writeln('this is another procedure call'); end else begin writeln('a_condition is false'); writeln('This line and the line above will however never be printed'); end;
Lape contains a few special logical operators: Not, And, Or and Xor.
The Not instruction negates the value that follows it:
var a_boolean: boolean; begin a_boolean := not False; if a_boolean then writeln('a_boolean is True'); end;
A simple Truth Table for the not operator:
The And operator takes two logical values (or constructs that evaluate to a value) and evaluates to True if both these values are True, otherwise it evaluates to False.
Truth table for the and operator (treat A and B as logical values/constructs):
|A||B||A and B|
The Or operator takes two logical values (or constructs that evaluate to a value) and evaluates to True if any of these values are True, otherwise it evaluates to False.
Truth table for the or operator (treat A and B as logical values/constructs):
|A||B||A or B|
|A||B||A xor B|
The section Variables and Types gave a very basic introduction on variables, just enough to get you to this section. First, we'll introduce a few more basic types:
var b: boolean; s: string; i: integer; begin b := True or False; // b = True s := 'Hello, ' + 'World'; // Hello, World i := 24 * 2; end;
We've introduced one new type:
- A string consists of one or more characters, denoted by the surrounding '.
As a short reminder:
- A boolean can either hold the value True or False.
- An integer holds a number.
Now, looking at the previous code, we notice the or operator being applied to True and False, but this is nothing new.
Moving on, we can see that the string s is being given the value 'Hello, ' + 'World'. What does an addition of two strings even mean? In this case, the two strings 'Hello, ' and 'World' are combined to 'Hello, World'. The + operator is not defined for every type: it mainly works on strings and integers.
The last statement takes the number 24 and multiplies it by 2.
- Integers(Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64)
- Booleans(Boolean, ByteBool, WordBool, LongBool)
- Arrays(static, dynamic)
- function pointers
var b: boolean; a: integer; s: string; sa: array of string; begin b := True; a := 41+1; s := 'This parrot is an ex-parrot'; setlength(sa, 4); // Pick the odd one out sa := 'This parrot is no more'; sa := 'It is pleading demise'; sa := 'If you had not nailed him to the perch he would be pushing up the daisies!'; sa := 'My hovercraft is full of eels'; end;
The assignment operator assigns a value to a variable.
The = operator checks for equality of two basic types of the same type:
if (42 = 42) and ('God is God' = ('God is' + ' God') ) then writeln('Everything equals itself, surprisingly');
The <> operator is similar to the = operator, but checks for inequality rather than equality:
if '42' <> 'The answer to life, the universe and everything' then writeln('Blasphemy!');
The > operator returns true if the first value is greater than the second value:
if 43 > 42 then writeln('42 is larger than 43');
The >= operator returns true if the first value is greater than or equal to the second value:
if (43 >= 42) and (42 >= 42) then writeln('42 is equal to or larger than both 42 and 43');
The < operator returns true if the first value is smaller than the second value:
if 42 < 43 then writeln('42 is smaller than 43');
The <= operator returns true if the first value is smaller than or equal to the second value:
if (42 <= 42) and (42 <= 43) then writeln('42 is smaller than or equal to 42 and 43');
The @ operator returns the memory address of a variable, whereas the ^ operator retrieves the value from a memory address:
var ip: ^Integer; i: Integer; begin i := 41; ip := @i; ip^ := ip^ + 1; writeln(i); end;
The + operator performs an addition, note that it does not have to be a numerical addition. The + operator can be defined for other types with Operator Overloading.
writeln(40+2); // Integer addition adds two numbers. writeln('Hello, ' + ' World'); // String addition concatenates strings
The - operator performs a subtraction:
writeln(44-2); // Integer substraction.
The * operator
The / operator performs a division:
writeln(84/2); writeln(1/3); writeln(1/3.0);
The ** operator performs the mathematical power operation:
Where a is the first value; and b the second value:
The AND operator takes two logical values (or constructs that evaluate to a value) and evaluates to True if both these values are True, otherwise it evaluates to False.
Truth table for the AND operator (treat A and B as logical values/constructs):
|A||B||A and B|
The OR operator takes two logical values (or constructs that evaluate to a value) and evaluates to true if any of these values are true, otherwise it evaluates to false.
Truth table for the OR operator (treat A and B as logical values/constructs):
|A||B||A or B|
The XOR operator takes two logical values (or constructs that evaluate to a value) and evaluates to True if (only) one of these values is true otherwise it evaluates to False.
Truth table for the XOR operator (treat A and B as logical values/constructs):
|A||B||A xor B|
The NOT instruction negates the value that follows:
The NOT operator inverts all the bits.
The AND operator performs a logical AND operation on each bit of the two input numbers.
001010 and 101010 = (0 and 1)(0 and 0)(1 and 1)(0 and 0)(1 and 1)(0 and 0) = 001010
writeln(10 and 42); // results in 10
The OR operator performs a logical OR operation on each bit of the two input numbers.
writeln(32 or 10); // results in 42
The XOR operator performs a logical XOR operation on each bit of the two input numbers.
writeln(5 xor 5);
The SHL operator performs a left shift by n bits on the first value, where n is the second value.
writeln(21 shl 1); // 21 = '0b10101' // 42 = '0b101010'
The SHR operator performs a right shift by n bits on the first value, where n is the second value.
writeln(84 shr 1);