Eve Structure

Eve is designed to quickly build a data processing app that can run several jobs in order on a precise schedule. You can create one module app but sometimes you need to divide a project into many small modules that run together.

Page bookmarks:

Next topics describe overal structure of Eve applications.


A project is a folder with a specific structure. It contains one or more applications that can run independent of each other on the same computer or a group of computers.

project structure

Next project contains two applications: server/agent and show folders where you should put your code (src+lib) and documentation (doc). This is a recommendation but not a hard rule.

  |-- agent
  |   |-- aspect1.bee
  |   |-- aspect2.bee
  |   ...
  |-- server
  |   |--  aspect1.bee
  |   |--- aspect2.bee
  |   ...
  |-- library
  |   |-- module1
  |   |     |-- module_script1.bee
  |   |     |-- module_script2.bee
  |   |     ...
  |   |-- module2
  |   ... 
  |-- documents
  |   |--
  |   |-- index.html
  |   ...
  |-- agent.eve
  |-- server.eve


Eve define several kind of scripts that together makes a "project suite". Some scripts are reusable but some are specific to a single project. Here are all the possible scripts:

Notes: One project can contain one or many drivers. Each driver is an independend script. A driver has a single executable process. Eve virtual machine can run a single driver at a time but several aspects in the same time. A driver can "import" modules and can "start" several aspects in parallel.



A script file is divided into regions using keywords: {import, alias, global, process}. Regions members are using indentation, like Python. A region ends when next region begins. Eve try to be flat as much as possible. Therefore these regions are right side aligned.

Syntax Pattern:

An Eve script begins with one of these keywords: {"driver", "aspect", "module"}. Script name is the same as the file name without the extension. A driver or aspect script can have parameters, defined after script name in a list, but a module do not have parameters.

 Header comments: explain the module purpose  
 These comments can be used on top of module      
[driver | aspect | module] name(parameters):

** set system variables
  set $sys_con    = value;

** import region
  from $path/library_name use (*);

** qualifier suppression region
  AliasName1 = library_name.MemberName;
  AliasName2 = ClassName[parameters];

** define user types
  NewType  = {} <: Type;
** define functions using Lambda expression
  set expression_name = (params) => (expression);
** global & shared states
  set local = value1: user_tupe;
** main process, or initialization region
[process | init]
  new my_var  = value;  -- private variable
[finalize | release]
  ** release locked resources & log reports
/* notes: can be used at the end of the script. 
   usually the notes use C like, block comments.


Note: Any script has one or more global regions. In this regions, you can set system states and define global states. In declaration region you can also define: classes, methods, functions & routines.

All variables defined in global scope are static. You must use keyword "set" to define them and assign initial value. Static variables are created on the heap and have a permanent nature.

System variables

Shared states use prefix "$". These are called system variables. Can be loaded from a configuration file (*.cfg). Eve modules and drivers cana define, initialize or reset values for shared states.

Shared states can be defined in the first region after ":", after indentation. No need to use global keyword for this region. You need to use global if you declare some globals later before the process or init region.


Several system variables are provided by Eve environment:

System objects are instantiated at startup and are part of core library. These contain runtime information that you can use for debuging. System objects do not need module qualifier. You can access them directly once the module is imported.

Constants have at least first letter capitalized. The best practice is to use all capital letters for constants. The next symbols in a constant name can be numbers or underscore but no special or Unicode character.


** gobal scope
  set $PI  = 3.14 :Float;      -- shared constant
  set $var = 0    :Integer;    -- shared variable


Global states

Global states are static variable defined in global scope . You can access clobal states in functions and methods without qualifier.

Global states can be constant or variables. Constats use capital letters while variables are using lowercase letters. First letter is important, other letters can be numbers, lowercase or uppdercase letters or undrscore.


driver test():

** private class
class Person = {name:String, age:Integer} <: Object;

** create states using type inference
  set  E = 2.52 :Real;    -- Euler's number
  set  x = 0    :Integer; -- private state

** create a global object of type Person.
  new  me := Person("Elucian", "56"); 


Import region

The import is used to include public members from modules:


driver script_name:
  ** define global states
  set $user_path := root_path/relative_path;

  from $user_path use (module_name,...);  -- specific modules
  from $user_path use (*);                -- find all modules
  ** create alias for some of the hiden members
  set new_name := module_name.member_name;



library is a set of reusable modules. A library can be installed in EVE environment or can be project specific. EVE machine is using a special system variable to search for a library: $EVE_LIB. If the library is not found the module can't be imported and the script fails.

Note: Library name is the name of the subfolder. Module is the name of the last folder in a path. By convention you can create itermediate subfolders but only the last folder is relevant and it must be unique in a library.


driver represents the application main script. It has the role to lead the application main process. When driver execution is over the application give control back to the EVE virtual machine. If no other process is running, the machine shuts-down after it clean-up the memory.



An "aspect" is a script specific to a particular project. It resolve a problem or address a specific concern. Aspect files are executable. One aspect can execute other aspects, however it can't be recursive.

An aspect can receive parameters. One aspect has a declaration region and an executable region. You can resolve an aspect by using keyword: "apply" or "start". An aspect must handle it's own errors. If errors are not handled, the program panic and stop execution.

Syntax Pattern:

aspect aspect_name(parameter_list):
  ** declare variables
  ** executable region
  ** handle all errors

Parameters  are defined in round brackets () separated by comma. Each parameter must have type and name. Using parameters require several conventions:


Mandatory parameters do not have initial values but only type. Optional parameters have initial value that is assign using operator "=" with explicit :type, or ":=" with type inference. Not both.


  1. One aspect can receive one or more parameters,
  2. Parameters having initial values are optional,
  3. Values used for parameters at runtime, are called "arguments",
  4. You can assign arguments by position using a list of values,
  5. You can assign arguments by name using (name:value) pairs;

Vararg parameters

One aspect can receive multiple arguments of the same type into a single collection parameter. This can be a List, DataSet or HashMap, depending on declaration.


# print all arguments
aspect test(*args: ()String):

** list all arguments
    new arg :String;
  for arg in args loop
    print arg;

Process context

One script can have one single process. Every process has a local context. In this context you can define variables, and instantiate objects but you can't define routines, classes, methods or functions. Process local members can't be shared but can be send as input/output parameters to other subprograms.

Output Parameters

To avoid overuse of global variables you must use input/output parameters. We prefix output parameters using symbol "@". Output parameters require a variable as argument, otherwise you will not be able to capture the output value.

#demo output parameters
aspect output_params:

** private subroutine
routine add(p1 = 0, p2 = 1: Integer, @op: Integer):
  let op := p1 + p2;

  new result: Integer;

  ** inpur/output argument require a variable
  call add(1,2, op:result);
  print result;     -- expected value 3

  ** negative test, will fail
  call add(1,2,4); -- error, "out" parameter require a variable



Eve modules are abstract concepts. One module exist in a folder. A module consist of several scripts with extension ".eve". Modules can be combined together in large projects. Some modules are common for many projects. These are called system modules or library modules.

modules ...

Syntax Pattern:

An Eve module begins with "module" keyword. Module name is the same as the last folder in a library path. A module can have an initialization region. This is executed when the module is imported for the first time.

module name is the folder name, so that
one module can have more then one scripts.    
module module_name:

** shared states
  set $system_variable: Type;

** import region
  from $path/library_name use (*);

** declare members
** setup intial states 
  let $system_variable := value;
** verify states & log


Module names are using lowercase letters, can contain underscore or digits but no special characters and no Unicode strings. Longer names that use several words can be separate with underscore. The module name can be 30 characters long.

Module scripts A module can be a single script file but usually represents several files. The main script has the same name as the module name. In the main script you can define ony the public members. In secondary scripts, you can define only the private members.

Script Execution

Eve scripts are executed using a virtual machine. You can start the virtual machine as a service or as console application. In console you can run only a one driver script at a time. In service mode you can run multiple drivers. Each driver is independent and can't communicate with other drivers.

Configuration:  Eve services using a general configuration file: eve.cfg. This file contains default settings for EVE machine. System variables are shared. A copy of EVE system variables is send to every new driver instance.

A driver can define default settings using "set". Configuration setings are loaded over the default values and have priority. In a process, you can temporarly change the settings using let. These changes do not propagate back into the condifuration file.

Memory allocation: EVE service is in charge of allocating memory for each process. There is no shared memory between processes. When a process is terminated the memory is cleaned up of garbage and the machine continue to run until all processes are finished.

To execute a driver there are 2 methods:

  1. Using the "eve" system command with parameters,
  2. Using console REPL commands with "load" command,
  3. EVE virtual machine can be run as a daemon,
  4. You can control EVE virtual machine using command: eve with parameters

Driver Execution:

When a driver is loaded, all it's components are compiled in memory, then the process is executed. If a driver do not have a "process", it can be manually executed from eve console, one routine at a time.


~/eve -c file.cfg

Running a Driver

eve:> load ~/path/driver_name.eve -c file.cfg -m 2048GB

Debug a Driver

eve:> debug ~/path/driver_name.eve -c file.cfg

Eve REPL can be used to load or debug a driver manually, using special commands. The command options are not yet fully designed. We will implement these basic commands:

command description
load compile a driver and execute the main process
debug compile a driver but does not execute main process
begin start the driver main process step by step execution
enter this is actually the enter key. execute next step
print display value for a global variable, it can't print locals
resume continue running until a "halt" statement is enconter
report create a debugging report about system state
stop stop the driver execution but do not clean memory
clear stop the driver and clean the memory
setup load configuration file and set "$" variables
quit stop EVE machine and exit from REPL

You can use "halt" inside the script to stop a script and debug the script later. "halt" is working only when debug mode is active. Statement "halt" can be conditioned with "if" to create a debugging break-point.

Aspect Execution:

One aspect is executed from driver or from another aspect. You can not execute an aspect from itself. Recursive aspects are not supported. The compiler will detect a recursive aspect and will fail at runtime.

You can debug an aspect just like a driver. You can load an aspect, execute the aspect step by step and create a report. Aspects are independent processes. However you can't debug aspects in parallel.


Aspects can be run in serial mode one after another. Let's consider we have 3 aspects: {one, two, three}. We can execute each aspect using keyword: "apply". This will intrerupt the driver process and will execute aspec process one by one then return control to driver and continue the main process:

driver test_apply:

# synchronous call
  ** apply each aspect
  apply [folder/]aspect_one(arguments);
  apply [folder/]aspect_two(arguments);
  apply [folder/]aspect_three(arguments);

Note: You do not have to import an aspect into a driver but you must specify the relative path of the aspect. If the aspect is in a subfolder, you must include folder name. If the aspect is in the same location as the driver, you do not need a folder name.


Aspects can be resolved in parallel mode using keyword "start".

# asynchronous call demo
driver async_demo:
  ** enqueue aspects to be resolved
  start [folder/]aspect_one(arguments);
  start [folder/]aspect_two(arguments);
  start [folder/]aspect_three(arguments);

  ** wait for all aspects to finish

Parallel processes

One script can start an aspect with different parameters.

** resolve several aspects
driver async_loop:
  ** enqueue same aspect 4 times
    new i: Integer;
  for i in (1..4) loop
    start demo(i);

Module import:

The driver or aspect can import modules. After import, all public elements of modules can be used on demand. The parent process is controling the execution. Modules are not directly executable.

Modules are "singleton" once a module is loaded in memory, it will not load a second time for same process. Eve is a multi-session system. Module states are bound the the current process.

Exclusive mode:

When a eve is executed, it can be started with parameter: -x or --exclusive. This is a signal that only one process can connect or use resources. In this mode "start" is not starting a new process but works like "apply" in serial mode. In this mode you can alter a database structure.

Program Termination:

Program can be early terminated be done using: "over" or "panic". This is a way to release all locked resources and terminate the application. Program can end with an error code using "panic N" statement, otherwise it will automatically return 1 with panic and 0 with "over". Actually "panic 0" is equivalent to "over".

When drive is terminated, it depends what is heppening next. When was started from a console in debug mode the module remains in memory, parsed and ready for debugging. The memory can be investigated using commands. When driver is executed in regular mode, the memory is erased and the EVE machine stop running.


Next code sequence is terminated after 100 iterations:

# terminate a program with: over
driver test_over:
    new i = 0 :Integer;
    write "."; wait  10;
    over if i > 10;
    let   i += 1;


EVE virtual machine can load system environment variables from a configuration file. These are stored as "$name:value" pairs. Some system constants can be derived from environment variables using concatenation operators "+", "/" or "\".

A configuration file have extension .cfg. One application can run with different configuration file. Application documentation must contain demoduleion of all variables required by the application.

A good practice is to provide a configuration template . The template file may contain comments and $key = value pairs. Values can be numeric, string, symbol, date, time or data literals: [],(),{}. Eve application will automatically parse configuration file to read values for the system variables.

In debug mode you can modify the configuration and reload using "setup" command. REPL must be in "ready" state when you reload settings otherwise you will get an error.

Read next: Data Types