A program that determines if number 17 is prime in Brua2:
(set check (func (
(set n (arg 0))
(if (le n 1) (
(return false)
) ())
(for (set i 2) (le (mult i i) n) (set i (add i 1)) (
(if (eq (rem n i) 0) (
(return false)
) ())
))
(return true)
)))
(set num 17)
(call println "Number " num " is prime: " (call check num))
There are only 8 data types:
- bool
- char (signed, 8-bit)
- int (signed, 64-bit)
- real (double precision)
- pointer
- string
- dict (dictionary)
- func (function)
Each data type except for func supports literal values.
Most types (bool
, char
, int
, real
and string
) use the same rules as in C++. For pointer
type, the only recongized literal is NULL
. For dict
type, the only recognized literal is an empty dictionary {}
. func
type doesn't have literals.
Some objects may not be referenceable (for example - literals), therefore cannot be assigned a value.
bool
values can be true
or false
. They are used in statements.
char
values are ASCII characters. They are returned when string
values are indexed.
int
values represent signed 64-bit numbers. int
is one of the only two types (the other being real
) which support arithmetic operations. string
indexation can only be done using int
values.
real
values represent double precision floating point numbers. real
supports arithmetic operations.
pointer
values point to other objects. passing pointer
values is the only way to modify variables inside of functions.
string
values represent sequences of char
values. Each character can be accessed, but cannot be modified. However, prefix and suffix operations are supported.
dict
is a very universal data type which contains pairs of keys and values inside of it. Each key object is assigned a value object, and no key can have two values assigned to it. Each value can be accessed by a resprectful key. Keys are compared by value, therefore different objects with the same value are treated as the same key inside of the dict
. Each key and value object stored in a dict
is a copy of its original self, therefore pointer
type may be used to store references to values outside of the dict.
func
stores parts of code that can be executed multiple times. Each function can access arguments that were passed during the function call. Each function may return at least one object. Some functions may be implemented inside of the language engine.
Namespace is a virtual structure that stores information about objects created during its lifetime. It stores variables with their names, as well as many other things which are required for the language to work.
Each namespace when created may or may not be able to access its parent namespace. If a value has to be located in the namespace, it may start a search in the parent namespace if it can access it. It may repeat several times until the value is found. If the required value is not found, a runtime error happens. Each namespace may access the first namespace, which has its own name: namespace 0. Namespace 0 is the namespaces where all your code is executed in. Therefore, some variables (which are called global variables) created inside of it may be accessed in any part of the code.
Since namespaces may look for variables in parent namespaces (and namespace 0), variable shadowing is not supported.
Variables are objects with names. Variables are created in the most recent namespace. However, as noted above, a variable will not be created if the name given to it can be found in the accessible namespaces. Instead, the already present variable will be used.
When a namespace gets destroyed, all the objects created during its lifetime are destroyed as well.
Functions heavily rely on namespaces. If a function wants to access its arguments, it looks for them in most recent namespace. When a function is called, a new namespace is created, where all the arguments are put, and the called function runs in that namespace. Note that only copies of the arguments are put in the namespace.
Each code structure must be inside of a pair of brackets. However, names and literals MUST be left without brackets, or a block of invalid instructions will be created**
If a name is recognized, it is almost always (the only exclusion being set
statement) replaced with a value assigned to it. If such name is not found in the namespace, a runtime error happens.
- A must be a referenceable value
- B must be a value
- The result of execution is not a value
Sets value of A being equal to B. It is implemented as replacing A with a copy of B.
If A is a name, then a variable is modified. If a variable with such name doesn't exist, a new one is created in the most recent namespace, and gets assiged value of B.
A
must be of typebool
B
is treated as a code part- The result of execution is not a value
As long as A
is true
, B
is executed in a new namespace which is destroyed each time when B
completes.
A
is treated as a code partB
must be of typebool
C
is treated as a code partD
is treated as a code part- The result of execution is not a value
Executes A
once.
Then, as long as B
is true
, D
is executed in a new namespace which is destroyed each time when D
completes.
At the end of each D
execution, C
gets executed,
A
is treated as a code partB
must be of typebool
- The result of execution is not a value
Executes A
until B
becomes true
. A
is executed in a new namespace, which gets destroyed each time when A
completes.
A
must be of typebool
B
is treated as a code partC
is treated as a code part- The result of execution is not a value
If A
is true
, executes B
in a new namespace, which gets destroyed at the end. Otherwise, execute C
in a new namespace, which gets destroyed at the end.
When inside of a code block, stops executing any further code in the block. When inside of a loop body, stops executing any further code in the body, and begins a new loop execution. Has no effect in other places.
- The result of execution is not a value
When inside of a code block, stops executing any further code in the block. When inside of a loop body, stops executing any further code in the body, and stops the whole loop. Has no effect in other places.
- The result of execution is not a value
- If present, A must be a value
- The result of execution is not a value
If inside of a function body, stops executing any further code in the body, and completes the function call. If a value A
is present, returns it as the result of the function call. Has no effect in other places.
A
is treated as a code part- The result of execution is an unreferenceable object of type
func
Creates a new object (function) of type func
which will execute code A
.
A
must be of typeint
- The result of execution is a referenceable object
Returns a function argument with index A
which was passed during the function call. Arguments are numbered in first-to-last order.
A
must be of typefunc
*B
represent zero or more arguments. Each argument must be a value.- The result of execution is an unreferenceable object or not a value, depending on if the function returns an object
Calls function A
with arguments *B
. Creates a new namespace, where arguments *B
are put. Then, function A
is executed. After that, the namespace gets destroyed, and the value that function returned is taken as a result.
A
must be a value- The result of execution is an unreferenceable object of type
bool
Returns an bool
value which represents boolean value of A
. Values that are false
are:
false
(typebool
)0
(typechar
,int
, andreal
)NULL
(typepointer
)""
(typestring
){}
(typedict
)
Every other value is treated as true
A
must be a value of typebool
,char
, orint
- The result of execution is an unreferenceable object of type
char
Returns a char
object with value of A
(via standard C casts)
A
must be a value of typebool
,char
,int
,real
, orstring
- The result of execution is an unreferenceable object of type
int
Returns an int
object with value of A
(via standard C casts). If A
is string
, then it parses contents of A
and tries to recognize an integer.
A
must be a value of typebool
,char
,int
,real
, orstring
- The result of execution is an unreferenceable object of type
real
Returns a real
object with value of A
(via standard C casts). If A
is string
, then it parses contents of A
and tries to recognize a floating point number.
A
must be a value- The result of execution is an unreferenceable object of type
string
Returns textual representation of A
. If A
is a function, returns "function"
A
must be of typepointer
, and cannot beNULL
- The result of execution is a referenceable object.
Returns the original object that is pointed by A
.
A
must be a referenceable value- The result of execution is an unreferenceable object of type
pointer
.
Returns a pointer pointing to A
A
must be of typeint
- The result of execution is an unreferenceable object of type
int
Returns a binary inversed copy of A
A
must be of typebool
- The result of execution is an unreferenceable object of type
nool
Returns a logicaly negated copy of A
A
must be of typeint
orreal
- The result of execution is an unreferenceable object of the same type as
A
Returns a negated copy of A
A
must be of typeint
orreal
B
must be of typeint
orreal
- The result of execution is an unreferenceable object of the smallest fitting type based on
A
andB
Returns a multiplication result of A
and B
A
must be of typeint
orreal
B
must be of typeint
orreal
- The result of execution is an unreferenceable object of the smallest fitting type based on
A
andB
Returns a division result of A
and B
A
must be of typeint
orreal
B
must be of typeint
orreal
- The result of execution is an unreferenceable object of the smallest fitting type based on
A
andB
Returns a division remainder result of A
and B
A
must be of typeint
orreal
B
must be of typeint
orreal
- The result of execution is an unreferenceable object of the smallest fitting type based on
A
andB
Returns an addition result of A
and B
A
must be of typeint
orreal
B
must be of typeint
orreal
- The result of execution is an unreferenceable object of the smallest fitting type based on
A
andB
Returns a subtraction result of A
and B
A
must be of typeint
B
must be of typeint
- The result of execution is an unreferenceable object of type
int
Returns a binary left shift result of A
and B
A
must be of typeint
B
must be of typeint
- The result of execution is an unreferenceable object of type
int
Returns a binary right shift result of A
and B
A
must be of typeint
orreal
B
must be of typeint
orreal
- The result of execution is an unreferenceable object of type
bool
Returns a less-then result of A
and B
A
must be of typeint
orreal
B
must be of typeint
orreal
- The result of execution is an unreferenceable object of type
bool
Returns a greater-then result of A
and B
A
must be of typeint
orreal
B
must be of typeint
orreal
- The result of execution is an unreferenceable object of type
bool
Returns a less-then-or-equal-to result of A
and B
A
must be of typeint
orreal
B
must be of typeint
orreal
- The result of execution is an unreferenceable object of type
bool
Returns a greater-then-or-equal-to result of A
and B
A
must be a valueB
must be a value- The result of execution is an unreferenceable object of type
bool
Returns true
if values of A
and B
are equal, otherwise returns false
A
must be a valueB
must be a value- The result of execution is an unreferenceable object of type
bool
Returns true
if values of A
and B
are not equal, otherwise returns false
A
must be of typeint
B
must be of typeint
- The result of execution is an unreferenceable object of type
int
Returns binary and of A
and B
A
must be of typeint
B
must be of typeint
- The result of execution is an unreferenceable object of type
int
Returns binary xor of A
and B
A
must be of typeint
B
must be of typeint
- The result of execution is an unreferenceable object of type
int
Returns binary xor of A
or B
A
must be of typebool
B
must be of typebool
- The result of execution is an unreferenceable object of type
bool
Returns logical and of A
or B
A
must be of typebool
B
must be of typebool
- The result of execution is an unreferenceable object of type
bool
Returns logical or of A
or B
A
must be a referenceable object of typedict
B
must be a value- The result of execution is a referenceable object
Returns value that is assigned key B
in dictionary A
. If not found, runtime error happens.
A
must be a referenceable object of typedict
- The result of execution is an unreferenceable object of type
int
Returns number of elements in dictionary A
A
must be a referenceable object of typedict
B
must be a value- The result of execution is an unreferenceable object of type
bool
Returns true
is key B
is present in the dictionary A
, otherwise returns false
A
must be a referenceable object of typedict
B
must be a valueC
must be a value- The result of execution is not a value
Inserts pair (B
, C
) into dictionary A
. If a pair with the same key already exists, it gets replaced by the new one.
A
must be a referenceable object of typedict
B
must be a value- The result of execution is not a value
Removes pair with key B
from dictionary A
. If such pair is not found, nothing happens.
A
must be a referenceable object of typedict
- The result of execution is an unreferenceable value of type
dict
Returns a dictionary which has all the keys that are present in A
. They are given their keys, which are numbers from 0 to the size of A
minus 1.
A
must be a referenceable object of typedict
- The result of execution is an unreferenceable value of type
dict
Returns a dictionary which has all the values that are stored in A
. They are given their keys, which are numbers from 0 to the size of A
minus 1.
A
must be a referenceable object of typedict
- The result of execution is not a value
Removes all contents from dictionary A
A
must be a referenceable object of typestring
B
must be a value of typeint
- The result of execution is an unreferenceable object of type
char
Returns character in string A
at index B
. Note, that the returned character is a copy of the original one.
A
must be a referenceable object of typestring
A
must be a value of typestring
- The result of execution is not a value
Adds string B
to the end of string A
, modifying A
A
must be a referenceable object of typestring
A
must be a value of typestring
- The result of execution is not a value
Adds string B
to the beginning of string A
, modifying A
A
must be a referenceable object of typestring
A
must be a value of typeint
- The result of execution is not a value
Removes B
characters from the end of string A
A
must be a referenceable object of typestring
A
must be a value of typeint
- The result of execution is not a value
Removes B
characters from the beginning of string A
*A
is treated as zero or more instructions- The result of execution is not a value
Creates a block of code
Builtin functions can be easily added in src/predefined.cpp
file.
- takes zero or more arguments
Prints all its arguments to the standard output stream. Doesn't add any spaces or newline character.
- takes zero or more arguments
Prints all its arguments to the standard output stream. Doesn't add any spaces, but adds a newline character at the end.
- takes zero arguments
Returns the amout of time passed since the beginning of the epoch. Returns time in milliseconds.
- takes one
int
argument
Sleeps for the given amount of milliseconds.
- takes one
int
argument
Exits with return code being its argument.
- takes one
bool
argument an onestring
argument
Checks if the first given argument is true
. If it's false
, a runtime error happens and the string
message is printed.
- takes one
int
argument
Returns a random non-negative int
number not greater than it's argument.
- takes one
int
orreal
argument
Returns sin of the given value.
- takes one
int
orreal
argument
Returns cos of the given value.
- takes one
int
orreal
argument
Returns absolute of the given value.
- takes zero arguments
Clears all text from the terminal. Added only for a ping-ping game
- takes zero arguments
Returns a character read without blocking the standard input stream. Added only for a ping-ping game
In tests
directory I prepared some programs that are supposed to check if the language works correctly. I've also included one program that checks the speed of some instructions. All tests may be run with a single command: bash runtests.sh
In programs
directory I prepared a single terminal-based game "ping-pong", which should run in any modern terminal of enough size.
To run the language on a code file, simple pass it to the bash run.sh
command as an argument.
(call println "Hello world!")