In this article you will learn about:
#demo: hello world
driver hello:
process
** main process
print "Hello World!";
return;
Next code fragment represents a very simple program written in Eve language. Let's identify the main syntactic elements and punctuation. This is how we will present eve, using examples of code and fragments.
# main script in Eve is called: "driver"
driver syntax_elements(a, b: Integer)::
** define two global lambda expressions
global
set add = (p1, p2: Integer) => (p1 + p2);
set sub = (p1, p2: Integer) => (p1 - p2);
** define local variables
process
** main process has access to parameters
print "param1: #{a}, param2: #{b}";
new v1, v2 :Integer;
let v1 := add(4, 5);
let v2 := sub(5, 3);
** print the result
print ("result:", v1); -- 9
print ("result:", v2); -- 2
return;
I describe the syntax using some conventions. The code snippets you are going to see are not all real executable code. Some are just fragments of code, syntax "design patterns" or "pseudo-code". You will get it after a while.
When the snippets is a "pattern" then we use square brackets like [...] for optional parts. Sometimes we use 3 dots "..." for a sequence that is missing. Sometimes [x] represents real code and is mandatory, depending on the context. Read the "example" snippets to understend better the syntax.
# boxed comments in Eve language
+--------------------------------------------
| Eve boxed comments can be used on top |
| You can create a box using this new style |
--------------------------------------------+
driver comment_demo:
# line comments in Eve language
----------------------------------------------
-- Single line comments are inspired from Ada
-- You can use these comments at end of lines
----------------------------------------------
process
** this comment style is inspired from "md"
new a = 0, b = 1 :Integer;
** next demo use end of line comments:
let a := a + b * -- end of line comments can
(a - 1); -- be useful in expressions
return;
# Final Notes:
/*
-- Eve also has C legacy style comments. These are
used for notes or outline large blocks of code.
-- Eve block comments can be nested over boxed
comments. So you can comment out large sections
of code that aredy have some comments.
*/
The name of identifiers in Eve can have a length of 30 characters. A name starts with lowercase letters (a..z) or capital letters (A..Z) followed by one or more characters or numbers. No special characters or spaces are permitted in the name except underscore ("_"). An identifier can contain underscore and can start with underscore but it can not end with underscore and can not use two consecutive underscores.
These are valid identifiers
_ x, y, z a1, a2, a3 thisIsOK this_is_ok _this_is_valid
These are invalid identifiers
1st not_valid_ _not_valid_
Indetifier prefix is used to declare a variable, but is not required when using the variable. A sigil is part of variable name and it must be used when you use the variable.
* | vararg parameter prefix |
---|---|
@ | receiver parameter prefix |
_ | protected member sigil |
$ | system state/variable sigil |
System variables start with sigil: "$", that is making a "system state". System states are static and public, shared in a process. A sigil is part of the identifier.
variable | Description |
---|---|
$object | current instance of a class, current object |
$result | default result of a routine when a name is not specified |
$error | current exception object of type Exception |
In any script you can define global variables. These are primitive values or references to objects. A global variable is represented by an identifier and value. Type is optional hint.
Global variables can be declared using "set" statement. Initial value is establish with operator "=" follow by a type hint. Globals can be modified during the program execution using "let" statement with modifier operators like: { :=, ::, +=, -= ... }.
Most of the examples are also stored on GitHub. However it is possible the one in GitHub to be different from then the one in documentation. This is due to fast evolution of the language and not by intention.
** define global system states
global
set $s = "test" :String;
** two integers
set $a :Integer;
set $b :Integer;
** one Double variable
set $d = 0.5 :Double;
Globals are also called "state variables" because they are staticly defined in module scope. We use "set" keyword to create new states. If the state alredy exist, it can be modified using "let". Compiler will signal an error if you set a variable two times.
The initial value can be establish using the initializer "=" (single equal). This operator can use only data literals but no expressions. It is not able to execute the right operator. That is, the initial value can be a constant literal or an expression but the expression is not evaluated.
When a variable is specified, with no initializer, the variables takes default zero values. These values are different for each data type. For example zero value for Integer = 0 for Double = 0.0 and for String = "" (empty string). Composite data types are initialized to "Null", that is (), [], {}, all equivalent to "∅" used in set theory.
Operator "=" is used to create an expression. That means you can initialize multiple variables using a single declaration. This is different than assignment ":=" or clone "::" that create a statement and not an expression. Operator "=" has a result. So it can be chained.
# multiple variables
process
new a = b = 1 :Integer;
new x = y = z = 0.5 :Double;
...
return;
An expression is a syntax element that can be evaluated using mathematical rules and principles. Expressions are created using identifiers, operators, functions and constant literals.
expressions...
## simple expressions
process
print 10;
write "this is a test";
** complex expressions can use ()
print (10 + 10 + 15); -- numeric expression
print (10 > 5) or (2 < 3); -- logical expression
** list of expressions are enclosed in ()
print (1, 2, 3); -- expect: 1 2 3
print (10, 11, 12); -- expect: 10 11 12
** using write to: avoid new line and print
write (1,2);
write (3,4);
** now create a new line and output the text
print; -- 1234
...
return;
To assign result of an expression to a variable you can use assign operator: ":=". This operator has a strange behavior that you must understand to avoid unintended side-effects. When a boxed variable is used as an expression, the operator transfer a value "by sharing" a reference, so it does not "copy" the value but the reference to that value. When the type is native, the value is transfered and not the reference.
#expressions pseudo-code
...
new identifier1 := literal; -- constant literal
new identifier2 := expression; -- execute expression
new identifier3 := function_name(); -- function call
new identifier4 := variable; -- borrow
new identifier5 := native_var; -- copy value
...
To make a clone/copy of an Object attributes you must use clone operator that is (::) instead of (:=). This will transfer values not references. After cloning, we can modify one value without affecting the original.
// making a clone
new object :: original;
expect object is not original;
Note: Native types are exceptions. For native type, the operator "is" do not work at all. Attempting to use "is" or "is not" with a native type will always return false even if the values are equal.
The ternary operator in Eve is the "if" keyword. This keyword has actually two roles in EVE. It can be used to create a conditional statement or an expression. It can be used to return a value or other depending on one or several logical expressions. In other languages we use ternary operator "?" and ":" but in Eve these two symbols are used for more important other purposes.
# ternary expression
process
** regular style using a single line of code:
new variable1 := (value1 if condition else value2);
** alternative style using multiple lines of code:
new variable2 := (value1 if condition1 else
value2 if condition2 else
value3);
...
return;
In next example we use a ternary expression as argument.
process
** create a logic variable
new test := True;
...
expect (True if test else False); -- will pass
...
return;
One statement can be declarative or imperative. We use both but mostly declarative statements. Thoug many times the statements are imperative. I guess Eve is hybrid then.
The most simple statements are definitely single line statements:
driver assign_demo:
process
** initialization statements
new a := 2;
new b := .0;
** execute expression
let b := a + 0.5;
** verification statements
expect a == 2;
expect b == 2.5;
return;
One expression can span multiple lines.
# multiple line demo
process
** multi-row expression
new var := 1
+2
+3 + 4 +
5 + 6;
** multi-row literal
new map := {
'two' :2,
'four':4,
'six' :6
};
return;
Computer was invented in England during WW2, so we prefer English keywords, even though a computer language could be created using keywords from other spoken languages. Eve is using about 100 reserved keywords.
abort | alias | alter | analyze |
append | apply | ascend | augment |
start | method | stop | by |
case | class | clone | close |
commit | constant | create | cursor |
begin | delete | descend | discard |
else | end | error | exit |
expect | fail | feature | fetch |
for | from | function | group |
halt | if | import | inherit |
insert | into | item | join |
limit | loop | method | object |
offset | open | order | one |
over | package | pass | |
process | raise | read | record |
recover | release | resume | repeat |
reset | rest | result | on |
retry | return | rollback | routine |
globa | select | all | skip |
step | store | switch | job |
then | trial | try | reset |
update | use | labe | view |
where | while | with | write |
call | panic | any | other |
Keyword | Description |
---|---|
import | define import region |
alias | define identifier for some imported module members |
class | define region for user defined composite types |
global | define a region for state variables and constants |
Keyword | Description |
---|---|
module | define a program file (module-name = file-name) |
function | declare a function of type Function |
class | define a composite data type for object oriented programming |
create | begin constructor region for a classes |
feature | define a design pattern that can be enabled by a class |
augment | define an augment for an existing class |
method | define behaviour for user defined data types |
recover | define a recover region for a method |
release | define a object clear region for a class |
process | define a named block of code that has several steps |
return | terminate a process/function or a class declaration |
reset | create the "initialization" region for a module |
Keyword | Description |
---|---|
begin | used before a block of code to create a local scope |
match | multi-path conditional selector |
when | define a pathway in multi-path selector |
other | define a default pathway in a selector |
cycle | start declaration region for a repetitive block |
loop | unconditional repetitive block |
while | conditional repetition block |
for | visitor iteration loop |
if | start a branch or a fork |
else | start alternative branch |
repeat | repeat a block of code in a cycle |
done | close a control statement |
Keyword | Description |
---|---|
is | check data type | reference identity |
in | check element is belonging to a list/set |
not | logical NOT operator |
and | logical AND operator |
or | logical OR operator |
xor | logical XOR operator |
For any kind of assignment or modification you must us a specific keyword. This is why we use keywords like: {set, new, let}. User must read what's going on and will understand much better the code by using keywords.
Keyword | Description |
---|---|
new | Create local variable or attribute |
set | Create global variable or property |
let | Alter existing variable or attribute |
Keyword | Description |
---|---|
panic | create unrecoverable error and stop application, status > 0 (os error) |
stop | intrerupt current cycle and continue after the "repeat" keyword. |
abort | stop current process and skip finalization region. |
raise | create exception with error code > 0 (recoverable). |
repeat | end a repetitive block and continue program. |
fail | create a fail status and skip the rest of the job. |
pass | create a pass status and skip the rest of the job. |
retry | work-flow jump backwards to specified job. |
resume | continue a process with the next job after an error. |
apply | execute a process or aspect in synchronous mode |
start | execute asynchronously an aspect |
yield | interrupt current process and wait for other processes |
run | execute a routine in asynchronous mode |
call | execute a routine in synchronous mode |
halt | temporarly intrerupt the process for debug |
exit | intrerupt execution of a process or sub-program |
over | intrerupt current process and terminate application |
In the syntax description "..." represent content and "_,_,_," represents a sequence of elements. "_" represent one of the elements. In descriptions vertical bar "|" represents second alternative. Some operators can have multiple purposes depending on the context and data types.
Symbol | Description |
---|---|
**...** | Single line separator |
/*...*/ | Outline comments | Expression comments |
+-...-+ | Block comments | Boxed comments |
"/.../g" | Regular expression search pattern |
#(...) | String interpolation (placeholder) for operator "?" |
Symbol | Description | (_,_,_) | List literal | parameters | arguments |
---|---|
[_,_,_] | Array literal for (Vector | Matrix) |
{_,_,_} | Ordinal | DataSet | HashMap | Class / Object |
Symbol | Description | '...' | Symbol = Unicode UTF8 codepoint (4 Bytes). |
---|---|
"..." | Variable capacity UTF8 String literal. |
"""...""" | Variable capacity large / multiline UTF8 text literal. |
Eve us ASCII symbols for operators. One operator can be single character or two characters with no space between tem. Sometimes we use the same character twice for example "==" or ">>". This convention is well known in many other computer languages.
Single symbol:
# , : . ; = ~ ? % ^ * - + / < > & | ! @ $
Two symbols:
== != => <= >= :> <: .. !. !~
Three symbols:
""" .|. .&. .+.
Modifiers:
:: := += -= *= /= %= ^= &= |= +> <+ >> << -> <-
Delimiters:
"_" '_' (...) [...] {...} #(...)
Eve use al single symbols found on a standard keyboard.
Symbol | Description |
---|---|
! | Negation symbol |
? | String template find & replace |
# | Title at begging of line | Digit in string pattern |
# | Last element index in a collection |
$ | Sigil for share variable or system variable | constant |
@ | Iput/output parameter | result prefix |
; | Statement separator | End of statement |
: | Define type, routine, class or block | Pair-up/binding operator (a:b) |
= | Type descriptor, initial value for variables | parameters |
~ | Regular expression comparison/check |
. | Decimal separator | Member qualifier |
, | Enumeration for elements | complex expression |
* | Variable arguments | Multiplication | All elements | * | Usable in import to create a file pattern/search |
| | Used in set builders | Set union "∪" |
& | String concatenation | Set intersection "∩" |
_ | Void variable that accept any value and clear memory. |
Eve use two symbols to create supplementary operators.
Symbol | Description |
---|---|
** | Single line comment |
-- | End of line comment |
.. | Slice [n..m] | Domain [n..m] or Range (n..m) |
<: | Define super-type in a derived type declaration |
:> | Numeric data conversion or convert a subtype into a supertype. |
<< | Shift ordered collection to left with n: X := C << n |
>> | Shift ordered collection to right with n: Y := C >> n |
:= | Assign value of expression to a variable. |
Symbol | Description |
---|---|
+ | Concatenate two strings as they are without trim |
- | Concatenate two strings after trimming to one space |
/ | Concatenate two strings with "/" separator and de-duplicate "//" |
\ | Concatenate two strings with "\" separator and de-duplicate "\\" |
. | Concatenate path or URL strings with a symbol and de-duplicate "//" |
Symbol | Description |
---|---|
* | Numeric multiplication | Scalar operator |
/ | Numeric division |
% | Reminder operator | Scalar operator |
+ | Numeric addition | String concatenation | Set union |
- | Numeric subtraction | String concatenation | Set difference |
^ | Power. (We can't use ** that is for comments) |
Eve use two symbols to create a additional operators.
Symbol | Description |
---|---|
== | Equal | deep comparison |
!= | Different value | (deep comparison) |
> | Greater than value |
< | Less than value |
>= | Greater than or equal to values |
<= | Less than or equal to values |
Each modifier is created with pattern "?=", where "?" is a symbol, haiving one of these values: {:, +, -, *, /, %, ^}. Also the symbol "::" is a modifier.
symbol | meaning |
---|---|
:= | Assign by reference | shallow assignment |
:: | Assign by copy | clone assignment |
+= | Increment value |
-= | Decrement value |
*= | Multiplication modifier |
/= | Double division modifier |
%= | Modulo modifier |
^= | Power modifier |
These operators are expected logical values T = True, F = False
Symbol | Description |
---|---|
if | conditional operator |
is | check element are the same (compare locations) |
is not | check elements are different. (compare locations) |
eq | equivalence "≡" (compare value & type) |
not eq | non equivalence "!≡" (compare value & type) |
in | logic belong to: instead of "∈" |
not in | logic not belong to: instead of "!∈" |
not | logic NOT (negation) |
and | logic AND (intersection) |
or | logic OR (union) |
xor | logic Exclusive OR |
A | B | A and B | A or B | A xor B |
---|---|---|---|---|
True | True | True | True | False |
True | False | False | True | True |
False | True | False | True | True |
False | False | False | False | False |
These operators are working for natural numbers ≥ 0
symbol | description |
---|---|
!. | bitwise NOT (unary) |
.&. | bitwise AND |
.|. | bitwise OR |
.+. | bitwise XOR |
<< | shift bits to left |
>> | shift bits to right |
Binary operators
A | B | A.&.B | A.|.B | A.+.B |
---|---|---|---|---|
00 | 00 | 00 | 00 | 00 |
01 | 00 | 00 | 01 | 01 |
11 | 01 | 01 | 11 | 10 |
10 | 11 | 10 | 11 | 01 |
11 | 11 | 11 | 11 | 00 |
Unary operators
A | !.A | A << 1 | A >> 1 |
---|---|---|---|
0000 | 1111 | 0000 | 0000 |
1111 | 0000 | 1110 | 0111 |
0111 | 1000 | 1110 | 0011 |
0110 | 1001 | 1100 | 0011 |
For printing output using a format we use operator as that is the "quick format" operator. We can use system constant templates that are available for making different formats for different data types. This operator is a bit smarter than the "?" operator that we can use for "string templates".
Constant | Value |
---|---|
YDM | YYYY/DD/MM |
DMY | DD/MM/YYYY |
MDY | MM/DD/YYYY |
Constant | Value |
---|---|
T24 | HH:MM:SS,MS |
T12 | HH:MM:SSpm,MS | HH:MM:SSam,MS |
Constant | Value |
---|---|
EUR | ,. |
USA | ., |
Read next: Structure