about summary refs log tree commit diff stats
path: root/js/baba-yaga/scratch/baba/with.baba
diff options
context:
space:
mode:
Diffstat (limited to 'js/baba-yaga/scratch/baba/with.baba')
-rw-r--r--js/baba-yaga/scratch/baba/with.baba217
1 files changed, 217 insertions, 0 deletions
diff --git a/js/baba-yaga/scratch/baba/with.baba b/js/baba-yaga/scratch/baba/with.baba
new file mode 100644
index 0000000..05de150
--- /dev/null
+++ b/js/baba-yaga/scratch/baba/with.baba
@@ -0,0 +1,217 @@
+// with.baba — Dev playground and implementation plan for header `with` locals
+//
+// This file documents the proposed `with` and `with rec` header clauses for
+// local bindings inside function bodies. It contains:
+// - Syntax and semantics
+// - Typing rules (locals treated like globals)
+// - Semicolon policy
+// - Examples (untyped, typed, shadowing, with `when`, mutual recursion)
+// - Error cases
+// - Implementation plan (lexer, parser, interpreter, tests)
+//
+// NOTE: All examples are commented out so this file remains parseable until the
+// feature is implemented.
+
+// -----------------------------------------------------------------------------
+// Syntax
+//
+// Function declaration (untyped params):
+//   name : params -> with ( headerEntries ) -> body;
+//
+// Function declaration (typed params + return type):
+//   name : (x: T, y: U) -> R -> with ( headerEntries ) -> body;
+//
+// Header entries inside `with ( ... )` are separated by semicolons `;` and may
+// end with an optional trailing semicolon.
+// Each entry is either:
+//   - Type declaration (same style as global):
+//       ident Type;
+//   - Assignment (value):
+//       ident : expression;
+//
+// Mutually recursive locals use `with rec` (or `with recursion`) to pre-bind:
+//   name : args -> ...
+//     with rec (
+//       f : a -> ... g ...;
+//       g : b -> ... f ...;
+//     ) ->
+//       body;
+//
+// Soft keywords:
+// - `with` and `rec` are recognized only in the function-header position
+//   (immediately after an arrow). Elsewhere they remain plain identifiers.
+
+// -----------------------------------------------------------------------------
+// Semantics
+//
+// with (non-rec):
+// - Create an inner scope layered over the function call scope.
+// - Process header entries left-to-right:
+//   - Type decl: record `name -> Type` in the with-scope types map.
+//   - Assignment: evaluate expression in the current with-scope, then
+//     if a type was declared for `name`, validate using the existing runtime
+//     type lattice (Int ⊂ Float ⊂ Number). Bind `name` to the result.
+// - Evaluate `body` in that inner scope; discard the scope after.
+// - No forward references among assignments.
+// - Shadowing permitted (locals shadow params/globals).
+//
+// with rec (mutual recursion):
+// - Pre-bind all names in the header to placeholders in the with-scope.
+// - Evaluate each RHS in order and assign into the same with-scope.
+// - Restrict RHS to functions (to avoid non-lazy cycles). If non-function is
+//   assigned under `rec`, throw a clear error.
+// - Body executes after all bindings are assigned.
+
+// -----------------------------------------------------------------------------
+// Semicolons
+// - Inside `with ( ... )`: semicolons separate entries; trailing `;` allowed.
+// - Between header and body: only the arrow `->`.
+// - After `body`: same as today at top-level (semicolon optional/tolerated).
+
+// -----------------------------------------------------------------------------
+// Executable Examples
+
+// 1) Basic locals (untyped)
+addMul : x y ->
+  with (inc : x + 1; prod : inc * y;) ->
+    inc + prod;
+addMulResult : addMul 2 5;
+
+// 2) Quadratic roots (untyped)
+quadraticRoots : a b c ->
+  with (
+    disc : b * b - 4 * a * c;
+    sqrtDisc : math.sqrt disc;
+    denom : 2 * a;
+  ) ->
+    { r1: (-b + sqrtDisc) / denom, r2: (-b - sqrtDisc) / denom };
+roots : quadraticRoots 1 -3 2;
+
+// 3) Typed params + typed locals (global-like declarations inside header)
+sumNext : (x: Int, y: Int) -> Int ->
+  with (
+    nextX Int; nextY Int;
+    nextX : x + 1;
+    nextY : y + 1;
+  ) ->
+    nextX + nextY;
+sumNextResult : sumNext 2 3;
+
+// 4) Shadowing and ordering
+shadow : x ->
+  with (x : x + 1; y : x * 2) ->
+    x + y;
+shadowResult : shadow 3;
+
+// 5) With + when
+classify : n ->
+  with (
+    lo Int; hi Int;
+    lo : 10; hi : 100;
+  ) ->
+    when n is
+      0 then "zero"
+      _ then when (n > hi) is
+               true then "large"
+               _    then when (n > lo) is
+                          true then "medium"
+                          _    then "small";
+classify0 : classify 0;
+classify50 : classify 50;
+classify200 : classify 200;
+
+// Multi-discriminant with local
+bucket : x y ->
+  with (t : x + y) ->
+    when x t is
+      0 0 then "origin"
+      _ _ then "other";
+bucketResult : bucket 0 0;
+
+// 6) Result + with + when
+safeDivide : x y ->
+  with (zero : 0) ->
+    when y is
+      0 then Err "Division by zero"
+      _ then Ok (x / y);
+
+useDivide : a b ->
+  with (fallback Int; fallback : 0) ->
+    when (safeDivide a b) is
+      Ok v  then v
+      Err _ then fallback;
+divOk : useDivide 10 2;
+divErr : useDivide 10 0;
+
+// 7) with rec — mutual recursion among locals
+isEvenOdd : z ->
+  with rec (
+    isEven : n ->
+      when n is
+        0 then true
+        _ then isOdd (n - 1);
+    isOdd : n ->
+      when n is
+        0 then false
+        _ then isEven (n - 1);
+  ) ->
+    { even: isEven 10, odd: isOdd 7 };
+rEvenOdd : isEvenOdd 0;
+
+// Sample I/O to visualize outputs when running this file directly
+io.out addMulResult;
+io.out roots;
+io.out sumNextResult;
+io.out shadowResult;
+io.out classify0 classify50 classify200;
+io.out bucketResult;
+io.out divOk divErr;
+io.out rEvenOdd;
+
+// -----------------------------------------------------------------------------
+// Error cases (intended)
+// - Non-rec forward reference among assignments in `with`: error.
+// - In `with rec`, assignment RHS must evaluate to a function: error otherwise.
+// - Type mismatch for a typed local: reuse existing error messaging similar to
+//   function parameter/return mismatches.
+
+// -----------------------------------------------------------------------------
+// Implementation plan
+// 1) Lexer (none/minimal):
+//    - Keep `with` / `rec` as IDENTIFIER tokens; treat as soft keywords in parser.
+//
+// 2) Parser (parser.js):
+//    - After params and optional return type, detect: IDENT('with') [IDENT('rec'|'recursion')] LPAREN ... RPAREN ARROW
+//    - Parse header entries list:
+//        entry := IDENT TYPE ';'  |  IDENT ':' expression ';'
+//        allow repeated entries and optional trailing ';'
+//    - AST: augment FunctionDeclaration/CurriedFunctionDeclaration body with optional
+//      WithHeader { recursive: boolean, entries: Array< TypeDecl | Assign > }
+//      where TypeDecl { name, typeAnnotation }, Assign { name, expr }
+//    - Ensure support both in top-level function and nested curried bodies.
+//
+// 3) Interpreter (interpreter.js):
+//    - When invoking a function with WithHeader:
+//        - Create with-scope Map layered over call-scope; maintain withTypes Map.
+//        - If recursive:
+//            - Pre-bind all names to undefined in with-scope.
+//            - Evaluate each Assign RHS with with-scope in effect; verify RHS is Function; set binding.
+//          Else:
+//            - Process entries left-to-right: on TypeDecl store in withTypes; on Assign evaluate and bind.
+//        - On each Assign, if a type exists in withTypes, validate via existing lattice.
+//        - Evaluate body in with-scope; finally restore original scope.
+//
+// 4) Tests (tests/*.test.js):
+//    - parser-with-header.test.js (new): parsing of with/with rec, typed locals, trailing semicolon, shadowing, disallow forward refs.
+//    - interpreter-with-header.test.js (new):
+//        * Basic untyped locals
+//        * Typed locals pass and fail
+//        * With + when interactions
+//        * Shadowing behavior
+//        * with rec mutual recursion (success), non-function RHS (error)
+//    - Back-compat pass: ensure existing tests still green.
+//
+// 5) Docs:
+//    - Update README and ref.txt with the new form, semicolon policy, and examples.
+
+