diff options
Diffstat (limited to 'js/baba-yaga/scratch/baba')
32 files changed, 2554 insertions, 0 deletions
diff --git a/js/baba-yaga/scratch/baba/compatibility-test.baba b/js/baba-yaga/scratch/baba/compatibility-test.baba new file mode 100644 index 0000000..4b13231 --- /dev/null +++ b/js/baba-yaga/scratch/baba/compatibility-test.baba @@ -0,0 +1,30 @@ +// Compatibility test between optimized and legacy engines + +// Test variable names with underscores and numbers +var_with_underscore : 42; +var123 : 123; +test_var_2 : "hello"; + +// Test complex expressions +result1 : var_with_underscore + var123; +result2 : when (result1 > 100) is true then "big" _ then "small"; + +// Test function definitions +testFunc : a b -> a * b + var123; +funcResult : testFunc 5 6; + +// Test nested when expressions +nested : when (funcResult > 150) is + true then when (var123 = 123) is true then "both true" _ then "first true" + _ then "first false"; + +// Output results +io.out "Compatibility Test Results:"; +io.out "var_with_underscore:"; io.out var_with_underscore; +io.out "var123:"; io.out var123; +io.out "test_var_2:"; io.out test_var_2; +io.out "result1:"; io.out result1; +io.out "result2:"; io.out result2; +io.out "funcResult:"; io.out funcResult; +io.out "nested:"; io.out nested; +io.out "Test complete!"; diff --git a/js/baba-yaga/scratch/baba/conway-simple.baba b/js/baba-yaga/scratch/baba/conway-simple.baba new file mode 100644 index 0000000..1054106 --- /dev/null +++ b/js/baba-yaga/scratch/baba/conway-simple.baba @@ -0,0 +1,116 @@ +// Conway's Game of Life - Simple Working Version + +// Get element at index from list (safe) +at : xs i -> + when (i >= 0 and i < length xs) is + true then slice xs i (i + 1).0 + _ then 0; + +// Get 2D element from grid (safe) +get2d : grid row col -> + when (row >= 0 and row < length grid and col >= 0) is + true then + with (rowData : at grid row) -> + when (col < length rowData) is + true then at rowData col + _ then 0 + _ then 0; + +// Count living neighbors around position (row, col) +countNeighbors : grid row col -> + with ( + n1 : get2d grid (row - 1) (col - 1); + n2 : get2d grid (row - 1) col; + n3 : get2d grid (row - 1) (col + 1); + n4 : get2d grid row (col - 1); + n5 : get2d grid row (col + 1); + n6 : get2d grid (row + 1) (col - 1); + n7 : get2d grid (row + 1) col; + n8 : get2d grid (row + 1) (col + 1); + ) -> n1 + n2 + n3 + n4 + n5 + n6 + n7 + n8; + +// Apply Game of Life rules to a single cell +nextCellState : grid row col -> + with ( + current : get2d grid row col; + neighbors : countNeighbors grid row col; + ) -> + when current is + 1 then + when (neighbors = 2 or neighbors = 3) is + true then 1 + _ then 0 + _ then + when (neighbors = 3) is + true then 1 + _ then 0; + +// Generate next generation of the entire grid +nextGeneration : grid -> + with ( + height : length grid; + width : length (at grid 0); + // Create new grid row by row + newRow : rowIdx -> + with ( + newCol : colIdx -> nextCellState grid rowIdx colIdx; + cols : [0, 1, 2, 3, 4]; // Assuming 5x5 for now + ) -> map newCol cols; + rows : [0, 1, 2, 3, 4]; // Assuming 5x5 for now + ) -> map newRow rows; + +// Print a single row +printRow : row -> + with ( + cellToChar : cell -> when cell is 1 then "#" _ then "."; + chars : map cellToChar row; + ) -> io.out chars; + +// Print entire grid with title +printGrid : grid title -> + with ( + _ : io.out ""; + _ : io.out title; + _ : io.out "-----"; + _ : map printRow grid; + ) -> 0; // Return dummy value + +// Test patterns + +// Glider pattern (moves diagonally) +glider : [ + [0, 1, 0, 0, 0], + [0, 0, 1, 0, 0], + [1, 1, 1, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0] +]; + +// Blinker pattern (oscillates) +blinker : [ + [0, 0, 0, 0, 0], + [0, 1, 1, 1, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0] +]; + +// Run simulations +io.out "Conway's Game of Life"; +io.out "===================="; + +// Show initial glider +dummy1 : printGrid glider "Glider - Generation 0"; +g1 : nextGeneration glider; +dummy2 : printGrid g1 "Glider - Generation 1"; +g2 : nextGeneration g1; +dummy3 : printGrid g2 "Glider - Generation 2"; + +// Show blinker oscillation +dummy4 : printGrid blinker "Blinker - Generation 0"; +b1 : nextGeneration blinker; +dummy5 : printGrid b1 "Blinker - Generation 1"; +b2 : nextGeneration b1; +dummy6 : printGrid b2 "Blinker - Generation 2"; + +io.out "Done!"; diff --git a/js/baba-yaga/scratch/baba/conway-test.baba b/js/baba-yaga/scratch/baba/conway-test.baba new file mode 100644 index 0000000..ef8be99 --- /dev/null +++ b/js/baba-yaga/scratch/baba/conway-test.baba @@ -0,0 +1,16 @@ +// Simple Game of Life test + +// Safe array access +at : xs i -> + when (i >= 0 and i < length xs) is + true then slice xs i (i + 1).0 + _ then 0; + +// Test pattern +pattern : [[0, 1, 0], [0, 0, 1], [1, 1, 1]]; + +io.out "Testing:"; +io.out pattern; +io.out "Cell at (1,1):"; +io.out (at (at pattern 1) 1); +io.out "Done!"; diff --git a/js/baba-yaga/scratch/baba/conway-working.baba b/js/baba-yaga/scratch/baba/conway-working.baba new file mode 100644 index 0000000..e010e96 --- /dev/null +++ b/js/baba-yaga/scratch/baba/conway-working.baba @@ -0,0 +1,120 @@ +// Conway's Game of Life - Minimal Working Version + +// Safe array access +at : xs i -> + when (i >= 0 and i < length xs) is + true then slice xs i (i + 1).0 + _ then 0; + +// Safe 2D grid access +get2d : grid row col -> + when (row >= 0 and row < length grid) is + true then at (at grid row) col + _ then 0; + +// Count living neighbors +countNeighbors : grid row col -> + (get2d grid (row - 1) (col - 1)) + + (get2d grid (row - 1) col) + + (get2d grid (row - 1) (col + 1)) + + (get2d grid row (col - 1)) + + (get2d grid row (col + 1)) + + (get2d grid (row + 1) (col - 1)) + + (get2d grid (row + 1) col) + + (get2d grid (row + 1) (col + 1)); + +// Apply Game of Life rules +nextCell : grid row col -> + with ( + current : get2d grid row col; + neighbors : countNeighbors grid row col; + ) -> + when current is + 1 then when (neighbors = 2 or neighbors = 3) is true then 1 _ then 0 + _ then when (neighbors = 3) is true then 1 _ then 0; + +// Generate next generation (hardcoded for 5x5) +nextGeneration : grid -> [ + [ + nextCell grid 0 0, + nextCell grid 0 1, + nextCell grid 0 2, + nextCell grid 0 3, + nextCell grid 0 4 + ], + [ + nextCell grid 1 0, + nextCell grid 1 1, + nextCell grid 1 2, + nextCell grid 1 3, + nextCell grid 1 4 + ], + [ + nextCell grid 2 0, + nextCell grid 2 1, + nextCell grid 2 2, + nextCell grid 2 3, + nextCell grid 2 4 + ], + [ + nextCell grid 3 0, + nextCell grid 3 1, + nextCell grid 3 2, + nextCell grid 3 3, + nextCell grid 3 4 + ], + [ + nextCell grid 4 0, + nextCell grid 4 1, + nextCell grid 4 2, + nextCell grid 4 3, + nextCell grid 4 4 + ] +]; + +// Test patterns +glider : [ + [0, 1, 0, 0, 0], + [0, 0, 1, 0, 0], + [1, 1, 1, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0] +]; + +blinker : [ + [0, 0, 0, 0, 0], + [0, 1, 1, 1, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0] +]; + +// Run simulation +io.out "Conway's Game of Life"; +io.out "===================="; + +io.out "Glider - Generation 0:"; +io.out glider; + +g1 : nextGeneration glider; +io.out "Glider - Generation 1:"; +io.out g1; + +g2 : nextGeneration g1; +io.out "Glider - Generation 2:"; +io.out g2; + +io.out ""; +io.out "Blinker - Generation 0:"; +io.out blinker; + +b1 : nextGeneration blinker; +io.out "Blinker - Generation 1:"; +io.out b1; + +b2 : nextGeneration b1; +io.out "Blinker - Generation 2:"; +io.out b2; + +io.out ""; +io.out "Simulation complete!"; diff --git a/js/baba-yaga/scratch/baba/conway.baba b/js/baba-yaga/scratch/baba/conway.baba new file mode 100644 index 0000000..a8811a7 --- /dev/null +++ b/js/baba-yaga/scratch/baba/conway.baba @@ -0,0 +1,126 @@ +// Conway's Game of Life in Baba Yaga +// Clean, working implementation + +// Get element at index from list (with bounds checking) +at : xs i -> + when (i >= 0 and i < length xs) is + true then slice xs i (i + 1).0 + _ then 0; + +// Get 2D element from grid +get2d : grid row col -> + when (row >= 0 and row < length grid) is + true then at (at grid row) col + _ then 0; + +// Create range of integers [start, end) +range : start end -> + when (start >= end) is + true then [] + _ then prepend start (range (start + 1) end); + +// Sum a list of numbers +sum : xs -> reduce (acc x -> acc + x) 0 xs; + +// Count living neighbors around position (row, col) +countNeighbors : grid row col -> + with ( + // Get all 8 neighbor positions + neighbors : [ + get2d grid (row - 1) (col - 1), + get2d grid (row - 1) col, + get2d grid (row - 1) (col + 1), + get2d grid row (col - 1), + get2d grid row (col + 1), + get2d grid (row + 1) (col - 1), + get2d grid (row + 1) col, + get2d grid (row + 1) (col + 1) + ]; + ) -> sum neighbors; + +// Apply Game of Life rules to a single cell +nextCellState : grid row col -> + with ( + current : get2d grid row col; + neighbors : countNeighbors grid row col; + isAlive : current = 1; + ) -> + when isAlive is + true then + when (neighbors = 2 or neighbors = 3) is + true then 1 + _ then 0 + _ then + when (neighbors = 3) is + true then 1 + _ then 0; + +// Generate next row for the grid +nextRow : grid rowIndex width -> + map (col -> nextCellState grid rowIndex col) (range 0 width); + +// Generate next generation of the entire grid +nextGeneration : grid -> + with ( + height : length grid; + width : length (at grid 0); + ) -> + map (row -> nextRow grid row width) (range 0 height); + +// Pretty print a grid +printGrid : grid title -> + with ( + printRow : row -> io.out (map (cell -> when cell is 1 then "#" _ then ".") row); + ) -> with ( + _ : io.out ""; + _ : io.out title; + _ : io.out (map (_ -> "-") (range 0 20)); + _ : map printRow grid; + _ : io.out ""; + ) -> grid; + +// Test patterns + +// Glider pattern (moves diagonally) +glider : [ + [0, 1, 0, 0, 0], + [0, 0, 1, 0, 0], + [1, 1, 1, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0] +]; + +// Blinker pattern (oscillates) +blinker : [ + [0, 0, 0], + [1, 1, 1], + [0, 0, 0] +]; + +// Block pattern (still life) +block : [ + [1, 1], + [1, 1] +]; + +// Run simulations +io.out "Conway's Game of Life in Baba Yaga"; +io.out "===================================="; + +// Glider evolution +g0 : printGrid glider "Glider - Generation 0"; +g1 : printGrid (nextGeneration g0) "Glider - Generation 1"; +g2 : printGrid (nextGeneration g1) "Glider - Generation 2"; +g3 : printGrid (nextGeneration g2) "Glider - Generation 3"; +g4 : printGrid (nextGeneration g3) "Glider - Generation 4"; + +// Blinker oscillation +b0 : printGrid blinker "Blinker - Generation 0"; +b1 : printGrid (nextGeneration b0) "Blinker - Generation 1"; +b2 : printGrid (nextGeneration b1) "Blinker - Generation 2"; + +// Block (should stay the same) +bl0 : printGrid block "Block - Generation 0"; +bl1 : printGrid (nextGeneration bl0) "Block - Generation 1"; + +io.out "Simulation complete!"; diff --git a/js/baba-yaga/scratch/baba/crash-course-code.baba b/js/baba-yaga/scratch/baba/crash-course-code.baba new file mode 100644 index 0000000..bae2810 --- /dev/null +++ b/js/baba-yaga/scratch/baba/crash-course-code.baba @@ -0,0 +1,240 @@ +// Baba Yaga in Y Minutes + +// Test 1: Basic with examples +testBasicWith : x y -> + with (inc : x + 1; prod : inc * y;) -> inc + prod; + +testTypedWith : x y -> + with (nx Int; ny Int; nx : x + 1; ny : y + 1;) -> nx + ny; + +// Test 2: with rec examples +testEvenOdd : 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 z, odd: isOdd z}; + +// Test 3: Computed intermediate values +testQuadraticRoots : a b c -> + with ( + discriminant : b * b - 4 * a * c; + sqrtDisc : math.sqrt discriminant; + denominator : 2 * a; + ) -> + { + r1: (-b + sqrtDisc) / denominator, + r2: (-b - sqrtDisc) / denominator + }; + +// Test 4: Complex calculations with named steps +testCalculateTax : income deductions -> + with ( + taxableIncome : income - deductions; + taxRate : when (taxableIncome <= 50000) is + true then 0.15 + _ then when (taxableIncome <= 100000) is + true then 0.25 + _ then 0.35; + baseTax : taxableIncome * taxRate; + finalTax : when (baseTax < 1000) is true then 1000 _ then baseTax; + ) -> + finalTax; + +// Test 5: Data transformation pipelines +testProcessUserData : user -> + with ( + normalizedName : str.upper (str.trim user.name); + ageGroup : when (user.age < 18) is + true then "minor" + _ then when (user.age < 65) is + true then "adult" + _ then "senior"; + status : when user.active is + true then "active" + _ then "inactive"; + ) -> + { + id: user.id, + displayName: normalizedName, + category: ageGroup, + status: status + }; + +// Test 6: Error handling with multiple validations +testValidateOrder : order -> + with ( + hasItems : (length order.items) > 0; + hasValidTotal : order.total > 0; + allValid : hasItems and hasValidTotal; + ) -> + when allValid is + true then Ok order + _ then Err "Order validation failed"; + +// Test 7: Complex pattern matching with computed values +testClassifyTriangle : a b c -> + with ( + sorted : [math.min a b, math.max a b, math.max (math.max a b) c]; + side1 : sorted.0; + side2 : sorted.1; + side3 : sorted.2; + isValid : ((side1 + side2) > side3); + isEquilateral : ((a = b) and (b = c)); + isIsosceles : ((a = b) or (b = c) or (a = c)); + isRight : (math.abs ((side1 * side1 + side2 * side2) - (side3 * side3))) < 0.001; + ) -> + when isValid is + false then "Invalid triangle" + _ then when isEquilateral is + true then "Equilateral" + _ then when isIsosceles is + true then when isRight is + true then "Right isosceles" + _ then "Isosceles" + _ then when isRight is + true then "Right scalene" + _ then "Scalene"; + +// Test 8: Tree operations with with rec +testTreeOperations : tree -> + with rec ( + // Count total nodes + countNodes : t -> + when ((length (keys t)) = 0) is + true then 0 + _ then 1 + (countNodes t.left) + (countNodes t.right); + + // Calculate tree height + treeHeight : t -> + when ((length (keys t)) = 0) is + true then 0 + _ then 1 + (math.max (treeHeight t.left) (treeHeight t.right)); + + // Check if tree is balanced + isBalanced : t -> + when ((length (keys t)) = 0) is + true then true + _ then + (((math.abs ((treeHeight t.left) - (treeHeight t.right))) <= 1) and + (isBalanced t.left) and + (isBalanced t.right)); + ) -> + { + nodeCount: countNodes tree, + height: treeHeight tree, + balanced: isBalanced tree + }; + +// Test 9: State machine with recursive state transitions +testTrafficLight : initialState -> + with rec ( + // State transition function + nextState : current -> + when current is + "red" then "green" + "green" then "yellow" + _ then "red"; + + // Count transitions until back to start + countCycles : start current count -> + when (current = start) is + true then count + _ then countCycles start (nextState current) (count + 1); + + // Get state after N transitions + stateAfter : current n -> + when n is + 0 then current + _ then stateAfter (nextState current) (n - 1); + ) -> + { + cycles: countCycles initialState initialState 0, + after10: stateAfter initialState 10, + next: nextState initialState + }; + +// Test 10: Combinatorial functions with shared helpers +testCombinatorics : n r -> + with rec ( + // Factorial function + factorial : k -> + when k is + 0 then 1 + 1 then 1 + _ then k * (factorial (k - 1)); + + // Permutation: P(n,r) = n! / (n-r)! + permutation : n r -> + (factorial n) / (factorial (n - r)); + + // Combination: C(n,r) = n! / (r! * (n-r)!) + combination : n r -> + (factorial n) / ((factorial r) * (factorial (n - r))); + ) -> + { + n: n, + r: r, + permutations: permutation n r, + combinations: combination n r + }; + +// Test 11: Best practices examples +testProcessData : data -> + with ( + cleaned : str.trim data; + normalized : str.lower cleaned; + validated : (length normalized) > 0; + ) -> + when validated is + true then Ok normalized + _ then Err "Empty data"; + +// Test 12: Validation examples +testValidateUserBasic : user -> + with ( + nameValid : (length user.name) > 0; + emailValid : (str.length user.email) > 0; // Simplified validation + ageValid : (user.age >= 0) and (user.age <= 150); + ) -> + (nameValid and emailValid and ageValid); + +testValidateUserContact : user -> + with ( + phoneValid : (length user.phone) >= 10; + ) -> + phoneValid; + +testProcessUser : user -> + when ((testValidateUserBasic user) and (testValidateUserContact user)) is + true then Ok user + _ then Err "Validation failed"; + +// Execute tests +result1 : testBasicWith 2 5; +result2 : testTypedWith 3 4; +result3 : testEvenOdd 10; +result4 : testQuadraticRoots 1 -5 6; +result5 : testCalculateTax 75000 10000; +result6 : testProcessUserData { id: 1, name: " john doe ", age: 25, active: true }; +result7 : testValidateOrder { items: [1, 2, 3], total: 100 }; +result8 : testClassifyTriangle 3 4 5; +result9 : testTreeOperations { left: { left: {}, right: {} }, right: {} }; +result10 : testTrafficLight "red"; +result11 : testCombinatorics 5 2; +result12 : testProcessData " Hello World "; +result13 : testProcessUser { name: "John", email: "john@example.com", age: 30, phone: "1234567890" }; + +// Output results +io.out result1; +io.out result2; +io.out result3; +io.out result4; +io.out result5; +io.out result6; +io.out result7; +io.out result8; +io.out result9; +io.out result10; +io.out result11; +io.out result12; +io.out result13; diff --git a/js/baba-yaga/scratch/baba/example.baba b/js/baba-yaga/scratch/baba/example.baba new file mode 100644 index 0000000..2311f86 --- /dev/null +++ b/js/baba-yaga/scratch/baba/example.baba @@ -0,0 +1,269 @@ +// This file demonstrates all features of Baba Yaga. + +// 1. Comments +// Single-line comments start with `//`. +myVar : 10; // Comments can also be at the end of a line. + +// 2. Types +// The language supports Int, Float, String, and Result types. +myInt : 10; // Inferred as Int +myFloat : 3.14; // Inferred as Float +myString : "Baba Yaga"; // Inferred as String + +// Type declarations are optional but enforced if provided. +myExplicitInt Int; +myExplicitInt : 20; + +myExplicitString String; +myExplicitString : "Explicitly typed string."; + +// Explicit List and Table type declarations +myExplicitList List; +myExplicitList : [1 2 3 4 5]; + +myExplicitTable Table; +myExplicitTable : { name: "John" age: 25 city: "New York" }; + +// 3. Variable and Type Declarations +// Variables are declared using an identifier followed by a colon and their value. +// Example: myVariable : value; + +// 4. Functions (Anonymous, Currying, Partial Application) + +// A simple anonymous function (x -> x + 1) +addOne : x -> x + 1; +resultAddOne : addOne 5; // resultAddOne will be 6 +io.out resultAddOne; + +// A curried function with type annotations +multiply : (x: Float) -> (Float -> Float) -> y -> x * y; +// The type signature here breaks down like: +// 1. (x: Float) - First parameter is a Float called x +// 2. -> - Returns... +// 3. (Float -> Float) - A function that takes a Float and returns a Float +// 4. -> y -> x * y - The implementation: take y, multiply x by y + +// Partial application: create a new function by applying some arguments +multiplyByTwo : multiply 2.0; +resultMultiply : multiplyByTwo 7.0; // resultMultiply will be 14.0 +io.out resultMultiply; + +// 5. Operators +// Arithmetic: +, -, *, /, % +// Comparison: =, >, <, >=, <= + +// Arithmetic operations +sum : 10 + 5; // 15 +difference : 10 - 5; // 5 +product : 10 * 5; // 50 +quotient : 10 / 5; // 2 +remainder : 10 % 3; // 1 + +io.out sum; +io.out difference; +io.out product; +io.out quotient; +io.out remainder; + +// Comparison operations +isEqual : 10 = 10; // true +isGreaterThan : 10 > 5; // true +isLessThan : 5 < 10; // true +isGreaterThanOrEqualTo : 10 >= 10; // true +isLessThanOrEqualTo : 5 <= 10; // true + +io.out isEqual; +io.out isGreaterThan; +io.out isLessThan; +io.out isGreaterThanOrEqualTo; +io.out isLessThanOrEqualTo; + +// 6. Control Flow: The `when` Expression + +// Literal Matching +checkNumber : num -> + when num is + 1 then "One" + 2 then "Two" + _ then "Something else"; // '_' matches any value + +resultCheckNumberOne : checkNumber 1; // "One" +resultCheckNumberThree : checkNumber 3; // "Something else" + +io.out resultCheckNumberOne; +io.out resultCheckNumberThree; + +// Multiple Discriminants +checkCoords : x y -> + when x y is + 0 0 then "Origin" + 1 1 then "Diagonal" + _ _ then "Somewhere else"; + +resultCheckCoordsOrigin : checkCoords 0 0; // "Origin" +resultCheckCoordsOther : checkCoords 5 10; // "Somewhere else" + +io.out resultCheckCoordsOrigin; +io.out resultCheckCoordsOther; + +// Type Matching +checkType : val -> + when val is + Bool then "It's a Boolean" + Int then "It's an Integer" + Float then "It's a Float" + String then "It's a String" + List then "It's a List" + Table then "It's a Table" + _ then "Unknown Type"; + +resultCheckTypeBool : checkType true; // "It's a Boolean" +resultCheckTypeInt : checkType 123; // "It's an Integer" +resultCheckTypeFloat : checkType 3.14; // "It's a Float" +resultCheckTypeString : checkType "abc"; // "It's a String" +resultCheckTypeList : checkType [1 2 3]; // "It's a List" +resultCheckTypeTable : checkType { name: "test" }; // "It's a Table" + +io.out resultCheckTypeBool; +io.out resultCheckTypeInt; +io.out resultCheckTypeFloat; +io.out resultCheckTypeString; +io.out resultCheckTypeList; +io.out resultCheckTypeTable; + +// List Pattern Matching +matchList : list -> + when list is + [1 2 3] then "Exact List Match" + [1 _ 3] then "List with Wildcard Match" + _ then "No List Match"; + +resultMatchListExact : matchList [1 2 3]; // "Exact List Match" +resultMatchListWildcard : matchList [1 99 3]; // "List with Wildcard Match" +resultMatchListNoMatch : matchList [4 5 6]; // "No List Match" + +io.out resultMatchListExact; +io.out resultMatchListWildcard; +io.out resultMatchListNoMatch; + +// Table Pattern Matching +matchTable : table -> + when table is + { name: "Alice" age: 30 } then "Exact Table Match" + { name: "Bob" age: _ } then "Table with Wildcard Value Match" + _ then "No Table Match"; + +resultMatchTableExact : matchTable { name: "Alice" age: 30 }; // "Exact Table Match" +resultMatchTableWildcardValue : matchTable { name: "Bob" age: 99 }; // "Table with Wildcard Value Match" +resultMatchTableNoMatch : matchTable { city: "New York" }; // "No Table Match" + +io.out resultMatchTableExact; +io.out resultMatchTableWildcardValue; +io.out resultMatchTableNoMatch; + +// 7. Error Handling: The `Result` Type + +// Function returning a Result type +divide : x y -> + when y is + 0 then Err "Division by zero is not allowed." + _ then Ok (x / y); + +resultDivideOk : divide 10 2; // Result: Ok 5 +resultDivideErr : divide 5 0; // Result: Err "Division by zero is not allowed." + +// Extracting values from Result types using 'when' +finalResultOk : when resultDivideOk is + Ok val then val // 'val' binds to the inner value of Ok (5) + Err msg then 0; // If error, return 0 + +finalResultErr : when resultDivideErr is + Ok val then 0 + Err msg then msg; // 'msg' binds to the inner value of Err ("Division by zero...") + +io.out finalResultOk; +io.out finalResultErr; + +// 8. Lists +myListExample : [10 20 30 "hello"]; + +// Accessing elements by index (0-based) +firstElement : myListExample.0; // 10 +secondElement : myListExample.1; // 20 + +io.out myListExample; +io.out firstElement; +io.out secondElement; + +// 9. Tables +myTableExample : { name: "Baba Yaga" version: 1.0 isActive: true }; + +// Accessing properties by key +userName : myTableExample.name; // "Baba Yaga" +userVersion : myTableExample.version; // 1.0 + +io.out myTableExample; +io.out userName; +io.out userVersion; + +// Function within a Table +myCalculator : { + add: x y -> x + y; + subtract: x y -> x - y; +}; + +resultTableAdd : myCalculator.add 10 5; // 15 +resultTableSubtract : myCalculator.subtract 10 5; // 5 + +io.out resultTableAdd; +io.out resultTableSubtract; + +// 10. Higher-Order Functions + +// map: Applies a function to each element of a list, returning a new list. +doubledList : map (x -> x * 2) [1 2 3]; // [2 4 6] +io.out doubledList; + +// filter: Creates a new list containing only elements for which a predicate returns true. +evenNumbers : filter (x -> x % 2 = 0) [1 2 3 4 5]; // [2 4] +io.out evenNumbers; + +// reduce: Applies a function against an accumulator and each element in the list to reduce it to a single value. +sumOfList : reduce (acc item -> acc + item) 0 [1 2 3 4]; // 10 +io.out sumOfList; + +// 11. Typed Functions with Type Enforcement + +// Typed function declarations with parameter and return type annotations +add : (x: Int, y: Int) -> Int -> x + y; +multiply : (x: Number, y: Number) -> Number -> x * y; +greet : (name: String) -> String -> str.concat "Hello " name; +fullName : (first: String, last: String) -> String -> first .. " " .. last; +isEven : (n: Int) -> Bool -> n % 2 = 0; +isPositive : (n: Int) -> Bool -> n > 0; + +// Test typed functions +io.out add 5 3; +io.out multiply 2.5 3.0; +io.out greet "World"; +io.out fullName "John" "Doe"; +io.out isEven 4; +io.out isEven 5; +io.out isPositive 10; +io.out isPositive -5; + +// 12. String Functions + +// Core string operations +io.out str.length "hello"; +io.out str.upper "hello world"; +io.out str.lower "HELLO WORLD"; +io.out str.split "hello,world,test" ","; +io.out str.join ["a" "b" "c"] "-"; +io.out str.trim " hello "; +io.out str.substring "hello world" 0 5; +io.out str.replace "hello hello" "hello" "hi"; + +// String concatenation with .. operator +message : "Hello" .. " " .. "World" .. "!"; +io.out message; diff --git a/js/baba-yaga/scratch/baba/functional-features-demo.baba b/js/baba-yaga/scratch/baba/functional-features-demo.baba new file mode 100644 index 0000000..c9cb12b --- /dev/null +++ b/js/baba-yaga/scratch/baba/functional-features-demo.baba @@ -0,0 +1,128 @@ +// Functional Programming Features Demo +// Testing all the new features we've implemented + +io.out "=== Testing New Functional Programming Features ==="; +io.out ""; + +// === Pattern Guards === +io.out "1. Pattern Guards:"; + +classifyNumber : n -> + when n is + 0 then "zero" + x if (x > 0) then "positive" + x if (x < 0) then "negative" + _ then "unknown"; + +result1 : classifyNumber 5; +result2 : classifyNumber -3; +result3 : classifyNumber 0; + +io.out ("5 is " .. result1); +io.out ("-3 is " .. result2); +io.out ("0 is " .. result3); +io.out ""; + +// === Scan Operations === +io.out "2. Scan Operations:"; + +numbers : [1, 2, 3, 4, 5]; +cumulative : cumsum numbers; +product : cumprod numbers; + +addFunc : acc x -> acc + x; +customScan : scan addFunc 10 numbers; + +io.out ("Numbers: " .. numbers); +io.out ("Cumulative sum: " .. cumulative); +io.out ("Cumulative product: " .. product); +io.out ("Custom scan from 10: " .. customScan); +io.out ""; + +// === Array Indexing === +io.out "3. Array Indexing:"; + +data : [10, 20, 30, 40, 50]; +indices : [0, 2, 4]; +selected : at indices data; + +evenPredicate : x -> x % 2 = 0; +evenIndices : where evenPredicate data; + +firstThree : take 3 data; +lastTwo : drop 3 data; + +io.out ("Data: " .. data); +io.out ("Selected at [0,2,4]: " .. selected); +io.out ("Even indices: " .. evenIndices); +io.out ("First 3: " .. firstThree); +io.out ("Last 2: " .. lastTwo); +io.out ""; + +// === Broadcasting === +io.out "4. Broadcasting Operations:"; + +values : [1, 2, 3, 4]; +addTen : broadcast (a b -> a + b) 10 values; + +array1 : [1, 2, 3]; +array2 : [4, 5, 6]; +multiplied : zipWith (a b -> a * b) array1 array2; + +flatData : [1, 2, 3, 4, 5, 6]; +matrix : reshape [2, 3] flatData; + +io.out ("Values: " .. values); +io.out ("Add 10 to each: " .. addTen); +io.out ("Array 1: " .. array1); +io.out ("Array 2: " .. array2); +io.out ("Element-wise multiply: " .. multiplied); +io.out "Reshaped matrix:"; +io.print matrix; +io.out ""; + +// === Function Combinators === +io.out "5. Function Combinators:"; + +addOp : x y -> x + y; +flippedAdd : flip addOp; +flipResult : flippedAdd 3 7; // 7 + 3 + +doubler : x -> x * 2; +applyResult : apply doubler 5; + +tripler : x -> x * 3; +pipeResult : pipe 4 tripler; + +increment : x -> x + 1; +composed : compose doubler increment; +composeResult : composed 5; // (5 + 1) * 2 + +io.out ("Flip add 3 7: " .. flipResult); +io.out ("Apply double to 5: " .. applyResult); +io.out ("Pipe 4 through triple: " .. pipeResult); +io.out ("Compose increment then double on 5: " .. composeResult); +io.out ""; + +// === FlatMap === +io.out "6. FlatMap Operations:"; + +duplicator : x -> [x, x]; +original : [1, 2, 3]; +duplicated : flatMap duplicator original; + +io.out ("Original: " .. original); +io.out ("Duplicated: " .. duplicated); +io.out ""; + +// === Summary === +io.out "=== Summary ==="; +io.out "All functional programming features working:"; +io.out "✓ Pattern Guards with conditional expressions"; +io.out "✓ Scan operations (scan, cumsum, cumprod)"; +io.out "✓ Array indexing (at, where, take, drop)"; +io.out "✓ Broadcasting (broadcast, zipWith, reshape)"; +io.out "✓ Function combinators (flip, apply, pipe, compose)"; +io.out "✓ Monadic operations (flatMap)"; +io.out ""; +io.out "Baba Yaga now has powerful functional programming capabilities!"; diff --git a/js/baba-yaga/scratch/baba/game-of-life.baba b/js/baba-yaga/scratch/baba/game-of-life.baba new file mode 100644 index 0000000..2721b3e --- /dev/null +++ b/js/baba-yaga/scratch/baba/game-of-life.baba @@ -0,0 +1,76 @@ +// Conway's Game of Life - Working Implementation + +// Count neighbors for a 3x3 grid (hardcoded positions) +countNeighbors : grid row col -> + when row is + 0 then when col is + 0 then grid.0.1 + grid.1.0 + grid.1.1 + 1 then grid.0.0 + grid.0.2 + grid.1.0 + grid.1.1 + grid.1.2 + 2 then grid.0.1 + grid.1.1 + grid.1.2 + _ then 0 + 1 then when col is + 0 then grid.0.0 + grid.0.1 + grid.1.1 + grid.2.0 + grid.2.1 + 1 then grid.0.0 + grid.0.1 + grid.0.2 + grid.1.0 + grid.1.2 + grid.2.0 + grid.2.1 + grid.2.2 + 2 then grid.0.1 + grid.0.2 + grid.1.1 + grid.2.1 + grid.2.2 + _ then 0 + 2 then when col is + 0 then grid.1.0 + grid.1.1 + grid.2.1 + 1 then grid.1.0 + grid.1.1 + grid.1.2 + grid.2.0 + grid.2.2 + 2 then grid.1.1 + grid.1.2 + grid.2.1 + _ then 0 + _ then 0; + +// Apply Game of Life rules +nextCell : grid row col -> + with ( + current : when row is + 0 then when col is 0 then grid.0.0 1 then grid.0.1 2 then grid.0.2 _ then 0 + 1 then when col is 0 then grid.1.0 1 then grid.1.1 2 then grid.1.2 _ then 0 + 2 then when col is 0 then grid.2.0 1 then grid.2.1 2 then grid.2.2 _ then 0 + _ then 0; + neighbors : countNeighbors grid row col; + ) -> + when current is + 1 then when (neighbors = 2 or neighbors = 3) is true then 1 _ then 0 + _ then when (neighbors = 3) is true then 1 _ then 0; + +// Generate next generation for 3x3 grid +step : grid -> { + 0: { + 0: nextCell grid 0 0, + 1: nextCell grid 0 1, + 2: nextCell grid 0 2 + }, + 1: { + 0: nextCell grid 1 0, + 1: nextCell grid 1 1, + 2: nextCell grid 1 2 + }, + 2: { + 0: nextCell grid 2 0, + 1: nextCell grid 2 1, + 2: nextCell grid 2 2 + } +}; + +// Blinker pattern (oscillator) +blinker : { + 0: { 0: 0, 1: 1, 2: 0 }, + 1: { 0: 0, 1: 1, 2: 0 }, + 2: { 0: 0, 1: 1, 2: 0 } +}; + +// Run simulation +io.out "Conway's Game of Life - Blinker Pattern"; +io.out "Generation 0:"; +io.out blinker; + +gen1 : step blinker; +io.out "Generation 1:"; +io.out gen1; + +gen2 : step gen1; +io.out "Generation 2:"; +io.out gen2; + +io.out "Complete!"; diff --git a/js/baba-yaga/scratch/baba/indentation_test.baba b/js/baba-yaga/scratch/baba/indentation_test.baba new file mode 100644 index 0000000..3e0a659 --- /dev/null +++ b/js/baba-yaga/scratch/baba/indentation_test.baba @@ -0,0 +1,20 @@ +// Test proper indentation +simpleFunc : x -> x + 1; + +complexFunc : x -> + when x is + 0 then "zero" + 1 then "one" + _ then "other"; + +withFunc : a b -> + with ( + sum : a + b; + diff : a - b; + ) -> + {sum: sum, diff: diff}; + +varWithWhen : + when true is + true then "yes" + false then "no"; diff --git a/js/baba-yaga/scratch/baba/life-demo-alt.baba b/js/baba-yaga/scratch/baba/life-demo-alt.baba new file mode 100644 index 0000000..b4c35ce --- /dev/null +++ b/js/baba-yaga/scratch/baba/life-demo-alt.baba @@ -0,0 +1,91 @@ +// Conway's Game of Life Demo + +// Simple blinker pattern demonstration +// Initial state: vertical line of 3 cells +// Next state: horizontal line of 3 cells + +// Generation 0 - vertical blinker +cell_0_1 : 1; // top +cell_1_1 : 1; // middle +cell_2_1 : 1; // bottom + +// All other cells are 0 +cell_0_0 : 0; +cell_0_2 : 0; +cell_1_0 : 0; +cell_1_2 : 0; +cell_2_0 : 0; +cell_2_2 : 0; + +io.out "Conway's Game of Life - Blinker Demo"; +io.out "===================================="; + +io.out "Generation 0 (vertical line):"; +io.out "Row 0:"; +io.out cell_0_0; +io.out cell_0_1; +io.out cell_0_2; +io.out "Row 1:"; +io.out cell_1_0; +io.out cell_1_1; +io.out cell_1_2; +io.out "Row 2:"; +io.out cell_2_0; +io.out cell_2_1; +io.out cell_2_2; + +// Calculate Generation 1 +// For the middle cell (1,1): has 2 vertical neighbors, survives +// For cells (1,0) and (1,2): each has 3 neighbors, become alive +// All other cells die or stay dead + +// Middle cell (1,1) - count neighbors +neighbors_1_1 : cell_0_1 + cell_2_1; // 2 neighbors +next_1_1 : when (cell_1_1 = 1 and (neighbors_1_1 = 2 or neighbors_1_1 = 3)) is + true then 1 _ then 0; + +// Left cell (1,0) - count neighbors +neighbors_1_0 : cell_0_0 + cell_0_1 + cell_1_1 + cell_2_0 + cell_2_1; // 3 neighbors +next_1_0 : when (cell_1_0 = 0 and neighbors_1_0 = 3) is + true then 1 _ then 0; + +// Right cell (1,2) - count neighbors +neighbors_1_2 : cell_0_1 + cell_0_2 + cell_1_1 + cell_2_1 + cell_2_2; // 3 neighbors +next_1_2 : when (cell_1_2 = 0 and neighbors_1_2 = 3) is + true then 1 _ then 0; + +// All other cells in generation 1 will be 0 +next_0_0 : 0; +next_0_1 : 0; +next_0_2 : 0; +next_2_0 : 0; +next_2_1 : 0; +next_2_2 : 0; + +io.out ""; +io.out "Generation 1 (horizontal line):"; +io.out "Row 0:"; +io.out next_0_0; +io.out next_0_1; +io.out next_0_2; +io.out "Row 1:"; +io.out next_1_0; +io.out next_1_1; +io.out next_1_2; +io.out "Row 2:"; +io.out next_2_0; +io.out next_2_1; +io.out next_2_2; + +io.out ""; +io.out "Neighbor counts:"; +io.out "Cell (1,1) neighbors:"; +io.out neighbors_1_1; +io.out "Cell (1,0) neighbors:"; +io.out neighbors_1_0; +io.out "Cell (1,2) neighbors:"; +io.out neighbors_1_2; + +io.out ""; +io.out "The blinker oscillates between vertical and horizontal!"; +io.out "This demonstrates Conway's Game of Life rules."; diff --git a/js/baba-yaga/scratch/baba/life-demo.baba b/js/baba-yaga/scratch/baba/life-demo.baba new file mode 100644 index 0000000..b4c35ce --- /dev/null +++ b/js/baba-yaga/scratch/baba/life-demo.baba @@ -0,0 +1,91 @@ +// Conway's Game of Life Demo + +// Simple blinker pattern demonstration +// Initial state: vertical line of 3 cells +// Next state: horizontal line of 3 cells + +// Generation 0 - vertical blinker +cell_0_1 : 1; // top +cell_1_1 : 1; // middle +cell_2_1 : 1; // bottom + +// All other cells are 0 +cell_0_0 : 0; +cell_0_2 : 0; +cell_1_0 : 0; +cell_1_2 : 0; +cell_2_0 : 0; +cell_2_2 : 0; + +io.out "Conway's Game of Life - Blinker Demo"; +io.out "===================================="; + +io.out "Generation 0 (vertical line):"; +io.out "Row 0:"; +io.out cell_0_0; +io.out cell_0_1; +io.out cell_0_2; +io.out "Row 1:"; +io.out cell_1_0; +io.out cell_1_1; +io.out cell_1_2; +io.out "Row 2:"; +io.out cell_2_0; +io.out cell_2_1; +io.out cell_2_2; + +// Calculate Generation 1 +// For the middle cell (1,1): has 2 vertical neighbors, survives +// For cells (1,0) and (1,2): each has 3 neighbors, become alive +// All other cells die or stay dead + +// Middle cell (1,1) - count neighbors +neighbors_1_1 : cell_0_1 + cell_2_1; // 2 neighbors +next_1_1 : when (cell_1_1 = 1 and (neighbors_1_1 = 2 or neighbors_1_1 = 3)) is + true then 1 _ then 0; + +// Left cell (1,0) - count neighbors +neighbors_1_0 : cell_0_0 + cell_0_1 + cell_1_1 + cell_2_0 + cell_2_1; // 3 neighbors +next_1_0 : when (cell_1_0 = 0 and neighbors_1_0 = 3) is + true then 1 _ then 0; + +// Right cell (1,2) - count neighbors +neighbors_1_2 : cell_0_1 + cell_0_2 + cell_1_1 + cell_2_1 + cell_2_2; // 3 neighbors +next_1_2 : when (cell_1_2 = 0 and neighbors_1_2 = 3) is + true then 1 _ then 0; + +// All other cells in generation 1 will be 0 +next_0_0 : 0; +next_0_1 : 0; +next_0_2 : 0; +next_2_0 : 0; +next_2_1 : 0; +next_2_2 : 0; + +io.out ""; +io.out "Generation 1 (horizontal line):"; +io.out "Row 0:"; +io.out next_0_0; +io.out next_0_1; +io.out next_0_2; +io.out "Row 1:"; +io.out next_1_0; +io.out next_1_1; +io.out next_1_2; +io.out "Row 2:"; +io.out next_2_0; +io.out next_2_1; +io.out next_2_2; + +io.out ""; +io.out "Neighbor counts:"; +io.out "Cell (1,1) neighbors:"; +io.out neighbors_1_1; +io.out "Cell (1,0) neighbors:"; +io.out neighbors_1_0; +io.out "Cell (1,2) neighbors:"; +io.out neighbors_1_2; + +io.out ""; +io.out "The blinker oscillates between vertical and horizontal!"; +io.out "This demonstrates Conway's Game of Life rules."; diff --git a/js/baba-yaga/scratch/baba/life-example.baba b/js/baba-yaga/scratch/baba/life-example.baba new file mode 100644 index 0000000..7ae7164 --- /dev/null +++ b/js/baba-yaga/scratch/baba/life-example.baba @@ -0,0 +1,181 @@ +headAt : xs i -> + with ( + tmp : slice xs i (i + 1); + ) -> + tmp.0; + +get2 : grid r c -> + headAt (headAt grid r) c; + +safeGet2 : grid r c -> + with ( + rows : length grid; + cols : length (headAt grid 0); + rOk : r >= 0 and r < rows; + cOk : c >= 0 and c < cols; + ) -> + when rOk and cOk is + true then get2 grid r c + _ then 0; + +range : lo hi -> + when lo >= hi is + true then [] + _ then prepend lo (range (lo + 1) hi); + +sum : xs -> + reduce (acc x -> acc + x) 0 xs; + +deltas : [-1, 0, 1]; + +neighborsValues : grid r c -> + reduce (acc dr -> reduce (acc2 dc -> when dr = 0 and dc = 0 is + true then acc2 + _ then append acc2 (safeGet2 grid (r + dr) (c + dc))) acc deltas) [] deltas; + +countNeighbors : grid r c -> + sum (neighborsValues grid r c); + +nextCell : grid r c -> + with ( + cell : get2 grid r c; + n : countNeighbors grid r c; + isAlive : cell = 1; + born : cell = 0 and n = 3; + survive : isAlive and n = 2 or n = 3; + ) -> + when survive is + true then 1 + _ then + when born is + true then 1 + _ then 0; + +rowNext : grid w r -> + map (c -> nextCell grid r c) (range 0 w); + +step : grid -> + with ( + h : length grid; + w : length (headAt grid 0); + ) -> + map (r -> rowNext grid w r) (range 0 h); + +g0 : [ + [0, 1, 0, 0, 0], + [0, 0, 1, 0, 0], + [1, 1, 1, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0] +]; +g1 : step g0; +g2 : step g1; +g3 : step g2; +g4 : step g3; +blinker0 : [[1, 1, 1], [0, 0, 0], [0, 0, 0]]; +blinker1 : step blinker0; +blinker2 : step blinker1; +toad0 : [ + [0, 1, 1, 1], + [1, 1, 1, 0], + [0, 0, 0, 0], + [0, 0, 0, 0] +]; +toad1 : step toad0; +toad2 : step toad1; +beacon0 : [ + [1, 1, 0, 0], + [1, 1, 0, 0], + [0, 0, 1, 1], + [0, 0, 1, 1] +]; +beacon1 : step beacon0; +beacon2 : step beacon1; +block : [[1, 1], [1, 1]]; +block1 : step block; +beehive : [[0, 1, 1, 0], [1, 0, 0, 1], [0, 1, 1, 0]]; +beehive1 : step beehive; +pulsar0 : [ + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1], + [0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], + [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1], + [0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], + [0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0] +]; +pulsar1 : step pulsar0; +pulsar2 : step pulsar1; +pulsar3 : step pulsar2; + +// Enhanced Conway's Game of Life display using io.print +io.print ""; +io.print "Conway's Game of Life - Pattern Evolution"; +io.print "=========================================="; + +io.print ""; +io.print "Glider Pattern Evolution:"; +io.print "Step 0:"; +io.print g0; +io.print "Step 1:"; +io.print g1; +io.print "Step 2:"; +io.print g2; +io.print "Step 3:"; +io.print g3; +io.print "Step 4:"; +io.print g4; + +io.print ""; +io.print "Blinker Oscillation:"; +io.print "Step 0:"; +io.print blinker0; +io.print "Step 1:"; +io.print blinker1; +io.print "Step 2:"; +io.print blinker2; + +io.print ""; +io.print "Toad Breathing Pattern:"; +io.print "Step 0:"; +io.print toad0; +io.print "Step 1:"; +io.print toad1; +io.print "Step 2:"; +io.print toad2; + +io.print ""; +io.print "Beacon Blinking:"; +io.print "Step 0:"; +io.print beacon0; +io.print "Step 1:"; +io.print beacon1; +io.print "Step 2:"; +io.print beacon2; + +io.print ""; +io.print "Still Life Patterns:"; +io.print "Block:"; +io.print block; +io.print "Beehive:"; +io.print beehive; + +io.print ""; +io.print "Pulsar Oscillation (Period 3):"; +io.print "Step 0:"; +io.print pulsar0; +io.print "Step 1:"; +io.print pulsar1; +io.print "Step 2:"; +io.print pulsar2; +io.print "Step 3:"; +io.print pulsar3; + +// End of program - visual patterns shown above diff --git a/js/baba-yaga/scratch/baba/life-final.baba b/js/baba-yaga/scratch/baba/life-final.baba new file mode 100644 index 0000000..a489c89 --- /dev/null +++ b/js/baba-yaga/scratch/baba/life-final.baba @@ -0,0 +1,59 @@ +// Conway's Game of Life - Final Working Demo + +// Simple blinker pattern - just show the concept + +// Initial state: 3 cells in a vertical line +top : 1; +middle : 1; +bottom : 1; + +io.out "Conway's Game of Life - Blinker Pattern"; +io.out "=========================================="; + +io.out "Generation 0 (vertical line):"; +io.out " .#."; +io.out " .#."; +io.out " .#."; + +io.out ""; +io.out "Applying Game of Life rules..."; + +// Count neighbors for middle cell +middleNeighbors : top + bottom; // 2 neighbors (top and bottom) + +// Apply rules: live cell with 2-3 neighbors survives +middleNext : when (middle = 1 and (middleNeighbors = 2 or middleNeighbors = 3)) is + true then 1 + _ then 0; + +// Count neighbors for left and right of middle row (each has 3 neighbors) +leftNeighbors : 3; // top, middle, bottom +rightNeighbors : 3; // top, middle, bottom + +// Apply rules: dead cell with exactly 3 neighbors becomes alive +leftNext : when (leftNeighbors = 3) is true then 1 _ then 0; +rightNext : when (rightNeighbors = 3) is true then 1 _ then 0; + +io.out "Generation 1 (horizontal line):"; +io.out " ..."; +io.out " ###"; +io.out " ..."; + +io.out ""; +io.out "Neighbor counts:"; +io.out "Middle cell had neighbors:"; io.out middleNeighbors; +io.out "Middle cell survives:"; io.out middleNext; +io.out "Left cell becomes alive:"; io.out leftNext; +io.out "Right cell becomes alive:"; io.out rightNext; + +io.out ""; +io.out "The pattern oscillates between:"; +io.out "Vertical: .#. Horizontal: ..."; +io.out " .#. ###"; +io.out " .#. ..."; + +io.out ""; +io.out "This demonstrates Conway's Game of Life!"; +io.out "Rules: Live cell with 2-3 neighbors survives"; +io.out " Dead cell with exactly 3 neighbors becomes alive"; +io.out " All other cells die or stay dead"; diff --git a/js/baba-yaga/scratch/baba/life-simple.baba b/js/baba-yaga/scratch/baba/life-simple.baba new file mode 100644 index 0000000..b2da07c --- /dev/null +++ b/js/baba-yaga/scratch/baba/life-simple.baba @@ -0,0 +1,51 @@ +// Simple Conway's Game of Life + +// Create a simple 3x3 blinker using individual variables +c00 : 0; c01 : 1; c02 : 0; +c10 : 0; c11 : 1; c12 : 0; +c20 : 0; c21 : 1; c22 : 0; + +// Count neighbors for center cell (1,1) +neighbors11 : c00 + c01 + c02 + c10 + c12 + c20 + c21 + c22; + +// Apply Game of Life rules to center cell +next11 : when (c11 = 1) is + true then when (neighbors11 = 2 or neighbors11 = 3) is true then 1 _ then 0 + _ then when (neighbors11 = 3) is true then 1 _ then 0; + +// Count neighbors for top-left cell (0,0) +neighbors00 : c01 + c10 + c11; + +// Apply rules to top-left cell +next00 : when (c00 = 1) is + true then when (neighbors00 = 2 or neighbors00 = 3) is true then 1 _ then 0 + _ then when (neighbors00 = 3) is true then 1 _ then 0; + +// Count neighbors for top-center cell (0,1) +neighbors01 : c00 + c02 + c10 + c11 + c12; + +// Apply rules to top-center cell +next01 : when (c01 = 1) is + true then when (neighbors01 = 2 or neighbors01 = 3) is true then 1 _ then 0 + _ then when (neighbors01 = 3) is true then 1 _ then 0; + +// Display results +io.out "Conway's Game of Life - Blinker Pattern"; +io.out "Generation 0:"; +io.out c00; io.out c01; io.out c02; +io.out c10; io.out c11; io.out c12; +io.out c20; io.out c21; io.out c22; + +io.out "Generation 1 (center cell):"; +io.out "Center cell neighbors:"; io.out neighbors11; +io.out "Center cell next state:"; io.out next11; + +io.out "Generation 1 (top-left cell):"; +io.out "Top-left neighbors:"; io.out neighbors00; +io.out "Top-left next state:"; io.out next00; + +io.out "Generation 1 (top-center cell):"; +io.out "Top-center neighbors:"; io.out neighbors01; +io.out "Top-center next state:"; io.out next01; + +io.out "Done!"; diff --git a/js/baba-yaga/scratch/baba/life.baba b/js/baba-yaga/scratch/baba/life.baba new file mode 100644 index 0000000..a5fbe79 --- /dev/null +++ b/js/baba-yaga/scratch/baba/life.baba @@ -0,0 +1,90 @@ +// Conway's Game of Life in Baba Yaga + +// headAt: return the element at index i from list xs +headAt : xs i -> with (tmp : slice xs i (i + 1)) -> tmp.0; + +// get2: 2D index for a grid (list of lists) +get2 : grid r c -> headAt (headAt grid r) c; + +// safeGet2: bounds-checked 2D get; returns 0 when out of bounds +safeGet2 : grid r c -> + with ( + rows : length grid; + cols : length (headAt grid 0); + rOk : (r >= 0) and (r < rows); + cOk : (c >= 0) and (c < cols); + ) -> + when (rOk and cOk) is + true then get2 grid r c + _ then 0; + +// range [lo, hi) as a list of Int +range : lo hi -> + when (lo >= hi) is + true then [] + _ then prepend lo (range (lo + 1) hi); + +// sum a list of numbers +sum : xs -> reduce (acc x -> acc + x) 0 xs; + +// deltas for neighborhood offsets +deltas : [-1, 0, 1]; + +// neighborsValues: list of neighbor cell values for (r,c) +neighborsValues : grid r c -> + reduce (acc dr -> + reduce (acc2 dc -> + when ((dr = 0) and (dc = 0)) is + true then acc2 + _ then append acc2 (safeGet2 grid (r + dr) (c + dc)) + ) acc deltas + ) [] deltas; + +// count live neighbors at (r,c) +countNeighbors : grid r c -> sum (neighborsValues grid r c); + +// nextCell: apply Game of Life rules at (r,c) +nextCell : grid r c -> + with ( + cell : get2 grid r c; + n : countNeighbors grid r c; + isAlive : cell = 1; + born : (cell = 0) and (n = 3); + survive : isAlive and ((n = 2) or (n = 3)); + ) -> + when survive is + true then 1 + _ then when born is true then 1 _ then 0; + +// build next row r given width w +rowNext : grid w r -> map (c -> nextCell grid r c) (range 0 w); + +// Single simulation step for the entire grid +step : grid -> + with ( + h : length grid; + w : length (headAt grid 0); + ) -> map (r -> rowNext grid w r) (range 0 h); + +// Demo: glider pattern in a 5x5 grid +g0 : [ + [0, 1, 0, 0, 0], + [0, 0, 1, 0, 0], + [1, 1, 1, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0] +]; + +g1 : step g0; +g2 : step g1; +g3 : step g2; +g4 : step g3; + +// Print successive generations +io.out g0; +io.out g1; +io.out g2; +io.out g3; +io.out g4; + + diff --git a/js/baba-yaga/scratch/baba/nested_when_test.baba b/js/baba-yaga/scratch/baba/nested_when_test.baba new file mode 100644 index 0000000..a626634 --- /dev/null +++ b/js/baba-yaga/scratch/baba/nested_when_test.baba @@ -0,0 +1,30 @@ +// Test deeply nested when expressions +classify : x y -> + when x is + 0 then when y is + 0 then "origin" + 1 then "y-axis" + _ then when y > 0 is + true then "positive y-axis" + false then "negative y-axis" + 1 then when y is + 0 then "x-axis" + 1 then "diagonal" + _ then when y > 0 is + true then when y > 10 is + true then "far positive diagonal" + false then "close positive diagonal" + false then "negative diagonal" + _ then "other quadrant"; + +// Test with multiple discriminants and nesting +complexCase : a b c -> + when a b is + 0 0 then when c is + 1 then "case 1" + 2 then when true is + true then "nested true" + false then "nested false" + _ then "default c" + 1 _ then "partial match" + _ _ then "catch all"; diff --git a/js/baba-yaga/scratch/baba/nested_when_working.baba b/js/baba-yaga/scratch/baba/nested_when_working.baba new file mode 100644 index 0000000..9552632 --- /dev/null +++ b/js/baba-yaga/scratch/baba/nested_when_working.baba @@ -0,0 +1,12 @@ +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"; diff --git a/js/baba-yaga/scratch/baba/simple.baba b/js/baba-yaga/scratch/baba/simple.baba new file mode 100644 index 0000000..e0f0b33 --- /dev/null +++ b/js/baba-yaga/scratch/baba/simple.baba @@ -0,0 +1,8 @@ +x : 2 + 3; +io.out x; +inc : a -> a + 1; +io.out (inc 4); +y : when 1 is + 1 then 10 + _ then 20; +io.out y; diff --git a/js/baba-yaga/scratch/baba/simple_nested_when.baba b/js/baba-yaga/scratch/baba/simple_nested_when.baba new file mode 100644 index 0000000..7f7a258 --- /dev/null +++ b/js/baba-yaga/scratch/baba/simple_nested_when.baba @@ -0,0 +1,8 @@ +// Simple nested when test +test : x -> + when x is + 0 then when true is + true then "nested true" + false then "nested false" + 1 then "simple case" + _ then "default"; diff --git a/js/baba-yaga/scratch/baba/test_comprehensive_features.baba b/js/baba-yaga/scratch/baba/test_comprehensive_features.baba new file mode 100644 index 0000000..7a205b1 --- /dev/null +++ b/js/baba-yaga/scratch/baba/test_comprehensive_features.baba @@ -0,0 +1,87 @@ +// Comprehensive test combining all new functional programming features + +io.out "=== Comprehensive Feature Test ==="; + +// Example: Processing student data with advanced functional programming + +// Sample student data +students : [ + {name: "Alice", scores: [85, 92, 78, 90]}, + {name: "Bob", scores: [75, 88, 82, 79]}, + {name: "Charlie", scores: [95, 96, 94, 97]}, + {name: "Diana", scores: [65, 70, 68, 72]} +]; + +// Calculate average score +calculateAverage : scores -> + with ( + total : reduce (acc x -> acc + x) 0 scores; + count : length scores; + ) -> + total / count; + +// Process each student using flatMap and array operations +processStudent : student -> + with ( + scores : student.scores; + average : calculateAverage scores; + cumulative : cumsum scores; + + // Use pattern guards to assign grades + grade : when average is + a if (a >= 90) then "A" + a if (a >= 80 and a < 90) then "B" + a if (a >= 70 and a < 80) then "C" + a if (a >= 60 and a < 70) then "D" + a if (a < 60) then "F" + _ then "Invalid"; + + // Use broadcasting to normalize scores + maxScore : reduce (acc x -> math.max acc x) 0 scores; + normalized : broadcast (score max -> score / max * 100) maxScore scores; + ) -> + { + name: student.name, + average: average, + grade: grade, + cumulative: cumulative, + normalized: normalized + }; + +// Process all students +processedStudents : map processStudent students; + +io.out "Processed Students:"; +io.out processedStudents; + +// Advanced analysis using array programming +io.out "=== Advanced Analysis ==="; + +// Extract all scores using flatMap +allScores : flatMap (s -> s.scores) students; +io.out "All scores:"; +io.out allScores; + +// Find top performers using where and at +highScoreIndices : where (score -> score >= 90) allScores; +highScores : at highScoreIndices allScores; +io.out "High scores (>=90):"; +io.out highScores; + +// Use zipWith to compare consecutive students +studentNames : map (s -> s.name) processedStudents; +studentAverages : map (s -> s.average) processedStudents; + +// Reshape data into matrix for analysis +scoresMatrix : reshape [4, 4] allScores; +io.out "Scores as 4x4 matrix:"; +io.print scoresMatrix; + +// Combine multiple operations in a pipeline +topStudents : filter (s -> s.average >= 85) processedStudents; +topStudentAnalysis : sort.by topStudents (s -> s.average); + +io.out "Top students (avg >= 85), sorted by average:"; +io.out topStudentAnalysis; + +io.out "=== All comprehensive tests completed ==="; diff --git a/js/baba-yaga/scratch/baba/test_error_docs.baba b/js/baba-yaga/scratch/baba/test_error_docs.baba new file mode 100644 index 0000000..2efef40 --- /dev/null +++ b/js/baba-yaga/scratch/baba/test_error_docs.baba @@ -0,0 +1,40 @@ +// Test some examples from the error handling documentation + +io.out "Testing error handling documentation examples..."; + +// Basic Result usage +divide : x y -> + when y is + 0 then Err "Division by zero" + _ then Ok (x / y); + +handleDivision : x y -> + when (divide x y) is + Ok result then result + Err message then 0; + +io.out "Division test:"; +io.out (handleDivision 10 2); // Should be 5 +io.out (handleDivision 10 0); // Should be 0 + +// Validation patterns +validateAge : age -> + when (validate.type "Int" age) is + false then Err "Age must be an integer" + true then + when (validate.range 0 150 age) is + false then Err "Age must be between 0 and 150" + true then Ok age; + +io.out "Validation test:"; +io.out (validateAge 25); // Should be Ok 25 +io.out (validateAge 200); // Should be error + +// Simple assertion +assert (2 + 2 = 4) "Math works"; +io.out "Assertion passed!"; + +// Debug example +debug.print "Debug test" 42; + +io.out "Error handling documentation examples work!"; diff --git a/js/baba-yaga/scratch/baba/test_error_handling.baba b/js/baba-yaga/scratch/baba/test_error_handling.baba new file mode 100644 index 0000000..d886e09 --- /dev/null +++ b/js/baba-yaga/scratch/baba/test_error_handling.baba @@ -0,0 +1,47 @@ +// Test error handling patterns from the documentation + +io.out "=== Testing Error Handling Patterns ==="; + +// Basic Result usage +divide : x y -> + when y is + 0 then Err "Division by zero" + _ then Ok (x / y); + +handleDivision : x y -> + when (divide x y) is + Ok result then result + Err message then 0; + +io.out "Division results:"; +io.out (handleDivision 10 2); // Should be 5 +io.out (handleDivision 10 0); // Should print error and return 0 + +// Validation patterns +validateAge : age -> + when (validate.type "Int" age) is + false then Err "Age must be an integer" + true then + when (validate.range 0 150 age) is + false then Err "Age must be between 0 and 150" + true then Ok age; + +io.out ""; +io.out "Validation results:"; +io.out (validateAge 25); // Should be Ok 25 +io.out (validateAge 200); // Should be Err message +io.out (validateAge "not a number"); // Should be Err message + +// Simple assertion example +io.out ""; +io.out "Assertion example:"; +assert (2 + 2 = 4) "Math works"; +io.out "Assertion passed!"; + +// Debug example +io.out ""; +io.out "Debug example:"; +debug.print "Testing debug output" 42; + +io.out ""; +io.out "Error handling tests completed!"; diff --git a/js/baba-yaga/scratch/baba/test_functional_enhancements.baba b/js/baba-yaga/scratch/baba/test_functional_enhancements.baba new file mode 100644 index 0000000..e8e922a --- /dev/null +++ b/js/baba-yaga/scratch/baba/test_functional_enhancements.baba @@ -0,0 +1,132 @@ +// Test file for new functional programming enhancements +// This file tests: scan operations, indexing operations, combinators, and flatMap + +io.out "=== Testing Scan Operations ==="; + +// Test basic scan operation +numbers : [1, 2, 3, 4, 5]; +addFunc : acc x -> acc + x; +scanned : scan addFunc 0 numbers; +io.out "scan (+) 0 [1,2,3,4,5]:"; +io.out scanned; // Should be [0, 1, 3, 6, 10, 15] + +// Test cumsum utility +cumsumResult : cumsum numbers; +io.out "cumsum [1,2,3,4,5]:"; +io.out cumsumResult; // Should be [0, 1, 3, 6, 10, 15] + +// Test cumprod utility +cumprodResult : cumprod numbers; +io.out "cumprod [1,2,3,4,5]:"; +io.out cumprodResult; // Should be [1, 1, 2, 6, 24, 120] + +io.out "=== Testing Array Indexing Operations ==="; + +data : [10, 21, 30, 43, 50]; + +// Test 'at' operation +indices : [0, 2, 4]; +selected : at indices data; +io.out "at [0,2,4] [10,21,30,43,50]:"; +io.out selected; // Should be [10, 30, 50] + +// Test 'where' operation +evenPredicate : x -> x % 2 = 0; +evenIndices : where evenPredicate data; +io.out "where (even?) [10,21,30,43,50]:"; +io.out evenIndices; // Should be [0, 2, 4] (indices of 10, 30, 50) + +// Test 'take' operation +firstThree : take 3 data; +io.out "take 3 [10,21,30,43,50]:"; +io.out firstThree; // Should be [10, 21, 30] + +// Test 'drop' operation +lastTwo : drop 3 data; +io.out "drop 3 [10,21,30,43,50]:"; +io.out lastTwo; // Should be [43, 50] + +io.out "=== Testing Function Combinators ==="; + +// Test basic functions for combinators +add : x y -> x + y; +multiply : x y -> x * y; +double : x -> x * 2; +increment : x -> x + 1; + +// Test flip +flippedAdd : flip add; +result1 : flippedAdd 3 5; // Should be 5 + 3 = 8 +io.out "flip add 3 5:"; +io.out result1; + +// Test apply +result2 : apply double 7; // Should be 14 +io.out "apply double 7:"; +io.out result2; + +// Test pipe +result3 : pipe 5 double; // Should be 10 +io.out "pipe 5 double:"; +io.out result3; + +// Test compose +composed : compose increment double; // x -> (x * 2) + 1 +result4 : composed 4; // Should be 9 +io.out "compose increment double 4:"; +io.out result4; + +io.out "=== Testing flatMap ==="; + +// Test flatMap with simple function +duplicateFunc : x -> [x, x]; +original : [1, 2, 3]; +duplicated : flatMap duplicateFunc original; +io.out "flatMap (x -> [x,x]) [1,2,3]:"; +io.out duplicated; // Should be [1, 1, 2, 2, 3, 3] + +// Test flatMap with range generation +rangeFunc : x -> range 1 x; +rangeResult : flatMap rangeFunc [2, 3]; +io.out "flatMap (x -> range 1 x) [2,3]:"; +io.out rangeResult; // Should be [1, 2, 1, 2, 3] + +io.out "=== Combining Operations ==="; + +// Complex example: Find cumulative sums of doubled even numbers +evenNumbers : [2, 4, 6, 8]; +doubled : map double evenNumbers; +cumulative : cumsum doubled; +io.out "Cumsum of doubled evens [2,4,6,8]:"; +io.out cumulative; // [0, 4, 12, 24, 40] + +// Using combinators in a pipeline-like fashion +processNumber : x -> pipe x (compose increment double); +processed : map processNumber [1, 2, 3]; +io.out "Map (pipe x (compose inc double)) [1,2,3]:"; +io.out processed; // Should be [3, 5, 7] + +io.out "=== Testing Broadcasting Operations ==="; + +// Test broadcast (scalar-array operation) +addOp : x y -> x + y; +numbers2 : [1, 2, 3, 4]; +broadcasted : broadcast addOp 10 numbers2; +io.out "broadcast (+) 10 [1,2,3,4]:"; +io.out broadcasted; // Should be [11, 12, 13, 14] + +// Test zipWith (element-wise array-array operation) +array1 : [1, 2, 3]; +array2 : [10, 20, 30]; +zipped : zipWith addOp array1 array2; +io.out "zipWith (+) [1,2,3] [10,20,30]:"; +io.out zipped; // Should be [11, 22, 33] + +// Test reshape (2D matrix creation) +flatArray : [1, 2, 3, 4, 5, 6]; +matrixShape : [2, 3]; // 2 rows, 3 columns +matrix : reshape matrixShape flatArray; +io.out "reshape [2,3] [1,2,3,4,5,6]:"; +io.print matrix; // Should display as 2x3 matrix + +io.out "=== All tests completed ==="; diff --git a/js/baba-yaga/scratch/baba/test_grid_display.baba b/js/baba-yaga/scratch/baba/test_grid_display.baba new file mode 100644 index 0000000..037230e --- /dev/null +++ b/js/baba-yaga/scratch/baba/test_grid_display.baba @@ -0,0 +1,20 @@ +// Test grid display +showCell : cell -> + when cell is + 1 then "█" + _ then "·"; + +showRow : row -> + reduce (acc cell -> str.concat acc (showCell cell)) "" row; + +showGrid : grid -> + reduce (acc row -> str.concat acc (str.concat (showRow row) "\n")) "" grid; + +testGrid : [ + [1, 0, 1], + [0, 1, 0], + [1, 0, 1] +]; + +io.out "Test Grid:"; +io.out showGrid testGrid; diff --git a/js/baba-yaga/scratch/baba/test_io_print.baba b/js/baba-yaga/scratch/baba/test_io_print.baba new file mode 100644 index 0000000..4623089 --- /dev/null +++ b/js/baba-yaga/scratch/baba/test_io_print.baba @@ -0,0 +1,34 @@ +// Test the new io.print functionality + +// Simple grid for testing +testGrid : [ + [1, 0, 1], + [0, 1, 0], + [1, 0, 1] +]; + +// Test basic grid printing +io.print "Testing io.print with automatic grid detection:"; +io.print testGrid; + +io.print ""; +io.print "Testing explicit grid format:"; +io.print "grid" testGrid; + +io.print ""; +io.print "Testing regular data:"; +io.print "Number" 42; +io.print "String" "Hello World"; + +// Test with a larger grid (like from Game of Life) +glider : [ + [0, 1, 0, 0, 0], + [0, 0, 1, 0, 0], + [1, 1, 1, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0] +]; + +io.print ""; +io.print "Conway's Game of Life - Glider Pattern:"; +io.print glider; diff --git a/js/baba-yaga/scratch/baba/test_logical_and.baba b/js/baba-yaga/scratch/baba/test_logical_and.baba new file mode 100644 index 0000000..0b2b565 --- /dev/null +++ b/js/baba-yaga/scratch/baba/test_logical_and.baba @@ -0,0 +1,7 @@ +// Test logical and in when discriminant +test : x y -> + when x and y is + true then "both true" + false then "at least one false"; + +result : test true false; diff --git a/js/baba-yaga/scratch/baba/test_pattern_guards.baba b/js/baba-yaga/scratch/baba/test_pattern_guards.baba new file mode 100644 index 0000000..8b8e2cd --- /dev/null +++ b/js/baba-yaga/scratch/baba/test_pattern_guards.baba @@ -0,0 +1,57 @@ +// Test file for pattern guards +io.out "=== Testing Pattern Guards ==="; + +// Test basic guard with literal pattern +classifyNumber : n -> + when n is + 0 if n = 0 then "exactly zero" + n if n > 0 then "positive" + n if n < 0 then "negative" + _ then "unknown"; + +io.out "classifyNumber 5:"; +io.out (classifyNumber 5); // Should be "positive" + +io.out "classifyNumber -3:"; +io.out (classifyNumber -3); // Should be "negative" + +io.out "classifyNumber 0:"; +io.out (classifyNumber 0); // Should be "exactly zero" + +// Test guard with range conditions (avoiding .. operator) +categorizeAge : age -> + when age is + a if (a >= 0 and a < 18) then "minor" + a if (a >= 18 and a < 65) then "adult" + a if (a >= 65) then "senior" + _ then "invalid"; + +io.out "categorizeAge 16:"; +io.out (categorizeAge 16); // Should be "minor" + +io.out "categorizeAge 30:"; +io.out (categorizeAge 30); // Should be "adult" + +io.out "categorizeAge 70:"; +io.out (categorizeAge 70); // Should be "senior" + +// Test guard with complex conditions +gradeStudent : score -> + when score is + s if (s >= 90) then "A" + s if (s >= 80 and s < 90) then "B" + s if (s >= 70 and s < 80) then "C" + s if (s >= 60 and s < 70) then "D" + s if (s < 60) then "F" + _ then "Invalid score"; + +io.out "gradeStudent 95:"; +io.out (gradeStudent 95); // Should be "A" + +io.out "gradeStudent 75:"; +io.out (gradeStudent 75); // Should be "C" + +io.out "gradeStudent 45:"; +io.out (gradeStudent 45); // Should be "F" + +io.out "=== Pattern Guards Tests Completed ==="; diff --git a/js/baba-yaga/scratch/baba/test_then_alignment.baba b/js/baba-yaga/scratch/baba/test_then_alignment.baba new file mode 100644 index 0000000..42b3072 --- /dev/null +++ b/js/baba-yaga/scratch/baba/test_then_alignment.baba @@ -0,0 +1,18 @@ +// Test then alignment +checkNumber : num -> + when num is + 1 then "One" + 2 then "Two" + 10 then "Ten" + 100 then "One Hundred" + _ then "Something else"; + +// Test with nested when +classify : n -> + when n is + 0 then "zero" + _ then when n > 100 is + true then "large" + _ then when n > 10 is + true then "medium" + _ then "small"; diff --git a/js/baba-yaga/scratch/baba/test_utilities.baba b/js/baba-yaga/scratch/baba/test_utilities.baba new file mode 100644 index 0000000..1245e8a --- /dev/null +++ b/js/baba-yaga/scratch/baba/test_utilities.baba @@ -0,0 +1,106 @@ +// Test file for new utility functions + +io.out "Testing new Baba Yaga utilities..."; +io.out ""; + +// Test validate namespace +io.out "=== Testing validate.* functions ==="; +io.out (validate.notEmpty "hello"); // true +io.out (validate.notEmpty ""); // false +io.out (validate.notEmpty [1, 2, 3]); // true +io.out (validate.notEmpty []); // false + +io.out (validate.range 1 10 5); // true +io.out (validate.range 1 10 15); // false + +io.out (validate.email "test@example.com"); // true +io.out (validate.email "invalid-email"); // false + +io.out (validate.type "Int" 42); // true +io.out (validate.type "String" 42); // false + +io.out ""; + +// Test text namespace +io.out "=== Testing text.* functions ==="; +lines : text.lines "hello\nworld\ntest"; +io.out lines; // ["hello", "world", "test"] + +words : text.words "hello world test"; +io.out words; // ["hello", "world", "test"] + +io.out (text.padLeft 10 "hi"); // " hi" +io.out (text.padRight 10 "hi"); // "hi " + +io.out ""; + +// Test utility functions +io.out "=== Testing utility functions ==="; +numbers : [1, 2, 3, 4, 5, 6]; +chunks : chunk numbers 2; +io.out chunks; // [[1, 2], [3, 4], [5, 6]] + +rangeList : range 1 5; +io.out rangeList; // [1, 2, 3, 4, 5] + +repeated : repeat 3 "hello"; +io.out repeated; // ["hello", "hello", "hello"] + +io.out ""; + +// Test sort namespace +io.out "=== Testing sort.by ==="; +people : [ + {name: "Alice", age: 30}, + {name: "Bob", age: 25}, + {name: "Charlie", age: 35} +]; + +sortedByAge : sort.by people (p -> p.age); +io.out sortedByAge; + +io.out ""; + +// Test group namespace +io.out "=== Testing group.by ==="; +grouped : group.by people (p -> p.age > 25); +io.out grouped; + +io.out ""; + +// Test random namespace +io.out "=== Testing random.* functions ==="; +testList : [1, 2, 3, 4, 5]; +choice : random.choice testList; +io.out choice; // random element + +shuffled : random.shuffle testList; +io.out shuffled; // shuffled version + +randomNum : random.range 1 10; +io.out randomNum; // random number 1-10 + +io.out ""; + +// Test debug namespace +io.out "=== Testing debug functions ==="; +testFunc : x -> x * 2; +debug.print testFunc; +debug.print people; +debug.print 42; + +inspection : debug.inspect testFunc; +io.out inspection; + +io.out ""; + +// Test assert function +io.out "=== Testing assert ==="; +assert (2 + 2 = 4) "Math works!"; +io.out "Assert passed - math works!"; + +// This should throw an error if uncommented: +// assert (2 + 2 = 5) "This will fail"; + +io.out ""; +io.out "All utility tests completed successfully!"; diff --git a/js/baba-yaga/scratch/baba/then_alignment_demo.baba b/js/baba-yaga/scratch/baba/then_alignment_demo.baba new file mode 100644 index 0000000..4a4ce35 --- /dev/null +++ b/js/baba-yaga/scratch/baba/then_alignment_demo.baba @@ -0,0 +1,27 @@ +processRequest : method path -> +when method path is + "GET" "/" then "Home page" + "GET" "/about" then "About page" + "POST" "/api/users" then "Create user" + "DELETE" "/api/users" then "Delete user" + "PATCH" "/api/users/profile" then "Update profile" + _ _ then "Not found"; + +analyzeData : type value -> +when type is + "number" then + when value > 0 is + true then + when value > 1000 is + true then "large positive" + false then "small positive" + false then "negative or zero" + "string" then + when length value > 10 is + true then "long string" + false then "short string" + "boolean" then + when value is + true then "truthy" + false then "falsy" + _ then "unknown type"; 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. + + |