– Typee Documentation –
3 – Typee Language Description
3.9 – Declarations and Assignments
Declarations and assignments in Typee are really simple to use, but the formal specification of the related grammar rules is a little bit more complex.
In the document specifying these rules, their root rule is <assign decl def func-call statement>
which is one of the derivations of <compound statements>
.
This root rule covers everything about assignments, declarations, definitions and function calls. We will explain all of this in this section and in the next one. Let’s first focus here on declarations and assignments. These concepts are linked together since assignments can be done at declaration time. It will be easy to generalize assignments then.
The rules (the ones that are part of the global rule) related to declarations and assignments, as formerly expressed in their extended Backus-Naur form, are:
<decl statement> ::= [<access qualifier>] [ 'static' ] <decl statement'> <decl statement'> ::= 'volatile' <type> <identifier> [<memory address>] ';' | <type alias> ';' | <enum definition> ';' | [ 'const' ] <type> <identifier> [<var declarations or assignments>] ';' <memory address> ::= '@' <integer number> <var declarations or assignments> ::= [ '=' <expression> ] [ ( ',' <identifier> [ '=' <expression> ] )* ] <access qualifier> ::= 'hidden' | 'local' | 'private' | 'protected' | 'public'
<assignment statement> ::= <targets list> <assign statement> <assign statement> ::= '=' <expr list> <expr list> ::= <expression> ( ',' <expression> )* <target> ::= <dotted name> (<subscription or slicing>)* <targets list> ::= <target> ( ',' <target> )* <type alias> ::= 'type' <TYPE> 'as' <identifier> ( ',' <TYPE> 'as' <identifier> )*
3.9.1 Declarations
Typee is a typed language. As such, any entity has to be declared with its own type. Auto-typing is allowed but even then a specific type sign is used to declare auto-typed variables.
Typee accepts declarations and forward declarations. We discuss only declaration statement here. Forward declarations are discussed at a next sub-section.
Access protection level
Declarations are applied to variables. When declared at the highest level of nested blocks of statements in a module, these variables may be associated with an access protection qualifier. In this case, the used keyword qualifies the protection of the declared entity outside the module (i.e. the source code file) where this entity declared.
The different levels of protection are:
<access qualifier> ::= 'hidden' | 'local' | 'private' | 'protected' | 'public'
The default protection level is public
. It specifies that the declared entity can be used outside the module with no restriction. It can be read, assigned, modified within any other module belonging to the global software project (i.e. the developed program).
The highest protection level is hidden
. It specifies that the declared entity cannot be accessed outside this module. Meanwhile, it is fully accessible to the whole module statements. Typee specifies two aliases, or wrappers, to hidden
:
private
, which is a more used keyword but mainly for classes, and local
, which is also used in other programming languages and for the same purpose. Programmers are nevertheless strongly encouraged to use keyword hidden
in Typee.
An intermediate protection level is protected
. This is a common keyword in OOP languages. Used at the highest module level, it gives full control on the declared entity to every other module that is contained in the same directory than the module it is declared in, and to every module that is contained in sub-directories of this directory. In Java and in Python, such modules are said to belong to a same package. There are restrictions however in these programming languages when using or declaring packages. In Typee there is nothing more to do to create a package than putting source code files (i.e. modules) in a same directory and in its sub-directories.
Then, any protected
entity declared in a module cannot be accessed by any module that would not belong to the same package.
When no access protection qualifier is used, what does happen? We have seen in the section about Simple Statements that an access protection statement
exists in Typee:
<access protection statement> ::= ':' <access qualifier> ':'
When present at the highest level of a module, every declarations below this statement get the declared protection level unless they get an individual different one, directly at the beginning of their declaration.
Finally, when no access protection level is specified, the declared entities are considered by default to be public
.
3.9.2 Volatile Declarations
Volatile declarations are well known by Java, C and C++ programmers but not by Python programmers. It is a very specific declaration type.
Its formal specification in Typee is:
<volatile decl> ::= 'volatile' <type> <identifier> [<memory address>] ';' <memory address> ::= '@' <integer number>
When an entity is declared volatile
, the final compiler or interpreter of the targeted programming language is informed that this entity is subject to change of value at any time and from any hardware external source. Optimizations on the access to this entity should then be disabled. This is typically the case when accessing a hardware register on some board, for instance when reading the value of some measured physical event (level of registered sound, rounds per minute of a rotating object, pressure level or temperature value as measured by a sensor, etc.)
We could have left this kind of declaration to the sole possibility of embedded code, since this kind of declaration is NOT available in every programming language. We have prefered to integrate it in Typee specifications. Programmers are informed that this keyword may not be used when translating Typee source code in some other programming languages and that Typee source code declaring such variables may not be ported the same way on different platforms due to the targeted programming languages capabilities.
In Typee grammar specification, a memory address can be associated with a volatile declaration. The physical address of the related hardware register and the type of the data it controls can then be specified at declaration time. Token ‘@
‘ informs Typee translator that a memory address is specified. This address must be an integer. It can be then written in an hexadecimal form. Anything other than integer will set an error at Typee translation time.
3.9.3 Type Aliasing
Typee allows the renaming of types. This is type aliasing. The related syntax is very simple:
<type alias> ::= 'type' <TYPE> 'as' <identifier> ( ',' <TYPE> 'as' <identifier> )*
First, keyword type
specifies the type aliasing statement. Then is specified the type to be aliased, keyword as
and finally the alias, i.e. the new name, of the aliased type.
Examples:
type int32 as int; // int is now a new name for int32 type uint8 as byte; type float32 as float; // float and double type float64 as double; // usual definitions forward class ThisIsAVeryLongClassName; type ThisIsAVeryLongClassName as TheClass; // shorter wrapper to class long name
3.9.4 Enum Definitions
Enumerations are ordered declarations of valued labels. Labels are identifiers. They are grouped into a same block that is preceded by keyword enum
and are characterize by a type identifier. Labels may be assigned values. Up to now in Typee, those values are integers.
If not explicitely assigned an integer value, labels get incremented values in the order of their declaration, with values starting at 0
.
When an integer value is explicitely assigned to a lable, next labels will get incremented integer values from this one if they are not themselves explicitely assigned a value.
Their formal EBNF syntax is:
<enum definition> ::= <enum type> <identifier> '{' <enum list> '}' <enum item> ::= <identifier> [ '=' <expression> ] <enum list> ::= <enum item> ( ',' <enum item> )*
Example:
enum ColorPlanes { ALPHA = 3, RED = 0, GREEN, BLUE }; /** Here, values associated with labels are 0: RED, 1: GREEN, 2: BLUE, 3: ALPHA **/
3.9.5 Forward Declarations
A forward declaration is a declaration with no associated assignment or definition. It informs Typee translators that a declaration or a definition (of a class or a function, for instance) is to be provided later in a source code. It allows for the typed declaration of an entity that is to be appearing in some expression near below while it will be defined or fully declared later in the Typee source code.
Since forward declaration lets declaring further definitions as well as further declarations, its syntax is a little bit more complex than the syntax of direct declarations. We fully explain it in this sub-section.
The formal EBNF specification of forward declarations is:
<forward decl> ::= <forward> ( ([ 'static' ] <forward decl'>) | <fwd class decl> ) ';' <forward decl'> ::= <volatile qualifier> <type> <identifier> | <fwd type decl> | <identifier> <fwd decl constructor> | <TYPE> ( <operator declaration> | (<identifier> (<fwd var decl> | <function declaration>)) ) <forward> ::= 'forward' | 'fwd' <fwd class decl> ::= 'class' <identifier> <template def> [<inheritance>] <fwd decl constructor> ::= ( '.' <identifier> )* (<operator declaration> | <identifier> (<fwd var decl> | <function declaration>)) | <function args declaration> <fwd type decl> ::= 'type' <identifier> <fwd var decl> ::= ( ',' <identifier> )* <TYPE> ::= [ 'const' ] <type>
<function declaration> ::= [<template def>] <function args declaration> <function args declaration> ::= '(' [<typed args list>] ')' <typed args list> ::= <TYPE> <identifier> ( ',' <TYPE> <identifier> )*
<inheritance> ::= [ ':' <inheritance item> (',' <inheritence item>)* ] <access qualifier> ::= 'hidden' | 'local' | 'private' | 'protected' | 'public' <inheritance item> ::= [<access qualifier>] <dotted name> [<template args>]
<operator declaration> ::= 'operator' ( (<operator> [<template def>] <function args declaration>) | (<operator'> [<spaced template def>] <function args declaration>) | (<call operator> <template def>) ) <operator> ::= '<=' | '==' | '!=' | '>=' | '&' | '|' | '^' | '++' | '--' | '#' | 'in' | '+' | '-' | '*' | '/' | '%' | '??' | '**' | '^^' | <user op> | <assign op> | <cast op> <operator'> ::= '<' | '>' | '<<' | '>>' | '<<<' | '>>>' <assign op> ::= '=' | <augmented assign op> <augmented assign op> ::= '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '<<<=' | '>>=' | '>>>=' | '**=' | '^^=' | '@=' | '><=' | '!!=' | '::=' | '??=' <call operator> ::= '(' ')' <cast op> ::= 'cast' <dotted name> <user op> ::= '@' | '><' | '!!' | '::'
<template args> ::= '<' <template args'> '>' <template args'> ::= [<condition> ( ',' <condition> )*] <template def> ::= '<' <template def'> '>' <template def'> ::= (<identifier> | <const qualifier> <template def const name>) ( ',' (<identifier> | <const qualifier> <template def const name>) )* <scalar type> ::= 'bool' | 'char' | 'char16' | 'float32' | 'float64' | 'int8' | 'int16' | 'int32' | 'int64' | 'uint8' | 'uint16' | 'uint32' | 'uint64' | 'str' | 'str16' <spaced template args> ::= ' <' <template args'> '>' <spaced template def> ::= ' <' <template def'> '>' <template def const name> ::= (<scalar type> | <dotted name>) <identifier> [ '=' <expression> ]
“Very long, isn’t it?” would have said Tex Avery. Nevertheless, aAll of this may be summarized quite simply.
A forward declaration begins with keyword forward
, which can be shortened to fwd
also. Next is the forwarded declaration itself.
- If it is about a variable, its type and its identifier are specified, maybe preceded by keywords
const
orvolatile
and any of the access protection levels. - If it is about a class, the only “signature” of the class is provided: keyword
class
, the identifier of the class and if needed the template arguments declaration associated with this class (more on this when discussing classes, later in this documentation) and finally its inheriting chain if any is needed (more on this also in the next further section about classes in this documentation). This signature may also be preceded by any of the access protection keywords. - If it is about a function, the only signature of the function is provided: the returned type of the function, its identifier, its templated arguments if needed and the declaration of its arguments (more on this in next section on Functions).
- If it is about an operator, then again the only signature of the operator redefinition is provided: the returned type of the operator, its associated token (e.g. ‘
+
‘ or ‘<<=
‘), its templated arguments if needed and the declaration of its arguments (more on this later in this documentation, when presenting operators overloading). - If it is about a type alias, keyword
type
precedes the only identifier of the new alias for the type.
According to these typed forward declarations, Typee translators can process type checking on next statements while the needed full declarations have not yet been specified.
3.9.6 Assignments
Assignments in Typee appear in declarations as well as in assignment statements. They imply the use of an assignment operator which can only be =
for declarations while it can also be augmented assignment operators in assignment statements.
The formal EBNF specification for any assignment statement in Typee is:
<assignment statement> ::= <targets list> <assign op> <expr list> <assign op> ::= '=' | <augmented assign op> <augmented assign op> ::= '+=' | '-=' | '*=' | '/=' | '%=' | '**=' | '^^=' | '??=' | '&=' | '|=' | '^=' | '<<=' | '<<<=' | '>>=' | '>>>=' | '><=' | '!!=' | '::=' | '@=' | <expr list> ::= <expression> ( ',' <expression> )* <target> ::= <dotted name> (<subscription or slicing>)* <targets list> ::= <target> ( ',' <target> )*
Reminder: this is not for declaration statement, only for assignment statement.
Examples:
int32 a = 0; uint32 b = c = d = 1; float64 e = 2.718_281_828_459_045, f = 6.022_140_857e+23;
(do you know Amadeo Avogadro? Number f
above is his – a cool number from a cool looking guy)
Next section formerly explains Functions definitions and calls.