Sage-Code Laboratory
index<--

Eve Syntax

Eve syntax is inspired from many other languages. We use short English keywords without abbreviation. We get inspired from many other languages: Ada, Ruby, Fortran & Python. Eve is not a curly bracket language. We hope you will enjoy learning it.

Page bookmarks

In this article you will learn about:



Hello World

For start let's honor a tradition: We should print "Hello world!" to the console using EVE. Next is a simple program that ca write a message on the console.

Example:

#demo: hello world
driver hello:

process
  ** main process
  print "Hello World!";
return;

Syntax Elements

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.

Example:


# 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;

Punctuation:

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.

Comments

Examples:


# 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.
*/

Notes:

Identifiers

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_

Prefix & Sigil

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

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

Notes:

Globals

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: { :=, ::, +=, -= ... }.

Globals example:

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.

Fragment


** 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.

Initial Value

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.

Zero Values

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.

Cascade Initialization

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.

Fragment


# multiple variables
process
  new a = b = 1 :Integer;
  new x = y = z = 0.5 :Double;
  ...
return;

Expressions

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...

Fragment


## 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;

Notes:

Assign Expression

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.

Assign: by 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
  ...

Assign: by 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.

Syntax:

// 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.

Ternary expression

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.

Syntax:

# 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;

Example:

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;

Statements

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.

Single line statement

The most simple statements are definitely single line statements:

Fragment:

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;

Multi-line statements

One expression can span multiple lines.

Example:


# 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;

Reserved keywords

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 print
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

Definition regions

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

Semantic keywords

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

Blocks of code/sections

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

Operator keywords

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

Assign keywords

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

Interruption statements

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

Delimiters

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.

Comments

Symbol Description
**...** Single line separator
/*...*/ Outline comments | Expression comments
+-...-+ Block comments | Boxed comments
"/.../g" Regular expression search pattern
#(...) String interpolation (placeholder) for operator "?"

Collections

Symbol Description
(_,_,_) List literal | parameters | arguments
[_,_,_] Array literal for (Vector | Matrix)
{_,_,_} Ordinal | DataSet | HashMap | Class / Object

Strings

Symbol Description
'...' Symbol = Unicode UTF8 codepoint (4 Bytes).
"..." Variable capacity UTF8 String literal.
"""...""" Variable capacity large / multiline UTF8 text literal.

Operators

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:

"_" '_' (...) [...] {...} #(...)

Single symbols

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.

Double symbols

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.

String concatenation

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 "//"

Numeric operators

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)

Relation Operators

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

Modifiers

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

Logical operators

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

Unary operator: not

Table of truth

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

Bitwise operators

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

Quick Format

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".

Date Format

ConstantValue
YDMYYYY/DD/MM
DMYDD/MM/YYYY
MDYMM/DD/YYYY

Time Format

ConstantValue
T24HH:MM:SS,MS
T12HH:MM:SSpm,MS | HH:MM:SSam,MS

Numeric Format

ConstantValue
EUR,.
USA.,

Read next: Structure