about summary refs log tree commit diff stats
path: root/js/scripting-lang/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'js/scripting-lang/README.md')
-rw-r--r--js/scripting-lang/README.md205
1 files changed, 87 insertions, 118 deletions
diff --git a/js/scripting-lang/README.md b/js/scripting-lang/README.md
index 877f566..5890a06 100644
--- a/js/scripting-lang/README.md
+++ b/js/scripting-lang/README.md
@@ -1,43 +1,51 @@
-# Scripting Language
+# Baba Yaga
+## A Scripting Language
 
-A combinator-based scripting language with functional programming features, pattern matching, and a comprehensive standard library.
+Baba Yaga is a combinator-based scripting language that aims to be dangerously functional-brained, has minimal syntax, an intuitive approach to pattern matching, and hopefully enough of a standard library to be useful...but not too much of a standard library to be difficult to recall.
 
-## Overview
+This whole thing started as an aesthetic curiosity, and continued on from there. I wanted to be able to do pattern matching like this: 
 
-This is a functional scripting language that translates all operations into function calls to standard library combinators. The language supports:
-
-- **Function Definitions**: Arrow syntax with lexical scoping
-- **Pattern Matching**: When expressions with wildcards and nested expressions
-- **Tables**: Array-like and key-value entries with boolean keys
-- **Function References**: @ operator for higher-order programming
-- **IO Operations**: Input, output, and assertions
-- **Standard Library**: Complete set of arithmetic, comparison, logical, and higher-order combinators
-- **Table Enhancements**: APL-inspired element-wise operations and immutable table operations
+```plaintext
+factorial : n -> 
+  when n is
+    0 then 1
+    _ then n * (factorial (n - 1));
+```
 
-## Quick Start
+I've implemented a whole bunch of [forths](https://git.sr.ht/~eli_oat/chupacabra), and a couple schemes, but never have I ever implemented something like a "regular" programming language. And, while, an [ML-flavored](https://en.wikipedia.org/wiki/Standard_ML) programming language isn't exactly regular, this has grown from an aesthetic curiosity to a full-blown aesthetic indulgence.
 
-### Usage
-```bash
-# Run a script file
-node lang.js your-script.txt
+Baba Yaga supports...
 
-# Or with Bun
-bun lang.js your-script.txt
-```
+- **Function definitions** using arrow syntax with lexical scoping
+- **Pattern matching** with a single `when ... is ... then` expression that handles wildcards and arbitrarily nested features
+- **Tables** inspired by Lua's tables, with array-like and key-value entries, including boolean keys
+- **Function references** using an `@` operator for higher-order programming
+- **IO Operations** including input, output, and assertions, plus an `..emit` and `..listen` pattern for interfacing a functional core with the outside world. This contains side effects to a very limited surface area
+- **Standard Library** with a complete set of arithmetic, comparison, logical, and higher-order combinators...I think (let me know if I'm missing anything)
+- **APL-style operations** with element-wise and immutable table operations so that you can use broadcasting instead of looping
+- **Function composition** with `compose`, `pipe`, and `via` operators, supporting a bunch of different ways to chain functions together
+- **Currying by default** - all functions are automatically curried
+- **Combinator-based architecture** everything is "just" a function call or reference under the hood...because this supposedly made parsing easier...but I'm not yet totally sold on that reasoning
 
-### Example Script
+## Example Script
 ```plaintext
-// Basic arithmetic
+/* Basic arithmetic */
 result : 5 + 3 * 2;
 ..out result;
 
-// Function definition
+/* Function definition */
 factorial : n -> 
   when n is
     0 then 1
     _ then n * (factorial (n - 1));
 
-// Pattern matching
+/* Function composition */
+double : x -> x * 2;
+increment : x -> x + 1;
+composed : compose @double @increment 5;
+..out composed;
+
+/* Pattern matching */
 classify : x y -> 
   when x y is
     0 0 then "both zero"
@@ -45,40 +53,37 @@ classify : x y ->
     _ 0 then "y is zero"
     _ _ then "neither zero";
 
-// Tables
-person : {name: "Alice", age: 30, active: true};
+/* Tables */
+person : {name: "Baba Yaga", age: 99, active: true};
 ..out person.name;
 ..out person["age"];
 
-// Function composition
-double : x -> x * 2;
-increment : x -> x + 1;
-composed : compose @double @increment 5;
-..out composed;  // Output: 12
-
-// Table enhancements
 numbers : {1, 2, 3, 4, 5};
 doubled : map @double numbers;
-..out doubled[1];  // Output: 2
+..out doubled[1]; 
 
-// APL-style element-wise operations
+/* APL-style element-wise operations over tables */
 table1 : {a: 1, b: 2, c: 3};
 table2 : {a: 10, b: 20, c: 30};
 sum : each @add table1 table2;
-..out sum.a;  // Output: 11
+..out sum.a;
 ```
 
+Baba Yaga files should use either the `.txt` file extension, or the `.baba` extension.
+
 ## Key Features
 
 ### Function Application
-Functions are applied using juxtaposition (space-separated):
+
+Functions are applied using juxtaposition (space-separated), and you can use parentheses to help disambiguate precedence: 
 ```plaintext
-f x          // Apply function f to argument x
-f x y        // Apply f to x, then apply result to y
-f (g x)      // Apply g to x, then apply f to result
+f x          /* Apply function f to argument x */
+f x y        /* Apply f to x, then apply result to y */
+f (g x)      /* Apply g to x, then apply f to result */
 ```
 
 ### Pattern Matching
+
 Use `when` expressions for pattern matching:
 ```plaintext
 result : when value is
@@ -88,20 +93,22 @@ result : when value is
 ```
 
 ### Tables
+
 Create and access data structures:
 ```plaintext
-// Array-like
+/* Array-like */
 numbers : {1, 2, 3, 4, 5};
 
-// Key-value pairs
-person : {name: "Alice", age: 30, active: true};
+/* Key-value pairs */
+person : {name: "Beatrice", age: 26};
 
-// Boolean keys
+/* Boolean keys */
 flags : {true: "enabled", false: "disabled"};
 ```
 
 ### Function References
-Use `@` to reference functions:
+
+Use the `@` to make reference to functions as arguments for other functions: 
 ```plaintext
 numbers : {1, 2, 3, 4, 5};
 doubled : map @double numbers;
@@ -109,27 +116,32 @@ doubled : map @double numbers;
 
 ## Combinators and Higher-Order Functions
 
-The language provides a comprehensive set of combinators for functional programming:
+Baba Yaga tries to provide a comprehensive set of combinators for functional programming:
 
 ### Core Combinators
-- **`map(f, x)`** - Transform elements in collections
-- **`filter(p, x)`** - Select elements based on predicates  
-- **`reduce(f, init, x)`** - Accumulate values into a single result
-- **`each(f, x)`** - Multi-argument element-wise operations
+
+- `map f x` - Transform elements in collections
+- `filter p x` - Select elements based on predicates  
+- `reduce f init x` - Accumulate values into a single result
+- `each f x` - Multi-argument element-wise operations
 
 ### Function Composition
-- **`compose(f, g)`** - Right-to-left composition (mathematical style)
-- **`pipe(f, g)`** - Left-to-right composition (pipeline style)
-- **`via` operator** - Natural composition syntax: `f via g via h`
 
-### Table Operations (`t.` namespace)
-- **`t.map`**, **`t.filter`**, **`t.set`**, **`t.delete`**, **`t.merge`**, **`t.get`**, **`t.has`**, **`t.length`**
-- All operations are immutable and return new tables
+- `compose f g` - Right-to-left composition (mathematical style)
+- `pipe f g` - Left-to-right composition (pipeline style)
+- `via` - Kinda like `.` composition syntax: `f via g via h`
+
+### Table Operations
+
+All table operations are immutable so they return new tables. 
+
+- `t.map`, `t.filter`, `t.set`, `t.delete`, `t.merge`, `t.get`, `t.has`, `t.length`
 
 ### When to Use Which Combinator
-- **`map` vs `t.map`**: Use `map` for general collections, `t.map` to emphasize table operations
-- **`each` vs `map`**: Use `each` for multi-argument operations, `map` for single-table transformations
-- **`compose` vs `pipe`**: Use `compose` for mathematical notation, `pipe` for pipeline notation
+
+- Use `map` for general collections, `t.map` to emphasize table operations
+- Use `map` for single-table transformations, `each` for combining multiple collections.
+
 
 ### Standard Library
 
@@ -142,84 +154,41 @@ The language includes a comprehensive standard library:
 **Enhanced**: `identity`, `constant`, `flip`, `on`, `both`, `either`  
 **Table Operations**: `t.map`, `t.filter`, `t.set`, `t.delete`, `t.merge`, `t.get`, `t.has`, `t.length`
 
-## Key Language Takeaways
-
-- **Function application with negative arguments requires parentheses:**
-  - Example: `f (-5)` applies `f` to `-5`.
-- **Infix minus (`-`) is always parsed as subtraction:**
-  - Example: `3 - 4` is parsed as `subtract(3, 4)`.
-- **Ambiguous syntax like `f -5` is not supported:**
-  - Use parentheses for negative arguments in function application.
-- **Table operations are immutable:**
-  - All `t.` namespace operations return new tables, never modify existing ones.
-- **`each` is for multi-argument operations:**
-  - Use `map` for single-table transformations, `each` for combining multiple collections.
-
-These rules ensure that function application and infix operators are unambiguous and match functional language conventions.
-
 ## Architecture
 
-The language uses a combinator-based architecture where all operations are translated to function calls:
+Baba Yaga uses a combinator-based architecture where all operations are translated to function calls:
 
 1. **Lexer**: Converts source code into tokens
 2. **Parser**: Translates tokens into AST, converting operators to combinator calls
 3. **Interpreter**: Executes combinator functions from the standard library
 
-This approach eliminates parsing ambiguity while preserving syntax and enabling powerful functional programming patterns.
+The idea behind this approach is that it should eliminate parsing ambiguity while preserving syntax and enabling functional programming patterns like currying and composition, but the implementation is likely a little bit janky.
 
 ## Testing
 
-Run the complete test suite:
+Run the complete test suite!
 ```bash
 ./run_tests.sh
 ```
 
-All 24 tests should pass, covering:
-- Basic lexer and parser functionality
-- Arithmetic and comparison operations
-- Function definitions and calls
-- Pattern matching and case expressions
-- Table literals and access
-- Standard library functions
-- Error handling and edge cases
-- Table enhancements and combinators
-- Integration tests
-
-## Documentation
-
-- **[tutorials/Introduction.md](tutorials/Introduction.md)** - Learn how to use the language
-- **[tutorials/Combinators_Deep_Dive.md](tutorials/Combinators_Deep_Dive.md)** - Advanced combinator patterns and problem-solving
-- **[design/ARCHITECTURE.md](design/ARCHITECTURE.md)** - Detailed architecture overview
-- **[design/README.md](design/README.md)** - Design principles and patterns
-- **[design/HISTORY/](design/HISTORY/)** - Implementation journey and decisions
-
-## Development
-
-### Project Structure
-```
-scripting-lang/
-├── lang.js          # Main interpreter and standard library
-├── lexer.js         # Lexical analysis
-├── parser.js        # Parsing and AST generation
-├── tests/           # Test files (.txt format)
-├── design/          # Architecture and design documentation
-│   ├── ARCHITECTURE.md
-│   ├── README.md
-│   └── HISTORY/     # Historical implementation records
-└── docs/            # Generated documentation
-```
+This assumes you are using bun, but I've also tested extensively with both node and the browser, too. I haven't validated it, yet, but I think Baba Yaga should work with quickjs, too.
 
 ### Debug Mode
-Enable debug output for development:
+
+Enable debug output for development using the flag `DEBUG=1` or `DEBUG=2`:
 ```bash
 DEBUG=1 node lang.js your-script.txt
 ```
 
+This'll output a lot of debug info, including the AST (as JSON). 
+
 ### Adding Features
-The language is designed to be extensible. To add new features:
 
-1. **Add tokens** in `lexer.js`
-2. **Add parsing logic** in `parser.js`
-3. **Add evaluation logic** in `lang.js`
-4. **Add tests** in `tests/`
-5. **Update documentation**
\ No newline at end of file
+If you wanna add language features, the easiest way to do it is to see if you can implement them in Baba Yaga script, if you need to get into the guts of the thing, though, you wanna follow this pattern, 
+
+1. Add tests in `tests/`
+2. Add tokens in `lexer.js`
+3. Add parsing logic in `parser.js`
+4. Add evaluation logic in `lang.js`
+5. Validate against the tests you added earlier
+6. Update documentation
\ No newline at end of file