GitHub - ryanmcdermott/spress: A tiny vibe coded dynamic programming language in a single header file for maximum portability

4 min read Original article ↗

Spress

Spress is a tiny, dynamically-typed programming language implemented in a single C++ header. It supports integers, floats, booleans, strings, lists, hash maps, first-class functions, control flow, iteration, slicing, and external variable injection.

This language was made as a test to test the limits of state of the art LLMs.

Caution

DO NOT USE IN PRODUCTION. This is completely vibe coded with o4-mini-high.


Table of Contents

  1. Installation
  2. Getting Started
  3. Limitations
  4. Data Types
  5. Variables and Assignment
  6. Expressions
  7. Statements and Control Flow
  8. Functions
  9. Built-in Functions
  10. Iteration and Slicing
  11. External Variables Injection
  12. Grammar

Installation

Download this repo, cd to the directory where this code is, then run the following commands.

Run an example:

spress example/quicksort.spress

Getting Started

Include spress.h in your C++ project and call:

#include "spress.h"

// Evaluate code without injections:
auto result = spress::Eval(R"(
  func main() {
    print("Hello, SPRESS!");
    return 0;
  }
)");

// Evaluate code with external injections:
std::unordered_map<std::string, spress::Value> inj = {{"x", 3}, {"y", 4}};
auto sum = spress::Eval(R"(
  x = external;
  y = external;
  func main() { return x + y; }
)", inj);

Limitations

  • No classes.
  • No stack traces.
  • No optimizer.
  • Probably many bugs (it was vibe coded).

Data Types

Type Literal Syntax Example
Integer 42 a = 10;
Float 3.14 f = 2.0;
Boolean true, false b = false;
String "hello" s = "world";
List [ expr₁, expr₂, … ] l = [1,2,3];
Map { key₁:val₁, key₂:val₂, … } m = {"a":1,"b":2};
Function via func declaration see Functions

Variables and Assignment

Global vs Local

  • Assignments at the top level create global variables.
  • Assignments inside functions create local variables (unless a global with the same name already exists).

Assignment Operator

  • Uses = to bind a value to a variable.
  • The assignment expression itself evaluates to the assigned value.
x = 100;        # Defines a global variable x with value 100

func inc() {
  x = x + 1;    # Inside a function: if x was global, this refers to the global x
  return x;     # Returns the new value of x
}

func demo() {
  a = 5;        # Defines local variable a
  b = a * 2;    # Defines local variable b based on a
  return b;     # Returns 10
}

Expressions

Literals
Numbers (42, 3.14), strings ("hello"), booleans (true, false).

Variables
Identifiers referencing values.

Binary Operators
Arithmetic: +, -, *, /
Comparison: ==, !=, <, <=, >, >=
Bitwise: &, |, ^, <<, >>
Logical: &&, ||

Unary Operators
Logical NOT: !
Negation: -
Bitwise NOT: ~

Concatenation

  • Lists: [1,2] + [3][1,2,3]
  • Strings: "a" + "b""ab"

Indexing & Slicing

Function Calls

  • Direct: f(a, b)
  • First-class: assign functions to variables and call via fnVar(args…)

Map Literals
{ key1: expr1, key2: expr2, … }

External Keyword
external denotes a value provided at runtime via injection.

Statements and Control Flow

<statement> ::= <expr>;         # expression statement
              | return <expr>;  # return
              | if (e) {…}      # conditional
              | while (e) {…}   # loop
              | for (v in e) {…}# for-in
if (x > 0) {
  print("positive");
} else {
  print("non-positive");
}

while (n > 0) {
  n = n - 1;
}

for (i in [1,2,3]) {
  print(i);
}

for (k, v in {"a":1,"b":2}) {
  print(k, "→", v);
}

Functions

  • Defined with func name(params…) { body }

  • Parameters are passed by value.

  • Return via return expr;. Implicitly returns 0 if none.

func fib(n) {
  if (n < 2) return n;
  return fib(n-1) + fib(n-2);
}

print(fib(5));  # → 5

Built-in Functions

  • print(arg₁, arg₂, …)*: writes to stdout, returns 0.

  • length(x): returns size of list, string, or map.

Iteration and Slicing

  • List or string indexing: a[2]

  • Slicing: a[start:end] yields sub-list or substring

  • Map indexing: m["key"]

  • Slice assignment:

l = [0,1,2,3];
l[1:3] = [9,9];   # → [0,9,9,3]

External Variables Injection

Use external in a top-level assignment to mark a variable for injection:

x = external;
func main() { return x * 2; }

Then provide at runtime:

spress::Eval(source, {{"x", 10}});  // → 20

Grammar

<program>        ::= { <declaration> }

<declaration>    ::= <function-decl> | <statement>

<function-decl>  ::= "func" <identifier> "("
                      [ <identifier> { "," <identifier> } ]
                    ")" <block>

<statement>      ::= <expr-stmt>
                   | <return-stmt>
                   | <if-stmt>
                   | <while-stmt>
                   | <for-stmt>

<expr-stmt>      ::= <expression> ";"
<return-stmt>    ::= "return" <expression> ";"

<if-stmt>        ::= "if" "(" <expression> ")" <block>
                   [ "else" <block> ]

<while-stmt>     ::= "while" "(" <expression> ")" <block>

<for-stmt>       ::= "for" "(" <identifier>
                      [ "," <identifier> ]
                      "in" <expression> ")"
                    <block>

<block>          ::= "{" { <declaration> } "}"

<expression>     ::= <assignment>
<assignment>     ::= <logical-or> [ "=" <assignment> ]

<logical-or>     ::= <logical-and> { "||" <logical-and> }
<logical-and>    ::= <