Eymenium Logo

Eymenium Language: Complete Architecture, Reference, and Engineering Guide

1. Executive Summary and Mental Model

Eymenium (.eym) is an independent, indentation-sensitive, dynamically-typed programming language executed via a C++ native runtime. Although its syntax shares visual tropes with Python, its underlying execution architecture, keyword mapping, scoping rules, and module semantics are entirely distinct.

1.1 Architectural Disambiguation

Interpreter Design: The native interpreter is a pure tree-walking interpreter written in C++. It consists of a custom lexer, a recursive-descent parser, an Abstract Syntax Tree (AST) constructed from tagged node variants (NodeKind), and an evaluator.

Public Documentation vs. Native Source: Public web documentation occasionally refers to a VM/bytecode pipeline or asynchronous primitives (keep, hold, using, outof). The native runtime source strictly evaluates an AST via tree-walking and does not execute bytecode or async event loops.

1.2 Pipeline Lifecycle

 Source Text (.eym)
        │
        ▼
 Lexer (Indentation Stack, INDENT/DEDENT Generation)
        │
        ▼
 Recursive-Descent Parser (Operator Precedence, AST Nodes)
        │
        ▼
 Abstract Syntax Tree (AST)
        │
        ▼
 Evaluator / Tree-Walking Interpreter (Shared Pointers, Dynamic Scoping Environments)
        │
        ▼
 Execution Side-Effects / Errors / Output

2. Command Line Interface and Execution Modes

The native executable is named eym.

2.1 File Execution

To execute an Eymenium script:

eym application.eym

CLI arguments can be passed after the file path:

eym application.eym --env=production --port=8080

Note: Flags passed on the CLI are arguments to the native executable wrapper and are not automatically exposed as an argv list variable within the core language environment.

2.2 Interactive REPL Mode

Executing eym without arguments starts the REPL. Multi-line blocks (e.g., function definitions, loops) are evaluated when a blank line is submitted:

eym> exp greet(name):
...>     out("Hello, " + name)
...> 
eym> greet("Developer")
Hello, Developer

3. Lexical Structure and Syntax Rules

3.1 Indentation Mechanics

Eymenium enforces strict indentation sensitivity using spaces only.

# Correct: Consistent 4-space indentation
chk total > 100:
    out("High total")
    chk status == yes:
        out("Active")

# Incorrect: Throws an Indentation Error
chk total > 100:
    out("High total")
  out("Active")

3.2 Line Continuation

The native lexer does not support implicit multi-line parsing inside brackets [] or braces {}. Multi-line statements must explicitly use a trailing backslash (\) immediately prior to the newline character:

# Valid explicit continuation
grand_total = base_price + \
              tax_rate + \
              shipping_cost

# INVALID - Will trigger a parse error
data = [
    10,
    20
]

3.3 Comments

Single-line comments begin with # and run to the end of the line. Block comments (/* ... */ or ''' ... ''') are not supported at the lexer level.


4. Formal Reserved Keyword Index

The table below maps Eymenium keywords to their conceptual equivalents in languages like Python or JavaScript:

Eymenium Keyword Semantic Equivalent Description
expdef / functionDefines a standard function.
fnlambdaDefines an inline, single-expression anonymous function.
chkifOpens a conditional branch.
orchkelif / else ifEvaluates an alternative condition.
nahelseDefault conditional fallback branch.
spinwhileLoops while a condition evaluates to truthy.
loopforIterates over an iterable object.
withininCollection iteration or membership check.
backreturnReturns a value from a function.
stopbreakExits the innermost loop immediately.
skipcontinueSkips to the next loop iteration.
noppassNull operation; explicit placeholder.
blueprintclassDefines an object class structure.
attempttryOpens an exception monitoring block.
catchexcept / catchTraps and handles specified exceptions.
atlastfinallyBlock that executes regardless of exception state.
throwraise / throwRaises an exception or instance.
calledasBinds an exception instance to a local variable.
addimport / includeEvaluates another file directly into current scope.
globglobalBinds identifier scope to top-level global environment.
nlocnonlocalBinds identifier scope to immediate outer closure environment.
removedelDeletes variables, list elements, dict keys, or fields.
ensureassertEvaluates condition; throws AssertionError if false.
yestrueBoolean True.
nofalseBoolean False.
nullNone / nullRepresents missing or uninitialized value.
alsoand / &&Logical AND operator.
eitheror / ||Logical OR operator.
denynot / !Logical NOT operator.
sameisChecks object identity (shared pointer reference).

5. Value System, Types, and Literals

5.1 Scalar Primitives

5.2 Strings

Strings are delimited by matching single (') or double (") quotes. Multi-line strings are not permitted without trailing line-continuation backslashes.

Supported Escape Sequences:

5.3 Compound Datatypes

Lists (Array Structures): Ordered, dynamic arrays.

items = [10, "Text", yes, null]
out(items[0])    # 10
out(items[-1])   # Accesses last element via negative indexing
items[1] = "Updated"

Dictionaries (Hash Maps): Key-value mappings. In native Eymenium, dictionary keys are internally cast to strings, and key order is non-deterministic (unordered native map implementation).

config = {
    "host": "127.0.0.1",
    "port": 8080
}
out(config["host"])

Ranges: Created using the built-in nums() generator function.

r1 = nums(5)        # 0, 1, 2, 3, 4
r2 = nums(1, 5)     # 1, 2, 3, 4
r3 = nums(0, 10, 2) # 0, 2, 4, 6, 8

6. Operators, Evaluation, and Precedence

6.1 Operator Precedence (Lowest to Highest)

  1. either (Logical OR)
  2. also (Logical AND)
  3. deny (Logical NOT)
  4. Comparison / Membership / Identity (==, !=, <, <=, >, >=, within, same)
  5. Additive (+, -)
  6. Multiplicative (*, /, //, %)
  7. Unary (-)
  8. Power (**) — Right-associative
  9. Postfix Operators (.attribute, [index], (arguments))
  10. Primary Values (Literals, Identifiers, Parenthesized Expressions)

6.2 Key Operational Behaviors

String Auto-Concatenation: When using +, if either operand is a string, Eymenium automatically stringifies the other operand without throwing a type error.

out("Error code: " + 500) # Output: "Error code: 500"

Division Semantics: / produces floating-point values (7 / 2 yields 3.5). Floor division // follows mathematical flooring (e.g., -7 // 2 yields -4).

Value vs. Identity: == tests structural content equality. same tests exact object memory reference/pointer equality.


7. Scope Resolution Mechanics (glob and nloc)

Eymenium uses local-by-default variable binding inside function blocks. Modifying non-local variables requires explicit scope declaration.

7.1 Global Scope Mutation (glob)

counter = 0

exp increment_global():
    glob counter
    counter += 1

increment_global()
out(counter) # 1

7.2 Nonlocal Scope Mutation (nloc)

Functions retain outer lexical frames, enabling stateful closures. Updating an outer function variable requires nloc.

exp make_accumulator(initial_value):
    total = initial_value
    
    exp add_val(amount):
        nloc total
        total += amount
        back total
        
    back add_val

acc = make_accumulator(100)
out(acc(20)) # 120
out(acc(30)) # 150

8. Control Flow Systems

8.1 Branching (chk, orchk, nah)

exp evaluate_score(score):
    chk score >= 90:
        back "A"
    orchk score >= 80:
        back "B"
    orchk score >= 70:
        back "C"
    nah:
        back "F"

8.2 Loops and Control (spin, loop, stop, skip, nop)

While-Style Loops (spin):

count = 3
spin count > 0:
    out("Countdown:", count)
    count -= 1

Iteration Loops (loop ... within):

# Iterating over lists
loop name within ["Alice", "Bob", "Charlie"]:
    out("Member:", name)

# Iterating over numeric ranges
loop i within nums(1, 10):
    chk i % 2 == 0:
        skip # Continue to next iteration
    chk i > 7:
        stop # Exit loop immediately
    out("Odd number:", i)

9. Functions and Anonymous Lambdas

9.1 Functions (exp)

Functions support fixed positional parameters and standard optional default parameters. Standard default parameters can follow positional arguments. Variable arguments (*args or **kwargs) are not supported by the native implementation.

exp build_server(host, port = 8080, verbose = no):
    chk verbose:
        out("Binding to " + host + ":" + strval(port))
    back {"host": host, "port": port}

srv = build_server("localhost", verbose = yes)

9.2 Lambdas (fn)

Anonymous functions are defined using fn. The body must consist of a single expression whose evaluation is implicitly returned.

double = fn(x): x * 2
multiply = fn(a, b): a * b

out(double(21))      # 42
out(multiply(3, 7))   # 21

10. Object-Oriented Programming (blueprint)

Object-oriented programming in Eymenium utilizes the blueprint keyword. Class instances store properties in dynamic internal dictionary maps.

10.1 Blueprint Structure and Methods

Constructors must be named init. Methods require an explicit self reference as their first parameter.

blueprint Vehicle:
    exp init(self, make, model):
        self.make = make
        self.model = model
        self.speed = 0

    exp accelerate(self, increment):
        self.speed += increment
        back self.speed

    exp get_info(self):
        back self.make + " " + self.model + " running at " + strval(self.speed) + " km/h"

car = Vehicle("Toyota", "Corolla")
car.accelerate(50)
out(car.get_info())

10.2 Single Inheritance Mechanics

Eymenium supports single inheritance only. Multiple inheritance and a super() builtin are not supported. Parent initialization requires calling the base blueprint constructor explicitly by passing self.

blueprint ElectricVehicle(Vehicle):
    exp init(self, make, model, battery_capacity):
        Vehicle.init(self, make, model)
        self.battery_capacity = battery_capacity

    exp charge(self):
        back "Charging battery (" + strval(self.battery_capacity) + " kWh)..."

ev = ElectricVehicle("Tesla", "Model 3", 75)
ev.accelerate(80)
out(ev.get_info())
out(ev.charge())

11. Built-in Function Reference

The following native primitives are available globally in all Eymenium runtime environments without importing:

Function Signature Description
outout(...args)Prints arguments space-separated to stdout, followed by a newline.
getusergetuser(prompt="")Prompts standard input and returns line as a string.
cmdcmd(command_str)Executes OS subshell command; returns integer return code.
sizeofsizeof(collection)Returns element count of String, List, or Dict. Throws TypeMismatchError otherwise.
kindkind(value)Returns string type descriptor ("int", "float", "string", "bool", "null", "list", "dict", "function", "class", "instance", "range").
classnameclassname(instance)Returns string name of blueprint from which instance was created.
grabgrab(obj, key, default=null)Dynamically gets object attribute or dictionary value.
putput(obj, key, value)Dynamically assigns field/attribute on object or dictionary key.
hashas(obj, key)Returns yes/no based on property presence.
numsnums(stop) / nums(start, stop, step)Returns a iterable range object.
appendappend(list, item)Appends element to end of target list in-place.
poppop(list)Removes and returns last element of list. Throws IndexError on empty list.
keyskeys(dict)Returns list of string keys contained within target dictionary.
valuesvalues(dict)Returns list of values contained within target dictionary.
joinstrjoinstr(delimiter, list)Joins list of strings using delimiter.
splitstrsplitstr(string, delimiter)Splits string by delimiter into list of strings.
sqrtsqrt(val)Returns square root as float.
floorfloor(val)Returns largest integer <= val.
ceilceil(val)Returns smallest integer >= val.
absvalabsval(val)Returns absolute numeric value.
roundvalroundval(val)Rounds float to nearest integer.
intvalintval(val)Casts value or numeric string to integer.
floatvalfloatval(val)Casts value or numeric string to float.
strvalstrval(val)Casts value to string representation.

12. Collections In Depth and List Comprehensions

12.1 Dynamic List Operations & Comprehensions

List comprehensions take the functional syntax form:
[ RESULT loop VARIABLE within ITERABLE ] or [ RESULT loop VARIABLE within ITERABLE chk CONDITION ]

# Transformation
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
doubled = [n * 2 loop n within numbers]

# Filtering with conditions
evens = [n loop n within numbers chk n % 2 == 0]

# Mathematical transformation with filtering
squared_evens = [n ** 2 loop n within numbers chk n % 2 == 0]

Note on Slicing: Array slicing like list[1:4] is unsupported natively. Slicing logic must be performed using explicit loop and index bounds.

12.2 Dictionary Manipulation

user_data = {"username": "admin", "role": "superuser"}

# Mutate/Add
user_data["status"] = "active"

# Safely verify presence
chk "role" within user_data:
    out("User Role:", user_data["role"])

# Key removal
remove user_data["status"]

13. Module Architecture (add)

Eymenium manages code modularity through the add statement.

13.1 Inclusion Semantics

Unlike Python modules, add does not create a separate namespace object. It directly evaluates the target module in the calling script's global scope (similar to a C #include or a global symbol import).

Given math_utils.eym:

exp double_value(val):
    back val * 2

In main.eym:

add math_utils

# Correct invocation (Symbol directly added into top-level scope)
out(double_value(10)) # Output: 20

# INCORRECT (Namespaces are NOT supported)
# out(math_utils.double_value(10)) -> Causes AttributeError/NameError

13.2 File Path Resolution

When executing add helper, the runtime seeks helper.eym inside the same directory as the file being executed. Modules are executed once; subsequent add calls to the same module in the same runtime session are ignored.


14. Error Handling (attempt, catch, atlast, throw)

14.1 Custom Exceptions and Typed Handlers

Exceptions can be typed by specifying error class names. The optional called clause binds the caught error instance.

blueprint ValidationFailure:
    exp init(self, message):
        self.message = message

exp register_age(age_str):
    attempt:
        age = intval(age_str)
        chk age < 0:
            throw ValidationFailure("Age cannot be negative.")
        chk age < 18:
            throw ValidationFailure("User must be an adult.")
        back yes
    catch ValueError called err:
        out("Type Error: Could not convert input to integer.", err)
        back no
    catch ValidationFailure called err:
        out("Validation Error:", err.message)
        back no
    atlast:
        out("Registration execution frame finished.")

register_age("-5")

14.2 Native Error Types


15. Defensive Programming (ensure) and Unsetting (remove)

15.1 Assertions (ensure)

ensure evaluates a boolean statement. If the expression evaluates to no, the execution halts and throws an AssertionError. An optional error string can be appended.

exp process_transaction(amount, balance):
    ensure amount > 0, "Transaction amount must be positive"
    ensure balance >= amount, "Insufficient funds"
    back balance - amount

15.2 Resource Removal (remove)

remove unbinds variables, dictionary keys, list indices, or dynamic attributes.

# Variable deletion
temp_var = "data"
remove temp_var

# Dict key deletion
data_map = {"a": 1, "b": 2}
remove data_map["a"]

# List item deletion by index
arr = [100, 200, 300]
remove arr[0] # arr is now [200, 300]

# Dynamic instance field deletion
remove car.speed

16. Comprehensive End-to-End Application Example

The production-style Eymenium program below models an Inventory Management Engine. It integrates Object-Oriented Principles, Error Trapping, Assertions, Functional Comprehensions, Custom Exceptions, and System Utilities.

# =====================================================================
# INVENTORY MANAGEMENT ENGINE (.eym)
# Demonstrating Eymenium Core Language Features
# =====================================================================

blueprint InventoryError:
    exp init(self, msg):
        self.msg = msg

blueprint Product:
    exp init(self, id, name, price, stock):
        self.id = id
        self.name = name
        self.price = price
        self.stock = stock

    exp update_stock(self, quantity_change):
        nloc_stock = self.stock + quantity_change
        ensure nloc_stock >= 0, "Stock balance cannot fall below zero"
        self.stock = nloc_stock

    exp get_value(self):
        back self.price * self.stock

blueprint InventorySystem:
    exp init(self, store_name):
        self.store_name = store_name
        self.products = {}

    exp add_product(self, product):
        ensure kind(product) == "instance", "Must pass a valid product instance"
        chk has(self.products, product.id):
            throw InventoryError("Product ID " + product.id + " already exists.")
        put(self.products, product.id, product)

    exp restock(self, product_id, amount):
        attempt:
            chk deny (product_id within self.products):
                throw InventoryError("Product ID " + product_id + " not found.")
            
            item = self.products[product_id]
            item.update_stock(amount)
            out("Successfully restocked " + item.name + ". New level: " + strval(item.stock))
        catch InventoryError called err:
            out("Inventory Warning:", err.msg)
        catch AssertionError called err:
            out("Stock Level Assertion Failed:", err)

    exp calculate_total_valuation(self):
        total = 0.0
        all_keys = keys(self.products)
        
        loop k within all_keys:
            p = self.products[k]
            total += p.get_value()
            
        back total

    exp get_out_of_stock_items(self):
        all_prods = values(self.products)
        # Using list comprehension with conditional filter
        back [p.name loop p within all_prods chk p.stock == 0]

# =====================================================================
# SYSTEM TEST SUITE RUNNER
# =====================================================================

exp run_system():
    out("Initializing Inventory System...")
    sys = InventorySystem("Central Hub")

    # Instantiate Products
    p1 = Product("P100", "Enterprise Server", 2500.00, 5)
    p2 = Product("P200", "Gigabit Switch", 300.00, 0)
    p3 = Product("P300", "Fiber Cable", 25.50, 100)

    # Register Products
    sys.add_product(p1)
    sys.add_product(p2)
    sys.add_product(p3)

    out("Store Location:", sys.store_name)
    out("Total Initial Valuation: $" + strval(sys.calculate_total_valuation()))

    # Check Out of Stock Items
    empty_items = sys.get_out_of_stock_items()
    out("Out-of-stock items count:", sizeof(empty_items))
    loop item_name within empty_items:
        out(" - Item requires restock:", item_name)

    # Trigger stock updates & boundary exceptions
    out("\n--- Executing Stock Transactions ---")
    sys.restock("P200", 15)  # Restock out of stock item
    sys.restock("P999", 5)   # Non-existent item (Triggers InventoryError)
    sys.restock("P100", -10) # Over-drain item (Triggers AssertionError)

    out("\nFinal Valuation: $" + strval(sys.calculate_total_valuation()))

# Program Entry Point
run_system()

17. Practical Debugging and Troubleshooting Guide

When debugging Eymenium programs, use the following systematic checklist to resolve common runtime errors:

               [Error Detected]
                      │
        Is it a Syntax/Indentation Error?
        ├── YES ──► Check spaces (NO tabs allowed). Verify colons (:) 
        │           at block starts. Ensure multi-line statements 
        │           use explicit trailing backslashes (\).
        │
        └── NO
             │
      Is it a NameError or Scope Defect?
      ├── YES ──► Verify variable assignment ordering. Ensure global 
      │           mutations use `glob` and lexical closure mutations 
      │           use `nloc`.
      │
      └── NO
           │
    Is it an Unexpected Operator Behavior?
    ├── YES ──► Inspect types with `kind(val)`. Remember that `+` 
    │           auto-stringifies when paired with strings. Convert 
    │           string inputs via `intval()` or `floatval()`.
    │
    └── NO ──► Validate module imports (`add` puts variables into global scope).
               Check array boundaries with `sizeof()`. Use `ensure` to 
               verify assertions, or wrap target code in `attempt/catch`.

17.1 Quick-Check Verification Matrix