Ricochet Reference

A working reference for the current Ricochet toolchain: stack words, declaration operators, symbols, OOP, MVC, Active Record, templates, tests, and debugger behavior.

rco new my_app
rco fmt app.rco
rco routes my_app
rco test my_app
rco run --debug --step app.rco
Ricochet stack and MVC flow Value::String Value::Map Value::Class Value::Block bytecode VM Controller View Postgres $name "home/index" swap view $className $methodName [ ... ] !method

Copy/Paste Smoke Script

Verify your local virtual machine installation works correctly with this bootstrap class and execution sequence.

User Model subclass
  email field
  "displayName" [ $self .email ] !method
end

User new
"ada@example.com" swap .email set
.displayName
println

Syntax And Symbols

Key lexer tokens, comment formatting, blocks, OOP declarations, HTML views, and routes.

Comments

(( Any documentation comment or note. ))

Comments are delimited with double parentheses and are ignored by compilation.

Class Declarations

User Model subclass
  users table
  email field
end

Declaration shape stays postfix: declaration name first, declaration operator last.

Collection Declarations

users array
settings map
queue list
tags Set

Name-first collection declarations bind mutable shared collections. Use `Array new`, `Map new`, `List new`, or `Set new` for anonymous values.

Argument Lists

( ctx -> Response ) "index" [
  $ctx "home/index" swap view
] !method

Parentheses create optional input/output metadata for functions and methods.

Blocks

[ $self .email ]

Square brackets create first-class bytecode blocks. Use `call` to execute a block value.

Conditionals

result dup ok? if
  value
else
  error .message
end

`if else end` is postfix: the condition is already on the stack before `if`.

Loops

$count 10 < while
  $count 1 + $count set
end

The condition expression before `while` is re-executed before every iteration. `break` exits and `continue` rechecks the condition.

Members

$user .email
"ada@example.com" $user .email set

Dot words push member selectors for `get` and `set`, and call methods when used directly.

Imports

"lib/math" import
7 triple

"greeter/greeting" import
packageHello

Static string imports load relative `.rco` files before the importing file. If the relative file is missing, imports shaped like `package/module` resolve through `[dependencies.package]` in `ricochet.toml`. Dynamic imports remain a future package/runtime-loader feature.

Templates

<strong>{ $user .name }</strong>
<small>{ 20 22 + }</small>

Each `{ ... }` expression runs Ricochet and must leave exactly one renderable value.

Routes

GET "/" HomeController "index" route
POST "/users" UserController "create" route
DELETE "/users/:id" UserController "destroy" route

Route files are line-oriented and accept quoted paths and action names.

Words And Operators

Search, filter, and inspect postfix operators built into the core bytecode engine.

Filter Category:

OOP Examples

How OOP works under the hood in a concatenative environment.

Class-First Model File

Project style is one class per file, with the filename matching the class name.

(( app/Models/User.rco ))
User Model subclass
  users table
  id field
  email field
  name field

  "displayName" [
    $self .name
    dup nil? if
      drop $self .email
    else
      return
    end
  ] !method
end

Runtime Class And Method Names

Strings and variables can drive declaration operators, which is where Ricochet starts to feel different.

"Widget" className var
"label" methodName var

$className "Object" subclass
$className "name" field
$className $methodName [ $self .name ] !method

$className new
"dynamic" swap .name set
.label

Dynamic Dispatch

Use `.methodName` for direct method calls or `send` when the method name is itself a value.

User new
"ada@example.com" swap .email set
dup .displayName println
"displayName" send println

MVC Application Example

The default structure of a server-side web application running under Ricochet serve.

1
Route config/routes.rco
2
Controller app/Controllers
3
View app/Views
4
Model app/Models

Manifest

[package]
name = "ricochet_app"

[web]
mode = "mvc"
routes = "config/routes.rco"

[web.views]
escape = "html"

[dependencies.greeter]
path = "./packages/greeter"

Routes

GET "/" HomeController "index" route
GET "/users" UserController "index" route
GET "/users/show" UserController "show" route
POST "/users" UserController "create" route
DELETE "/users/:id" UserController "destroy" route

Controller

(( app/Controllers/HomeController.rco ))
HomeController Controller subclass
  "index" [
    "Hello Ricochet" title var
    $ctx
    "home/index" swap view
  ] !method
end

Model Used By MVC

(( app/Models/User.rco ))
User Model subclass
  email field
  name field

  "displayName" [
    $self .name nil? if
      $self .email
    else
      $self .name
    end
  ] !method
end

Controller With Collection

(( app/Controllers/UserController.rco ))
UserController Controller subclass
  "index" [
    users array
    User new
    "ada@example.com" swap .email set
    "Ada Lovelace" swap .name set
    $users .push! drop
    $users .count userCount var
    "Users" title var
    $ctx
    "users/index" swap view
  ] !method
end

Redirect And Headers

LoginController Controller subclass
  "create" [
    "/dashboard" redirect
    303 status
    "cache-control" "no-store" header
  ] !method
end

View

<main>
  <h1>{ title get }</h1>
  <p>{ 20 22 + }</p>
</main>

Active Record Examples

Interact with Postgres schemas using simple, stack-based ORM words.

Model Mapping

(( app/Models/User.rco ))
User Model subclass
  users table
  id field
  email field
  name field
end

Model Class Calls

User .all
42 User .find
"email" "ada@example.com" User .where
10 User .limit
User .count
User .first
1 User .exists?
attributes map
"email" "ada@example.com" $attributes .put! drop
"name" "Ada" $attributes .put! drop
$attributes User .insert

updates map
"email" "grace@example.com" $updates .put! drop
42 $updates User .update

Controller With Stack Result Handling

(( app/Controllers/UserController.rco ))
UserController Controller subclass
  ( ctx -> Response ) "index" [
    User .all
    dup ok? if
      value users var
      $ctx "users/index" swap view
    else
      error .message text
    end
  ] !method
end

Loops And Computational Completeness

Mutable counters, Peano numerals, and conditional backward jumps.

Counter-Machine Multiplication

Mutable counters, conditional branching, decrement, and backward jumps provide the core WHILE-machine model. This program computes `6 * 7` without a multiplication word.

0 product var
6 multiplicand var
7 multiplier var

$multiplier 0 > while
  product get multiplicand get + product set
  $multiplier 1 - $multiplier set
end

product get println

Loop Control

0 count var

$count 10 < while
  $count 1 + $count set
  $count 3 = if continue end
  $count 6 = if break end
  $count println
end

Unary Counter Shape

For an abstract unbounded counter, object chains can represent Peano-style natural numbers independently of the fixed-width integer convenience type.

Counter Object subclass
  previous field
end

nil counter var

counter get Counter new .previous set counter set
counter get Counter new .previous set counter set
counter get nil? false = while
  counter get .previous counter set
end

Debugging And Tests

Interactive execution traces, break-on-fault logs, and unit testing support.

Realtime Trace

Debug mode prints each instruction with stack before and after. Step mode pauses and accepts `step`, `continue`, or `abort`.

rco run --debug app.rco
rco run --debug --step app.rco
rco run --breakpoint 12 app.rco
rco repl --debug

Fault Shape

Runtime errors preserve the relevant stack when an operation fails loudly.

TRACE app.rco:3 [<main>] CallWord("+")
  before: [Number(20), Number(22)]
  after:  [Number(42)]
FAULT [<main>] unknown word typo
  stack:  [Number(42)]

TestCase

(( tests/UserTest.rco ))
UserTest TestCase subclass
  "testDisplayName" [
    "Ada"
    "Ada" assert-equals
  ] !method
end

CLI Reference

Comprehensive list of commands available in the Ricochet command-line interface.

CLI Script Words

args .count println
"DATABASE_URL" env dup ok? if value println else error .message eprint end
cwd value println
now println
100 random println

Packages

rco add ./packages/greeter
rco add github:BARKx4/ricochet_auth@v0.1.0 --no-fetch

Capabilities

"README.md" fs .read-text value .count println
"https://example.com" http .get value response var
"status" response get .at println

Acceptance Suite

cargo build -p ricochet_cli --bin rco
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scriptscceptance.ps1

Known Current Limits

The bounds of the v1.0.0 draft specification. Be aware of these rules in your application code.

  • Integer values are `i64`; the lexer currently reads non-negative decimal number literals.
  • HTTP and filesystem access are host capabilities. The CLI enables them for trusted local scripts; embedded hosts can leave them disabled. HTTP calls currently use a 10 second timeout and a 1 MiB response body cap.
  • Web controller execution and template expressions have instruction budgets so runaway server code returns a fault instead of hanging a request.
  • `rco serve --watch` is a planned hot reload surface and currently exits with a clear not-implemented error.
  • Package imports are static, and `rco install` is not implemented yet. GitHub sources can be recorded with `--no-fetch`; fetching uses `git clone` when enabled.
  • Async and AI package words are not implemented yet.
  • Result values cannot be used directly as conditions. Use `ok?`, then `value` or `error`.
  • Top-level `method` declarations are rejected; methods belong inside classes or are installed with `!method`.
  • Active Record targets existing PostgreSQL schemas in v1. Schema migrations are a later branch.
  • Template expressions must leave exactly one scalar renderable value: nil, bool, number, or string.