Article by Ayman Alheraki on January 11 2026 10:37 AM
After identifying the motivations, evaluating similar languages, and articulating the design philosophy, we arrive at a critical turning point: the first formal milestone in building our new C-style language—a concrete, initial language specification accompanied by representative code examples. This section sets the groundwork for the parsing engine, interpreter, and further compiler stages, all to be implemented in modern C++20/23.
Rather than attempting to deliver a complete language upfront, this milestone focuses on a minimal but functional subset that reflects the design intent, demonstrates language behavior, and validates the foundational choices through real examples. It serves as a practical prototype to test the syntax, type system, memory model, and runtime behavior using C++ as the host language for implementation.
The initial specification is deliberately compact, focused on proving the most essential aspects of the language:
Syntax familiarity for C/C++ developers
Strong static typing and early error detection
Deterministic and explicit variable lifetime
Function calls and scope rules
Minimal standard library (print, input, math)
Compile-time constant evaluation
Safe handling of optional and result values
By delivering a working interpreter for this subset, we build a strong foundation for advanced features such as modules, traits, generics, and concurrency in later milestones.
Here is a simplified Backus-Naur Form (BNF)-like definition of the core syntax:
program ::= { function | struct }*
function ::= "fn" identifier "(" [ parameters ] ")" [ "->" type ] blockparameters ::= parameter { "," parameter }*parameter ::= identifier ":" typeblock ::= "{" statement* "}"
statement ::= variable_decl | assignment | if_stmt | while_stmt | return_stmt | expr_stmtvariable_decl ::= "let" ["mut"] identifier ":" type "=" expression ";"assignment ::= identifier "=" expression ";"return_stmt ::= "return" expression ";"if_stmt ::= "if" expression block [ "else" block ]while_stmt ::= "while" expression blockexpr_stmt ::= expression ";"
expression ::= literal | identifier | call_expr | binary_expr | groupingcall_expr ::= identifier "(" [ expression { "," expression }* ] ")"binary_expr ::= expression binary_op expressiongrouping ::= "(" expression ")"
type ::= "int" | "float" | "bool" | "string" | identifierliteral ::= integer | float | string | booleanThis grammar defines the basic structures required to build meaningful programs. The interpreter will tokenize, parse, and execute code written in this subset using C++20/23 features like std::variant, std::visit, and std::monostate to represent and handle expressions and types.
int: 64-bit signed integer
float: 64-bit floating-point number
bool: Boolean true/false
string: UTF-8 encoded string
Option<T>: Represents a value that may or may not exist
Result<T, E>: Represents success or failure of operations
All variables are immutable unless marked with mut
No implicit type conversions (e.g., int to float requires explicit cast)
Arithmetic follows type safety rules; overflow and underflow behavior are defined
All function parameters are passed by value unless specified otherwise
Scope: Variables and functions are scoped to their enclosing block
Typing: All expressions and function return types must be explicitly typed
Control Flow: Conditional and loop expressions work with boolean types only
Error Handling: No exceptions; Option and Result used for recoverable errors
Ownership: All values follow value semantics; reference types will be added in a later stage
These behaviors will be validated and enforced by the interpreter’s semantic analysis layer, powered by modern C++’s type traits, templates, and strong typing mechanisms.
fn factorial(n: int) -> int { if n <= 1 { return 1; } return n * factorial(n - 1);}
fn main() -> int { let x: int = 5; let y: int = factorial(x); print("Factorial: ", y); return 0;}This code demonstrates:
Function definition and recursion
Immutable variable binding
Typed function parameters and return type
Print output using minimal standard I/O
Basic integer arithmetic
The interpreter implementing this specification will include:
Tokenizer (Lexer): Converts source code into tokens using std::regex or custom matchers
Parser: Generates an AST using recursive descent, backed by std::variant nodes
AST Types:
Expression: base class with variants for literals, binary ops, function calls
Statement: variants for declaration, assignment, control flow, return
Type System: Checked statically using template-like rules with concepts and type traits
Runtime:
Evaluation of expressions using std::visit
Memory and variable tracking via scoped environments
Function call stack using managed frames
C++23 features like constexpr virtual dispatch, std::expected, and structured bindings will help us maintain readable, robust, and efficient interpreter code.
This milestone serves as both a deliverable and a foundation. With the initial grammar and runtime working, the following next steps will include:
Expanding the parser to support user-defined structs
Adding pattern matching to Option and Result values
Introducing loop constructs and basic collection types (array, slice)
Establishing a standard library interface
Modularizing the interpreter using C++20 modules and build system integration
The initial language specification outlined here is a compact yet expressive subset that embodies the language’s core goals: simplicity, safety, clarity, and deterministic behavior. It is designed for immediate implementation using modern C++ tools and constructs, offering a solid launchpad for rapid iteration and refinement.
This milestone reflects a balance between theoretical design and practical engineering. With carefully selected features and minimal syntax, we now have a functional language core that can evolve into a full-fledged system through a staged development process—driven by C++20/23’s expressive power, compile-time evaluation, and modular infrastructure.