Skip to content

Reni Programming Language

Harald Herbert Hoyer edited this page Sep 9, 2022 · 5 revisions

Translation from German by www.guydollman.com


1. "Hello world"

Reni's simplest elements are whole numbers. There's not much to explain here: Rows of the numerals 0-9, possibly preceded by a minus symbol (-).

A bit more complex elements are character chains. These are strings of characters that are surrounded by single (') or double (") quotation marks.

With these, note the following:

  1. The marks at the beginning and the end must be the same.
    Examples:
    "asdf"
    or
    'qwer'
  2. If the characters in the chain are to contain quotation marks, they need to be doubled.
    Examples:
    "Say ""Goodnight"", Irene"
    or
    'L''Oreal'.
    But:
    "L'Oreal"
    or
    'Say "Goodnight", Irene'
  3. A chain of characters can not extend over more than one line.

There are some predefined names for things. One of these is "dump_print". With this, something is outputted to the console, a logfile or the debug output window.

  • Example:
    42 dump_print
    This first, small program will write 42 in the console.

  • Example:
    "Hello world" dump_print
    This is the widely-known hello world program in "Reni".

2. Assigning names

In programming, it is important to give things names, as follows:

x: 157

This example defines a synonym "x" for the number 157.

There are two kinds of names.

The first variety consists of a string of letters, numbers and the underscore (_). It is known as an alphanumeric name.

Note the following:

  1. These names can not begin with a numeral
  2. Capital letters are important

Examples: _ a A asdf a12 a_d FileName _1

Examples that are not names: 1a 1 1_

The second variety consists of one or more symbols, and is called a symbol or symbol group. The following symbols are allowed: °^!²§³$%&/=?\@€*+~><|:.-. Such names are always formed of symbols that follow each other. For example, *- is a name.

For both kinds of name the following needs to be noted:

  1. In specific situations, some names have a predefined meaning. One example is dump_print, as mentioned previously.
  2. Some names are reserved. Examples follow.

3. And, and, and…

Programs that only consist of one line are mostly not very sensical. For this reason, things are written after each other, as follows.

x : 157;
*- : "A star and a minus"

Here, two synonyms are defined: x for the number 157 and the symbol group *- for the chain "A star and a minus". The two individual definitions are separated by a semicolon (;), a comma (,) or a dot (.). Which of these three is used is irrelevant: It simply needs to be the same one for long lists, or else there is an error. It is not relevant to the meaning of the program whether line breaks are used or not. It does increase readability in some cases, however.

Not every such instruction defines a name:

x : 157;
x dump_print;
*- : "A star and a minus";
*- dump_print

Here "x" and "*-" are again defined and assigned their values in the console. I.e.: 157A star and a minus. (One can see here that stupidly, the results appear directly after each other. How to fix that is explained later.)

A series of results can be used at all points. For example:

x: (4, 8, 15, 16, 23, 42);
("The lottery numbers are: "; x; "Congratulations to the winners.") dump_print

In order for it to be unequivocal, brackets need to be used. After these instructions, the console contains: (The lottery numbers are: , (4, 8, 15, 16, 23, 42), Congratulations to the winners.)

With the brackets, we are not restricted to one kind. As per the example, round brackets can be used, but also square ([) (]) or curly ones ({) (}). As with the list dividing symbols semicolon and comma, it is irrelevant which brackets are used. They just need to be used consistently. This can help when things become more complex:

AllPresidents :
{
    [0, (Surname: "Johnson", Name: {"Lyndon", "Baines"}, Start: 1963)];
    [1, (Surname: "Nixon", Name: "Richard", Start: 1969)];
    [2, (Surname: "Ford", Name: "Gerald", Start: 1974)];
    [3, (Surname: "Carter", Name: "Jimmy", Start: 1977)];
    [4, (Surname: "Reagan", Name: "Ronald", Start: 1981)];
    [5, (Surname: "Bush", Name: {"George", "H. W."}, Start: 1989)];
    [6, (Surname: "Clinton", Name: "Bill", Start: 1993)];
    [7, (Surname: "Bush", Name: {"George", "W."}, Start: 2001)]
    [8, (Surname: "Obama", Name: "Barack" Start: 2009)]
}

4. Expressions

Instead of numbers of strings of characters, complicated expressions can be used. There are a lot of predefined operations that can be used for this. Later we will also find out how to define new operations.

For numbers, there are calculating operations plus (+), minus (-), times (*), divided by (/) and modulo (). These operations produce a number.

In addition, there are the comparative operations less than (<), greater than (>), equal to (=), less than or equal to (<=), greater than or equal to (>=) and not equal to (<>). These produce a Boolean value that can be either "true" or "false".

For lists, there is the deliberately ugly operator "_A_T_" with which individual elements in the list can be accessed. For example, AllPresidents _A_T_ 2 _A_T_ 1 Name produces the result "Ford". One could have written AllPresidents _A_T_ 2 _A_T_ 1 _A_T_ 0 (even worse).

Comment: The "At" operator is normally not available. So that the example actually works, access rights need to be extended. We explain how this works later.

Example:

x : 157;
y : x * 3 - 451;
z : (sum: x+y; diff: x-y);
b : z sum < z diff;
(x, y, z, b) dump_print

(157, 20, (177, 137), false)) is produced.

5. Bracketing

If 3+4*5 is written, it is clear that first 4*5 is calculated and then 3 is added to the result. This is the case because the priority of the operation "times" is higher than that of the operation "plus". For this to work differently, brackets need to be used: (3+4)*5. Now, 3+4 is calculated first and the result is multiplied by 5. Priorities and brackets are also used in Reni in order to make a structured program out of a pile of names and symbols. Reni's priority table looks like this:

  1. List dividing symbol dot
  2. List dividing symbol semicolon
  3. List dividing symbol comma 4
  4. Lambda symbols "@", "@!" and "@@"
  5. Exclamation mark
  6. then and else
  7. The value change operator ":="
  8. Comparative operators "=" und "<>"
  9. Comparative operators "<", "<=", ">" und ">="
  10. “Dash operations" plus and minus
  11. "Point operations" times, divided by, and modulo
  12. Chain operators "<<" and "<<:=" as well as instance operators ">>" and "_A_T_"
  13. All others

Here, some operators are listed that are first explained later.

6. Functions

For real programs, functions are necessary. These provide regulations and can be used in expressions. To define a function, the lambda symbol "/\" and possibly the argument symbol "^" are used. Here is a simple example:

AddOne : @ ^ + 1;
AddOne(15) dump_print

16 is produced.

Like other expressions, functions can be used in practically all positions.

Example:

x : 157;
y : x * 3 - 451;
z : @(sum: ^ + y; diff: ^ - y);
b : z(x) sum < z(x) diff;
(x, y, z(x), b) dump_print

Again (157, 20, (177, 137), false)) is produced.