In programming languages, a type system is a collection of rules that assign a property called type to various members of a program, such as constants, variables, parameters and function results. We can have system define types and user defined types.

Type Paradigms:

Level language is statically typed with  type inference and polymorphic types.  That means a variable and constants must be declared with type information and can’t be changed during run-time.

We wish Level to be a safe language. Having strong types has advantages and some minor inconveniences. Our focus is productivity and maintainability. We create a compiler not an interpreter therefore strong types better for Level.

Native Types

Native types are data types known by the operating system that can provide support for manipulation and storage. That means native types are the most important and must be defined first in the language.

Level-1 native types are: { number, logic, string }

Composite Types

Composite types are defined by Level language as base types to be extended by the user.Most significant composite types are:

{ tuple, vector, matrix, record, list, set, map }.

User Defined Types

All type names start with capital letter and contains digits and lowercase ASCII letters. We do not support Unicode identifiers and also no special characters except underscore that is used instead of space.

  • Developers can define types in the declaration region of a program;
  • Users can define types in a library and these types can be exported;
  • The program or modules can import types or classes from a library;
  • For readability purpose we include keyword type in front of a user type declarations;

Type usage

Once a user type is defined it can be reused as a built-in type. The type can be associated with other composite types or with variables. We know that we declare a type not a variable because type names start with a capital letter.


procedure main is
  Point:Record of (a:Integer, b:Integer);
  p1, p2: Point; --> type reference
  print("p1: a=#n, b=#n" <- p1);
  print("p2: a=#n, b=#n" <- p2);
end procedure;
p1: a=1, b=1
p2: a=2, b=2


A constant is a memory container that is initialized with a literal. Constants are immutable. That is a constant can’t be changed during program execution and must be initialized to a value. A constant is declared in a constants region. Constants can use only uppercase letters, underscore and digits. Some example of predefined constants are: { PI, TRUE, FALSE }.

Note: A constant can’t be defined with one single uppercase letter, it needs at least 2. A good practice is to use C_… prefix. Using uppercase letters is not mandatory for example c_constant is as good as C_CONSTANT. We recommend uppercase though.


  C_ERR="Error măi ţâcă!":Unicode;


A variable is represented by a symbol, and is associated to a type. Variables represents a memory container having a defined structure and size. Variable value is stored on a specific memory address and use several other memory addresses that are usually consecutive. Content of a variable can be changed during the execution of the program.


We use keyword “variables” to declare one or several variables. Identifiers for variables are using lowercase letters, digits and underscore. It is good practice to use several characters not only one. A good convetion is to use a prefix for example v_this_variable. Having (v_) prefix we will know every time we read this identifier that is a variable.

Syntax for Region:

  r2=0.2, r3=0.3 :Real;

Variables can be defined in one line. We separate multiple variables using comma separator. When multiple variables are declared in one line all will have the same type. The value for each can be set using  define symbol “:”.  Variable keyword is optional if we do not have other regions to care about.

Syntax Alternative:

This alternative allow use of optional keyword variable with indentation of two spaces. This keyword is useful when we declar only several variables of the same type and we do not have a group of variables to define.

[variable] <name>=<value>[,<name>=<value>] ... :<type>;

Note: The variable keyword is optional

Initial value:

It is a good practice to initialize variables with explicit literals. Literals are constants but they are used one single time and have no name in the program except after they are assigned to a variable.

If the initialization is missing the variable take default Zero value. This is 0 or .0 if a variable is numeric and Empty ” for strings. Composite types are not initialized. Uninitialized composite variables are Void and can be checked using “is” operator like this: “m is void”.

System Variables

We can define system variables using “$” name prefix. These variables can be created using operating system and are known as Environment Variables. Users can define global variables using this prefix: “$”. They can be derived from the existing environment variables using concatenation “.” notation. This concatenation is depending on operating system. On Windows it is replaced by “\\” on Linux is replaced by “/”. There is no need to use “…” for strings when we use this notation except if the string contains spaces.

  $SEARCH_PATH = $PRO_HOME.components;


We use several operators for assignment: The primary operator is “=”  used for initialization. Other assign operators are called modifiers: {:=, +=, -=, /=, *=, %=, ^= }. This operators are polymorphic. The assignment triggers automatic memory allocation if there variable is a reference to composite type.

In declaration region a variable can be initialized using “=” to a constant literal, parameter value or other variable value. We can’t use an expression to initialize a variable. Expression based initialization is done in executable area. This is called deferred initialization.

Note: We use colon “:” to set value for collection literals or tuples of arguments. This is called pair-up operator. It is used for records and maps as well as procedure, function and method call with named parameters.


procedure test_assign is
  <variable_name>=<value_literal>:<type>; !declare with initial value
  <variable_name>:=<level_expression>; !assign new value
end procedure;


-- in this example we use multiple lines to declare variables
  a=10:Integer; --define 1 variable with initial value 10
  b,c,d=40 :Integer; --define 3 variables b=0, c=0, d=40 all integers

Note: variables b and c will have default value zero.


This example introduce a concept that is called “slicing” operator “..”

-- int this example we define several constants and variables
  PI=3.14:Real; ! define a constant 
  var1, var2:Integer; !define module variables; 
  $big_data:Vector(1000) of Integer; !define global variable 
program test_var is
  a,b,c=40:Integer; !define and initialize b=0, c=0, d=40 
  big_data:=var1+var2; !set all 1000 elements to 25
  big_data[50..]:=50; !make last 950 elements 50
  big_data[..49]:=10; !make first 50 elements 10
  big_data[100..149]:=100; !make 50 elements starting from 100 to 149 equal to 100
  big_data[0]:=a; !set first element to 0
  big_data[1]:=b; !set second element to 0
  big_data[2]:=c; !set third element to 40
end program;
You need to login to view the rest of the content. Please . Not a Member? Join Us