Language Specification

Prime Language
Technical Specification

Prime is a general-purpose, statically typed programming language designed to compete with Go and Rust as the language of choice for the AI era. It combines a familiar object-oriented structure with probabilistic types, first-class tensor operations, and quantum-ready linear types — all built into the core language, not bolted on as libraries. Prime compiles to efficient bytecode executed by PrimeVM, making it well-suited for systems programming, cloud-native services, AI inference pipelines, and future quantum-hybrid workloads.

0.1 DRAFT
OO · Probabilistic · Linear Types
PrimeVM (.primevm bytecode)
Static · Strong · Inferred
0.3B local (AI-assisted authoring)

Try Prime in the browser — § 09 Playground →

§ 01

Language Architecture Overview

1.1 Design Philosophy

Prime is built on the conviction that the next generation of general-purpose languages must treat AI inference and quantum computation as first-class language concerns — not as external library calls made over opaque APIs. In the same way that Go made concurrency a core language primitive (goroutines, channels) and Rust made memory safety a compile-time guarantee (ownership, lifetimes), Prime makes probabilistic reasoning and linear resource management structural properties of the type system itself.

Three structural pillars define Prime:

  • Object-Oriented Familiarity. Prime adopts a Java-inspired class and module system. Classes, interfaces, modules, and a strict access-modifier hierarchy (pub, priv, prot) provide scaffolding that engineers from Java, C#, or TypeScript backgrounds can adopt immediately.
  • Probabilistic Type Integration. The prob<T> wrapper elevates uncertainty into the type system. The compiler tracks confidence at every inference boundary and enforces explicit handling of low-confidence branches — making probabilistic programs as rigorous as deterministic ones.
  • Quantum Readiness via Linear Types. The qstate modifier subjects a variable to the compiler's linear-type borrow checker, enforcing the No-Cloning Theorem at compile time. When Prime targets quantum hardware or a simulator, these invariants are already guaranteed — no runtime assertion required.

Prime is general-purpose: it is equally suited to writing a web server, a CLI tool, a machine-learning pipeline, or a quantum optimisation routine. The AI and quantum features impose zero overhead on programs that do not use them.

1.2 Compilation Pipeline

Stage 1.prime source
→
Stage 2Prime Compiler (primec)
→
Stage 3.primevm bytecode
→
Stage 4PrimeVM Runtime
StageArtifactResponsibility
primec — Lexer / Parser AST Tokenises source; validates against CFG; emits parse errors in machine-readable JSON.
primec — Type Checker Typed AST Resolves prob<T> propagation; enforces linear-type move semantics for qstate variables; validates tensor shape at compile time.
primec — Bytecode Emitter .primevm file Emits stack-based bytecode with opcode extensions for INFER, QGATE, and TMUL.
PrimeVM Runtime Execution result Interprets .primevm; routes INFER opcodes to the local 0.3B model; routes QGATE opcodes to the quantum simulation layer or hardware adapter.

1.3 Module System

Each .prime file declares exactly one module at its head. Modules are the unit of compilation, linking, and access control. Module paths are hierarchical and reverse-DNS scoped, following Go and Java conventions.

module com.example.risk.scoring;

import com.example.quantum.Gates;
import com.example.ai.ClassificationModel;
import std.io;
import std.time;

1.4 Comparison with Go and Rust

FeatureGoRustPrime
Memory safetyGCOwnership / borrow checkerGC + linear types for qstate
Concurrency modelGoroutines + channelsasync/await + Send/SyncCoroutines + channels (planned)
Probabilistic typesNone (library only)None (library only)Native prob<T>
Tensor mathNone (library only)None (library only)Native tensor<T, Dims> with shape checking
AI inferenceExternal callExternal callNative infer() keyword
Quantum safetyNoneNoneCompile-time No-Cloning enforcement
Compilation targetNative binaryNative binary / WASMPrimeVM bytecode (.primevm)
§ 02

Type System & Primitives

2.1 Classical Primitives

TypeWidthDefaultNotes
int64-bit signed0Two's complement; detectable overflow is a compile-time error.
float64-bit IEEE 7540.0NaN propagation follows IEEE 754; comparing with NaN emits a compiler warning.
stringImmutable UTF-8 heap""Interned by the VM; == performs value equality, not reference equality.
boolean1-bit logicalfalseOnly the literals true and false are legal values.
byte8-bit unsigned0Used for binary I/O and buffer operations.
void——Method return type only; not a first-class value.
int     customerId  = 481923;
float   riskScore   = 0.74;
string  policyRef   = "POL-2024-EU-00391";
boolean isEligible  = true;

2.2 Probabilistic Types — prob<T>

prob<T> wraps any type T together with a compiler-managed confidence scalar in the range [0.0, 1.0]. Confidence is a type-level annotation — not a runtime field — that primec propagates through the dataflow graph and exposes as a read-only property.

Declaration Syntax

prob<T> identifier = value confidence float_literal ;

Compiler Rules

  • The confidence clause is mandatory on any direct literal assignment to a prob<T> variable.
  • When a prob<T> is produced by an infer() expression, confidence is populated from the model's softmax output — no explicit clause is written.
  • Confidence propagates through arithmetic: for binary operations a op b, the result confidence is min(a.confidence, b.confidence) (conservative model).
  • Assigning a prob<T> to a bare T variable is a compile-time error unless guarded by a confidence >= threshold gate.

Example

// Direct construction
prob<string> tradingIntent = "BUY" confidence 0.94;

// Accessing properties
float  c = tradingIntent.confidence;  // 0.94
string v = tradingIntent.value;       // "BUY"

// Confidence-gated unwrap — required before assigning to classical type
if (tradingIntent.confidence >= 0.90) {
    string confirmed = tradingIntent.value;
    executeOrder(confirmed);
} else {
    flagForReview(tradingIntent);
}

2.3 Tensor Types — tensor<T, Dims...>

Tensor types are native to Prime's type system. Shape is encoded in the type signature and checked at compile time — mismatched shapes cause a type error, not a runtime panic. No external library is required.

Syntax

tensor<float, 2, 3>     // 2×3 matrix of float64
tensor<int,   4>        // 1-D vector of 4 int64
tensor<float, 3, 3, 3>  // 3-D tensor

Native Operators

OperatorOperationShape Constraint
+Element-wise additionIdentical shape required.
-Element-wise subtractionIdentical shape required.
*Matrix multiplicationtensor<T,M,N> * tensor<T,N,P> → tensor<T,M,P>
@Hadamard (element-wise) productIdentical shape required.
.TTransposetensor<T,M,N>.T → tensor<T,N,M>
tensor<float, 2, 3> featureMatrix = [
    [1.0, 2.0, 3.0],
    [4.0, 5.0, 6.0]
];

tensor<float, 3, 2> projection = [
    [1.0, 0.0],
    [0.0, 1.0],
    [0.5, 0.5]
];

// (2×3) * (3×2) → (2×2) — shape verified at compile time
tensor<float, 2, 2> reduced    = featureMatrix * projection;
tensor<float, 3, 2> transposed = featureMatrix.T;
Compile-Time Shape Error
Writing featureMatrix * featureMatrix (both 2×3) emits: "E0051: matrix multiplication requires inner dimensions to match: got 3 ≠ 2." No shape mismatch can reach runtime.
§ 03

Native AI Keywords & Dispatch

3.1 The infer() Operator

infer() is a first-class language keyword — not a library call — that suspends the executing coroutine, serialises input into PrimeVM's inference protocol, dispatches to the local 0.3B model, and deserialises the result into a prob<T> value. The confidence scalar comes from the model's post-softmax probability for the top-1 token class.

Syntax Forms

// Form 1 — open-ended generation
prob<string> result = infer(inputExpr);

// Form 2 — constrained classification
prob<string> label  = infer(inputExpr) classifying ["LabelA", "LabelB", "LabelC"];

// Form 3 — typed generation with schema hint
prob<float>  score  = infer(inputExpr) as float;

VM Bytecode Lowering

PUSH_STR    <serialised input>
PUSH_LABELS <label array>       ; Form 2 only
INFER_CLS                       ; blocks until model responds
STORE_PROB  <target register>   ; writes (value, confidence) pair

3.2 Enterprise Classification Example

Document triage pipeline for a regulatory compliance platform. Incoming case narratives are classified into three disposition categories; low-confidence results are routed to human review.

module com.example.compliance.triage;

pub class CaseTriage {

    pub static string triageCase(string narrative, int caseId) {

        prob<string> classification = infer(narrative)
            classifying ["APPROVE", "ESCALATE", "REJECT"];

        if (classification.confidence >= 0.92) {
            auditLog(caseId, classification.value, classification.confidence);
            return classification.value;
        }

        if (classification.confidence >= 0.70) {
            string enriched = "[REVIEW CONTEXT] " + narrative;
            prob<string> refined = infer(enriched)
                classifying ["APPROVE", "ESCALATE", "REJECT"];
            if (refined.confidence >= 0.85) {
                auditLog(caseId, refined.value, refined.confidence);
                return refined.value;
            }
        }

        ReviewQueue.enqueue(caseId, classification.confidence);
        return "PENDING_REVIEW";
    }

    priv static void auditLog(int id, string disposition, float conf) {
        AuditStore.write(id, disposition, conf, Timestamp.now());
    }
}
Grammar-Constrained Decoding
The classifying clause enables logit masking (see §5.1). PrimeVM passes the label set to the inference subsystem, so the model can only emit tokens that prefix one of the declared labels. Hallucinated output categories are impossible at the VM level.
§ 04

Quantum-Ready System — Linear Types

4.1 The qstate Modifier

A variable declared with qstate enters the compiler's linear-type borrow checker. Linear types guarantee a value is consumed exactly once — it cannot be copied, aliased, or read after being passed to a gate function. This directly encodes the No-Cloning Theorem: an arbitrary unknown quantum state cannot be duplicated.

Compiler Rules

  • A qstate variable may appear as an argument to a gate function at most once after its declaration.
  • Any gate function accepting a qstate parameter consumes it. Subsequent references are compile-time errors.
  • qstate variables may not be captured by closures or assigned to non-qstate bindings.
  • Quantum.measure() collapses a qstate register into a classical boolean. This is a consuming operation.

4.2 Quantum Gate API

MethodInputOutputDescription
Quantum.register(n)intqstateAllocates an n-qubit register in |0⟩.
Quantum.applyHadamard(q)qstate (consumed)qstateHadamard gate; puts qubit into superposition.
Quantum.applyCNOT(ctrl, tgt)two qstates (consumed)qstateControlled-NOT; entangles two qubits.
Quantum.applyPhase(q, theta)qstate (consumed), floatqstatePhase rotation by θ radians.
Quantum.measure(q)qstate (consumed)booleanCollapses state; returns classical measurement.

4.3 Hybrid Quantum–Classical Example

module com.example.quantum.demo;

pub class QuantumDecisionGate {

    pub static string evaluatePath(string workflowId) {

        // Allocate a 2-qubit register — both qubits in |0⟩
        qstate reg       = Quantum.register(2);

        // Hadamard — reg is consumed, q1 produced
        qstate q1        = Quantum.applyHadamard(reg);

        // Split into single-qubit handles — q1 consumed on first .qubit() call
        qstate ctrl      = q1.qubit(0);
        qstate tgt       = q1.qubit(1);

        // Entangle — ctrl and tgt consumed, entangled pair produced
        qstate entangled = Quantum.applyCNOT(ctrl, tgt);

        // Measure — collapses to classical boolean; entangled is consumed
        boolean outcome  = Quantum.measure(entangled.qubit(0));

        // Classical branching on quantum measurement result
        if (outcome) {
            WorkflowEngine.route(workflowId, "PATH_ALPHA");
            return "PATH_ALPHA";
        } else {
            WorkflowEngine.route(workflowId, "PATH_BETA");
            return "PATH_BETA";
        }
    }
}
No-Cloning Violation — Compile Error
qstate reg = Quantum.register(1);
qstate a   = Quantum.applyHadamard(reg);
qstate b   = Quantum.applyHadamard(reg);  // E0041 — reg already consumed

E0041: use of moved qstate variable 'reg' at line 3. Linear type constraint: qstate may only be consumed once.

§ 05

AI-Assisted Authoring

Prime is designed to be written by models as well as by people. A strict grammar, a type checker, native tests and a sandboxed VM make every piece of machine-written code checkable: it either compiles, passes its tests and runs within its limits, or it is rejected with a structured reason. Four mechanisms build on that: constrained decoding (§5.1) keeps generated code valid, the error loop (§5.2) lets a model repair it, verified training data (§5.3) teaches a model to write Prime, and code mode (§5.4) lets agents act through Prime programs instead of individual tool calls.

Prime standardizes the interfaces — what valid code is, how it is checked, what a verified example looks like, how an agent submits code — not the models or the training methods behind them. Prompt formats, tokenizers and fill-in-the-middle tokens belong to the model and its tooling and are not part of the language.

5.1 Grammar-Constrained Decoding

Prime's CFG is made available to the inference subsystem in compiled form. At each decoding step, the set of grammatically valid next tokens is computed from the CFG, and all other vocabulary entries have their logits set to -∞ before softmax. This means the model cannot emit:

  • Keywords from other languages (def, fn, func, lambda).
  • API names not registered in PrimeVM's type registry for the active module.
  • Type combinations that would be caught by the type-checker.
  • Unclosed qstate linear variables.

The CFG used for masking is the same prime.cfg artefact shipped with the compiler. A version mismatch between compiler and VM is a fatal startup error.

5.2 Compiler / VM Error Feedback Loop

When a generated snippet fails compilation, PrimeVM emits a machine-readable JSON error document fed back into the model's self-correction loop.

Error JSON Schema

{
  "prime_error": {
    "schema_version": "1.0",
    "source_file":    "string",
    "stage":          "LEXER | PARSER | TYPE_CHECK | BYTECODE | VM_RUNTIME",
    "errors": [
      {
        "code":      "string",         // e.g. "E0041"
        "message":   "string",
        "line":      "integer",        // 1-based
        "character": "integer",        // 1-based
        "end_line":  "integer",
        "end_char":  "integer",
        "context":   "string",         // source line text
        "hint":      "string | null"   // repair suggestion
      }
    ],
    "fatal": "boolean"
  }
}

Concrete Error Example

{
  "prime_error": {
    "schema_version": "1.0",
    "source_file":    "scoreContract.prime",
    "stage":          "TYPE_CHECK",
    "errors": [
      {
        "code":      "E0041",
        "message":   "use of moved qstate variable 'reg' after consumption at line 8",
        "line":      10,
        "character": 9,
        "end_line":  10,
        "end_char":  11,
        "context":   "        qstate b = Quantum.applyHadamard(reg);",
        "hint":      "qstate variables are linear; split the register before passing to gates"
      }
    ],
    "fatal": false
  }
}

Self-Correction Loop Protocol

  1. The model generates a candidate: a whole file, or the code between a given prefix and suffix.
  2. PrimeVM checks the assembled source and runs its tests. On success, the code is presented to the developer or agent.
  3. On failure, the JSON error document is passed back with the original context and the model generates a correction. After at most 3 iterations the error is shown to the developer.
  4. Every attempt is logged; failed attempts with their corrections become repair samples (§5.3).

5.3 Verified Training Data

A model learns to write Prime from examples, and Prime can prove an example correct. The toolchain therefore defines one sample format and one verification pipeline that every Prime training set uses, whether it comes from human code, generated code or the correction log of §5.2. Training itself — pretraining, supervised fine-tuning, reinforcement learning — runs in standard ML frameworks outside Prime; this section fixes only what goes in and how it is checked.

Sample kindContentTeaches
verifiedTask, accepted source, its testsWriting correct Prime from a request (SFT)
repairFailing source, its diagnostics, corrected sourceFixing code from compiler and test errors
completionPrefix, suffix and the accepted middleEditor completion; the trainer chooses the token format

Sample Record (JSON Lines, one sample per line)

{
  "schema":  "prime-sample/1",
  "kind":    "verified | repair | completion",
  "task":    "string",               // natural-language request, may be empty
  "hosts":   ["demo.weather"],       // host modules the code may use
  "source":  "string",               // accepted Prime source (the target)
  "broken":  "string | null",        // repair: the failing source
  "diagnostics": [ ... ],            // repair: §5.2 errors of "broken"
  "prefix":  "string | null",        // completion: code before the gap
  "suffix":  "string | null",        // completion: code after the gap
  "verification": {
    "compiler":     "prime 0.1.0",
    "fingerprint":  "sha256 of the sources",
    "tests_passed": 6,
    "tests_failed": 0,
    "admitted":     true,
    "instructions": 18342
  }
}

Verification Pipeline

  1. Check — prime check with the declared host modules. Samples that do not parse or type-check are kept only as the broken side of a repair sample.
  2. Test — prime test runs the sample's tests in the sandbox with fixture data; a verified sample needs at least one test and no failures.
  3. Admit — the admission rule of §6 must accept every report in the sample.
  4. Deduplicate — samples with the same compiled fingerprint are stored once.
  5. Record — the compiler version and results are written into verification, so a set can be re-verified when the compiler changes.

Reward for Reinforcement Learning

The same pipeline scores a model's output, so reinforcement learning needs no learned reward model. A candidate is checked and then run against tests the model cannot see or change:

OutcomeReward
Does not parse0.0
Parses, fails type checking0.1
Type-checks; p of n hidden tests pass0.2 + 0.6 × p / n
All hidden tests pass and admitted1.0
Hidden Tests
Reward tests are held out from the model and run with fixed fixtures and limits. A candidate that edits, skips or special-cases tests cannot raise its reward, and a candidate that exhausts its instruction budget scores as a failed test.

5.4 Prime for Agents (Code Mode)

An agent that needs several tool calls to answer a request can instead write one Prime program that makes those calls, and submit it to PrimeVM. The program is type-checked against the tools it may use, runs under a fixed budget, and returns one result or one structured error. Tools are host modules: the host declares their functions and types, and a program can call nothing else.

// Written by an agent for the request:
// "On which days of this period did it rain more than 20 mm at the station?"
module agent.wet_days;

import std.math;
import demo.weather;

@Report(id = "agent_wet_days", title = "Days over 20 mm", mobile = false)
pub class WetDays {

    const float LIMIT_MM = 20.0;

    pub static void run(ReportContext ctx) {
        int days = 0;
        for (date day : ctx.period.days()) {
            float mm = rainfall(ctx.station, day);
            if (mm > LIMIT_MM) {
                ctx.out.row(day, metric("rainfall", Math.round(mm, 1), Unit.MM));
                days += 1;
            }
        }
        ctx.out.total(metric("days_over_limit", days, Unit.NONE));
    }
}

Tools as Host Modules

Host modules are declared in JSON (as hosts/demo.weather.json). A tool described for the Model Context Protocol (MCP) maps onto a host function, so existing MCP servers can be offered to Prime programs without new code:

MCP toolPrime host function
namefunction name in a host module (one module per MCP server)
descriptiondescription, shown to the model with the declaration
inputSchema propertiestyped parameters: string, integer → int, number → float, boolean, array → list<T>, object → a declared host class
result contentreturn type, decoded and type-checked at the call
tool errorruntime error E0405 at the calling line

Run Protocol

// Agent → PrimeVM
{
  "sources": [{ "name": "wet_days.prime", "text": "..." }],
  "grant":   ["demo.weather"],                     // host modules this run may use
  "limits":  { "fuel": 20000000, "memory": 67108864, "timeout_ms": 5000 },
  "run":     { "report": "agent_wet_days", "subject": 42, "from": "2026-10-26", "to": "2026-11-01" }
              // or { "function": "module.Main.main" }
}

// PrimeVM → Agent
{
  "ok": true,
  "errors": [],                                    // §5.2 errors when ok is false
  "output": [],                                    // lines written with print
  "tests":  [],                                    // results of the program's own @Test methods
  "result": [ ... ],                               // report rows, or the returned value
  "instructions": 18342
}
GuaranteeHow PrimeVM enforces it
CapabilityOnly granted host modules type-check; there is no other I/O.
BudgetInstruction, memory, call-depth and time limits per run (E0501–E0504).
DeterminismThe standard library reads no clock or randomness; the same data gives the same result.
RepairabilityEvery failure is a §5.2 error with a position, fed back to the agent.
AuditEach run is identified by the fingerprint of its compiled code and logged with its result.
Why Code Mode
One program replaces a chain of tool calls and model round-trips: loops and filters run inside PrimeVM instead of in the model's context, intermediate data never passes through the model, and the whole action is checked before any of it runs.
§ 06

Native Test Framework

6.1 Annotations

AnnotationTargetBehaviour
@TestSpecificationClassMarks the class as a test suite. The VM sandbox instantiates it before module load.
@TestMethodDeclares a test case. Must return void with no parameters.
@Test(timeout = n)MethodFails if execution exceeds n milliseconds.
@MockInfer(label, conf)MethodWithin this test, all infer() calls return the given label and confidence without invoking the model.

6.2 Assertion API

MethodDescription
Assert.equals(expected, actual)Fails if values are not equal.
Assert.notEquals(a, b)Fails if values are equal.
Assert.isTrue(condition)Fails if condition is false.
Assert.isFalse(condition)Fails if condition is true.
Assert.confidenceAbove(probVar, threshold)Fails if probVar.confidence < threshold.
Assert.tensorEquals(a, b, epsilon)Fails if any element differs by more than epsilon.
Assert.throws(ErrorType, lambda)Fails if the lambda does not throw the specified error type.

6.3 Pre-Admission Gate

The PrimeVM sandbox executes all @TestSpecification blocks before a .primevm module is admitted to the production execution environment. This is mandatory for any module containing an infer() call or a qstate variable. All AuditStore and queue writes inside the sandbox are transactional and rolled back after the suite completes.

6.4 Concrete Test Suite

module com.example.compliance.triage.tests;

@TestSpecification
pub class CaseTriageTests {

    @Test
    @MockInfer(label = "APPROVE", conf = 0.97)
    pub void highConfidenceApproveTakesDirectPath() {
        string result = CaseTriage.triageCase("Customer meets all KYC criteria.", 1001);
        Assert.equals("APPROVE", result);
    }

    @Test
    @MockInfer(label = "REJECT", conf = 0.95)
    pub void highConfidenceRejectIsLogged() {
        string result = CaseTriage.triageCase("Sanctioned entity match detected.", 1002);
        Assert.equals("REJECT", result);
        Assert.isTrue(AuditStore.contains(1002));
    }

    @Test
    @MockInfer(label = "ESCALATE", conf = 0.55)
    pub void lowConfidenceRoutesToReviewQueue() {
        string result = CaseTriage.triageCase("Ambiguous counterparty relationship.", 1003);
        Assert.equals("PENDING_REVIEW", result);
        Assert.isTrue(ReviewQueue.contains(1003));
    }

    @Test
    pub void tensorRiskScoreIsCorrect() {
        tensor<float, 2, 2> a        = [[1.0, 2.0], [3.0, 4.0]];
        tensor<float, 2, 2> b        = [[0.5, 0.5], [0.5, 0.5]];
        tensor<float, 2, 2> product  = a * b;
        tensor<float, 2, 2> expected = [[1.5, 1.5], [3.5, 3.5]];
        Assert.tensorEquals(expected, product, 0.0001);
    }

    @Test(timeout = 500)
    @MockInfer(label = "APPROVE", conf = 0.99)
    pub void triageCompletesWithinSLA() {
        string result = CaseTriage.triageCase("SLA stress test narrative.", 9999);
        Assert.equals("APPROVE", result);
    }
}
§ 07

EBNF Grammar Fragment

The following EBNF productions are normative. The prime.cfg artefact shipped with the compiler toolchain is generated from this specification. Notation: [ X ] = optional, { X } = zero or more, ( X | Y ) = alternation, terminals in "double quotes".

(* ─── Module Header ─── *)
module_decl      = "module" qualified_name ";" ;
import_decl      = "import" qualified_name ";" ;

(* ─── Type Expressions ─── *)
type_expr        = primitive_type | prob_type | tensor_type | qstate_type | class_type ;

primitive_type   = "int" | "float" | "string" | "boolean" | "byte" | "void" ;

prob_type        = "prob" "<" type_expr ">" ;

tensor_type      = "tensor" "<" primitive_type { "," integer_literal } ">" ;

qstate_type      = "qstate" ;

(* ─── Variable Declarations ─── *)
var_decl         = type_expr identifier "=" expr [ confidence_clause ] ";" ;

confidence_clause = "confidence" float_literal ;

(* ─── Expressions ─── *)
expr             = infer_expr | tensor_expr | binary_expr | unary_expr
                 | method_call | field_access | identifier | literal ;

(* ─── infer() ─── *)
infer_expr       = "infer" "(" expr ")" [ classifying_clause ] [ as_clause ] ;

classifying_clause = "classifying" "[" string_literal { "," string_literal } "]" ;

as_clause        = "as" primitive_type ;

(* ─── Tensor Literal ─── *)
tensor_expr      = "[" tensor_row { "," tensor_row } "]" ;
tensor_row       = "[" numeric_literal { "," numeric_literal } "]" | numeric_literal ;

(* ─── Binary Operators ─── *)
binary_expr      = expr ( "+" | "-" | "*" | "@" | "==" | "!="
                        | "<" | ">" | "<=" | ">=" | "&&" | "||" ) expr ;

(* ─── Quantum ─── *)
qstate_decl      = "qstate" identifier "=" quantum_expr ";" ;
quantum_expr     = "Quantum" "." quantum_call ;
quantum_call     = "register"      "(" integer_literal ")"
                 | "applyHadamard" "(" identifier ")"
                 | "applyCNOT"     "(" identifier "," identifier ")"
                 | "applyPhase"    "(" identifier "," expr ")"
                 | "measure"       "(" quantum_qubit_expr ")" ;
quantum_qubit_expr = identifier | identifier "." "qubit" "(" integer_literal ")" ;


(* ─── Annotations ─── *)
annotation       = "@" identifier [ "(" annotation_args ")" ] ;
annotation_args  = annotation_arg { "," annotation_arg } ;
annotation_arg   = identifier "=" literal | literal ;

(* ─── Test Declarations ─── *)
test_class       = "@TestSpecification" "pub" "class" identifier "{" { test_method } "}" ;
test_method      = { annotation } "pub" "void" identifier "(" ")" block ;

(* ─── Statements ─── *)
statement        = var_decl | qstate_decl | return_stmt | if_stmt | method_call ";" ;
if_stmt          = "if" "(" expr ")" block [ "else" block ] ;
block            = "{" { statement } "}" ;
return_stmt      = "return" [ expr ] ";" ;

(* ─── Class & Method Declarations ─── *)
class_decl       = { annotation } access_mod [ "static" ] "class" identifier "{" { member_decl } "}" ;
member_decl      = method_decl ;
method_decl      = { annotation } access_mod [ "static" ] type_expr identifier
                   "(" [ param_list ] ")" block ;
param_list       = param { "," param } ;
param            = type_expr identifier ;
access_mod       = "pub" | "priv" | "prot" ;

(* ─── Terminals ─── *)
qualified_name   = identifier { "." identifier } ;
identifier       = letter { letter | digit | "_" } ;
float_literal    = digit { digit } "." { digit } ;
integer_literal  = digit { digit } ;
string_literal   = '"' { character } '"' ;
numeric_literal  = float_literal | integer_literal ;
§ 08

End-to-End Enterprise Use Case

The following complete .prime file implements a production-grade Customer Risk Assessment Pipeline. It ingests customer workflow data, classifies intent via infer(), computes a tensor-based multi-factor risk score, runs a quantum-simulated optimisation gate for high-exposure decisions, and validates all logic with an embedded test suite — all in one self-contained module.

module com.example.risk.assessment;

import com.example.quantum.Gates;
import com.example.store.AuditStore;
import com.example.store.ReviewQueue;
import com.example.workflow.WorkflowEngine;
import std.time.Timestamp;

// ── Data transfer objects ─────────────────────────────────────────────────────

pub class CustomerWorkflow {
    pub int    customerId;
    pub string narrative;
    pub float  requestedExposure;
    pub string jurisdiction;
    pub int    accountAgeDays;
}

pub class AssessmentResult {
    pub string disposition;     // "APPROVE" | "ESCALATE" | "REJECT" | "PENDING_REVIEW"
    pub float  riskScore;       // composite 0.0–1.0
    pub float  aiConfidence;
    pub string quantumPath;     // "DETERMINISTIC" | "Q_STANDARD" | "Q_BIFURCATED"
    pub string auditTimestamp;
}

// ── Main pipeline ─────────────────────────────────────────────────────────────

pub class RiskAssessmentPipeline {

    // Segment weight matrix: 3 segments × 4 risk dimensions
    // Dimensions: [credit_history, exposure_ratio, jurisdiction_risk, tenure_score]
    // Segments:   [retail, institutional, sovereign]
    priv static tensor<float, 3, 4> SEGMENT_WEIGHTS = [
        [0.35, 0.25, 0.20, 0.20],
        [0.20, 0.40, 0.25, 0.15],
        [0.10, 0.30, 0.45, 0.15]
    ];

    pub static AssessmentResult assess(CustomerWorkflow wf, int segmentIdx) {

        // ── Step 1: AI Intent Classification ────────────────────────────────────
        prob<string> intent = infer(wf.narrative)
            classifying ["APPROVE", "ESCALATE", "REJECT"];

        if (intent.confidence < 0.65) {
            ReviewQueue.enqueue(wf.customerId, intent.confidence);
            AssessmentResult r;
            r.disposition    = "PENDING_REVIEW";
            r.riskScore      = -1.0;
            r.aiConfidence   = intent.confidence;
            r.quantumPath    = "N/A";
            r.auditTimestamp = Timestamp.now();
            return r;
        }

        // ── Step 2: Tensor Multi-Factor Risk Score ──────────────────────────────
        // Normalise four customer features into a 1×4 vector and dot-product
        // with the selected segment weight column to get a scalar risk score.
        float creditNorm   = CustomerData.getCreditNorm(wf.customerId);
        float exposureNorm = wf.requestedExposure / CustomerData.getLimit(wf.customerId);
        float jurisdRisk   = JurisdictionTable.getRiskScore(wf.jurisdiction);
        float tenureNorm   = Math.min(1.0, wf.accountAgeDays / 1825.0);

        tensor<float, 1, 4> features  = [[creditNorm, exposureNorm, jurisdRisk, tenureNorm]];
        tensor<float, 4, 1> weightCol = SEGMENT_WEIGHTS.row(segmentIdx).T;

        // (1×4) * (4×1) → (1×1)
        tensor<float, 1, 1> scoreTensor = features * weightCol;
        float compositeRisk = scoreTensor.scalar();

        // ── Step 3: Quantum Optimisation Gate ───────────────────────────────────
        // High-exposure requests (risk > 0.60) pass through a Hadamard-entangled
        // decision gate modelling portfolio diversification under uncertainty.
        string quantumPath = "DETERMINISTIC";

        if (compositeRisk > 0.60) {
            qstate reg        = Quantum.register(2);
            qstate superposed = Quantum.applyHadamard(reg);
            qstate ctrl       = superposed.qubit(0);
            qstate tgt        = superposed.qubit(1);
            qstate entangled  = Quantum.applyCNOT(ctrl, tgt);
            boolean qDecision = Quantum.measure(entangled.qubit(0));

            if (qDecision) {
                compositeRisk = compositeRisk * 1.15;
                quantumPath   = "Q_BIFURCATED";
            } else {
                quantumPath   = "Q_STANDARD";
            }
        }

        // ── Step 4: Final Disposition ────────────────────────────────────────────
        string disposition;
        if (intent.value == "REJECT" || compositeRisk > 0.85) {
            disposition = "REJECT";
        } else if (intent.value == "ESCALATE" || compositeRisk > 0.55) {
            disposition = "ESCALATE";
        } else {
            disposition = "APPROVE";
        }

        // ── Step 5: Audit and Return ─────────────────────────────────────────────
        AuditStore.write(wf.customerId, disposition, compositeRisk,
                         intent.confidence, Timestamp.now());

        AssessmentResult result;
        result.disposition    = disposition;
        result.riskScore      = compositeRisk;
        result.aiConfidence   = intent.confidence;
        result.quantumPath    = quantumPath;
        result.auditTimestamp = Timestamp.now();
        return result;
    }
}

// ── Embedded test suite ───────────────────────────────────────────────────────

@TestSpecification
pub class RiskAssessmentPipelineTests {

    priv static CustomerWorkflow retailWorkflow(float exposure, int ageDays) {
        CustomerWorkflow w;
        w.customerId        = 88001;
        w.narrative         = "Standard retail credit line application.";
        w.requestedExposure = exposure;
        w.jurisdiction      = "EU-DE";
        w.accountAgeDays    = ageDays;
        return w;
    }

    @Test
    @MockInfer(label = "APPROVE", conf = 0.96)
    pub void lowRiskRetailCustomerIsApproved() {
        CustomerWorkflow w = retailWorkflow(5000.0, 2190);
        AssessmentResult  r = RiskAssessmentPipeline.assess(w, 0);
        Assert.equals("APPROVE", r.disposition);
        Assert.isTrue(r.riskScore < 0.55);
        Assert.equals("DETERMINISTIC", r.quantumPath);
    }

    @Test
    @MockInfer(label = "APPROVE", conf = 0.91)
    pub void highExposureTriggersQuantumGate() {
        CustomerWorkflow w = retailWorkflow(980000.0, 365);
        AssessmentResult  r = RiskAssessmentPipeline.assess(w, 0);
        Assert.isTrue(r.quantumPath == "Q_BIFURCATED" || r.quantumPath == "Q_STANDARD");
    }

    @Test
    @MockInfer(label = "REJECT", conf = 0.98)
    pub void aiRejectOverridesLowTensorRisk() {
        CustomerWorkflow w = retailWorkflow(1000.0, 3650);
        AssessmentResult  r = RiskAssessmentPipeline.assess(w, 0);
        Assert.equals("REJECT", r.disposition);
        Assert.isTrue(AuditStore.contains(88001));
    }

    @Test
    @MockInfer(label = "APPROVE", conf = 0.50)
    pub void veryLowConfidenceRoutesToReviewQueue() {
        CustomerWorkflow w = retailWorkflow(20000.0, 730);
        AssessmentResult  r = RiskAssessmentPipeline.assess(w, 0);
        Assert.equals("PENDING_REVIEW", r.disposition);
        Assert.isTrue(ReviewQueue.contains(88001));
    }

    @Test
    pub void segmentWeightsFormProbabilitySimplex() {
        tensor<float, 3, 4> w = [
            [0.35, 0.25, 0.20, 0.20],
            [0.20, 0.40, 0.25, 0.15],
            [0.10, 0.30, 0.45, 0.15]
        ];
        Assert.equals(1.0, w.row(0).sum(), 0.001);
        Assert.equals(1.0, w.row(1).sum(), 0.001);
        Assert.equals(1.0, w.row(2).sum(), 0.001);
    }

    @Test(timeout = 300)
    @MockInfer(label = "APPROVE", conf = 0.93)
    pub void fullPipelineCompletesWithinSLA() {
        CustomerWorkflow w = retailWorkflow(15000.0, 1095);
        AssessmentResult  r = RiskAssessmentPipeline.assess(w, 0);
        Assert.isTrue(r.disposition != "");
    }
}
Production Admission Guarantee
All six tests must pass in the PrimeVM sandbox before the com.example.risk.assessment module is admitted to the production execution context. A single failure halts deployment and emits a structured error report to the CI/CD pipeline.
§ 09

Playground

Run Prime in this page. The playground compiles and executes code with the real PrimeVM, built to WebAssembly from the same Rust crates as the prime command, entirely in your browser. Choose an example or write your own: a class Main with pub static void main() is run and what it writes with print is shown, and every @Test is run and the admission rule (§6) applied.

Prime Core v0.1
The playground runs Prime Core v0.1, the buildable subset described in spec/prime-core-v0.1.md. Probabilistic types, tensors, infer(), qstate and the other features of §2–§4 are reserved keywords there and are rejected by the compiler. Host functions (data of the embedding application) are not available in the browser.
PrimeVM loads on first run
Run the code (Ctrl+Enter) to see its output.

The output shows the lines written with print, test results and admission verdicts, and diagnostics with phase, code, line and column (Prime Core §14). Each run gets 20 million instructions and 3 seconds; nothing leaves the page.