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 conditiondeğilse— used for the else clause
(Note:değilseandşayetcan 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:
- Fetch the next bytecode operation
- Decode the operation
- Execute the operation
- 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 assignmentBIN_ADD— AdditionBIN_SUB— SubtractionBIN_MUL— MultiplicationBIN_DIV— DivisionBIN_MOD— ModuloBIN_EQ— EqualityBIN_NEQ— InequalityBIN_LT— Less thanBIN_LTE— Less or equalBIN_GT— Greater thanBIN_GTE— Greater or equalBIN_BIT_AND— Bitwise ANDBIN_BIT_OR— Bitwise ORBIN_BIT_XOR— Bitwise XORBIN_BIT_LSHIFT— Left shiftBIN_BIT_RSHIFT— Right shiftBIN_AND— Logical ANDBIN_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