329 lines
8.3 KiB
Markdown
329 lines
8.3 KiB
Markdown
# OWA-RS
|
||
|
||
A Lisp-inspired programming language written in Rust. This is a personal learning project, so expect rough edges and experimental design.
|
||
|
||
## Content
|
||
|
||
- [OWA-RS](#owa-rs)
|
||
- [Content](#content)
|
||
- [Overview](#overview)
|
||
- [Syntax 📝](#syntax-)
|
||
- [Literals](#literals)
|
||
- [Collections](#collections)
|
||
- [Special Forms](#special-forms)
|
||
- [Comments](#comments)
|
||
- [Annotations](#annotations)
|
||
- [Example](#example)
|
||
- [Quick Start 🛠️](#quick-start-️)
|
||
- [Requirements](#requirements)
|
||
- [Build](#build)
|
||
- [Run a file](#run-a-file)
|
||
- [Run directly without owu](#run-directly-without-owu)
|
||
- [Flags](#flags)
|
||
- [Architecture 🏗️](#architecture-️)
|
||
- [Rust core](#rust-core)
|
||
- [Modular standard library](#modular-standard-library)
|
||
- [Built-in API 🔧](#built-in-api-)
|
||
- [Core operations](#core-operations)
|
||
- [Built-in namespaces](#built-in-namespaces)
|
||
- [Standard Library 📚](#standard-library-)
|
||
- [Core Library (`modules/core/`)](#core-library-modulescore)
|
||
- [Standard Library (`modules/std/`)](#standard-library-modulesstd)
|
||
- [owu (`modules/owu/`)](#owu-modulesowu)
|
||
- [Performance ⚡](#performance-)
|
||
- [Examples 🌟](#examples-)
|
||
- [Hello World](#hello-world)
|
||
- [Using Functions from Core](#using-functions-from-core)
|
||
- [Working with Collections](#working-with-collections)
|
||
- [Development 🛠️](#development-️)
|
||
- [Running Tests](#running-tests)
|
||
- [Building Documentation](#building-documentation)
|
||
- [TODOs 📋](#todos-)
|
||
- [High Priority](#high-priority)
|
||
- [Medium Priority](#medium-priority)
|
||
- [Lower Priority](#lower-priority)
|
||
- [Completed](#completed)
|
||
- [Contributing 🤝](#contributing-)
|
||
- [License 📄](#license-)
|
||
|
||
## Overview
|
||
|
||
OWA-RS is designed as a lightweight Lisp-like interpreter with:
|
||
|
||
- a small Rust runtime,
|
||
- a modular standard library,
|
||
- a simple CLI wrapper (owu),
|
||
- persistent immutable collections via `rpds`.
|
||
|
||
> ⚠️ This is a **personal project** for learning and experimentation. It's my very first Rust project, so expect some rough edges. Use at your own risk!
|
||
|
||
## Syntax 📝
|
||
|
||
OWA-RS uses a familiar Lisp-style syntax with nested expressions.
|
||
|
||
### Literals
|
||
|
||
- Integers: `42`, `-7`
|
||
- Floats: `3.14`, `-0.5`
|
||
- Strings: `"hello world"`
|
||
- Keywords: `:key`, `:value`
|
||
- Symbols: `variable-name`, `function?`
|
||
|
||
### Collections
|
||
|
||
- Lists / Calls: `(function arg1 arg2)`
|
||
- Vectors: `[1 2 3]`
|
||
- Maps: `{:key "value" :other 42}`
|
||
- Sets: `#{"a" "b" "c"}`
|
||
|
||
### Special Forms
|
||
|
||
- Lambdas: `(lambda [args] body)`
|
||
- Macros: `(macro [args] body)`
|
||
- Quotes: `'expression`
|
||
- Unquotes: `$expression`
|
||
|
||
### Comments
|
||
|
||
Comments start with `;;` and continue to the end of the line.
|
||
|
||
### Annotations
|
||
|
||
Annotations are placed in angle brackets (`<annotation>value`) and can contain any value that will be computedduring linting (⚠️ currently not implemented).
|
||
|
||
### Example
|
||
|
||
```owa
|
||
(seq
|
||
;; Define a function
|
||
(def greet (lambda [name]
|
||
(str.concat "Hello, " name "!")))
|
||
|
||
;; Call it
|
||
(trace (greet "World")))
|
||
```
|
||
|
||
## Quick Start 🛠️
|
||
|
||
### Requirements
|
||
|
||
- Rust 1.70+ (for building from source)
|
||
- Cargo
|
||
|
||
### Build
|
||
|
||
```bash
|
||
git clone https://github.com/RuJect/owa-rs.git
|
||
cd owa-rs
|
||
cargo build --release
|
||
```
|
||
|
||
### Run a file
|
||
|
||
```bash
|
||
./target/release/owa-rs run hello.owa
|
||
```
|
||
|
||
### Run directly without owu
|
||
|
||
```bash
|
||
./target/release/owa-rs --no-owu hello.owa
|
||
```
|
||
|
||
### Flags
|
||
|
||
When running via owu, these flags are available:
|
||
|
||
- `--no-builtins`: skip Rust built-ins
|
||
- `--no-core`: skip loading core library
|
||
- `--no-std`: skip loading standard library
|
||
- `--debug`: enable debug mode
|
||
- `--test`: run in test mode
|
||
|
||
## Architecture 🏗️
|
||
|
||
OWA-RS follows a **Parse → Interpret** pipeline with modular design:
|
||
|
||
### Rust core
|
||
|
||
- `src/parser/`: source code → AST
|
||
- `src/core/interpreter.rs`: evaluates AST nodes
|
||
- `src/core/scope.rs`: manages variables and closures
|
||
- `src/builtins/`: runtime primitives and host operations
|
||
|
||
### Modular standard library
|
||
|
||
- `modules/core/`: core language utilities, types, math, error handling, loops, tests
|
||
- `modules/std/`: higher-level helpers such as `path` and `platform`
|
||
- `modules/owu/`: command-line interface and `run` command support
|
||
|
||
The runtime stays intentionally small, while higher-level language features live in library code.
|
||
|
||
## Built-in API 🔧
|
||
|
||
OWA-RS follows a **minimalist principle** for Rust built-ins: the runtime only implements fundamental primitives and avoids domain/application logic. The result is a small, focused runtime with powerful libraries built on top.
|
||
|
||
### Core operations
|
||
|
||
- Language: `def`, `lambda`, `macro`, `seq`, `trace`, `apply`, `lookup`, `include`
|
||
- Scope: `scope`, `set!`, `unset!`, `exec`
|
||
- Type inspection: `typeof`, `cmp`
|
||
- Flow: `return`, `break`, `continue` (via `flow` namespace)
|
||
- Errors: `throw`, `catch` (via `errors` namespace)
|
||
|
||
### Built-in namespaces
|
||
|
||
- `math`: arithmetic and numeric helpers
|
||
- `str`: string construction and serialization
|
||
- `vec`: vector creation and folding
|
||
- `map`: maps and lookup
|
||
- `set`: set operations
|
||
- `cond`: conditional helpers like `if-eq` and `match`
|
||
- `platform`: environment, CLI parsing, debug flags
|
||
|
||
## Standard Library 📚
|
||
|
||
The standard library is organized in modules:
|
||
|
||
### Core Library (`modules/core/`)
|
||
|
||
Essential functionality available by default when running through owu:
|
||
|
||
- `assert.owa`: Assertion utilities for testing
|
||
- `types/`: Type checking and predicates, including:
|
||
- `main.owa`: Core type utilities and predicates
|
||
- `bool.owa`, `str.owa`, `vec.owa`, `map.owa`, `set.owa`, `null.owa`, `option.owa`: Type-specific operations
|
||
- `cmp.owa`: Comparison operations
|
||
- `math.owa`: Arithmetic operations
|
||
- `error.owa`: Error handling
|
||
- `loop.owa`: Looping constructs
|
||
- `test.owa`: Testing framework
|
||
|
||
### Standard Library (`modules/std/`)
|
||
|
||
Additional utilities:
|
||
|
||
- `platform.owa`: Platform-specific operations
|
||
|
||
### owu (`modules/owu/`)
|
||
|
||
The OWA Utility tool:
|
||
|
||
- `cli/`: Command-line interface framework
|
||
- `cli/run.owa`: The `run` command handler
|
||
|
||
## Performance ⚡
|
||
|
||
OWA-RS is a tree-walking interpreter with reasonable performance for its simplicity. Rust's persistent data structures (via rpds) provide efficient immutable collections.
|
||
|
||
For performance-critical workloads, consider:
|
||
|
||
- Writing hot paths in Rust as built-ins
|
||
- Avoiding deeply nested function calls
|
||
- Using tail recursion where possible
|
||
|
||
See `benchmarks/` for sample performance characteristics.
|
||
|
||
## Examples 🌟
|
||
|
||
### Hello World
|
||
|
||
```owa
|
||
(trace "Hello, OWA-RS!")
|
||
```
|
||
|
||
### Using Functions from Core
|
||
|
||
```owa
|
||
(def fib (lambda [n]
|
||
(if (>= n 2)
|
||
(+ (fib (- n 1)) (fib (- n 2)))
|
||
n)))
|
||
|
||
(trace (fib 10))
|
||
```
|
||
|
||
Run with: `./target/release/owa-rs run fib.owa`
|
||
|
||
### Working with Collections
|
||
|
||
```owa
|
||
(def numbers [1 2 3 4 5])
|
||
(trace (vec.len numbers))
|
||
(trace (vec.first numbers))
|
||
|
||
(def config {:name "OWA" :version "0.1.0"})
|
||
(trace (map.get config :name))
|
||
```
|
||
|
||
## Development 🛠️
|
||
|
||
### Running Tests
|
||
|
||
The core library has a built-in testing framework:
|
||
|
||
```bash
|
||
./target/release/owa-rs run --test modules/core/tests/main.owa
|
||
```
|
||
|
||
### Building Documentation
|
||
|
||
To understand the codebase:
|
||
|
||
- `src/core/interpreter.rs` - Main evaluation logic
|
||
- `src/builtins/` - Rust built-in implementations
|
||
- `modules/core/` - OWA standard library code
|
||
- `modules/owu/cli/` - Command-line interface implementation
|
||
|
||
## TODOs 📋
|
||
|
||
### High Priority
|
||
|
||
- [ ] Add proper error reporting with location information
|
||
- [ ] Improve debugging/tracing utilities
|
||
- [ ] Add REPL mode for interactive development
|
||
- [ ] Implement tail call optimization
|
||
|
||
### Medium Priority
|
||
|
||
- [ ] Pattern matching enhancements
|
||
- [x] Destructuring in set!/def
|
||
- [ ] More comprehensive std library
|
||
- [ ] Package manager / module repository
|
||
- [ ] Performance profiling tools
|
||
|
||
### Lower Priority
|
||
|
||
- [ ] Concurrency support
|
||
- [x] FFI (Foreign Function Interface)
|
||
- [ ] File system operations (fs module)
|
||
- [ ] Random number generation
|
||
- [ ] Compilation to bytecode
|
||
- [ ] Lint phase
|
||
|
||
### Completed
|
||
|
||
- [x] Annotations
|
||
- [x] Separate core and std libraries
|
||
- [x] CLI framework with commands
|
||
- [x] Testing framework
|
||
- [x] Error handling macros
|
||
|
||
## Contributing 🤝
|
||
|
||
This is a learning project exploring language design and implementation. Contributions are welcome!
|
||
|
||
Areas where help is appreciated:
|
||
|
||
- Standard library expansion
|
||
- Bug fixes and optimizations
|
||
- Documentation and examples
|
||
- Testing and benchmarking
|
||
|
||
## License 📄
|
||
|
||
Unlicense License - see LICENSE file.
|
||
|
||
---
|
||
|
||
Made with ❤️ and lots of ☕ as a Rust learning project!
|