mon-core 0.0.3

A robust parser and validator for the Mycel Object Notation (MON) language, designed for fast, efficient, and human-friendly configuration.
Documentation
# MON Cookbook: Practical Recipes

Welcome to the MON Cookbook! This guide provides practical examples and patterns to help you solve common data-structuring problems using MON. Think of it as a collection of recipes for writing clean, efficient, and powerful configurations.

## Recipe 1: Your First Configuration File

MON is designed for human readability. Let's create a simple server configuration.

**Ingredients:**
*   Unquoted keys for simplicity.
*   Comments (`//`) for notes.
*   Basic data types: `String`, `Number`, `Boolean`.

**Instructions:**

```mon
// config.mon
{
    // The name of our application
    app_name: "Awesome App",

    // Network settings
    host: "localhost",
    port: 8080,

    // Feature flags. MON accepts on/true and off/false for booleans.
    enable_feature_x: on,
    enable_https: false,

    // A list of admin users
    admins: ["alice", "bob"],
}
```

**Key Takeaway:** MON looks familiar but is less strict than JSON. You can write configurations that are easier for people to read and edit.

---

## Recipe 2: Avoiding Repetition (The DRY Principle)

One of MON's most powerful features is its ability to reuse data within a file. This is perfect for defining a value once and using it multiple times.

**Ingredients:**
*   **Anchors (`&`):** To create a reusable template.
*   **Aliases (`*`):** To make a perfect, independent copy of a template.
*   **Spreads (`...*`):** To merge a template's content and add or override values.

### 2a. Creating a Reusable Template with Anchors

An anchor (`&`) gives a nickname to any value (`object`, `array`, `string`, etc.), turning it into a template.

```mon
{
    // The & makes `default_user` a template.
    // Note: The anchor itself doesn't appear in the final output.
    &default_user: {
        theme: "dark",
        notifications: on,
    },
}
```

### 2b. Making Copies with Aliases

An alias (`*`) makes a **deep copy** of an anchor. Each copy is completely separate.

```mon
{
    &default_user: { theme: "dark" },

    // alice_settings is a perfect copy of the template
    alice_settings: *default_user,

    // bob_settings is another, totally independent copy
    bob_settings: *default_user,
}
```

### 2c. Extending Templates with Spreads

A spread (`...*`) unpacks an anchor's content into a new object or array, allowing you to extend it.

**For Objects:** Spreads merge keys. If a key exists in both the template and your new object, the **local value wins**.

```mon
{
    &base_config: {
        host: "localhost",
        log_level: "info",
    },

    prod_config: {
        ...*base_config,      // 1. Inherit host and log_level
        host: "api.myapp.com", // 2. Override the host
        log_level: "error",    // 3. Override the log_level
    },
}
```

**For Arrays:** Spreads combine elements.

```mon
{
    &base_permissions: ["READ", "WRITE"],

    admin_permissions: [
        "LOGIN",
        ...*base_permissions, // Inserts "READ" and "WRITE" here
        "DELETE",
    ],
}
```

---

## Recipe 3: Modular Data with Imports

You can split your MON configurations across multiple files. All `import` statements must appear at the top of the file, before the opening `{` of the root object.

**Ingredients:**
*   `import * as ... from "path"`: The safest way to import.
*   `import { Member } from "path"`: To import specific, named parts.
*   `import { &Anchor } from "path"`: An advanced technique to share templates between files.

### 3a. Namespace Imports (Safest)

This bundles everything from another file into a single name, preventing conflicts.

**`schemas.mon`**
```mon
{
    User: #struct { name(String) },
    Status: #enum { Active, Inactive },
}
```

**`main.mon`**
```mon
// Import everything from schemas.mon into the `schemas` name
import * as schemas from "./schemas.mon"

{
    // Access imported members using the namespace
    admin :: schemas.User = { name: "Admin" },
    current_status: $schemas.Status.Active,
}
```

### 3b. Named Imports (Convenient)

Import specific parts directly into your file's scope.

**`main.mon`**
```mon
// Import only User and Status
import { User, Status } from "./schemas.mon"

{
    // Use them without a prefix
    guest :: User = { name: "Guest" },
    current_status: $Status.Inactive,
}
```

### 3c. Sharing Templates Across Files (Advanced)

You can import an anchor from another file. This makes the anchored *value* a new, local anchor in your current file, ready for reuse.

**`templates.mon`**
```mon
{
    // Define a reusable template for a base user
    &base_user: {
        permissions: ["READ"],
        is_active: true,
    },
}
```

**`main.mon`**
```mon
// Import the &base_user anchor from templates.mon
import { &base_user } from "./templates.mon"

{
    // Now you can use `base_user` as a local anchor!
    admin_user: {
        ...*base_user, // Spread the template
        name: "Admin User",
        permissions: ["READ", "WRITE", "DELETE"], // Override permissions
    },
}
```

---

## Recipe 4: Enforcing Data Quality

MON's optional type system helps you prevent mistakes by validating your data's structure.

**Ingredients:**
*   `#enum`: For creating a type with a fixed set of choices.
*   `#struct`: For defining the "blueprint" of an object.
*   `::`: The validation operator to check an object against a struct.

### 4a. Defining a Struct Blueprint

A struct defines what keys an object should have and what their value types should be.

```mon
{
    // A blueprint for a Product object
    Product: #struct {
        id(String),                 // Required String field
        price(Number),              // Required Number field
        in_stock(Boolean) = false,  // Optional Boolean, defaults to false
    },
}
```

### 4b. Validating Your Data

Use the `::` operator to validate an object against a struct. The MON compiler will report an error if the data doesn't match the blueprint.

```mon
{
    Product: #struct { id(String), price(Number) },

    // This object is valid and matches the Product struct
    my_book :: Product = {
        id: "978-0321765723",
        price: 55.99,
    },

    // INVALID: The compiler would throw an error here because `price` is a string.
    // my_widget :: Product = {
    //     id: "widget-123",
    //     price: "25.00",
    // },
}
```

---

## Common Pitfalls & Tips

*   **Spread Precedence:** When using a spread (`...*`), local keys always win. Any key you define in your object will override a key from the spread template.
*   **Keep It Simple:** Anchors and spreads are powerful, but creating long, complex chains of them can make your data hard to debug. Prefer clarity and simplicity.
*   **Start with Namespace Imports:** When learning, `import * as ...` is your friend. It's the clearest way to see where data is coming from and prevents accidental name clashes.