# Craft++ Language Conformance Report

Verification date: 2026-11-10

This report records what was **empirically executed** against the Craft++
language and runtime, separating verified behavior from known gaps. Every claim
below is backed by a passing test in this repository — none of it is assumed.

## Method

Each case runs real Craft++ source through the full pipeline
(`Lexer` -> `Parser` -> `Interpreter.Execute`) and asserts observed runtime
values, or calls `BuiltinProcs.Execute` directly. Suites added for this audit:

- `LanguageConformanceTests` — syntax, literals, declarations, types,
  inheritance, procs, verbs, vars.
- `BuiltinConformanceTests` — every registered builtin plus value checks for the
  core string/list/math/type-predicate builtins.

## Verified working

| Area | Verified behavior |
|---|---|
| Literals | Integers, decimals, negatives, hex (`0xFF`), binary (`0b101`), text, quotes and `\n` escapes |
| Comments | `//` line and `/* */` block comments are ignored |
| Interpolation | `"value=[n]"` and multi-variable `"[who] said [m]"` |
| Declarations | `var`, typed `var/num/n`, `var/text/t`, `var/list/`, `var/global/`, `var/local/`, `var/const/` |
| Type registration | `mob/Thing` registers `/mob/Thing` with parent `/mob` |
| Inheritance | `mob/Base/Child` inherits parent vars, overrides procs, and `..()` calls the parent |
| Instance semantics | Per-instance variable independence (`a.value` vs `b.value`) |
| Type checks | `istype()` follows the full inheritance chain and rejects unrelated bases |
| Procs | Definition, calls, return values, default arguments, recursion |
| Verbs | `verb/Name()` is defined and callable like a proc |
| Builtins | **309 registered**; all execute without an unexpected exception |
| String builtins | `uppertext`, `lowertext`, `copytext` (1-based, exclusive end), `findtext` |
| List builtins | `list`, `length`, `min`, `max` over lists |
| Math builtins | `sqrt`, `floor`, `ceil`, `abs` |
| Type predicates | `isnum`, `istext` |

## Deep value verification (expanded)

Beyond "executes without throwing", the following builtins are now verified to
return **correct values**:

| Group | Verified cases |
|---|---|
| String case/length | `uppertext`, `lowertext`, `length` (incl. empty text) |
| `copytext` | 1-based, **exclusive** end; start-past-end → `""`; negative start clamps to 1 |
| `findtext` | first-match positions; missing → `0`; **empty needle → position 1** |
| `splittext` / `jointext` | text delimiters, field preservation |
| `replacetext` | single and repeated occurrences; no-match leaves text intact |
| `num2text` / `text2num` | round trip; non-numeric text → `0` |
| `hex2num` | hex digits to numbers |
| `round` | **`round(A)` is `floor(A)`**; `round(A, step)` to nearest step |
| `sign` | -1 / 0 / 1 |
| `sqrt`, `exp` | standard values |
| `log` | **`log(A)` is the natural log**; `log(base, value)` selects a base |
| `sin`/`cos`/`tan` | **degrees** (sin 90 = 1, cos 90 = 0, tan 45 = 1) |
| `clamp`, `fract` | bounded clamp; fractional part |
| `sort` | **returns a sorted copy**; source list is left untouched |
| `shuffle` | preserves contents, changes order |
| `sum`, `min`, `max`, `length` (lists) | correct reductions |
| `pick` | returns an actual member |
| `prob` | `prob(0)` false, `prob(100)` true |
| `isnull`, `islist`, `isnum`, `istext` | correct classification |
| `ckey` | lowercases and strips non-word characters |
| `html_encode` / `html_decode` | round trip, no raw `<` leaks |

### Control flow verified through the language

`while`, C-style `for (init; cond; inc)` (semicolon-separated), `for (x in list)`,
`break`, `continue`, `switch`/`if`/`else`, and nested `if/else if/else` all
produce correct results.

### Common authoring mistakes found while verifying

These are **correct engine behaviors** that are easy to write incorrectly:

- `for (init, cond, inc)` with commas is a parse error; Craft++/DM require
  semicolons.
- `sort(list)` does not mutate in place — assign the result.
- `round(3.6)` is `3` (floor), not 4.
- `log(10)` is `ln(10)`, not `log10`.


Craft++ correctly implements DM's tubular path rule: **the final path segment
names the type and everything before it is the parent.**

```dm
mob/Base          // declares /mob/Base        (parent: /mob)
mob/Base/Child    // declares /mob/Base/Child  (parent: /mob/Base)
mob/Child         // declares /mob/Child       (parent: /mob) — a SIBLING of Base
```

So `mob/Base` plus `mob/Child` does **not** create inheritance; `istype(childOfChild, /mob/Base)`
is correctly `False`. Inheritance requires the `Parent/Child` form, which was
verified end to end (parent var inheritance, proc override, `..()`, `istype`).

## Intentional aborts

`ASSERT()` and `CRASH()` raise runtime errors by design and are excluded from
the "executes without throwing" inventory.

## Gap verification (tested against BYOND DM semantics)

Each row was checked by executing Craft++ code and comparing against the
documented DM rule. "Verified" = behaves per DM; "Open" = still divergent.

| Matrix area | DM rule checked | Result |
|---|---|---|
| Lists — assoc | `l["k"] = v` then read back | **Verified** |
| Lists — duplicates | Same value may appear more than once | **Verified** |
| Lists — `in` | Membership test | **Verified** |
| Lists — `Add`/`Remove` | Grow/shrink the list | **Verified** |
| Lists — `length` with assoc keys | Keys count toward length | **Verified** |
| Object lifecycle — `del` | Deleted ref becomes null | **Verified** |
| Object lifecycle — `initial()` | Returns the declared default, not the mutated value | **Verified** |
| `istype` — deep hierarchy | Matches at every ancestor level | **Verified** |
| Coercion — truthiness | `0`/`null`/`""` false; nonzero/`"text"` true | **Verified** |
| Coercion — text+num | `"1" + 2 == 3` | **Verified** |
| Regex (P1) | `regex("\\d+").Find("abc123")` → match `"123"` | **Verified** |
| `input()` typing (P1) | `input(...) as num` converts numeric input | **Verified** |
| `call_ext()` (P1) | Missing library does not crash the runtime | **Verified (safe no-op)** |
| `walk()` vector (P0) | `walk(o, 0, 0)` cancels without error | **Verified** |
| `sleep()` time (P0) | Delay is deciseconds, independent of `tick_lag` | **Verified** (time only) |
| `sleep()` scheduling (P0) | Caller suspends and resumes; host thread not blocked | **Open** — `Thread.Sleep` blocks the host thread |
| Savefile index (P1) | `f["k"] = v` / `f["k"]` round trip | **Verified** |
| Savefile streams (P1) | `f["k"] << v` / `f["k"] >> x` | **Open** — `>>` reads `0`; test skipped and tracked |
| `/database` (P1) | SQLite adapter | **Open** — no built-in adapter |
| `call_ext()` native ABI (P1) | Load DLL/SO and call native entry points | **Open** — host delegate only |
| Native `.dmb`/`.rsc` + wire protocol (P0) | BYOND interchange | **Out of scope by design** |

The two open runtime items that change game behavior are **`sleep()` blocking
its host thread** and **savefile stream operators**. Both are recorded as
skipped/tracked tests rather than silently ignored.


These are tracked in `BYOND_DM_PARITY_MATRIX.md` and were **not** claimed as
verified here:

- `sleep()` still blocks its host thread instead of suspending the caller frame;
  `spawn(-1)` continuation splitting and `spawn(0)` queue ordering are open.
- `call_ext()`/`load_ext()` call host-registered delegates only; no BYOND native
  ABI.
- `/database` has no built-in SQLite adapter (dispatch exists).
- `/regex` covers common cases but not DM-specific pattern extensions or byte
  indexing.
- Savefile layout and `>>`/`<<` buffer semantics differ from DM.
- `input()` typed verb-argument prompting does not yet consume parameter
  metadata.
- Native BYOND `.dmb`/`.rsc` interchange and the BYOND wire protocol are out of
  scope by design.

Passing Craft++ tests verify Craft++ behavior; they are not a BYOND differential
conformance result.

## Conclusion

The core language — syntax, literals, declarations, variables (including
modifiers), types, inheritance, procs, verbs, and the registered builtin surface
— is verified working by executable tests. The remaining distance to "100%" is
concentrated in the scheduler (`sleep`/`spawn`), native extension ABI, database
adapter, regex edge cases, and savefile layout, not in the language grammar or
type system.
