Metadata-Version: 2.4
Name: chef-lang
Version: 0.1.0
Summary: Interpreter for the Chef esoteric programming language
Author-email: Tim Hoerner <thoerner@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/thoerner/chef-lang
Project-URL: Repository, https://github.com/thoerner/chef-lang
Project-URL: Issues, https://github.com/thoerner/chef-lang/issues
Keywords: chef,esoteric,programming-language,interpreter
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Education
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Interpreters
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# Chef Interpreter

A Python interpreter for the [Chef esoteric programming language](https://www.dangermouse.net/esoteric/chef.html), where programs are written as cooking recipes.

## Installation

Requires Python 3.10+. No external dependencies.

```bash
pip install .
```

This installs the `cook` command globally (or into the active virtualenv).

## Usage

```bash
cook <recipe.chef>
```

Pipe input for programs that use `Take ... from refrigerator`:

```bash
echo "5" | cook examples/interactive_factorial.chef
```

## Language Overview

Chef is a stack-based language designed by David Morgan-Mar (2002). Programs look like cooking recipes: variables are ingredients, stacks are mixing bowls, and output buffers are baking dishes.

- **Dry ingredients** (g, kg, pinches) output as numbers.
- **Liquid ingredients** (ml, l, dashes) output as Unicode characters.
- **Mixing bowls** are LIFO stacks for computation.
- **Baking dishes** accumulate output. The `Serves` statement prints them.

## Supported Instructions

### Data

| Instruction | Effect |
|---|---|
| `Take ingredient from refrigerator.` | Read an integer from stdin into the ingredient. |
| `Put ingredient into [nth] mixing bowl.` | Push the ingredient's value onto the bowl. |
| `Fold ingredient into [nth] mixing bowl.` | Pop the top value from the bowl into the ingredient. |

### Arithmetic

All arithmetic operates on the top of the specified mixing bowl.

| Instruction | Effect |
|---|---|
| `Add ingredient [to [nth] mixing bowl].` | top += ingredient |
| `Remove ingredient [from [nth] mixing bowl].` | top -= ingredient |
| `Combine ingredient [into [nth] mixing bowl].` | top *= ingredient |
| `Divide ingredient [into [nth] mixing bowl].` | top /= ingredient |
| `Add dry ingredients [to [nth] mixing bowl].` | Push the sum of all dry ingredient values. |

### Bowl / Dish Operations

| Instruction | Effect |
|---|---|
| `Liquefy ingredient.` | Convert the ingredient to liquid (character output). |
| `Liquefy contents of the [nth] mixing bowl.` | Convert all bowl contents to liquid. |
| `Stir [the [nth] mixing bowl] for N minutes.` | Roll the top N items in the bowl. |
| `Stir ingredient into the [nth] mixing bowl.` | Roll by the ingredient's value. |
| `Mix [the [nth] mixing bowl] well.` | Randomize the bowl's order. |
| `Clean [nth] mixing bowl.` | Empty the bowl. |
| `Pour contents of the [nth] mixing bowl into the [pth] baking dish.` | Copy bowl contents to dish. |

### Control Flow

| Instruction | Effect |
|---|---|
| `Verb the ingredient.` | Loop start: execute body while ingredient != 0. |
| `Verb [the ingredient] until verbed.` | Loop end: decrement the named ingredient (if present), jump to loop start. |
| `Set aside.` | Break out of the innermost loop. |
| `Serve with auxiliary-recipe.` | Call an auxiliary recipe (subroutine). |
| `Refrigerate [for N hours].` | In an auxiliary recipe: end the recipe. In the main recipe with N hours: print the first N baking dishes and continue. |

### Output

| Instruction | Effect |
|---|---|
| `Serves N.` | Print the first N baking dishes (top to bottom per dish, dish 1 first). |

## Ingredient Format

Each ingredient is one line in the `Ingredients.` section:

```
[initial-value] [[measure-type] measure] ingredient-name
```

- **initial-value** (optional): a non-negative integer. Omit for ingredients set later via `Take` or `Fold`.
- **measure-type** (optional): `heaped` or `level` (forces dry).
- **measure** (optional): determines dry/liquid type.
  - Dry: `g`, `kg`, `pinch`, `pinches`
  - Liquid: `ml`, `l`, `dash`, `dashes`
  - Either: `cup(s)`, `teaspoon(s)`, `tablespoon(s)`
- **ingredient-name**: any string (may contain spaces).

## Auxiliary Recipes

Auxiliary recipes are listed after the main recipe's `Serves` statement. Each has its own title, ingredients, and method. They act as subroutines invoked by `Serve with recipe-name.`

When called:
1. The sous-chef receives deep copies of all the caller's mixing bowls and baking dishes.
2. The sous-chef executes using its own ingredients.
3. On completion, the sous-chef's 1st mixing bowl is transferred back to the caller's 1st mixing bowl.

Auxiliary recipes can call other auxiliary recipes (or themselves recursively).

## Example Programs

### hello.chef — String Output

Pushes ASCII values as liquid ingredients and prints `Hi!`.

```bash
cook examples/hello.chef
# Hi!
```

### factorial.chef — Loops and Arithmetic

Computes 5! = 120 using a loop with `Combine` (multiply) and `Fold` (store result).

```bash
cook examples/factorial.chef
# 120
```

### calculator_cake.chef — Mixed Output

Reads a number, computes its factorial, and prints `N! = result` by combining liquid characters (`! = `) with dry numeric values across three baking dishes.

```bash
echo "5" | cook examples/calculator_cake.chef
# 5! = 120
```

### prompted_factorial.chef — Mid-Execution Output

Uses `Refrigerate for 1 hour` to flush the prompt `Enter a number: ` to stdout before reading input.

```bash
echo "7" | cook examples/prompted_factorial.chef
# Enter a number: 7! = 5040
```

### fibonacci.chef — Auxiliary Recipes

Computes the first 8 Fibonacci numbers using an `addition broth` auxiliary recipe that receives two values via the mixing bowl, computes their sum, and returns the result.

```bash
cook examples/fibonacci.chef
# 13
# 8
# 5
# 3
# 2
# 1
# 1
# 0
```

## Development

### Running Tests

```bash
pip install pytest
pytest
```

### Project Structure

```
chef-lang/
├── chef_lang/
│   ├── __init__.py          # Package exports
│   └── interpreter.py       # The interpreter
├── examples/                # Example .chef programs
│   ├── hello.chef
│   ├── appetit.chef
│   ├── factorial.chef
│   ├── interactive_factorial.chef
│   ├── calculator_cake.chef
│   ├── prompted_factorial.chef
│   └── fibonacci.chef
├── tests/
│   └── test_interpreter.py  # Test suite
├── LICENSE
├── README.md
└── pyproject.toml
```

## Spec Deviations

- **Refrigerate in main recipe**: when called with `for N hours`, prints N dishes and continues execution (rather than halting). Without hours, halts as per spec. This enables mid-execution output (prompts before input).
- **Method line breaks**: instructions must be one per line. The spec says line breaks are ignored (sentences delimited by periods), but all known Chef programs use one instruction per line.
- **Serves output order**: prints dish 1 first through dish N. The spec is ambiguous on order; some interpreters reverse it.
