Manisa Engereği Technical Documentation

1. Language Overview

Manisa Engereği is a general-purpose, high-level programming language designed with two goals in mind: simplicity and humor. It is a dynamically typed language, meaning that variable types are not explicitly declared by the programmer. Instead, all variables are defined using the keywords değişken (variable) or sabit (constant).

All types—even built-in functions—are derived from a unified polymorphic object model. Certain commonly used control structures such as for loops and switch statements have been deliberately omitted to reinforce a uniform style of decision-making, keeping the language surface exceptionally minimal.

2. Grammar and Syntax

2.1 Backus-Naur Form (BNF)

The parser utilizes explicit block declarations with braces {} and semicolons ; as statement terminators, akin to standard C or JavaScript constructs.

<program> ::= <stmt>*
<stmt> ::= <if_stmt>
| <while_stmt>
| <block>
| <method_decl>
| <return_stmt>
| <break_stmt>
| <continue_stmt>
| <expr_stmt>
<expr_stmt> ::= <expr> ";"
<if_stmt> ::= "şayet" "(" <expr> ")" <stmt> ["değilse" <stmt>]
<while_stmt> ::= "madem" "(" <expr> ")" <stmt>
<block> ::= "{" <stmt>* "}"
<method_decl> ::= "marifet" IDENTIFIER "(" [<parameters>] ")" <block>
<parameters> ::= IDENTIFIER ("," IDENTIFIER)*
<return_stmt> ::= "tebliğ" [<expr>] ";"
<break_stmt> ::= "yeter" ";"
<continue_stmt> ::= "devam" ";"

# Expressions
<expr> ::= <assignment>
<assignment> ::= <logical_or> ( ("=" | "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^=" | "~=") <assignment> )?
<logical_or> ::= <logical_and> (<logical_or_operator> <logical_and>)*
<logical_or_operator> ::= "||" | "yahut"
<logical_and> ::= <equality> (<logical_and_operator> <equality>)*
<logical_and_operator> ::= "&&" | "ve"
<equality> ::= <comparison> (("==" | "!=") <comparison>)*
<comparison> ::= <bitwise_or> (("<" | "<=" | ">" | ">=") <bitwise_or>)*
<bitwise_or> ::= <bitwise_xor> ("|" <bitwise_xor>)*
<bitwise_xor> ::= <bitwise_and> ("^" <bitwise_and>)*
<bitwise_and> ::= <shift> ("&" <shift>)*
<shift> ::= <term> (("<<" | ">>") <term>)*
<term> ::= <factor> (("+" | "-") <factor>)*
<factor> ::= <unary> (("*" | "/" | "%") <unary>)
<unary> ::= ("-" | "!" | "~" | "gayrı") <unary>
| <postfix>
<postfix> ::= <primary> ("++" | "--")?
<primary> ::= IDENTIFIER
| IDENTIFIER "(" [<arguments>] ")"
| INTEGER
| FLOAT
| STRING
| "(" <expr> ")"
<arguments> ::= <expr> ("," <expr>)*

# Terminals (Tokens)
IDENTIFIER ::= [a-zA-Z_][a-zA-Z0-9_]*
INTEGER ::= [0-9]+
FLOAT ::= [0-9]+\.[0-9]+
STRING ::= """ .* """
NEWLINE ::= ";"
COMMENT ::= # .* NEWLINE

2.2 Keywords Look-up Table

Manisa Engereği intrinsically supports Turkish characters in identifiers and keywords. Here is how standard programming terms map to Manisa constants:

Other Languages Manisa Engereği Description
const sabit Constant declaration
let / var değişken Variable declaration
and / && ve / && Logical AND
or / || yahut / || Logical OR
if şayet If condition
else değilse Else condition
while madem While loop
function marifet Function declaration
return tebliğ Return statement
break yeter Break out of loop
continue devam Continue loop
none yok Null/None value
not / ! gayrı / ! Logical NOT

3. Control Structures

Manisa Engereği supports only two control structures: the if statement and the while loop. These constructs are fundamental to nearly all programming languages, and they are sufficient for expressing most conditional logic and repetition patterns. In line with the language’s minimalist philosophy, we intentionally excluded other control structures such as for loops and switch cases, as discussed in the previous section.

The keywords used for control structures in Manisa Engereği reflect the language’s humorous and culturally specific character:

  • şayet — used to introduce an if condition
  • değilse — used for the else clause
    (Note: değilse and şayet can be used respectively to create an else if block.)
  • madem — used to begin a while loop

These keywords are both functional and playful, aiming to bring a smile to Turkish-speaking programmers while remaining clear in their intent.

Note: Manisa engereği can parse and interpret complex expressions like assignments / compound assignments in conditions.

4. Virtual Machine Architecture

The Manisa Engereği virtual machine (VM) is a stack-based interpreter that executes compiled bytecode.

4.1 Core Components

The VM consists of several key components:

  • Instruction Pointer (IP): Tracks the current bytecode instruction being executed
  • Stack Pointer (SP): Points to the top of the stack
  • Stack: Stores MEObject* pointers
  • Constant Pool: Contains all literal values used in the program
  • Global Variables: Stores all global variable references
  • Local Variables: Stores variables local to the current scope

4.2 Execution Model

The VM follows a simple execution cycle:

  1. Fetch the next bytecode operation
  2. Decode the operation
  3. Execute the operation
  4. Repeat until program completion or error

This cycle continues until either:

  • All bytecode instructions have been executed
  • A tebliğ (return) instruction is encountered
  • An error condition occurs

5. Bytecode Specification

Instruction formats consist of a strict 1-byte opcode mapped typically alongside static operand bytes. Current opcodes natively recognized include:

Opcode (Name) Description Operands
CO_OP_NOP No operation None
CO_OP_POP Pop top value None
CO_OP_LOAD_CONST Load constant 2-byte, constant index
CO_OP_LOAD_GLOBAL Load global variable 2-byte, global index
CO_OP_LOAD_VARIABLE Load local variable 2-byte, local index
CO_OP_STORE_GLOBAL Store global value 2-byte, global index
CO_OP_STORE_VARIABLE Store local value 2-byte, local index
CO_OP_BINARY_OP Binary arithmetic/logical operation 1-byte, operation type
CO_OP_UNARY_OP Unary operation 1-byte, operation type
CO_OP_CALL_FUNCTION Call a function 1-byte, argument count
CO_OP_RETURN Return from function None
CO_OP_JUMP_IF_FALSE Conditional jump if false 2-byte, jump offset
CO_OP_JUMP_REL Unconditional relative jump 2-byte, jump offset

5.2 Binary Operations

The VM supports the following binary operations, encoded as 1-byte operand values:

  • BIN_ASSIGN — Variable assignment
  • BIN_ADD — Addition
  • BIN_SUB — Subtraction
  • BIN_MUL — Multiplication
  • BIN_DIV — Division
  • BIN_MOD — Modulo
  • BIN_EQ — Equality
  • BIN_NEQ — Inequality
  • BIN_LT — Less than
  • BIN_LTE — Less or equal
  • BIN_GT — Greater than
  • BIN_GTE — Greater or equal
  • BIN_BIT_AND — Bitwise AND
  • BIN_BIT_OR — Bitwise OR
  • BIN_BIT_XOR — Bitwise XOR
  • BIN_BIT_LSHIFT — Left shift
  • BIN_BIT_RSHIFT — Right shift
  • BIN_AND — Logical AND
  • BIN_OR — Logical OR

5.3 Unary Operations

The VM supports these unary operations:

  • UNARY_NEGATIVE — Numeric negation (-)
  • UNARY_POSITIVE — Numeric positive (+)
  • UNARY_LOGICAL_NOT — Logical NOT (!, gayrı)
  • UNARY_PRE_INC — Pre-increment (++X)
  • UNARY_PRE_DEC — Pre-decrement (--X)
  • UNARY_POST_INC — Post-increment (X++)
  • UNARY_POST_DEC — Post-decrement (X--)

Note: Those unary operators get expanded to binary operations with one at bytecode generation so they do not directly live in bytecode.

6. Memory Management

Manisa Engereği uses reference counting for garbage collecting. Every Manisa Engereği Object (MEObject*) has its own ob_refcount which is initialized to 1 at start. The VM decrements and increments this reference count using macros (ME_DECREF, ME_INCREF) wherever those objects are interacted with.

While reference counting is sufficient for most scenarios, it is problematic when objects have references to each other (cyclic references). A potential future solution is implementing a mark-and-sweep garbage collector alongside reference counting.

6.1 MEObject

MEObject structures are generic and act as the backbone of the interpreter. They mimic polymorphism and inheritance in C, making internal functions very useful for potential future class implementations where operator overloading is handled by changing function pointers.

typedef struct {
    size_t ob_refcount;    // Reference count of object
    METypeObject* ob_type; // Pointer to the type object
} MEObject;

Every built-in object extends this definition and links to its own type object. Type objects are created statically at compile time if there is no inheritance (tp_base == NULL).

struct METypeObject {
    const char* tp_name;
    METypeObject* tp_base;
    size_t tp_sizeof;
    fn_destructor tp_dealloc;
    fn_str tp_str;
    fn_bool tp_bool;
    fn_call tp_call;
    // ... arithmetic and bitwise operation pointers (tp_nb_add, tp_nb_bit_and, etc.)
    // ... unary and comparison function pointers (tp_unary_negative, tp_cmp, etc.)
};

6.2 Stack Management

The stack-based architecture follows these principles:

  • Stack: Stack is a dynamic array.
  • Stack Pointer (SP): Points top of the stack.
  • Stack Operations:
    • PUSH: Increments SP and stores a value
    • POP: Retrieves a value and decrements SP
    • TOP: Accesses the top value without removing it

6.3 Object Representation

All values in Manisa Engereği are represented as MEObject structures.

7. Building & Running

Instructions for building the Manisa Engereği compiler and running a program written in Manisa Engereği:

For Linux and Mac Users

make && ./bin/me deneme.me

For Windows Users

mkdir -p build
cd build
cmake ..
cmake --build .
.\bin\me.exe deneme.me