index<--

Eve Structure

Eve is designed to quickly build a data processing app that can have jobs to be executed 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. Eve provide features to do both kind of applications.

Page bookmarks:

Next topics describe overall structure of Eve applications.



Projects

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.

$pro_home
project
  |-- agent
  |   |-- aspect1.bee
  |   |-- aspect2.bee
  |   ...
  |-- server
  |   |--  aspect1.bee
  |   |--- aspect2.bee
  |   ...
  |-- library
  |   |-- module1
  |   |     |-- module_script1.bee
  |   |     |-- module_script2.bee
  |   |     ...
  |   |-- module2
  |   ... 
  |       
  |-- documents
  |   |-- readme.md
  |   |-- index.html
  |   ...
  |-- agent.eve
  |-- server.eve

Scripts

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 independent script. A driver has a single executable process. A driver control the execution of aspects. An aspect is encapsulated and contains it's own process. An aspect can receive parameters from the driver. An aspect or driver can "import" modules and can use classes or functions defined in these modules.

Features:

Regions

A script file is divided into regions using keywords: {import, alias, constant, global, process, initialize}. 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:

** set system variables
  set $sys_con    = value;
  ...

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

** qualifier suppression region
alias
  AliasName1 = library_name.MemberName;
  AliasName2 = ClassName[parameters];
  ...
** define constants 
constant
  NAME = Value;
  ...

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

Members

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

System variables use prefix "$". These are defined and maintained by EVE virtual engine. Values for these variables can be read automaticly by EVE engine at startup. Can be loaded from a configuration file (*.cfg). New variables can be defined by user for each script.

New system variables can be defined in the first region after ":", with indentation. No need to use global keyword for this region. The first region is the global region.

Note:

Examples:

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 debugging. System objects do not need module qualifier. You can access them directly once the module is imported.

Global Constants

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.

Example


** define global scope
constant
  set PI  = 3.14 :Float;      -- global constant
  ...
global
  set var = 0    :Integer;    -- global variable
  ...

Notes:

Example


driver test:

** driver context constant
constant
  E = 2.52 :Real;    -- Euler's number
  
** driver private class
class Person = {name:String, age:Integer} <: Object;

** driver context variable
global
  set  x = 0    :Integer; -- global state
...

Notes:

Import region

The import is used to include public members from modules:

Syntax:


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

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

Process

A process is an executable region of a script, mandatory for drivers and aspects. While modules don't use the 'process' keyword, they have an initialization region that serves a similar purpose. This initialization region is executed first when a process starts. For modules imported by a driver, the initialization runs within the driver's main process. When imported by an aspect, it runs in the sub-process created by that aspect.

Process context

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 subprograms or aspects.

Process Termination:

Process can be early terminated using: "over" or "panic". This is a way to release all locked resources and terminate the process. 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".

Example:

Next code sequence is terminated after 100 iterations:


# terminate a program with: over
driver test_over:

process:
  cycle:
    new i = 0 :Integer;
  loop
    write "."; wait  10;
    over if i > 10;
    let   i += 1;
  repeat;
return;

Drivers

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.

Notes:

Aspects

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 execute main() process of an aspect by using keyword: "run". An aspect must handle it's own errors it can't raise errors. If errors are not handled, the program panic and stop execution.

Aspect Syntax:


aspect aspect_name(parameter_list):
  ** declare variables
  ...
process:
  ** executable region
  ...
recover
  ** handle all errors
  ...
return;

Running an Aspect

Aspect is executed with keyword "run". An aspect can be executed synchron or asynchorn. We will explain more about aspect execution after we define the control flow, coroutines, functions and error handling. At this time let's focus on Driver execution and Modules.

Modules

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

Module Syntax:

An Eve module begins with "module" keyword. Module name is the same as the last segment in a library path. A module can have an initialization region. This is executed when the module is imported for the first time. That is the difference, a module do not have a "main process".


+-----------------------------------------
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
import
  from $path/library_name use (*);

** declare members
  ...
initialize
** setup initial states 
  let $system_variable := value;
  ...
release
** verify states & log
  $error.log();
  ... 
return;

Notes:

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 filesA module is a single script file but modules ca be grouped into "crates". A crate is a folder that can contain many module script files. You can specify in the import statement module by module or you can specify the "crate" and concatenate with module name using "/" that can concatenate a root_path.

Configuration

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

Library

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 intermediate subfolder but only the last folder is relevant and it must be unique in a library.

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 in parallel. Each driver is independent, it has it's own scope (memory location) and can't communicate with other drivers executed by EVE in the same time.

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.

Configuration settings are loaded over the default values and have priority. In a process, you can temporary change the settings using let. These changes do not propagate back into the configuration 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 main process is executed. An aspect do not have a "main process", however it can be manually loaded from EVE console. Then you can call one process or function at a time, for testing purpose.

Start EVE REPL

EVE is a REPL machine. (Read Execute Print Loop). This machine has a menu and a command line. You can issue commands that can load, compile, debug a script. We have not yet created this machine. It should work using "eve" command in console on Linux, Windows or Mac.

~/eve -c file.cfg

Running a Driver

The load command will load a driver into memory without running the main process. You can use this to load any script not only the driver. You can specify how much memory to allocate to the process that is available to run when you start it.

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

Debug a Driver

You can debug a driver. In debug mode the messages are more comprehensive and the console echo automaticly more information that can be reported to console.

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

Eve REPL can be used to load or debug a driver step by step, 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 encounter
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. You should remove "halt" statements when the software is mature and do no longer need debugging.

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.

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 controlling the execution. Remember, modules are not directly executable and must be hosted into a process.

Modules are "singleton" once a module is loaded in memory, it will bind it's scope to the process. Global variables are all merged in the context of driver or aspect. Eve is a multi-session system. In each session you can have run single driver.

Exclusive mode:

When a eve is executed, it can be started with parameter: -x or --exclusive. This is a signal that only one session can run at a time. In this mode "start" is not starting a new driver if any other driver is active. You can use this more especially for debugging or tunning purpose.


Read next: Concurency