SimplifyC++ Article
#6 Foundation and Architecture Why Design a New Programming Language - Milestone — Initial Language Specification and
#6 Foundation and Architecture: Why Design a New Programming Language? -> Milestone — Initial Language Specification and Code Examples
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.
1. Language Subset Goals for the First Milestone
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.
2. Core Language Grammar (Minimal Specification)
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.
3. Built-in Types and Rules
Primitive Types
int: 64-bit signed integerfloat: 64-bit floating-point numberbool: Boolean true/falsestring: UTF-8 encoded string
Composite Types
Option<T>: Represents a value that may or may not existResult<T, E>: Represents success or failure of operations
Rules
All variables are immutable unless marked with
mutNo implicit type conversions (e.g.,
inttofloatrequires explicit cast)Arithmetic follows type safety rules; overflow and underflow behavior are defined
All function parameters are passed by value unless specified otherwise
4. Semantic Rules and Behaviors
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;
OptionandResultused for recoverable errorsOwnership: 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.
5. Example: Program Using the Initial Specification
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
6. Interpreter Architecture Preview (C++20/23)
The interpreter implementing this specification will include:
Tokenizer (Lexer): Converts source code into tokens using
std::regexor custom matchersParser: Generates an AST using recursive descent, backed by
std::variantnodesAST Types:
Expression: base class with variants for literals, binary ops, function callsStatement: variants for declaration, assignment, control flow, return
Type System: Checked statically using template-like rules with
conceptsand type traitsRuntime:
Evaluation of expressions using
std::visitMemory 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.
7. Development Plan for Next Phase
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
OptionandResultvaluesIntroducing loop constructs and basic collection types (array, slice)
Establishing a standard library interface
Modularizing the interpreter using
C++20modules and build system integration
Conclusion
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.