Version: 1.0.0-alpha
Status: Draft
Date: January 2026
Author: ProXPL Design Team
This document defines the formal specification of the ProX Programming Language (ProXPL). It serves as the authoritative reference for the language's syntax, semantics, type system, and execution model. This specification is intended for compiler implementers, tool developers, and advanced users requiring precise knowledge of the language behavior.
This specification describes the core language features, including lexical structure, grammar, type system, memory model, and standard library interfaces. It distinguishes between mandatory language features and implementation-specific behaviors.
ProXPL is designed with the following key objectives:
- Performance: Predictable performance suitable for systems programming and backend development.
- Clarity: A clean, readable syntax inspired by Python and JavaScript to reduce cognitive load.
- Scalability: Support for large codebases through a robust module system and static typing.
- Safety: Compile-time type safety to eliminate common classes of runtime errors.
- Undefined Behavior: The language aims to minimize undefined behavior; however, unsafe interfaces (FFI) are provided for system-level access.
- Dynamic Typing: While type inference is supported, ProXPL is fundamentally statically typed.
ProXPL is a statically-typed, general-purpose programming language. It combines the expressive high-level syntax of scripting languages with the performance characteristics of compiled languages.
- Explicit is better than implicit, except where type inference improves readability without sacrificing safety.
- Composition over inheritance, favoring interfaces and traits (planned) over deep class hierarchies.
- Batteries included, providing a comprehensive standard library for common tasks.
- specific Systems tooling and CLI applications.
- High-performance web servers and network services.
- Embedded logic and game scripting.
- Cross-platform application development.
ProXPL source code is encoded in UTF-8.
The language is free-form. Whitespace (spaces, tabs, newlines) acts as a token separator but is otherwise ignored, except in string literals. Semicolons (;) are recommended to terminate statements but arguments may vary on strict enforcement in future versions (current grammar requires valid statement termination).
Identifiers name variables, types, functions, and other entities.
- Pattern:
[a-zA-Z_][a-zA-Z0-9_]* - Case Sensitivity: Identifiers are case-sensitive.
myVarandmyvarare distinct.
The following tokens are reserved and cannot be used as identifiers:
| Declaration | Control Flow | Types/Values | OOP/Async | Modules |
|---|---|---|---|---|
let |
if |
true |
class |
use |
const |
else |
false |
new |
import |
func |
while |
null |
this |
from |
native |
for |
void |
super |
as |
extern |
return |
int |
extends |
|
break |
float |
interface |
||
continue |
bool |
static |
||
switch |
string |
async |
||
case |
await |
|||
default |
||||
try |
context |
|||
catch |
layer |
|||
throw |
activate |
- Integer Literals: Decimal (
123), Hexadecimal (0x7B), Binary (0b1111011). - Floating-Point Literals: Decimal with fractional part or exponent (
3.14,1.0e-5). - Boolean Literals:
true,false. - String Literals: Enclosed in double quotes (
"hello"). access escape sequences:\n,\t,\r,\",\\. - Null Literal:
null.
- Line Comments: Begin with
//and continue to end of line. - Block Comments: Begin with
/*and end with*/. Nesting is not supported.
The grammar is defined using Extended Backus-Naur Form (EBNF) notation.
A program consists of a sequence of declarations.
program ::= declaration* EOF
declaration ::= funcDecl | varDecl | classDecl | contextDecl | statementContexts group behavioral layers.
contextDecl ::= "context" IDENTIFIER "{" layerDecl* "}"
layerDecl ::= "layer" IDENTIFIER "{" funcDecl* "}"Variables are declared using let (mutable) or const (immutable).
varDecl ::= "let" IDENTIFIER ( ":" type )? ( "=" expression )? ";"
| "const" IDENTIFIER ( ":" type )? "=" expression ";"Functions are declared with the func keyword. Parameters may optionally define types.
funcDecl ::= "func" IDENTIFIER "(" parameters? ")" ( ":" type )? block
parameters ::= IDENTIFIER ( ":" type )? ( "," IDENTIFIER ( ":" type )? )*Statements execute actions or control flow.
statement ::= exprStmt
| ifStmt
| whileStmt
| forStmt
| returnStmt
| block
| tryStmt
| activateStmt-
Activate:
activate "(" IDENTIFIER ")" blockEnables a context for the duration of the block. -
Block:
{ statement* }introduces a new scope. -
If:
if (expr) stmt (else stmt)? -
While:
while (expr) stmt -
For:
for (init?; cond?; incr?) stmt -
Return:
return expr? ";"
Expressions evaluate to a value. Precedence follows standard C/Java rules.
expression ::= assignment
assignment ::= IDENTIFIER "=" assignment
| logicOr
logicOr ::= logicAnd ( "||" logicAnd )*
logicAnd ::= equality ( "&&" equality )*
equality ::= comparison ( ( "!=" | "==" ) comparison )*
comparison ::= term ( ( ">" | ">=" | "<" | "<=" ) term )*
term ::= factor ( ( "-" | "+" ) factor )*
factor ::= unary ( ( "/" | "*" | "%" ) unary )*
unary ::= ( "!" | "-" ) unary | call
call ::= primary ( "(" arguments? ")" | "." IDENTIFIER )*
primary ::= NUMBER | STRING | "true" | "false" | "null"
| "(" expression ")" | IDENTIFIER
| "[" elements? "]" | "{" members? "}"ProXPL employs a static type system with extensive type inference. Types are checked at compile-time to ensure safety.
The type system distinguishes logical types, though implementation representations may vary (e.g., boxing).
| Type | Description |
|---|---|
int |
Signed 64-bit integer (compile-time constraint). |
float |
64-bit IEEE 754 floating point number. |
bool |
Boolean value (true or false). |
string |
Immutable sequence of UTF-8 characters. |
void |
Absence of value (return type only). |
any |
Dynamic type (escape hatch from static checking). |
Note: In the current version 1.0 Runtime,
intandfloatmay both be represented as double-precision floats (NaN tagging), limiting accurate integer precision to 53 bits.
- List: Mutable, ordered collection of values (
[1, 2, 3]). Heterogeneous if typed asList<any>. - Dictionary: Key-value map (
{"key": "value"}). - Function: First-class function type.
- Class: User-defined type containing fields and methods.
- Interface: Abstract definition of behavior (method signatures).
- Instance: Concrete instance of a Class.
The compiler infers types for variables initialized at declaration.
let x = 10; // Inferred as int
let y = x; // Inferred as intFunction parameters defaulting to any if not annotated in the current grammar, though strict mode requires explicit types.
- Values: Primitive types (booleans, numbers, null) are typically passed by value.
- Objects: Complex types (strings, lists, instances) are allocated on the heap and accessed via references.
ProXPL manages memory automatically using a Mark-and-Sweep Garbage Collector.
- Reachability: Objects are retained as long as they are reachable from the root set (global variables, stack, upvalues).
- Cycles: The GC can handle reference cycles.
- Trigger: GC is triggered based on allocation pressure or explicit request (
std.gc.collect()).
Variables declared in a block ({}) exist until the end of that block. Objects created within the block persist as long as references exist.
ProXPL defines a dual-mode execution environment.
The source code is compiled to platform-independent bytecode.
- VM: A stack-based Virtual Machine executes the bytecode.
- Chunk: Bytecode is organized into chunks containing instructions and constants.
- Performance: Optimization passes (constant folding, dead code elimination) occur during bytecode generation.
ProXPL supports Ahead-of-Time (AOT) compilation via an LLVM Backend.
- Transforms ProXPL intermediate representation (IR) into LLVM IR.
- Compiles to native machine code for maximum performance.
- Eliminates interpretation overhead.
ProXPL integrates asynchronous execution directly into the runtime.
- Async/Await: Syntax for non-blocking operations.
- Coroutines: Built on top of LLVM Coroutines (or fibers in VM), allowing functions to suspend and resume state.
- Event Loop: Scheduler manages execution of Tasks.
The compiler detects:
- Syntax errors.
- Type mismatches (e.g., adding
booltofloat). - Undefined variables or symbols.
- Argument count mismatches.
Runtime conditions that cannot be checked statically raise specific errors:
- Exceptions: Structured mechanism using
try,catch,throw. (Roadmap v1.1) - Panic: Unrecoverable system errors (e.g., Stack Overflow, Out of Memory) terminate the process.
The rigid, versioned Standard Library provides essential capabilities protected by stability guarantees.
std.core: Fundamental types and assertions.std.io: File and console I/O.std.math: Mathematical functions and constants.std.sys: System interaction (env vars, processes).std.net: Networking capabilities (planned).
APIs within the std namespace follow semantic versioning. Breaking changes occur only in major version increments.
ProXPL allows binding to native system libraries.
externkeyword: Defines signatures for external C functions.- Dynamic Loading: Libraries (
.dll,.so) are loaded at runtime. - Type Mapping: ProXPL types are marshaled to C-compatible types (Number → double/int, String → char*).
extern "kernel32.dll" "Sleep" func sleep(ms);- Integer Size: Currently mapped to double-precision float (53-bit SAFE_INT). Future versions may implement strict 64-bit integers.
- Hash Order: Iteration order of Dictionaries is implementation-dependent (not guaranteed).
- Modifying a collection while iterating over it.
- Accessing FFI pointers incorrectly.
- Relying on specific GC timing.
ProXPL evolves through a Request for Comments (RFC) process. Breaking changes are reserved for major integer releases. The roadmap includes Generic Programming and Pattern Matching for v2.0.
End of Specification