96 lines
3.8 KiB
Markdown
96 lines
3.8 KiB
Markdown
# Peppermint C89 port
|
|
|
|
This repository root is a clean native C89 implementation of the behavior that
|
|
is implemented in the original TypeScript Peppermint tree, with no TypeScript,
|
|
Node.js, Beef, or third-party runtime dependency.
|
|
|
|
Original project: https://github.com/lainq/peppermint
|
|
|
|
## Build
|
|
|
|
```sh
|
|
make
|
|
./peppermint smoke.ppm hello
|
|
```
|
|
|
|
The build uses `-std=c89 -pedantic -Wall -Wextra -Wconversion -Wshadow`.
|
|
The language core is ISO C89; the project-oriented CLI commands use the usual
|
|
POSIX file APIs (`mkdir`, `stat`, `getcwd`) so `init`/`run`/`list` can create
|
|
and discover files as the TypeScript CLI does.
|
|
|
|
## CLI
|
|
|
|
Supported commands:
|
|
|
|
```sh
|
|
peppermint run [--file=FILE] [--args ARGS...]
|
|
peppermint init --name=NAME [--author=AUTHOR] [--license=LICENSE]
|
|
peppermint list
|
|
peppermint version
|
|
peppermint bf --file=FILE [--compile=true]
|
|
peppermint FILE.ppm [ARGS...]
|
|
```
|
|
|
|
Notes:
|
|
|
|
- `peppermint FILE.ppm [ARGS...]` preserves the first C89 port's direct-file
|
|
behavior.
|
|
- `run --file=...` executes a Peppermint source file.
|
|
- `run` without `--file` reads `.peppermint` in the current directory and uses
|
|
its `main` string field.
|
|
- `run --args ...` passes the remaining values to `@argv` / `@argv:N`.
|
|
- `init` creates `README.md`, `app.ppm`, `tests/test.ppm`, and `.peppermint`.
|
|
- `list` reads a simple project store. Set `PEPPERMINT_STORE=/path/to/store` to
|
|
override the default `$HOME/.peppermint/store.json` location.
|
|
- `version` prints `Peppermint Version 0.0.1[platform]`.
|
|
- `bf` is a separate Brainfuck runner. With `--compile=true`, it also writes the
|
|
original Long-language-style output to `dist/test.long`. The compiler follows
|
|
the upstream static conversion pass: it records cell values observed at `.`
|
|
instructions and ignores Brainfuck loop/control execution while compiling.
|
|
|
|
## Language behavior
|
|
|
|
Implemented:
|
|
|
|
- `let name := expression` constant bindings.
|
|
- `let name = expression` mutable bindings.
|
|
- `name = expression` assignment to existing mutable bindings.
|
|
- integer and floating-point literals, including unary minus.
|
|
- quoted strings with `\n`, `\r`, `\t`, and escaped-character handling.
|
|
- `+`, `-`, `*`, `/`, and `%` with normal arithmetic precedence.
|
|
- string concatenation with `+` when both operands are strings.
|
|
- relational operators tokenized by the TypeScript lexer: `==`, `!=`, `>=`,
|
|
`<=`, `>`, and `<`. They produce `1` for true and `0` for false.
|
|
- parenthesized expressions.
|
|
- `#` comments and line-oriented programs.
|
|
- `@argv`, `@argv:N`, `@env:NAME`, and `@exit`.
|
|
- robust file/line diagnostics for syntax and runtime errors.
|
|
|
|
## Upstream gaps and compatibility notes
|
|
|
|
The TypeScript parser in the upstream tree is incomplete: it tokenizes
|
|
assignment (`=`), constants (`:=`), and relational operators, but only executes
|
|
arithmetic builtins in practice and does not build a real AST. This C89 port
|
|
therefore implements the practical behavior those tokens imply instead of
|
|
claiming byte-for-byte parser parity. Unsupported higher-level semantics such
|
|
as functions, blocks, imports, conditionals, loops, objects, and a module system
|
|
are not present in the TypeScript implementation and are intentionally not
|
|
fabricated here.
|
|
|
|
The TypeScript project store was a JSON file under the compiled CLI directory.
|
|
A single native executable has no such package directory, so the C89 CLI uses a
|
|
portable tab-separated project store at `$HOME/.peppermint/store.json` (or
|
|
`PEPPERMINT_STORE`) while keeping the same user-visible `init`/`list` workflow.
|
|
|
|
## Tests
|
|
|
|
```sh
|
|
./test.sh
|
|
```
|
|
|
|
The test script rebuilds with strict C89 flags, then checks legacy direct-file
|
|
execution, command dispatch, expressions, relational operators, mutable vs.
|
|
constant assignment, builtins, project init/config/list/run behavior, version
|
|
output, and the Brainfuck runner/compiler command including static Long output
|
|
semantics.
|