๐Ÿ‰ CMRA User Guide

"Where code breathes fire and flows like flameโ€ฆ"

๐Ÿ“‘ Contents

โšก Installation

Option A โ€” pip install (recommended)

Install from PyPI to get the cmra command everywhere inside your virtual environment:

# From the project root, with your venv activated:
      pip install cmra

      # Development install from source (optional):
      pip install -e .

      # Then run any .cmra or .cmrash file:
cmra myprogram.cmra

Option B โ€” PowerShell wrapper (no install needed)

.\cmra.ps1 "test cases\test.cmra"

# Add to PATH for this session so `cmra` works anywhere:
$env:PATH = "C:\path\to\CMRA;$env:PATH"
cmra test.cmra

Option C โ€” Python directly

# Via the installed package:
python -m cmra.cli myprogram.cmra

# Or the legacy single-file interpreters:
python cmra.py myprogram.cmra
python cmrash.py myprogram.cmrash

Option D โ€” CMRA Esoteric Language Extension

For the best developer experience, install the official extension:

By default, extension run uses python -m cmra "<file>" and can be overridden with cmra.executablePath.

Diagnostics are randomized and themed for .cmra, and concise/technical for .cmrash.

Diagnostic message examples

  • Fire Dragon: Line 4: 'x' is but a myth in this realm. (Hint: bind before use)
  • Fire Dragon: Line 5: Fire Dragon rejects '=' in this chant. (Hint: use bind)
  • Shadow Dragon: Line 4: Undefined variable 'x'. (Hint: initialize with =)
  • Shadow Dragon: Line 5: Unexpected 'bind' in .cmrash. (Hint: use =)

Full diagnostics catalog: cmra-vscode-extension/ERROR_MESSAGES.md.

Option E โ€” Standalone Executable (Windows)

Don't have Python installed? No problem!

  • Executable: Download cmra.exe from the GitHub Releases, drop it anywhere, and optionally add it to your PATH to run natively.

โ–ถ๏ธ Running Programs

# Basic usage
cmra <filename>
    cmrash <filename>

# Examples
cmra "test cases\test.cmra"
cmra projects\calculator.cmra
    cmra projects\fizzbuzz.cmra
    cmrash "test cases cmrash\test.cmrash"
ExtensionDialectNotes
.cmraFire DragonExpressive aliases (bind, roar, โ€ฆ)
.cmrashShadow DragonMinimal commands (=, print, โ€ฆ)

Extensions are only conventions โ€” either interpreter can read any file.

๐Ÿฒ Fire Dragon Syntax

Entry point: cmra.py / src/cmra/fire.py. Expressive, dragon-flavored keywords.

KeywordRoleExample
bindAssign variablex bind 5
roarPrint valueroar "hello" / roar x + 1
sniffConditionalsniff x < 10 : roar x
diveDirection โ†’ forwarddive
soarDirection โ†’ reversesoar
murmurCommentmurmur this is ignored

Example

x bind 3
name bind "Chimera"
roar name          murmur prints: Chimera
roar x * 4        murmur prints: 12.0

๐ŸŒ‘ Shadow Dragon Syntax

Entry point: cmrash.py / src/cmra/shadow.py. Minimal syntax, same execution model.

KeywordRoleExample
=Assign variablex = 5
printPrint valueprint x + 1
checkConditionalcheck x < 10 : print x
reverseToggle directionreverse
;Comment; this is ignored
x = 3
name = "Chimera"
print name         ; prints: Chimera

๐Ÿ”ข Expressions & Types

x bind 4
roar x * 3 + 1        murmur โ†’ 13.0
roar "val: " + x      murmur โ†’ "val: 4.0"
roar x == 4           murmur โ†’ 1 (true) or 0 (false)

๐Ÿงญ Direction Control

CMRA's defining feature: a global direction controls how the interpreter steps through lines.

DirectionValueMovement
Forward (default)1Line 1 โ†’ 2 โ†’ 3 โ€ฆ
Reverse-1Line N โ†’ N-1 โ†’ N-2 โ€ฆ
CommandFire DragonShadow Dragon
Set forwarddiveโ€”
Set reversesoarโ€”
Toggleโ€”reverse

The program terminates when the instruction pointer goes past the first or last line.

Tip: Prefer soar/dive over reverse in loops โ€” they are idempotent (calling twice is safe). reverse toggles, so calling it twice cancels out.

๐Ÿ“ฆ Block Conditionals

A block groups multiple lines under a single condition:

sniff x < 5 :
{
  roar "x is small"
  roar x
}

Block entry rules

ConditionDirectionEnters at
TrueForwardFirst line of block
TrueReverseLast line of block
FalseEitherSkip entire block

This means a soar inside a block takes effect immediately on the reverse pass โ€” the key to building loops.

๐Ÿ” Writing Loops

CMRA has no native loop keyword. Use direction reversal + flag guards.

Pattern 1 โ€” Inline flagged loop

murmur โ”€โ”€ setup โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
i bind 0
flag bind 1

murmur โ”€โ”€ top boundary: re-enter forward if done โ”€
sniff i < 10 : sniff flag == 0 : dive

murmur โ”€โ”€ flag guard (0 = forward pass) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
flag bind 0

murmur โ”€โ”€ body: only runs on forward pass โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
sniff flag == 0 : roar i
sniff flag == 0 : i bind i + 1

murmur โ”€โ”€ restore flag โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
flag bind 1

murmur โ”€โ”€ bottom boundary: reverse if still looping
sniff i < 10 : sniff flag == 1 : soar

How it works step-by-step

  1. Reaches bottom sniff โ†’ condition true โ†’ soar โ†’ direction = reverse
  2. Re-traverses lines in reverse, skipping body (guarded by flag == 0)
  3. Reaches top boundary โ†’ dive โ†’ direction = forward
  4. Forward pass runs body, increments i, reaches bottom again
  5. Repeats until i < 10 is false

Pattern 2 โ€” Block loop

i bind 0
flag bind 0
sniff i < 10 :
{
  sniff flag == 1 : dive
  sniff i < 10 : flag bind 1
  sniff flag == 1 : roar i
  sniff flag == 1 : i bind i + 1
  sniff i < 10 : flag bind 0
  sniff flag == 0 : soar
}

Key rule: Always guard loop body lines with a flag variable so the reverse traversal doesn't re-execute them.

โš ๏ธ Common Pitfalls

๐Ÿ”ฅ Missing flag guards โ€” body runs twice per iteration

murmur BAD โ€” prints twice per iteration!
roar i
i bind i + 1
murmur GOOD โ€” only runs on forward pass
sniff flag == 0 : roar i
sniff flag == 0 : i bind i + 1

๐Ÿ”ฅ String growth in loops

Without a flag guard, s bind s + "x" runs on both forward and reverse passes, doubling the string.

Always guard string-building assignments: sniff flag == 0 : s bind s + "x"

๐Ÿ”ฅ Numbers always print as floats

roar 5 prints 5.0, not 5. This is by design โ€” all numeric literals are floats.

๐Ÿ”ฅ soar vs reverse

  • soar sets direction to reverse (idempotent)
  • reverse toggles โ€” calling it twice cancels out!
  • Use soar/dive in loops for safety

๐Ÿ”ฅ Nested loops need nested flags

Use separate flag variables for each loop level: flag_outer, flag_inner. Every inner body line must be guarded by flag_inner == 0.

๐ŸŽฎ Example Programs

Hello World

roar "Hello, Chimera!"

Count 0 to 5

i bind 0
flag bind 1
sniff i <= 5 : sniff flag == 0 : dive
flag bind 0
sniff flag == 0 : roar i
sniff flag == 0 : i bind i + 1
flag bind 1
sniff i <= 5 : sniff flag == 1 : soar

Run the bundled projects

cmra projects\calculator.cmra       # factorial, series, power
cmra projects\countdown.cmra        # reversible countdown
cmra projects\fizzbuzz.cmra         # fizzbuzz 1โ€“15
cmra projects\story_adventure.cmra  # interactive text adventure

Test cases live in test cases\ (Fire Dragon) and test cases cmrash\ (Shadow Dragon).

๐Ÿ› ๏ธ Extending the Language

To add a new command to the Fire Dragon interpreter (src/cmra/fire.py):

  1. Top-level dispatch โ€” add a branch in execute_line() alongside roar, bind, sniff
  2. Inline action support โ€” add it to execute_inline_action() so it can appear after : in sniff chains
  3. Test it โ€” add a .cmra file to test cases\

Look at how roar, bind, dive, and soar are implemented โ€” they follow the same two-step pattern.

๐Ÿ“– The full keyword mapping is in keybind.txt โ€” Fire โ†” Shadow cheatsheet.