Syntax Overview

EPL (Elastic Programming Language) is a C-like object-oriented scripting language with automatic memory management, designed for rapid application development.

Quick Reference

FeatureSyntax
String concatenation"Hello " . name (use . not +)
Global variables$MyGlobal = value;
Object creationTMyClass obj; obj = new TMyClass;
Pass by referencevoid Func(int ptr Value);
Foreach loopforeach(Arr; int i; variant item){ }
Print outputprint "Value: " . x . "\n";

Data Types

Primitive Types

int iValue = 10;              // 32-bit signed integer
int64 bigNum;                 // 64-bit signed integer
float fValue = 3.14;          // Single-precision float
double dValue = 3.14159;      // Double-precision float
string sText = "Hello";       // UTF-8 string
variant vData;                // Dynamic type (can hold anything)
object obj;                   // Object instance reference

Machine Types (Fixed-Size)

BYTE b = 255;                 // Unsigned 8-bit
WORD w;                       // Unsigned 16-bit
DWORD dw = 0xFFFFFFFF;        // Unsigned 32-bit
QWORD qw;                     // Unsigned 64-bit
char c;                       // Single byte/character

Pointer Types

// Single pointers
BYTE *buf = malloc(100);      // Byte pointer
DWORD *pixels;                // 32-bit pointer
char *str;                    // C-style string pointer
m_ptr ptr;                    // Generic memory pointer

// Double pointers (for output params and arrays)
BYTE **outBuf;                // Output buffer parameter
char **fields;                // Array of strings

Graphics Types

color col;                    // RGB color
vector vec;                   // 3D vector (x,y,z)
point pt;                     // 3D point
normal n;                     // Surface normal

Variables & Scope

public int PublicVar;         // Public class member
private int PrivateVar;       // Private class member
$GlobalVar = 0;               // Global variable ($ prefix)

String Interpolation

// Variables with $ are interpolated inside strings
string name = "John";
string domain = "example.com";
string msg = "Hello $name from $domain";  // "Hello John from example.com"

// Common in building dynamic strings
string query = "SELECT * FROM $tableName WHERE id=$id";

Operators

CategoryOperators
Arithmetic+, -, *, /, %
Comparison==, !=, <, >, <=, >=
Logical&&, ||, !
Bitwise|, &, ^, ~, <<, >>
String concat. (dot)
String append.=
// String concatenation uses . operator
string Result = "Hello" . " " . "World";
Result .= " More";  // Append

String Operations

int len = s_Len(str);                  // String length
string left = s_Left(str, n);          // Left n chars
string right = s_Right(str, n);        // Right n chars
string sub = s_Get(str, start, len);   // Substring
int pos = s_StrFind(str, search, 0);   // Find (0=case insensitive)
s_Replace(str, newStr, pos, len);      // Replace in place
s_Insert(str, insertStr, pos);         // Insert at position
s_Del(str, pos, len);                  // Delete substring
s_LCase(str);                          // To lowercase
s_UCase(str);                          // To uppercase
string trimmed = trim(str);            // Trim whitespace
variant parts = explode(",", str);     // Split string
string joined = implode(arr);          // Join array

Arrays

Arrays in EPL use the variant type for dynamic arrays.

// Create array
variant Arr = array("item1", "item2", "item3");

// Dynamic array
variant NewArray;
NewArray[0] = "first";
NewArray[1] = "second";

// Associative array (string keys)
array_set_index_str(Arr, "key", Value);
string Val = array_get_index_str(Arr, "key");

// Bracket access with quotes
Config["host"] = "localhost";
Headers['Content-Type'] = "text/html";

// Array operations
int cnt = count(Arr);                  // Get size
apush(Arr, Element);                   // Push element
array_delete(Arr, index);              // Delete at index
int isArr = is_array(Arr);             // Check if array

Control Flow

If/Else

if(condition){
    // code
}else if(condition2){
    // code
}else{
    // code
}

For Loop

for(int i=0; i<count(Array); i++){
    // code
}

Foreach Loop

// EPL-specific syntax with semicolons
foreach(Array; int Index; variant Item){
    print "Item " . Index . ": " . Item . "\n";
}

// Foreach with typed objects
foreach(ObjectArray; int i; TMyClass Obj){
    Obj->DoSomething();
}

While Loop

while(condition){
    // code
}

// Loop control
break;      // Exit loop
continue;   // Next iteration

Labels and Goto

label1:
// code
goto label1;  // Jump to label

Classes

Class Definition

class ClassName {
public:
    int PublicMember;
    string Name;
private:
    int PrivateData;
}

// Constructor (same name as class, defined outside)
ClassName::ClassName(){
    Name = "Default";
}

// Method definition (outside class body)
int ClassName::MethodName(){
    return 1;
}

Object Creation

// Correct pattern: declaration then initialization
TMyClass obj;
obj = new TMyClass;

// WRONG patterns - never use:
// TMyClass @obj;                 // @ auto-creates, causes issues
// TMyClass @obj = new TMyClass;  // Don't combine @ with = new

// Reference to current object
TMyClass self = this_obj;

// Dynamic method call using $ prefix
string methodName = "ProcessData";
obj->$methodName(args);  // Calls obj->ProcessData(args)

Forward Declaration

// Forward declare before definition
typedef class TClassB;

class TClassA {
    TClassB Ref;  // Can reference TClassB before it's defined
}

class TClassB {
    int Value;
}

Inheritance

class TChild : public TParent {
    // Child members
}

// Method override
virtual void TChild::OnEvent(){
    // Child implementation
}

Interfaces

// Define interface
class IMyInterface {
    virtual int Method1(int A);
    virtual int Method2(int B);
}

// Implement in class with nested class
class TMyClass {
    class EMyInterface : public IMyInterface {
        virtual int Method1(int A){ return A + 1; };
    }
    interface EMyInterface Interface1;  // Declare interface member
}

// Get interface from object
IMyInterface iface = GetInterface(obj, "IMyInterface");
iface->Method1(10);

Functions

Function Definition

// Return type, class, method name
int ClassName::Method(int param1, string ptr param2){
    return 1;
}

// Pointer parameters (pass by reference)
void Method(int ptr Value);           // Pass int by pointer
void Method(string ptr Str);          // Pass string by pointer
void Method(const int ptr Value);     // Const pointer
void Method(variant ptr Data);        // Pass variant by pointer

Virtual Methods

virtual void ClassName::OnEvent(){
    // Can be overridden in subclass
}

Thread Functions

// Marked with thread keyword
thread void WorkerFunc(variant ptr Param){
    // Runs in separate thread
}
CreateThread("WorkerFunc", args);

Common Built-in Functions

// Type conversion
float f = i2f(intVal);                 // Int to float
int i = f2i(floatVal);                 // Float to int
string s = i2s(intVal);                // Int to string

// Type checking
is_array(v)      // Check if array
is_object(v)     // Check if object
is_valid(obj)    // Check if valid object
is_null(v)       // Check if null
is_int(v)        // Check if integer
is_string(v)     // Check if string
isset(v)         // Check if set

// File I/O
int size = filesize(path);
int f = fopen(path, "r");              // "r", "w", "a", "rb", "wb"
string line = fgets(f);                // Read line
string data = fread(f, bytes);         // Read bytes
fwrite(f, data);                       // Write data
int eof = feof(f);                     // Check EOF
fclose(f);
int exists = DoesFileExist(path);
CreateDirectory(path);
CreateTextFile(path, content);

Memory Management

EPL has garbage collection with reference-counted smart pointers for objects.

Objects (Automatic)

TMyClass obj;            // Declare object
obj = new TMyClass;      // Create, refcount = 1

TMyClass obj2;
obj2 = obj;              // Reference same object, refcount = 2
obj2 = 0;                // Release reference, refcount = 1

// When last reference released -> GC frees object automatically
// NO manual delete needed for objects!

Raw Memory Buffers (Manual)

// Page-level allocation (4096 byte pages)
int buf = alloc_buf(size);             // Allocate in pages
free_buf(buf);                         // Free page buffer

// Heap allocation
m_ptr ptr = malloc(size);              // Allocate bytes
free(ptr);                             // Free heap memory

// Memory operations
memcpy(dest, src, size);               // Copy memory
ZeroMem(buf, size);                    // Zero memory

Threading

// Create thread
int tid = CreateThread("FunctionName");
int tid = CreateThread("FunctionName", args);
int tid = CreateObjThread(obj, "MethodName", args);

// Sleep
Sleep(milliseconds);
sleep(milliseconds);

// Spin lock (lightweight lock)
spin_lock(lockVar, timeoutMs);         // Acquire lock
lockVar = 0;                           // Release lock

Reflection

// Get class info
int hClass = GetClassHandle("ClassName");
string name;
GetClassName(obj, name);

// Iterate class functions
int hFunc = GetFirstClassFunc(hClass);
while(hFunc != 0){
    string funcName = GetClassFuncName(hClass, hFunc);
    int offset = GetObjFuncOff(obj, funcName);
    hFunc = GetNextClassFunc(hClass, hFunc);
}

// Check members/functions exist
is_such_member(obj, "memberName");
is_such_function(obj, "funcName");
is_such_class("ClassName");

Preprocessor

#ifndef IDENTIFIER
#define IDENTIFIER
// Code here
#endif

#define CONSTANT_NAME value

// Include files
include_file "$CUR_SCR_DIR/../path/file.epl";
include_file "$Studio/ElastLib/main_inc.epl";

Important Gotchas

  1. String concatenation uses . not +
    string s = "Hello" . " World";  // Correct
    // string s = "Hello" + " World";  // WRONG
  2. Pointer parameters use ptr keyword
    void Method(string ptr Str);    // Pass by reference
  3. Include guards are global - Use unique identifiers
  4. Global variables use $ prefix
    $MyGlobal = value;
  5. Constructor has same name as class, defined outside
  6. Arrays are variant type - Use variant for dynamic arrays
  7. Method definitions are outside class body
  8. foreach syntax uses semicolons
    foreach(Arr; int i; variant item){ }  // Correct
    // foreach(Arr, int i, variant item)  // WRONG
  9. Objects are garbage collected - No manual delete needed
  10. Only raw buffers need manual free