# Craft++ Dream Maker

A WPF desktop IDE and interpreter for a BYOND-like language called **Craft++**.  
It blends classic Dream Maker syntax with modern OOP features, and provides a full compile→run pipeline inside a Windows desktop app.

## What’s Inside

| Layer | Status | Notes |
|-------|--------|-------|
| Lexer | Done | Tokens, `//`/`/* */` comments, indentation-defined blocks, path strings, `..` |
| Keywords | Done | Full DM/Craft keyword map |
| Parser | Done | Recursive-descent AST builder |
| AST | Done | 14+ statement/expression node types, visitor pattern |
| Interpreter | Done | Tree-walking execution, scoped environments, control flow via exceptions |
| Runtime | Done | `num`, `text`, `bool`, `null`, `list`, typed objects |
| Type system | Done | `/datum` → `/mob`, `/obj`, `/turf`, `/area` inheritance |
| Builtins | Done | `rand`, `abs`, `max`, `min`, `length`, `copytext`, `istype`, `isnull`, `isnum`, `istext`, `sleep` |
| IDE | Functional; polish in progress | Custom WPF editor, syntax highlighting, compile/run, file/project tree, object tree; see known limitations below |

## Language Features

Blocks use indentation only. Literal `{ }` code blocks and inline block bodies
are rejected. Use four spaces per level (or tabs consistently), indent children,
and dedent to an existing level to finish a block. Blank lines and comments do
not affect nesting. Parentheses and square brackets still serve expressions,
arguments, and indexing; braces inside text and comments are allowed.

```text
proc/Main()
    if (1)
        world << "Hello"
    else
        world << "Goodbye"

Main()
```

Compile rechecks project code and included files, using open editor buffers.
Invalid indentation, missing bodies, brace blocks, malformed expressions,
unclosed strings/comments, mismatched delimiters, and malformed conditional
directives produce errors with file, line, and column. Files that cannot be read
fail the build rather than being silently skipped. Passing these checks does
not guarantee that a program is free of runtime or logic errors.

**Migration:** remove block braces, put each body on indented lines, and move
inline bodies (such as `if (ready) Start()`) beneath their headers. Existing
brace-based programs must be migrated before recompilation.

### OOP & Inheritance

```
mob
    var/name = "Mob"
    proc/Speak()
        world << "Hello"

mob/Player
    proc/Speak()
        ..()
        world << "I am [name]"
```

### Lists

```
var/list/items = new/list("Sword", "Shield")
items += "Potion"
items -= "Shield"
world << items        // list(Sword, Potion)
world << items.len     // 2
```

### Control Flow

- `if / else`
- `while`
- `for (init; cond; inc)`
- `for (var/x in list)`
- `switch / case / default`
- `return`, `break`, `continue`
- `spawn(delay)` with an indented body
- `del target`

### Operators

- Arithmetic: `+ - * / %`
- Comparison: `== != < > <= >=`
- Logical: `&& || !`
- Compound: `+= -= *= /= %=`
- Postfix: `++ --`
- Type path: `to` — checks if value is of/inherits from a type
- Type cast: `as` — returns value if cast is valid, otherwise `null`

```
if (player to /mob/Player)
    world << "Player"
var/mob/Player/p = datum as /mob/Player
```

### String Interpolation

```
var/name = "Hero"
world << "Welcome, [name]!"    // Welcome, Hero!
```

### Built-in Procs

| Proc | Description |
|------|-------------|
| `rand([min,] max)` | Random integer 1..max, or min..max |
| `abs(x)` | Absolute value |
| `max(a, b, ...)` | Maximum |
| `min(a, b, ...)` | Minimum |
| `length(x)` | Length of text or list |
| `copytext(text, start, end)` | Substring, 1-based |
| `istype(val, path)` | Type hierarchy check |
| `isnull(val)` | Null check |
| `isnum(val)` | Number check |
| `istext(val)` | Text check |
| `sleep(ticks)` | Delay execution |

### Globals

- `world` — world object (`maxx`, `maxy`, `name`)
- `usr` — current user
- `src` — current source object
- `null`, `TRUE`, `FALSE`

## IDE Shortcuts

| Key | Action |
|-----|--------|
| F5 | Compile |
| F6 | Run |
| Ctrl+N | New |
| Ctrl+O | Open |
| Ctrl+S | Save |

## Project Files

- `.craft` — Craft++ source files
- `.cp` — Craft++ source files (default save extension)
- `.dm` — DM-style source extension; Craft++ currently supports only its documented syntax/API subset
- `.cpe` — Craft++ project file
- `.dme` — Dream Maker environment / project file

Open a `.dme` to load a full project into the file tree.

## Building

Requires .NET 8 SDK and Windows.

```bash
dotnet build codelanguage.csproj -f net8.0-windows
```

For a validated Windows installer and complete `updateddata` package, run
`installer/build-release.ps1` from the repository root. Release output is kept
under `codelanguage/artifacts` instead of source `bin` directories.

The IDE Compile action uses the Craft++ compiler/runtime and writes self-hosted
`.dmb` and `.rsc` artifacts beside the project or source file. These artifacts
are designed for Craft++ Dream Seeker and are not native BYOND binaries.

### Interface fidelity

Interfaces designed in the interface window editor are applied to the game
client when the project runs. The editor preview and the Seeker render share one
appearance contract (`ControlVisualSpec`), so a saved `interface.cpf` displays
the same backgrounds, text colours, fonts, borders, sizes and visibility in both
places. `InterfaceFidelityTests` enforces that equality in CI.

## Running Tests

```bash
dotnet test CraftPlusPlus.Tests/CraftPlusPlus.Tests.csproj
```

The headless core, compiler, and runtime suites run on .NET 8. Windows is
required for the WPF application and installer pipeline. See
[DEVELOPMENT.md](DEVELOPMENT.md) for the complete validation matrix.

## Status

Core language engine and IDE are functional.  
Dream Maker asset formats (`.dmi`, `.dmm`) are partially supported; DMI metadata is read and DMM preview is limited.  
See source code comments for known TODOs.

### Known parity limits

Craft++ does not compile native BYOND `.dmb`/`.rsc` files and does not implement
all Dream Maker syntax, runtime APIs, Dream Daemon networking, Dream Seeker
behavior, or BYOND Hub account services. See
[`BYOND_DM_PARITY_MATRIX.md`](BYOND_DM_PARITY_MATRIX.md) for the tracked gaps.
Dream Seeker can load live game listings from the configured Craft++ Hub,
launch pinned TLS connections through `craft://`, and authenticate using a
Craft++ Hub account. Dream Daemon publishes player counts and authenticated
keys while the hosted world is live. The primary application and Hub source
build warning-free.
