diff --git a/examples/behavioral.lux b/examples/behavioral.lux index 8e89c9d..7ec9aa8 100644 --- a/examples/behavioral.lux +++ b/examples/behavioral.lux @@ -1,36 +1,19 @@ -// Demonstrating behavioral properties in Lux -// Behavioral properties are compile-time guarantees about function behavior -// -// Expected output: -// add(5, 3) = 8 -// factorial(5) = 120 -// multiply(7, 6) = 42 -// abs(-5) = 5 +fn add(a: Int, b: Int): Int is pure = a + b -// A pure function - no side effects, same input always gives same output -fn add(a: Int, b: Int): Int is pure = - a + b +fn factorial(n: Int): Int is deterministic = if n <= 1 then 1 else n * factorial(n - 1) -// A deterministic function - same input always gives same output -fn factorial(n: Int): Int is deterministic = - if n <= 1 then 1 - else n * factorial(n - 1) +fn multiply(a: Int, b: Int): Int is commutative = a * b -// A commutative function - order of arguments doesn't matter -fn multiply(a: Int, b: Int): Int is commutative = - a * b +fn abs(x: Int): Int is idempotent = if x < 0 then 0 - x else x -// An idempotent function - absolute value -fn abs(x: Int): Int is idempotent = - if x < 0 then 0 - x else x - -// Test the functions let sumResult = add(5, 3) + let factResult = factorial(5) + let productResult = multiply(7, 6) + let absResult = abs(0 - 5) -// Print results fn printResults(): Unit with {Console} = { Console.print("add(5, 3) = " + toString(sumResult)) Console.print("factorial(5) = " + toString(factResult)) diff --git a/examples/behavioral_types.lux b/examples/behavioral_types.lux index 4080bb3..6a5d8fd 100644 --- a/examples/behavioral_types.lux +++ b/examples/behavioral_types.lux @@ -1,82 +1,42 @@ -// Behavioral Types Demo -// Demonstrates compile-time verification of function properties - -// ============================================================ -// PART 1: Pure Functions -// ============================================================ - -// Pure functions have no side effects fn add(a: Int, b: Int): Int is pure = a + b + fn subtract(a: Int, b: Int): Int is pure = a - b -// ============================================================ -// PART 2: Commutative Functions -// ============================================================ - -// Commutative functions: f(a, b) = f(b, a) fn multiply(a: Int, b: Int): Int is commutative = a * b + fn sum(a: Int, b: Int): Int is commutative = a + b -// ============================================================ -// PART 3: Idempotent Functions -// ============================================================ - -// Idempotent functions: f(f(x)) = f(x) -fn abs(x: Int): Int is idempotent = - if x < 0 then 0 - x else x +fn abs(x: Int): Int is idempotent = if x < 0 then 0 - x else x fn identity(x: Int): Int is idempotent = x -// ============================================================ -// PART 4: Deterministic Functions -// ============================================================ +fn factorial(n: Int): Int is deterministic = if n <= 1 then 1 else n * factorial(n - 1) -// Deterministic functions always produce the same output for the same input -fn factorial(n: Int): Int is deterministic = - if n <= 1 then 1 else n * factorial(n - 1) +fn fib(n: Int): Int is deterministic = if n <= 1 then n else fib(n - 1) + fib(n - 2) -fn fib(n: Int): Int is deterministic = - if n <= 1 then n else fib(n - 1) + fib(n - 2) +fn sumTo(n: Int): Int is total = if n <= 0 then 0 else n + sumTo(n - 1) -// ============================================================ -// PART 5: Total Functions -// ============================================================ - -// Total functions are defined for all inputs (no infinite loops, no exceptions) -fn sumTo(n: Int): Int is total = - if n <= 0 then 0 else n + sumTo(n - 1) - -fn power(base: Int, exp: Int): Int is total = - if exp <= 0 then 1 else base * power(base, exp - 1) - -// ============================================================ -// RESULTS -// ============================================================ +fn power(base: Int, exp: Int): Int is total = if exp <= 0 then 1 else base * power(base, exp - 1) fn main(): Unit with {Console} = { Console.print("=== Behavioral Types Demo ===") Console.print("") - Console.print("Part 1: Pure functions") Console.print(" add(5, 3) = " + toString(add(5, 3))) Console.print(" subtract(10, 4) = " + toString(subtract(10, 4))) Console.print("") - Console.print("Part 2: Commutative functions") Console.print(" multiply(7, 6) = " + toString(multiply(7, 6))) Console.print(" sum(10, 20) = " + toString(sum(10, 20))) Console.print("") - Console.print("Part 3: Idempotent functions") Console.print(" abs(-42) = " + toString(abs(0 - 42))) Console.print(" identity(100) = " + toString(identity(100))) Console.print("") - Console.print("Part 4: Deterministic functions") Console.print(" factorial(5) = " + toString(factorial(5))) Console.print(" fib(10) = " + toString(fib(10))) Console.print("") - Console.print("Part 5: Total functions") Console.print(" sumTo(10) = " + toString(sumTo(10))) Console.print(" power(2, 8) = " + toString(power(2, 8))) diff --git a/examples/builtin_effects.lux b/examples/builtin_effects.lux index 2cb38cf..9598d9c 100644 --- a/examples/builtin_effects.lux +++ b/examples/builtin_effects.lux @@ -1,31 +1,7 @@ -// Demonstrating built-in effects in Lux -// -// Lux provides several built-in effects: -// - Console: print and read from terminal -// - Fail: early termination with error -// - State: get/put mutable state (requires runtime initialization) -// - Reader: read-only environment access (requires runtime initialization) -// -// This example demonstrates Console and Fail effects. -// -// Expected output: -// Starting computation... -// Step 1: validating input -// Step 2: processing -// Result: 42 -// Done! +fn safeDivide(a: Int, b: Int): Int with {Fail} = if b == 0 then Fail.fail("Division by zero") else a / b -// A function that can fail -fn safeDivide(a: Int, b: Int): Int with {Fail} = - if b == 0 then Fail.fail("Division by zero") - else a / b +fn validatePositive(n: Int): Int with {Fail} = if n < 0 then Fail.fail("Negative number not allowed") else n -// A function that validates input -fn validatePositive(n: Int): Int with {Fail} = - if n < 0 then Fail.fail("Negative number not allowed") - else n - -// A computation that uses multiple effects fn compute(input: Int): Int with {Console, Fail} = { Console.print("Starting computation...") Console.print("Step 1: validating input") @@ -36,7 +12,6 @@ fn compute(input: Int): Int with {Console, Fail} = { result } -// Main function fn main(): Unit with {Console} = { let result = run compute(21) with {} Console.print("Done!") diff --git a/examples/counter.lux b/examples/counter.lux index 201325e..0a13106 100644 --- a/examples/counter.lux +++ b/examples/counter.lux @@ -1,14 +1,3 @@ -// Counter Example - A simple interactive counter using TEA pattern -// -// This example demonstrates: -// - Model-View-Update architecture (TEA) -// - Html DSL for describing UI (inline version) -// - Message-based state updates - -// ============================================================================ -// Html Types (subset of stdlib/html) -// ============================================================================ - type Html = | Element(String, List>, List>) | Text(String) @@ -19,130 +8,96 @@ type Attr = | Id(String) | OnClick(M) -// Html builder helpers -fn div(attrs: List>, children: List>): Html = - Element("div", attrs, children) +fn div(attrs: List>, children: List>): Html = Element("div", attrs, children) -fn span(attrs: List>, children: List>): Html = - Element("span", attrs, children) +fn span(attrs: List>, children: List>): Html = Element("span", attrs, children) -fn h1(attrs: List>, children: List>): Html = - Element("h1", attrs, children) +fn h1(attrs: List>, children: List>): Html = Element("h1", attrs, children) -fn button(attrs: List>, children: List>): Html = - Element("button", attrs, children) +fn button(attrs: List>, children: List>): Html = Element("button", attrs, children) -fn text(content: String): Html = - Text(content) +fn text(content: String): Html = Text(content) -fn class(name: String): Attr = - Class(name) +fn class(name: String): Attr = Class(name) -fn onClick(msg: M): Attr = - OnClick(msg) - -// ============================================================================ -// Model - The application state (using ADT wrapper) -// ============================================================================ +fn onClick(msg: M): Attr = OnClick(msg) type Model = | Counter(Int) fn getCount(model: Model): Int = match model { - Counter(n) => n - } + Counter(n) => n, +} fn init(): Model = Counter(0) -// ============================================================================ -// Messages - Events that can occur -// ============================================================================ - type Msg = | Increment | Decrement | Reset -// ============================================================================ -// Update - State transitions -// ============================================================================ - fn update(model: Model, msg: Msg): Model = match msg { - Increment => Counter(getCount(model) + 1), - Decrement => Counter(getCount(model) - 1), - Reset => Counter(0) - } - -// ============================================================================ -// View - Render the UI -// ============================================================================ + Increment => Counter(getCount(model) + 1), + Decrement => Counter(getCount(model) - 1), + Reset => Counter(0), +} fn viewCounter(count: Int): Html = { let countText = text(toString(count)) let countSpan = span([class("count")], [countText]) let displayDiv = div([class("counter-display")], [countSpan]) - let minusBtn = button([onClick(Decrement), class("btn")], [text("-")]) let resetBtn = button([onClick(Reset), class("btn btn-reset")], [text("Reset")]) let plusBtn = button([onClick(Increment), class("btn")], [text("+")]) let buttonsDiv = div([class("counter-buttons")], [minusBtn, resetBtn, plusBtn]) - let title = h1([], [text("Counter")]) div([class("counter-app")], [title, displayDiv, buttonsDiv]) } fn view(model: Model): Html = viewCounter(getCount(model)) -// ============================================================================ -// Debug: Print Html structure -// ============================================================================ - fn showAttr(attr: Attr): String = match attr { - Class(s) => "class=\"" + s + "\"", - Id(s) => "id=\"" + s + "\"", - OnClick(msg) => match msg { - Increment => "onclick=\"Increment\"", - Decrement => "onclick=\"Decrement\"", - Reset => "onclick=\"Reset\"" - } - } + Class(s) => "class=\"" + s + "\"", + Id(s) => "id=\"" + s + "\"", + OnClick(msg) => match msg { + Increment => "onclick=\"Increment\"", + Decrement => "onclick=\"Decrement\"", + Reset => "onclick=\"Reset\"", +}, +} fn showAttrs(attrs: List>): String = match List.head(attrs) { - None => "", - Some(a) => match List.tail(attrs) { - None => showAttr(a), - Some(rest) => showAttr(a) + " " + showAttrs(rest) - } - } + None => "", + Some(a) => match List.tail(attrs) { + None => showAttr(a), + Some(rest) => showAttr(a) + " " + showAttrs(rest), +}, +} fn showChildren(children: List>, indent: Int): String = match List.head(children) { - None => "", - Some(c) => match List.tail(children) { - None => showHtml(c, indent), - Some(rest) => showHtml(c, indent) + showChildren(rest, indent) - } - } + None => "", + Some(c) => match List.tail(children) { + None => showHtml(c, indent), + Some(rest) => showHtml(c, indent) + showChildren(rest, indent), +}, +} fn showHtml(html: Html, indent: Int): String = match html { - Empty => "", - Text(s) => s, - Element(tag, attrs, children) => { - let attrStr = showAttrs(attrs) - let attrPart = if String.length(attrStr) > 0 then " " + attrStr else "" - let childStr = showChildren(children, indent + 2) - "<" + tag + attrPart + ">" + childStr + "" - } - } - -// ============================================================================ -// Entry point -// ============================================================================ + Empty => "", + Text(s) => s, + Element(tag, attrs, children) => { + let attrStr = showAttrs(attrs) + let attrPart = if String.length(attrStr) > 0 then " " + attrStr else "" + let childStr = showChildren(children, indent + 2) + "<" + tag + attrPart + ">" + childStr + "" +}, +} fn main(): Unit with {Console} = { let model = init() @@ -150,24 +105,19 @@ fn main(): Unit with {Console} = { Console.print("") Console.print("Initial count: " + toString(getCount(model))) Console.print("") - let m1 = update(model, Increment) Console.print("After Increment: " + toString(getCount(m1))) - let m2 = update(m1, Increment) Console.print("After Increment: " + toString(getCount(m2))) - let m3 = update(m2, Increment) Console.print("After Increment: " + toString(getCount(m3))) - let m4 = update(m3, Decrement) Console.print("After Decrement: " + toString(getCount(m4))) - let m5 = update(m4, Reset) Console.print("After Reset: " + toString(getCount(m5))) - Console.print("") Console.print("=== View (HTML Structure) ===") Console.print(showHtml(view(m2), 0)) } + let output = run main() with {} diff --git a/examples/datatypes.lux b/examples/datatypes.lux index 5994694..46152c2 100644 --- a/examples/datatypes.lux +++ b/examples/datatypes.lux @@ -1,57 +1,37 @@ -// Demonstrating algebraic data types and pattern matching -// -// Expected output: -// Tree sum: 8 -// Tree depth: 3 -// Safe divide 10/2: Result: 5 -// Safe divide 10/0: Division by zero! - -// Define a binary tree type Tree = | Leaf(Int) | Node(Tree, Tree) -// Sum all values in a tree fn sumTree(tree: Tree): Int = match tree { - Leaf(n) => n, - Node(left, right) => sumTree(left) + sumTree(right) - } + Leaf(n) => n, + Node(left, right) => sumTree(left) + sumTree(right), +} -// Find the depth of a tree fn depth(tree: Tree): Int = match tree { - Leaf(_) => 1, - Node(left, right) => { - let leftDepth = depth(left) - let rightDepth = depth(right) - 1 + (if leftDepth > rightDepth then leftDepth else rightDepth) - } - } - -// Example tree: -// Node -// / \ -// Node Leaf(5) -// / \ -// Leaf(1) Leaf(2) + Leaf(_) => 1, + Node(left, right) => { + let leftDepth = depth(left) + let rightDepth = depth(right) + 1 + if leftDepth > rightDepth then leftDepth else rightDepth +}, +} let myTree = Node(Node(Leaf(1), Leaf(2)), Leaf(5)) + let treeSum = sumTree(myTree) + let treeDepth = depth(myTree) -// Option type example -fn safeDivide(a: Int, b: Int): Option = - if b == 0 then None - else Some(a / b) +fn safeDivide(a: Int, b: Int): Option = if b == 0 then None else Some(a / b) fn showResult(result: Option): String = match result { - None => "Division by zero!", - Some(n) => "Result: " + toString(n) - } + None => "Division by zero!", + Some(n) => "Result: " + toString(n), +} -// Print results fn printResults(): Unit with {Console} = { Console.print("Tree sum: " + toString(treeSum)) Console.print("Tree depth: " + toString(treeDepth)) diff --git a/examples/effects.lux b/examples/effects.lux index ba02ae6..33ff506 100644 --- a/examples/effects.lux +++ b/examples/effects.lux @@ -1,17 +1,8 @@ -// Demonstrating algebraic effects in Lux -// -// Expected output: -// [info] Processing data... -// [debug] Result computed -// Final result: 42 - -// Define a custom logging effect effect Logger { fn log(level: String, msg: String): Unit fn getLevel(): String } -// A function that uses the Logger effect fn processData(data: Int): Int with {Logger} = { Logger.log("info", "Processing data...") let result = data * 2 @@ -19,17 +10,15 @@ fn processData(data: Int): Int with {Logger} = { result } -// A handler that prints logs to console handler consoleLogger: Logger { fn log(level, msg) = Console.print("[" + level + "] " + msg) fn getLevel() = "debug" } -// Run and print fn main(): Unit with {Console} = { let result = run processData(21) with { - Logger = consoleLogger - } + Logger = consoleLogger, +} Console.print("Final result: " + toString(result)) } diff --git a/examples/factorial.lux b/examples/factorial.lux index 177ecdf..a2ca893 100644 --- a/examples/factorial.lux +++ b/examples/factorial.lux @@ -1,16 +1,7 @@ -// Factorial function demonstrating recursion -// -// Expected output: 10! = 3628800 +fn factorial(n: Int): Int = if n <= 1 then 1 else n * factorial(n - 1) -fn factorial(n: Int): Int = - if n <= 1 then 1 - else n * factorial(n - 1) - -// Calculate factorial of 10 let result = factorial(10) -// Print result using Console effect -fn showResult(): Unit with {Console} = - Console.print("10! = " + toString(result)) +fn showResult(): Unit with {Console} = Console.print("10! = " + toString(result)) let output = run showResult() with {} diff --git a/examples/file_io.lux b/examples/file_io.lux index 0c7f643..2a9b13c 100644 --- a/examples/file_io.lux +++ b/examples/file_io.lux @@ -1,9 +1,6 @@ -// File I/O example - demonstrates the File effect -// -// This script reads a file, counts lines/words, and writes a report - fn countLines(content: String): Int = { - let lines = String.split(content, "\n") + let lines = String.split(content, " +") List.length(lines) } @@ -14,35 +11,28 @@ fn countWords(content: String): Int = { fn analyzeFile(path: String): Unit with {File, Console} = { Console.print("Analyzing file: " + path) - if File.exists(path) then { - let content = File.read(path) - let lines = countLines(content) - let words = countWords(content) - let chars = String.length(content) - - Console.print(" Lines: " + toString(lines)) - Console.print(" Words: " + toString(words)) - Console.print(" Chars: " + toString(chars)) - } else { - Console.print(" Error: File not found!") - } + let content = File.read(path) + let lines = countLines(content) + let words = countWords(content) + let chars = String.length(content) + Console.print(" Lines: " + toString(lines)) + Console.print(" Words: " + toString(words)) + Console.print(" Chars: " + toString(chars)) +} else { + Console.print(" Error: File not found!") +} } fn main(): Unit with {File, Console} = { Console.print("=== Lux File Analyzer ===") Console.print("") - - // Analyze this file itself analyzeFile("examples/file_io.lux") Console.print("") - - // Analyze hello.lux analyzeFile("examples/hello.lux") Console.print("") - - // Write a report - let report = "File analysis complete.\nAnalyzed 2 files." + let report = "File analysis complete. +Analyzed 2 files." File.write("/tmp/lux_report.txt", report) Console.print("Report written to /tmp/lux_report.txt") } diff --git a/examples/functional.lux b/examples/functional.lux index ea56581..cbbb055 100644 --- a/examples/functional.lux +++ b/examples/functional.lux @@ -1,55 +1,39 @@ -// Demonstrating functional programming features -// -// Expected output: -// apply(double, 21) = 42 -// compose(addOne, double)(5) = 11 -// pipe: 5 |> double |> addOne |> square = 121 -// curried add5(10) = 15 -// partial times3(7) = 21 -// record transform = 30 - -// Higher-order functions fn apply(f: fn(Int): Int, x: Int): Int = f(x) -fn compose(f: fn(Int): Int, g: fn(Int): Int): fn(Int): Int = - fn(x: Int): Int => f(g(x)) +fn compose(f: fn(Int): Int, g: fn(Int): Int): fn(Int): Int = fn(x: Int): Int => f(g(x)) -// Basic functions fn double(x: Int): Int = x * 2 + fn addOne(x: Int): Int = x + 1 + fn square(x: Int): Int = x * x -// Using apply let result1 = apply(double, 21) -// Using compose let doubleAndAddOne = compose(addOne, double) + let result2 = doubleAndAddOne(5) -// Using the pipe operator -let result3 = 5 |> double |> addOne |> square +let result3 = square(addOne(double(5))) -// Currying example -fn add(a: Int): fn(Int): Int = - fn(b: Int): Int => a + b +fn add(a: Int): fn(Int): Int = fn(b: Int): Int => a + b let add5 = add(5) + let result4 = add5(10) -// Partial application simulation fn multiply(a: Int, b: Int): Int = a * b let times3 = fn(x: Int): Int => multiply(3, x) + let result5 = times3(7) -// Working with records -let transform = fn(record: { x: Int, y: Int }): Int => - record.x + record.y +let transform = fn(record: { x: Int, y: Int }): Int => record.x + record.y let point = { x: 10, y: 20 } + let recordSum = transform(point) -// Print all results fn printResults(): Unit with {Console} = { Console.print("apply(double, 21) = " + toString(result1)) Console.print("compose(addOne, double)(5) = " + toString(result2)) diff --git a/examples/generics.lux b/examples/generics.lux index 13f32ff..6520ebe 100644 --- a/examples/generics.lux +++ b/examples/generics.lux @@ -1,54 +1,43 @@ -// Demonstrating generic type parameters in Lux -// -// Expected output: -// identity(42) = 42 -// identity("hello") = hello -// first(MkPair(1, "one")) = 1 -// second(MkPair(1, "one")) = one -// map(Some(21), double) = Some(42) - -// Generic identity function fn identity(x: T): T = x -// Generic pair type type Pair = | MkPair(A, B) fn first(p: Pair): A = match p { - MkPair(a, _) => a - } + MkPair(a, _) => a, +} fn second(p: Pair): B = match p { - MkPair(_, b) => b - } + MkPair(_, b) => b, +} -// Generic map function for Option fn mapOption(opt: Option, f: fn(T): U): Option = match opt { - None => None, - Some(x) => Some(f(x)) - } + None => None, + Some(x) => Some(f(x)), +} -// Helper function for testing fn double(x: Int): Int = x * 2 -// Test usage let id_int = identity(42) + let id_str = identity("hello") let pair = MkPair(1, "one") + let fst = first(pair) + let snd = second(pair) let doubled = mapOption(Some(21), double) fn showOption(opt: Option): String = match opt { - None => "None", - Some(x) => "Some(" + toString(x) + ")" - } + None => "None", + Some(x) => "Some(" + toString(x) + ")", +} fn printResults(): Unit with {Console} = { Console.print("identity(42) = " + toString(id_int)) diff --git a/examples/handlers.lux b/examples/handlers.lux index 986dd87..5bf3485 100644 --- a/examples/handlers.lux +++ b/examples/handlers.lux @@ -1,21 +1,8 @@ -// Demonstrating resumable effect handlers in Lux -// -// Handlers can use `resume(value)` to return a value to the effect call site -// and continue the computation. This enables powerful control flow patterns. -// -// Expected output: -// [INFO] Starting computation -// [DEBUG] Intermediate result: 10 -// [INFO] Computation complete -// Final result: 20 - -// Define a custom logging effect effect Logger { fn log(level: String, msg: String): Unit fn getLogLevel(): String } -// A function that uses the Logger effect fn compute(): Int with {Logger} = { Logger.log("INFO", "Starting computation") let x = 10 @@ -25,20 +12,19 @@ fn compute(): Int with {Logger} = { result } -// A handler that prints logs with brackets and resumes with Unit handler prettyLogger: Logger { - fn log(level, msg) = { - Console.print("[" + level + "] " + msg) - resume(()) - } + fn log(level, msg) = + { + Console.print("[" + level + "] " + msg) + resume(()) +} fn getLogLevel() = resume("DEBUG") } -// Main function fn main(): Unit with {Console} = { let result = run compute() with { - Logger = prettyLogger - } + Logger = prettyLogger, +} Console.print("Final result: " + toString(result)) } diff --git a/examples/hello.lux b/examples/hello.lux index b95096a..f1f6b7a 100644 --- a/examples/hello.lux +++ b/examples/hello.lux @@ -1,10 +1,3 @@ -// Hello World in Lux -// Demonstrates basic effect usage -// -// Expected output: Hello, World! +fn greet(): Unit with {Console} = Console.print("Hello, World!") -fn greet(): Unit with {Console} = - Console.print("Hello, World!") - -// Run the greeting with the Console effect let output = run greet() with {} diff --git a/examples/http.lux b/examples/http.lux index 33c8fa6..6476e6d 100644 --- a/examples/http.lux +++ b/examples/http.lux @@ -1,91 +1,72 @@ -// HTTP example - demonstrates the Http effect -// -// This script makes HTTP requests and parses JSON responses - fn main(): Unit with {Console, Http} = { Console.print("=== Lux HTTP Example ===") Console.print("") - - // Make a GET request to a public API Console.print("Fetching data from httpbin.org...") Console.print("") - match Http.get("https://httpbin.org/get") { - Ok(response) => { - Console.print("GET request successful!") - Console.print(" Status: " + toString(response.status)) - Console.print(" Body length: " + toString(String.length(response.body)) + " bytes") - Console.print("") - - // Parse the JSON response - match Json.parse(response.body) { - Ok(json) => { - Console.print("Parsed JSON response:") - match Json.get(json, "origin") { - Some(origin) => match Json.asString(origin) { - Some(ip) => Console.print(" Your IP: " + ip), - None => Console.print(" origin: (not a string)") - }, - None => Console.print(" origin: (not found)") - } - match Json.get(json, "url") { - Some(url) => match Json.asString(url) { - Some(u) => Console.print(" URL: " + u), - None => Console.print(" url: (not a string)") - }, - None => Console.print(" url: (not found)") - } - }, - Err(e) => Console.print("JSON parse error: " + e) - } - }, - Err(e) => Console.print("GET request failed: " + e) - } - + Ok(response) => { + Console.print("GET request successful!") + Console.print(" Status: " + toString(response.status)) + Console.print(" Body length: " + toString(String.length(response.body)) + " bytes") + Console.print("") + match Json.parse(response.body) { + Ok(json) => { + Console.print("Parsed JSON response:") + match Json.get(json, "origin") { + Some(origin) => match Json.asString(origin) { + Some(ip) => Console.print(" Your IP: " + ip), + None => Console.print(" origin: (not a string)"), +}, + None => Console.print(" origin: (not found)"), +} + match Json.get(json, "url") { + Some(url) => match Json.asString(url) { + Some(u) => Console.print(" URL: " + u), + None => Console.print(" url: (not a string)"), +}, + None => Console.print(" url: (not found)"), +} +}, + Err(e) => Console.print("JSON parse error: " + e), +} +}, + Err(e) => Console.print("GET request failed: " + e), +} Console.print("") Console.print("--- POST Request ---") Console.print("") - - // Make a POST request with JSON body let requestBody = Json.object([("message", Json.string("Hello from Lux!")), ("version", Json.int(1))]) Console.print("Sending POST with JSON body...") Console.print(" Body: " + Json.stringify(requestBody)) Console.print("") - match Http.postJson("https://httpbin.org/post", requestBody) { - Ok(response) => { - Console.print("POST request successful!") - Console.print(" Status: " + toString(response.status)) - - // Parse and extract what we sent - match Json.parse(response.body) { - Ok(json) => match Json.get(json, "json") { - Some(sentJson) => { - Console.print(" Server received:") - Console.print(" " + Json.stringify(sentJson)) - }, - None => Console.print(" (no json field in response)") - }, - Err(e) => Console.print("JSON parse error: " + e) - } - }, - Err(e) => Console.print("POST request failed: " + e) - } - + Ok(response) => { + Console.print("POST request successful!") + Console.print(" Status: " + toString(response.status)) + match Json.parse(response.body) { + Ok(json) => match Json.get(json, "json") { + Some(sentJson) => { + Console.print(" Server received:") + Console.print(" " + Json.stringify(sentJson)) +}, + None => Console.print(" (no json field in response)"), +}, + Err(e) => Console.print("JSON parse error: " + e), +} +}, + Err(e) => Console.print("POST request failed: " + e), +} Console.print("") Console.print("--- Headers ---") Console.print("") - - // Show response headers match Http.get("https://httpbin.org/headers") { - Ok(response) => { - Console.print("Response headers (first 5):") - let count = 0 - // Note: Can't easily iterate with effects in callbacks, so just show count - Console.print(" Total headers: " + toString(List.length(response.headers))) - }, - Err(e) => Console.print("Request failed: " + e) - } + Ok(response) => { + Console.print("Response headers (first 5):") + let count = 0 + Console.print(" Total headers: " + toString(List.length(response.headers))) +}, + Err(e) => Console.print("Request failed: " + e), +} } let result = run main() with {} diff --git a/examples/http_api.lux b/examples/http_api.lux index 40f270d..855b376 100644 --- a/examples/http_api.lux +++ b/examples/http_api.lux @@ -1,85 +1,48 @@ -// HTTP API Example -// -// A complete REST API demonstrating: -// - Route matching with path parameters -// - Response builders -// - JSON construction -// -// Run with: lux examples/http_api.lux -// Test with: -// curl http://localhost:8080/ -// curl http://localhost:8080/users -// curl http://localhost:8080/users/42 +fn httpOk(body: String): { status: Int, body: String } = { status: 200, body: body } -// ============================================================ -// Response Helpers -// ============================================================ +fn httpCreated(body: String): { status: Int, body: String } = { status: 201, body: body } -fn httpOk(body: String): { status: Int, body: String } = - { status: 200, body: body } +fn httpNotFound(body: String): { status: Int, body: String } = { status: 404, body: body } -fn httpCreated(body: String): { status: Int, body: String } = - { status: 201, body: body } +fn httpBadRequest(body: String): { status: Int, body: String } = { status: 400, body: body } -fn httpNotFound(body: String): { status: Int, body: String } = - { status: 404, body: body } +fn jsonEscape(s: String): String = String.replace(String.replace(s, "\\", "\\\\"), "\"", "\\\"") -fn httpBadRequest(body: String): { status: Int, body: String } = - { status: 400, body: body } +fn jsonStr(key: String, value: String): String = "\"" + jsonEscape(key) + "\":\"" + jsonEscape(value) + "\"" -// ============================================================ -// JSON Helpers -// ============================================================ +fn jsonNum(key: String, value: Int): String = "\"" + jsonEscape(key) + "\":" + toString(value) -fn jsonEscape(s: String): String = - String.replace(String.replace(s, "\\", "\\\\"), "\"", "\\\"") +fn jsonObj(content: String): String = toString(" + content + ") -fn jsonStr(key: String, value: String): String = - "\"" + jsonEscape(key) + "\":\"" + jsonEscape(value) + "\"" +fn jsonArr(content: String): String = "[" + content + "]" -fn jsonNum(key: String, value: Int): String = - "\"" + jsonEscape(key) + "\":" + toString(value) - -fn jsonObj(content: String): String = - "{" + content + "}" - -fn jsonArr(content: String): String = - "[" + content + "]" - -fn jsonError(message: String): String = - jsonObj(jsonStr("error", message)) - -// ============================================================ -// Path Matching -// ============================================================ +fn jsonError(message: String): String = jsonObj(jsonStr("error", message)) fn pathMatches(path: String, pattern: String): Bool = { let pathParts = String.split(path, "/") let patternParts = String.split(pattern, "/") - if List.length(pathParts) != List.length(patternParts) then false - else matchParts(pathParts, patternParts) + if List.length(pathParts) != List.length(patternParts) then false else matchParts(pathParts, patternParts) } fn matchParts(pathParts: List, patternParts: List): Bool = { - if List.length(pathParts) == 0 then true - else { - match List.head(pathParts) { - None => true, - Some(pathPart) => { - match List.head(patternParts) { - None => true, - Some(patternPart) => { - let isMatch = if String.startsWith(patternPart, ":") then true else pathPart == patternPart - if isMatch then { - let restPath = Option.getOrElse(List.tail(pathParts), []) - let restPattern = Option.getOrElse(List.tail(patternParts), []) - matchParts(restPath, restPattern) - } else false - } - } - } - } - } + if List.length(pathParts) == 0 then true else { + match List.head(pathParts) { + None => true, + Some(pathPart) => { + match List.head(patternParts) { + None => true, + Some(patternPart) => { + let isMatch = if String.startsWith(patternPart, ":") then true else pathPart == patternPart + if isMatch then { + let restPath = Option.getOrElse(List.tail(pathParts), []) + let restPattern = Option.getOrElse(List.tail(patternParts), []) + matchParts(restPath, restPattern) +} else false +}, +} +}, +} +} } fn getPathSegment(path: String, index: Int): Option = { @@ -87,15 +50,9 @@ fn getPathSegment(path: String, index: Int): Option = { List.get(parts, index + 1) } -// ============================================================ -// Handlers -// ============================================================ +fn indexHandler(): { status: Int, body: String } = httpOk(jsonObj(jsonStr("message", "Welcome to Lux HTTP API"))) -fn indexHandler(): { status: Int, body: String } = - httpOk(jsonObj(jsonStr("message", "Welcome to Lux HTTP API"))) - -fn healthHandler(): { status: Int, body: String } = - httpOk(jsonObj(jsonStr("status", "healthy"))) +fn healthHandler(): { status: Int, body: String } = httpOk(jsonObj(jsonStr("status", "healthy"))) fn listUsersHandler(): { status: Int, body: String } = { let user1 = jsonObj(jsonNum("id", 1) + "," + jsonStr("name", "Alice")) @@ -105,12 +62,12 @@ fn listUsersHandler(): { status: Int, body: String } = { fn getUserHandler(path: String): { status: Int, body: String } = { match getPathSegment(path, 1) { - Some(id) => { - let body = jsonObj(jsonStr("id", id) + "," + jsonStr("name", "User " + id)) - httpOk(body) - }, - None => httpNotFound(jsonError("User not found")) - } + Some(id) => { + let body = jsonObj(jsonStr("id", id) + "," + jsonStr("name", "User " + id)) + httpOk(body) +}, + None => httpNotFound(jsonError("User not found")), +} } fn createUserHandler(body: String): { status: Int, body: String } = { @@ -118,34 +75,21 @@ fn createUserHandler(body: String): { status: Int, body: String } = { httpCreated(newUser) } -// ============================================================ -// Router -// ============================================================ - fn router(method: String, path: String, body: String): { status: Int, body: String } = { - if method == "GET" && path == "/" then indexHandler() - else if method == "GET" && path == "/health" then healthHandler() - else if method == "GET" && path == "/users" then listUsersHandler() - else if method == "GET" && pathMatches(path, "/users/:id") then getUserHandler(path) - else if method == "POST" && path == "/users" then createUserHandler(body) - else httpNotFound(jsonError("Not found: " + path)) + if method == "GET" && path == "/" then indexHandler() else if method == "GET" && path == "/health" then healthHandler() else if method == "GET" && path == "/users" then listUsersHandler() else if method == "GET" && pathMatches(path, "/users/:id") then getUserHandler(path) else if method == "POST" && path == "/users" then createUserHandler(body) else httpNotFound(jsonError("Not found: " + path)) } -// ============================================================ -// Server -// ============================================================ - fn serveLoop(remaining: Int): Unit with {Console, HttpServer} = { if remaining <= 0 then { - Console.print("Max requests reached, stopping server.") - HttpServer.stop() - } else { - let req = HttpServer.accept() - Console.print(req.method + " " + req.path) - let resp = router(req.method, req.path, req.body) - HttpServer.respond(resp.status, resp.body) - serveLoop(remaining - 1) - } + Console.print("Max requests reached, stopping server.") + HttpServer.stop() +} else { + let req = HttpServer.accept() + Console.print(req.method + " " + req.path) + let resp = router(req.method, req.path, req.body) + HttpServer.respond(resp.status, resp.body) + serveLoop(remaining - 1) +} } fn main(): Unit with {Console, HttpServer} = { diff --git a/examples/http_router.lux b/examples/http_router.lux index 2c77718..d66fa76 100644 --- a/examples/http_router.lux +++ b/examples/http_router.lux @@ -1,24 +1,4 @@ -// HTTP Router Example -// -// Demonstrates the HTTP helper library with: -// - Path pattern matching -// - Response builders -// - JSON helpers -// -// Run with: lux examples/http_router.lux -// Test with: -// curl http://localhost:8080/ -// curl http://localhost:8080/users -// curl http://localhost:8080/users/42 - -import stdlib/http - -// ============================================================ -// Route Handlers -// ============================================================ - -fn indexHandler(): { status: Int, body: String } = - httpOk("Welcome to Lux HTTP Framework!") +fn indexHandler(): { status: Int, body: String } = httpOk("Welcome to Lux HTTP Framework!") fn listUsersHandler(): { status: Int, body: String } = { let user1 = jsonObject(jsonJoin([jsonNumber("id", 1), jsonString("name", "Alice")])) @@ -29,44 +9,31 @@ fn listUsersHandler(): { status: Int, body: String } = { fn getUserHandler(path: String): { status: Int, body: String } = { match getPathSegment(path, 1) { - Some(id) => { - let body = jsonObject(jsonJoin([jsonString("id", id), jsonString("name", "User " + id)])) - httpOk(body) - }, - None => httpNotFound(jsonErrorMsg("User ID required")) - } + Some(id) => { + let body = jsonObject(jsonJoin([jsonString("id", id), jsonString("name", "User " + id)])) + httpOk(body) +}, + None => httpNotFound(jsonErrorMsg("User ID required")), +} } -fn healthHandler(): { status: Int, body: String } = - httpOk(jsonObject(jsonString("status", "healthy"))) - -// ============================================================ -// Router -// ============================================================ +fn healthHandler(): { status: Int, body: String } = httpOk(jsonObject(jsonString("status", "healthy"))) fn router(method: String, path: String, body: String): { status: Int, body: String } = { - if method == "GET" && path == "/" then indexHandler() - else if method == "GET" && path == "/health" then healthHandler() - else if method == "GET" && path == "/users" then listUsersHandler() - else if method == "GET" && pathMatches(path, "/users/:id") then getUserHandler(path) - else httpNotFound(jsonErrorMsg("Not found: " + path)) + if method == "GET" && path == "/" then indexHandler() else if method == "GET" && path == "/health" then healthHandler() else if method == "GET" && path == "/users" then listUsersHandler() else if method == "GET" && pathMatches(path, "/users/:id") then getUserHandler(path) else httpNotFound(jsonErrorMsg("Not found: " + path)) } -// ============================================================ -// Server -// ============================================================ - fn serveLoop(remaining: Int): Unit with {Console, HttpServer} = { if remaining <= 0 then { - Console.print("Max requests reached, stopping server.") - HttpServer.stop() - } else { - let req = HttpServer.accept() - Console.print(req.method + " " + req.path) - let resp = router(req.method, req.path, req.body) - HttpServer.respond(resp.status, resp.body) - serveLoop(remaining - 1) - } + Console.print("Max requests reached, stopping server.") + HttpServer.stop() +} else { + let req = HttpServer.accept() + Console.print(req.method + " " + req.path) + let resp = router(req.method, req.path, req.body) + HttpServer.respond(resp.status, resp.body) + serveLoop(remaining - 1) +} } fn main(): Unit with {Console, HttpServer} = { diff --git a/examples/jit_test.lux b/examples/jit_test.lux index c935b09..34395f8 100644 --- a/examples/jit_test.lux +++ b/examples/jit_test.lux @@ -1,13 +1,6 @@ -// Test file for JIT compilation -// This uses only features the JIT supports: integers, arithmetic, conditionals, functions +fn fib(n: Int): Int = if n <= 1 then n else fib(n - 1) + fib(n - 2) -fn fib(n: Int): Int = - if n <= 1 then n - else fib(n - 1) + fib(n - 2) - -fn factorial(n: Int): Int = - if n <= 1 then 1 - else n * factorial(n - 1) +fn factorial(n: Int): Int = if n <= 1 then 1 else n * factorial(n - 1) fn main(): Unit with {Console} = { let fibResult = fib(30) diff --git a/examples/json.lux b/examples/json.lux index 028a880..8ff4df6 100644 --- a/examples/json.lux +++ b/examples/json.lux @@ -1,107 +1,79 @@ -// JSON example - demonstrates JSON parsing and manipulation -// -// This script parses JSON, extracts values, and builds new JSON structures - fn main(): Unit with {Console, File} = { Console.print("=== Lux JSON Example ===") Console.print("") - - // First, build some JSON programmatically Console.print("=== Building JSON ===") Console.print("") - let name = Json.string("Alice") let age = Json.int(30) let active = Json.bool(true) let scores = Json.array([Json.int(95), Json.int(87), Json.int(92)]) - let person = Json.object([("name", name), ("age", age), ("active", active), ("scores", scores)]) - Console.print("Built JSON:") let pretty = Json.prettyPrint(person) Console.print(pretty) Console.print("") - - // Stringify to a compact string let jsonStr = Json.stringify(person) Console.print("Compact: " + jsonStr) Console.print("") - - // Write to file and read back to test parsing File.write("/tmp/test.json", jsonStr) Console.print("Written to /tmp/test.json") Console.print("") - - // Read and parse from file Console.print("=== Parsing JSON ===") Console.print("") let content = File.read("/tmp/test.json") Console.print("Read from file: " + content) Console.print("") - match Json.parse(content) { - Ok(json) => { - Console.print("Parse succeeded!") - Console.print("") - - // Get string field - Console.print("Extracting fields:") - match Json.get(json, "name") { - Some(nameJson) => match Json.asString(nameJson) { - Some(n) => Console.print(" name: " + n), - None => Console.print(" name: (not a string)") - }, - None => Console.print(" name: (not found)") - } - - // Get int field - match Json.get(json, "age") { - Some(ageJson) => match Json.asInt(ageJson) { - Some(a) => Console.print(" age: " + toString(a)), - None => Console.print(" age: (not an int)") - }, - None => Console.print(" age: (not found)") - } - - // Get bool field - match Json.get(json, "active") { - Some(activeJson) => match Json.asBool(activeJson) { - Some(a) => Console.print(" active: " + toString(a)), - None => Console.print(" active: (not a bool)") - }, - None => Console.print(" active: (not found)") - } - - // Get array field - match Json.get(json, "scores") { - Some(scoresJson) => match Json.asArray(scoresJson) { - Some(arr) => { - Console.print(" scores: " + toString(List.length(arr)) + " items") - // Get first score - match Json.getIndex(scoresJson, 0) { - Some(firstJson) => match Json.asInt(firstJson) { - Some(first) => Console.print(" first score: " + toString(first)), - None => Console.print(" first score: (not an int)") - }, - None => Console.print(" (no first element)") - } - }, - None => Console.print(" scores: (not an array)") - }, - None => Console.print(" scores: (not found)") - } - Console.print("") - - // Get the keys - Console.print("Object keys:") - match Json.keys(json) { - Some(ks) => Console.print(" " + String.join(ks, ", ")), - None => Console.print(" (not an object)") - } - }, - Err(e) => Console.print("Parse error: " + e) - } - + Ok(json) => { + Console.print("Parse succeeded!") + Console.print("") + Console.print("Extracting fields:") + match Json.get(json, "name") { + Some(nameJson) => match Json.asString(nameJson) { + Some(n) => Console.print(" name: " + n), + None => Console.print(" name: (not a string)"), +}, + None => Console.print(" name: (not found)"), +} + match Json.get(json, "age") { + Some(ageJson) => match Json.asInt(ageJson) { + Some(a) => Console.print(" age: " + toString(a)), + None => Console.print(" age: (not an int)"), +}, + None => Console.print(" age: (not found)"), +} + match Json.get(json, "active") { + Some(activeJson) => match Json.asBool(activeJson) { + Some(a) => Console.print(" active: " + toString(a)), + None => Console.print(" active: (not a bool)"), +}, + None => Console.print(" active: (not found)"), +} + match Json.get(json, "scores") { + Some(scoresJson) => match Json.asArray(scoresJson) { + Some(arr) => { + Console.print(" scores: " + toString(List.length(arr)) + " items") + match Json.getIndex(scoresJson, 0) { + Some(firstJson) => match Json.asInt(firstJson) { + Some(first) => Console.print(" first score: " + toString(first)), + None => Console.print(" first score: (not an int)"), +}, + None => Console.print(" (no first element)"), +} +}, + None => Console.print(" scores: (not an array)"), +}, + None => Console.print(" scores: (not found)"), +} + Console.print("") + Console.print("Object keys:") + match Json.keys(json) { + Some(ks) => Console.print(" " + String.join(ks, ", ")), + None => Console.print(" (not an object)"), +} +}, + Err(e) => Console.print("Parse error: " + e), +} Console.print("") Console.print("=== JSON Null Check ===") let nullVal = Json.null() diff --git a/examples/modules/main.lux b/examples/modules/main.lux index 1e20fef..54cc45e 100644 --- a/examples/modules/main.lux +++ b/examples/modules/main.lux @@ -1,17 +1,9 @@ -// Main program that imports modules -import examples/modules/math_utils -import examples/modules/string_utils - fn main(): Unit with {Console} = { Console.print("=== Testing Module Imports ===") - - // Use math_utils Console.print("square(5) = " + toString(math_utils.square(5))) Console.print("cube(3) = " + toString(math_utils.cube(3))) Console.print("factorial(6) = " + toString(math_utils.factorial(6))) Console.print("sumRange(1, 10) = " + toString(math_utils.sumRange(1, 10))) - - // Use string_utils Console.print(string_utils.greet("World")) Console.print(string_utils.exclaim("Modules work")) Console.print("repeat(\"ab\", 3) = " + string_utils.repeat("ab", 3)) diff --git a/examples/modules/main_selective.lux b/examples/modules/main_selective.lux index e20ccda..e1b7c55 100644 --- a/examples/modules/main_selective.lux +++ b/examples/modules/main_selective.lux @@ -1,15 +1,7 @@ -// Test selective imports -import examples/modules/math_utils.{square, factorial} -import examples/modules/string_utils as str - fn main(): Unit with {Console} = { Console.print("=== Selective & Aliased Imports ===") - - // Direct imports (no module prefix) Console.print("square(7) = " + toString(square(7))) Console.print("factorial(5) = " + toString(factorial(5))) - - // Aliased import Console.print(str.greet("Lux")) Console.print(str.exclaim("Aliased imports work")) } diff --git a/examples/modules/main_wildcard.lux b/examples/modules/main_wildcard.lux index 5edcfc4..741e851 100644 --- a/examples/modules/main_wildcard.lux +++ b/examples/modules/main_wildcard.lux @@ -1,10 +1,5 @@ -// Test wildcard imports -import examples/modules/math_utils.* - fn main(): Unit with {Console} = { Console.print("=== Wildcard Imports ===") - - // All functions available directly Console.print("square(4) = " + toString(square(4))) Console.print("cube(4) = " + toString(cube(4))) Console.print("factorial(4) = " + toString(factorial(4))) diff --git a/examples/modules/math_utils.lux b/examples/modules/math_utils.lux index 0970c2b..b0218ae 100644 --- a/examples/modules/math_utils.lux +++ b/examples/modules/math_utils.lux @@ -1,14 +1,7 @@ -// Math utilities module -// Exports: square, cube, factorial +fn square(n: Int): Int = n * n -pub fn square(n: Int): Int = n * n +fn cube(n: Int): Int = n * n * n -pub fn cube(n: Int): Int = n * n * n +fn factorial(n: Int): Int = if n <= 1 then 1 else n * factorial(n - 1) -pub fn factorial(n: Int): Int = - if n <= 1 then 1 - else n * factorial(n - 1) - -pub fn sumRange(start: Int, end: Int): Int = - if start > end then 0 - else start + sumRange(start + 1, end) +fn sumRange(start: Int, end: Int): Int = if start > end then 0 else start + sumRange(start + 1, end) diff --git a/examples/modules/string_utils.lux b/examples/modules/string_utils.lux index 72f5b88..4b99c25 100644 --- a/examples/modules/string_utils.lux +++ b/examples/modules/string_utils.lux @@ -1,11 +1,5 @@ -// String utilities module -// Exports: repeat, exclaim +fn repeat(s: String, n: Int): String = if n <= 0 then "" else s + repeat(s, n - 1) -pub fn repeat(s: String, n: Int): String = - if n <= 0 then "" - else s + repeat(s, n - 1) +fn exclaim(s: String): String = s + "!" -pub fn exclaim(s: String): String = s + "!" - -pub fn greet(name: String): String = - "Hello, " + name + "!" +fn greet(name: String): String = "Hello, " + name + "!" diff --git a/examples/modules/use_stdlib.lux b/examples/modules/use_stdlib.lux index 9af692a..61b8dc1 100644 --- a/examples/modules/use_stdlib.lux +++ b/examples/modules/use_stdlib.lux @@ -1,17 +1,9 @@ -// Example using the standard library -import std/prelude.* -import std/option as opt - fn main(): Unit with {Console} = { Console.print("=== Using Standard Library ===") - - // Prelude functions Console.print("identity(42) = " + toString(identity(42))) Console.print("not(true) = " + toString(not(true))) Console.print("and(true, false) = " + toString(and(true, false))) Console.print("or(true, false) = " + toString(or(true, false))) - - // Option utilities let x = opt.some(10) let y = opt.none() Console.print("isSome(Some(10)) = " + toString(opt.isSome(x))) diff --git a/examples/pipelines.lux b/examples/pipelines.lux index 395a079..c00e03e 100644 --- a/examples/pipelines.lux +++ b/examples/pipelines.lux @@ -1,47 +1,31 @@ -// Demonstrating the pipe operator and functional data processing -// -// Expected output: -// 5 |> double |> addTen |> square = 400 -// Pipeline result2 = 42 -// process(1) = 144 -// process(2) = 196 -// process(3) = 256 -// clamped = 0 -// composed = 121 - -// Basic transformations fn double(x: Int): Int = x * 2 + fn addTen(x: Int): Int = x + 10 + fn square(x: Int): Int = x * x + fn negate(x: Int): Int = -x -// Using the pipe operator for data transformation -let result1 = 5 |> double |> addTen |> square +let result1 = square(addTen(double(5))) -// Chaining multiple operations -let result2 = 3 |> double |> addTen |> double |> addTen +let result2 = addTen(double(addTen(double(3)))) -// More complex pipelines -fn process(n: Int): Int = - n |> double |> addTen |> square +fn process(n: Int): Int = square(addTen(double(n))) -// Multiple values through same pipeline let a = process(1) + let b = process(2) + let c = process(3) -// Conditional in pipeline -fn clampPositive(x: Int): Int = - if x < 0 then 0 else x +fn clampPositive(x: Int): Int = if x < 0 then 0 else x -let clamped = -5 |> double |> clampPositive +let clamped = clampPositive(double(-5)) -// Function composition using pipe fn increment(x: Int): Int = x + 1 -let composed = 5 |> double |> increment |> square +let composed = square(increment(double(5))) -// Print results fn printResults(): Unit with {Console} = { Console.print("5 |> double |> addTen |> square = " + toString(result1)) Console.print("Pipeline result2 = " + toString(result2)) diff --git a/examples/postgres_demo.lux b/examples/postgres_demo.lux index b26131d..d7d2f02 100644 --- a/examples/postgres_demo.lux +++ b/examples/postgres_demo.lux @@ -1,72 +1,42 @@ -// PostgreSQL Database Example -// -// Demonstrates the Postgres effect for database operations. -// -// Prerequisites: -// - PostgreSQL server running locally -// - Database 'testdb' created -// - User 'testuser' with password 'testpass' -// -// To set up: -// createdb testdb -// psql testdb -c "CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT, email TEXT);" -// -// Run with: lux examples/postgres_demo.lux +fn jsonStr(key: String, value: String): String = "\"" + key + "\":\"" + value + "\"" -// ============================================================ -// Helper Functions -// ============================================================ +fn jsonNum(key: String, value: Int): String = "\"" + key + "\":" + toString(value) -fn jsonStr(key: String, value: String): String = - "\"" + key + "\":\"" + value + "\"" +fn jsonObj(content: String): String = toString(" + content + ") -fn jsonNum(key: String, value: Int): String = - "\"" + key + "\":" + toString(value) - -fn jsonObj(content: String): String = - "{" + content + "}" - -// ============================================================ -// Database Operations -// ============================================================ - -// Insert a user fn insertUser(connId: Int, name: String, email: String): Int with {Console, Postgres} = { let sql = "INSERT INTO users (name, email) VALUES ('" + name + "', '" + email + "') RETURNING id" Console.print("Inserting user: " + name) match Postgres.queryOne(connId, sql) { - Some(row) => { - Console.print(" Inserted with ID: " + toString(row.id)) - row.id - }, - None => { - Console.print(" Insert failed") - -1 - } - } + Some(row) => { + Console.print(" Inserted with ID: " + toString(row.id)) + row.id +}, + None => { + Console.print(" Insert failed") + -1 +}, +} } -// Get all users fn getUsers(connId: Int): Unit with {Console, Postgres} = { Console.print("Fetching all users...") let rows = Postgres.query(connId, "SELECT id, name, email FROM users ORDER BY id") Console.print(" Found " + toString(List.length(rows)) + " users:") - List.forEach(rows, fn(row: { id: Int, name: String, email: String }): Unit with {Console} => { - Console.print(" - " + toString(row.id) + ": " + row.name + " <" + row.email + ">") - }) + List.forEach(rows, fn(row: { id: Int, name: String, email: String }): Unit => { + Console.print(" - " + toString(row.id) + ": " + row.name + " <" + row.email + ">") +}) } -// Get user by ID fn getUserById(connId: Int, id: Int): Unit with {Console, Postgres} = { let sql = "SELECT id, name, email FROM users WHERE id = " + toString(id) Console.print("Looking up user " + toString(id) + "...") match Postgres.queryOne(connId, sql) { - Some(row) => Console.print(" Found: " + row.name + " <" + row.email + ">"), - None => Console.print(" User not found") - } + Some(row) => Console.print(" Found: " + row.name + " <" + row.email + ">"), + None => Console.print(" User not found"), +} } -// Update user email fn updateUserEmail(connId: Int, id: Int, newEmail: String): Unit with {Console, Postgres} = { let sql = "UPDATE users SET email = '" + newEmail + "' WHERE id = " + toString(id) Console.print("Updating user " + toString(id) + " email to " + newEmail) @@ -74,7 +44,6 @@ fn updateUserEmail(connId: Int, id: Int, newEmail: String): Unit with {Console, Console.print(" Rows affected: " + toString(affected)) } -// Delete user fn deleteUser(connId: Int, id: Int): Unit with {Console, Postgres} = { let sql = "DELETE FROM users WHERE id = " + toString(id) Console.print("Deleting user " + toString(id)) @@ -82,104 +51,63 @@ fn deleteUser(connId: Int, id: Int): Unit with {Console, Postgres} = { Console.print(" Rows affected: " + toString(affected)) } -// ============================================================ -// Transaction Example -// ============================================================ - fn transactionDemo(connId: Int): Unit with {Console, Postgres} = { Console.print("") Console.print("=== Transaction Demo ===") - - // Start transaction Console.print("Beginning transaction...") Postgres.beginTx(connId) - - // Make some changes insertUser(connId, "TxUser1", "tx1@example.com") insertUser(connId, "TxUser2", "tx2@example.com") - - // Show users before commit Console.print("Users before commit:") getUsers(connId) - - // Commit the transaction Console.print("Committing transaction...") Postgres.commit(connId) - Console.print("Transaction committed!") } -// ============================================================ -// Main -// ============================================================ - fn main(): Unit with {Console, Postgres} = { Console.print("========================================") Console.print(" PostgreSQL Demo") Console.print("========================================") Console.print("") - - // Connect to database Console.print("Connecting to PostgreSQL...") let connStr = "host=localhost user=testuser password=testpass dbname=testdb" let connId = Postgres.connect(connStr) Console.print("Connected! Connection ID: " + toString(connId)) Console.print("") - - // Create table if not exists Console.print("Creating users table...") Postgres.execute(connId, "CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name TEXT NOT NULL, email TEXT NOT NULL)") Console.print("") - - // Clear table for demo Console.print("Clearing existing data...") Postgres.execute(connId, "DELETE FROM users") Console.print("") - - // Insert some users Console.print("=== Inserting Users ===") let id1 = insertUser(connId, "Alice", "alice@example.com") let id2 = insertUser(connId, "Bob", "bob@example.com") let id3 = insertUser(connId, "Charlie", "charlie@example.com") Console.print("") - - // Query all users Console.print("=== All Users ===") getUsers(connId) Console.print("") - - // Query single user Console.print("=== Single User Lookup ===") getUserById(connId, id2) Console.print("") - - // Update user Console.print("=== Update User ===") updateUserEmail(connId, id2, "bob.new@example.com") getUserById(connId, id2) Console.print("") - - // Delete user Console.print("=== Delete User ===") deleteUser(connId, id3) getUsers(connId) Console.print("") - - // Transaction demo transactionDemo(connId) Console.print("") - - // Final state Console.print("=== Final State ===") getUsers(connId) Console.print("") - - // Close connection Console.print("Closing connection...") Postgres.close(connId) Console.print("Done!") } -// Note: This will fail if PostgreSQL is not running -// To test the syntax only, you can comment out the last line let output = run main() with {} diff --git a/examples/property_testing.lux b/examples/property_testing.lux index 8e40767..45e0fc0 100644 --- a/examples/property_testing.lux +++ b/examples/property_testing.lux @@ -1,18 +1,6 @@ -// Property-Based Testing Example -// -// This example demonstrates property-based testing in Lux, -// where we verify properties hold for randomly generated inputs. -// -// Run with: lux examples/property_testing.lux - -// ============================================================ -// Generator Functions (using Random effect) -// ============================================================ - let CHARS = "abcdefghijklmnopqrstuvwxyz" -fn genInt(min: Int, max: Int): Int with {Random} = - Random.int(min, max) +fn genInt(min: Int, max: Int): Int with {Random} = Random.int(min, max) fn genIntList(min: Int, max: Int, maxLen: Int): List with {Random} = { let len = Random.int(0, maxLen) @@ -20,10 +8,7 @@ fn genIntList(min: Int, max: Int, maxLen: Int): List with {Random} = { } fn genIntListHelper(min: Int, max: Int, len: Int): List with {Random} = { - if len <= 0 then - [] - else - List.concat([Random.int(min, max)], genIntListHelper(min, max, len - 1)) + if len <= 0 then [] else List.concat([Random.int(min, max)], genIntListHelper(min, max, len - 1)) } fn genChar(): String with {Random} = { @@ -37,195 +22,147 @@ fn genString(maxLen: Int): String with {Random} = { } fn genStringHelper(len: Int): String with {Random} = { - if len <= 0 then - "" - else - genChar() + genStringHelper(len - 1) + if len <= 0 then "" else genChar() + genStringHelper(len - 1) } -// ============================================================ -// Test Runner State -// ============================================================ - fn printResult(name: String, passed: Bool, count: Int): Unit with {Console} = { - if passed then - Console.print(" PASS " + name + " (" + toString(count) + " tests)") - else - Console.print(" FAIL " + name) + if passed then Console.print(" PASS " + name + " (" + toString(count) + " tests)") else Console.print(" FAIL " + name) } -// ============================================================ -// Property Tests -// ============================================================ - -// Test: List reverse is involutive fn testReverseInvolutive(n: Int, count: Int): Bool with {Console, Random} = { if n <= 0 then { - printResult("reverse(reverse(xs)) == xs", true, count) - true - } else { - let xs = genIntList(0, 100, 20) - if List.reverse(List.reverse(xs)) == xs then - testReverseInvolutive(n - 1, count) - else { - printResult("reverse(reverse(xs)) == xs", false, count - n + 1) - false - } - } + printResult("reverse(reverse(xs)) == xs", true, count) + true +} else { + let xs = genIntList(0, 100, 20) + if List.reverse(List.reverse(xs)) == xs then testReverseInvolutive(n - 1, count) else { + printResult("reverse(reverse(xs)) == xs", false, count - n + 1) + false +} +} } -// Test: List reverse preserves length fn testReverseLength(n: Int, count: Int): Bool with {Console, Random} = { if n <= 0 then { - printResult("length(reverse(xs)) == length(xs)", true, count) - true - } else { - let xs = genIntList(0, 100, 20) - if List.length(List.reverse(xs)) == List.length(xs) then - testReverseLength(n - 1, count) - else { - printResult("length(reverse(xs)) == length(xs)", false, count - n + 1) - false - } - } + printResult("length(reverse(xs)) == length(xs)", true, count) + true +} else { + let xs = genIntList(0, 100, 20) + if List.length(List.reverse(xs)) == List.length(xs) then testReverseLength(n - 1, count) else { + printResult("length(reverse(xs)) == length(xs)", false, count - n + 1) + false +} +} } -// Test: List map preserves length fn testMapLength(n: Int, count: Int): Bool with {Console, Random} = { if n <= 0 then { - printResult("length(map(xs, f)) == length(xs)", true, count) - true - } else { - let xs = genIntList(0, 100, 20) - if List.length(List.map(xs, fn(x) => x * 2)) == List.length(xs) then - testMapLength(n - 1, count) - else { - printResult("length(map(xs, f)) == length(xs)", false, count - n + 1) - false - } - } + printResult("length(map(xs, f)) == length(xs)", true, count) + true +} else { + let xs = genIntList(0, 100, 20) + if List.length(List.map(xs, fn(x: _) => x * 2)) == List.length(xs) then testMapLength(n - 1, count) else { + printResult("length(map(xs, f)) == length(xs)", false, count - n + 1) + false +} +} } -// Test: List concat length is sum fn testConcatLength(n: Int, count: Int): Bool with {Console, Random} = { if n <= 0 then { - printResult("length(xs ++ ys) == length(xs) + length(ys)", true, count) - true - } else { - let xs = genIntList(0, 50, 10) - let ys = genIntList(0, 50, 10) - if List.length(List.concat(xs, ys)) == List.length(xs) + List.length(ys) then - testConcatLength(n - 1, count) - else { - printResult("length(xs ++ ys) == length(xs) + length(ys)", false, count - n + 1) - false - } - } + printResult("length(xs ++ ys) == length(xs) + length(ys)", true, count) + true +} else { + let xs = genIntList(0, 50, 10) + let ys = genIntList(0, 50, 10) + if List.length(List.concat(xs, ys)) == List.length(xs) + List.length(ys) then testConcatLength(n - 1, count) else { + printResult("length(xs ++ ys) == length(xs) + length(ys)", false, count - n + 1) + false +} +} } -// Test: Addition is commutative fn testAddCommutative(n: Int, count: Int): Bool with {Console, Random} = { if n <= 0 then { - printResult("a + b == b + a", true, count) - true - } else { - let a = genInt(-1000, 1000) - let b = genInt(-1000, 1000) - if a + b == b + a then - testAddCommutative(n - 1, count) - else { - printResult("a + b == b + a", false, count - n + 1) - false - } - } + printResult("a + b == b + a", true, count) + true +} else { + let a = genInt(-1000, 1000) + let b = genInt(-1000, 1000) + if a + b == b + a then testAddCommutative(n - 1, count) else { + printResult("a + b == b + a", false, count - n + 1) + false +} +} } -// Test: Multiplication is associative fn testMulAssociative(n: Int, count: Int): Bool with {Console, Random} = { if n <= 0 then { - printResult("(a * b) * c == a * (b * c)", true, count) - true - } else { - let a = genInt(-100, 100) - let b = genInt(-100, 100) - let c = genInt(-100, 100) - if (a * b) * c == a * (b * c) then - testMulAssociative(n - 1, count) - else { - printResult("(a * b) * c == a * (b * c)", false, count - n + 1) - false - } - } + printResult("(a * b) * c == a * (b * c)", true, count) + true +} else { + let a = genInt(-100, 100) + let b = genInt(-100, 100) + let c = genInt(-100, 100) + if a * b * c == a * b * c then testMulAssociative(n - 1, count) else { + printResult("(a * b) * c == a * (b * c)", false, count - n + 1) + false +} +} } -// Test: String concat length is sum fn testStringConcatLength(n: Int, count: Int): Bool with {Console, Random} = { if n <= 0 then { - printResult("length(s1 + s2) == length(s1) + length(s2)", true, count) - true - } else { - let s1 = genString(10) - let s2 = genString(10) - if String.length(s1 + s2) == String.length(s1) + String.length(s2) then - testStringConcatLength(n - 1, count) - else { - printResult("length(s1 + s2) == length(s1) + length(s2)", false, count - n + 1) - false - } - } + printResult("length(s1 + s2) == length(s1) + length(s2)", true, count) + true +} else { + let s1 = genString(10) + let s2 = genString(10) + if String.length(s1 + s2) == String.length(s1) + String.length(s2) then testStringConcatLength(n - 1, count) else { + printResult("length(s1 + s2) == length(s1) + length(s2)", false, count - n + 1) + false +} +} } -// Test: Zero is identity for addition fn testAddIdentity(n: Int, count: Int): Bool with {Console, Random} = { if n <= 0 then { - printResult("x + 0 == x && 0 + x == x", true, count) - true - } else { - let x = genInt(-10000, 10000) - if x + 0 == x && 0 + x == x then - testAddIdentity(n - 1, count) - else { - printResult("x + 0 == x && 0 + x == x", false, count - n + 1) - false - } - } + printResult("x + 0 == x && 0 + x == x", true, count) + true +} else { + let x = genInt(-10000, 10000) + if x + 0 == x && 0 + x == x then testAddIdentity(n - 1, count) else { + printResult("x + 0 == x && 0 + x == x", false, count - n + 1) + false +} +} } -// Test: Filter reduces or maintains length fn testFilterLength(n: Int, count: Int): Bool with {Console, Random} = { if n <= 0 then { - printResult("length(filter(xs, p)) <= length(xs)", true, count) - true - } else { - let xs = genIntList(0, 100, 20) - if List.length(List.filter(xs, fn(x) => x > 50)) <= List.length(xs) then - testFilterLength(n - 1, count) - else { - printResult("length(filter(xs, p)) <= length(xs)", false, count - n + 1) - false - } - } + printResult("length(filter(xs, p)) <= length(xs)", true, count) + true +} else { + let xs = genIntList(0, 100, 20) + if List.length(List.filter(xs, fn(x: _) => x > 50)) <= List.length(xs) then testFilterLength(n - 1, count) else { + printResult("length(filter(xs, p)) <= length(xs)", false, count - n + 1) + false +} +} } -// Test: Empty list is identity for concat fn testConcatIdentity(n: Int, count: Int): Bool with {Console, Random} = { if n <= 0 then { - printResult("concat(xs, []) == xs && concat([], xs) == xs", true, count) - true - } else { - let xs = genIntList(0, 100, 10) - if List.concat(xs, []) == xs && List.concat([], xs) == xs then - testConcatIdentity(n - 1, count) - else { - printResult("concat(xs, []) == xs && concat([], xs) == xs", false, count - n + 1) - false - } - } + printResult("concat(xs, []) == xs && concat([], xs) == xs", true, count) + true +} else { + let xs = genIntList(0, 100, 10) + if List.concat(xs, []) == xs && List.concat([], xs) == xs then testConcatIdentity(n - 1, count) else { + printResult("concat(xs, []) == xs && concat([], xs) == xs", false, count - n + 1) + false +} +} } - -// ============================================================ -// Main -// ============================================================ fn main(): Unit with {Console, Random} = { Console.print("========================================") @@ -234,7 +171,6 @@ fn main(): Unit with {Console, Random} = { Console.print("") Console.print("Running 100 iterations per property...") Console.print("") - testReverseInvolutive(100, 100) testReverseLength(100, 100) testMapLength(100, 100) @@ -245,7 +181,6 @@ fn main(): Unit with {Console, Random} = { testAddIdentity(100, 100) testFilterLength(100, 100) testConcatIdentity(100, 100) - Console.print("") Console.print("========================================") Console.print(" All property tests completed!") diff --git a/examples/random.lux b/examples/random.lux index b957922..b2a867c 100644 --- a/examples/random.lux +++ b/examples/random.lux @@ -1,39 +1,22 @@ -// Demonstrating Random and Time effects in Lux -// -// Expected output (values will vary): -// Rolling dice... -// Die 1: -// Die 2: -// Die 3: -// Coin flip: -// Random float: <0.0-1.0> -// Current time: - -// Roll a single die (1-6) fn rollDie(): Int with {Random} = Random.int(1, 6) -// Roll multiple dice and print results fn rollDice(count: Int): Unit with {Random, Console} = { if count > 0 then { - let value = rollDie() - Console.print("Die " + toString(4 - count) + ": " + toString(value)) - rollDice(count - 1) - } else { - () - } + let value = rollDie() + Console.print("Die " + toString(4 - count) + ": " + toString(value)) + rollDice(count - 1) +} else { + () +} } -// Main function demonstrating random effects fn main(): Unit with {Random, Console, Time} = { Console.print("Rolling dice...") rollDice(3) - let coin = Random.bool() Console.print("Coin flip: " + toString(coin)) - let f = Random.float() Console.print("Random float: " + toString(f)) - let now = Time.now() Console.print("Current time: " + toString(now)) } diff --git a/examples/schema_evolution.lux b/examples/schema_evolution.lux index 9834d39..64d3dbe 100644 --- a/examples/schema_evolution.lux +++ b/examples/schema_evolution.lux @@ -1,67 +1,41 @@ -// Schema Evolution Demo -// Demonstrates version tracking and automatic migrations - -// ============================================================ -// PART 1: Type-Declared Migrations -// ============================================================ - -// Define a versioned type with a migration from v1 to v2 -type User @v2 { +type User = { name: String, email: String, - - // Migration from v1: add default email - from @v1 = { name: old.name, email: "unknown@example.com" } } -// Create a v1 user let v1_user = Schema.versioned("User", 1, { name: "Alice" }) -let v1_version = Schema.getVersion(v1_user) // 1 -// Migrate to v2 - uses the declared migration automatically +let v1_version = Schema.getVersion(v1_user) + let v2_user = Schema.migrate(v1_user, 2) -let v2_version = Schema.getVersion(v2_user) // 2 -// ============================================================ -// PART 2: Runtime Schema Operations (separate type) -// ============================================================ +let v2_version = Schema.getVersion(v2_user) -// Create versioned values for a different type (no migration) let config1 = Schema.versioned("Config", 1, "debug") + let config2 = Schema.versioned("Config", 2, "release") -// Check versions -let c1 = Schema.getVersion(config1) // 1 -let c2 = Schema.getVersion(config2) // 2 +let c1 = Schema.getVersion(config1) + +let c2 = Schema.getVersion(config2) -// Migrate config (auto-migration since no explicit migration defined) let upgradedConfig = Schema.migrate(config1, 2) -let upgradedConfigVersion = Schema.getVersion(upgradedConfig) // 2 -// ============================================================ -// PART 2: Practical Example - API Versioning -// ============================================================ +let upgradedConfigVersion = Schema.getVersion(upgradedConfig) -// Simulate different API response versions -fn createResponseV1(data: String): { version: Int, payload: String } = - { version: 1, payload: data } +fn createResponseV1(data: String): { version: Int, payload: String } = { version: 1, payload: data } -fn createResponseV2(data: String, timestamp: Int): { version: Int, payload: String, meta: { ts: Int } } = - { version: 2, payload: data, meta: { ts: timestamp } } +fn createResponseV2(data: String, timestamp: Int): { version: Int, payload: String, meta: { ts: Int } } = { version: 2, payload: data, meta: { ts: timestamp } } -// Version-aware processing -fn getPayload(response: { version: Int, payload: String }): String = - response.payload +fn getPayload(response: { version: Int, payload: String }): String = response.payload let resp1 = createResponseV1("Hello") + let resp2 = createResponseV2("World", 1234567890) let payload1 = getPayload(resp1) -let payload2 = resp2.payload -// ============================================================ -// RESULTS -// ============================================================ +let payload2 = resp2.payload fn main(): Unit with {Console} = { Console.print("=== Schema Evolution Demo ===") diff --git a/examples/shell.lux b/examples/shell.lux index 7228386..6814170 100644 --- a/examples/shell.lux +++ b/examples/shell.lux @@ -1,58 +1,43 @@ -// Shell/Process example - demonstrates the Process effect -// -// This script runs shell commands and uses environment variables - fn main(): Unit with {Process, Console} = { Console.print("=== Lux Shell Example ===") Console.print("") - - // Get current working directory let cwd = Process.cwd() Console.print("Current directory: " + cwd) Console.print("") - - // Get environment variables Console.print("Environment variables:") match Process.env("USER") { - Some(user) => Console.print(" USER: " + user), - None => Console.print(" USER: (not set)") - } + Some(user) => Console.print(" USER: " + user), + None => Console.print(" USER: (not set)"), +} match Process.env("HOME") { - Some(home) => Console.print(" HOME: " + home), - None => Console.print(" HOME: (not set)") - } + Some(home) => Console.print(" HOME: " + home), + None => Console.print(" HOME: (not set)"), +} match Process.env("SHELL") { - Some(shell) => Console.print(" SHELL: " + shell), - None => Console.print(" SHELL: (not set)") - } + Some(shell) => Console.print(" SHELL: " + shell), + None => Console.print(" SHELL: (not set)"), +} Console.print("") - - // Run shell commands Console.print("Running shell commands:") - let date = Process.exec("date") Console.print(" date: " + String.trim(date)) - let kernel = Process.exec("uname -r") Console.print(" kernel: " + String.trim(kernel)) - let files = Process.exec("ls examples/*.lux | wc -l") Console.print(" .lux files in examples/: " + String.trim(files)) Console.print("") - - // Command line arguments Console.print("Command line arguments:") let args = Process.args() let argCount = List.length(args) if argCount == 0 then { - Console.print(" (no arguments)") - } else { - Console.print(" Count: " + toString(argCount)) - match List.head(args) { - Some(first) => Console.print(" First: " + first), - None => Console.print(" First: (empty)") - } - } + Console.print(" (no arguments)") +} else { + Console.print(" Count: " + toString(argCount)) + match List.head(args) { + Some(first) => Console.print(" First: " + first), + None => Console.print(" First: (empty)"), +} +} } let result = run main() with {} diff --git a/examples/showcase/ask_pattern.lux b/examples/showcase/ask_pattern.lux index 00f79a2..5f85f82 100644 --- a/examples/showcase/ask_pattern.lux +++ b/examples/showcase/ask_pattern.lux @@ -1,15 +1,3 @@ -// The "Ask" Pattern - Resumable Effects -// -// Unlike exceptions which unwind the stack, effect handlers can -// RESUME with a value. This enables "ask the environment" patterns. -// -// Expected output: -// Need config: api_url -// Got: https://api.example.com -// Need config: timeout -// Got: 30 -// Configured with url=https://api.example.com, timeout=30 - effect Config { fn get(key: String): String } @@ -25,14 +13,13 @@ fn configure(): String with {Config, Console} = { } handler envConfig: Config { - fn get(key) = - if key == "api_url" then resume("https://api.example.com") - else if key == "timeout" then resume("30") - else resume("unknown") + fn get(key) = if key == "api_url" then resume("https://api.example.com") else if key == "timeout" then resume("30") else resume("unknown") } fn main(): Unit with {Console} = { - let result = run configure() with { Config = envConfig } + let result = run configure() with { + Config = envConfig, +} Console.print(result) } diff --git a/examples/showcase/custom_logging.lux b/examples/showcase/custom_logging.lux index 258f8da..bd5ac70 100644 --- a/examples/showcase/custom_logging.lux +++ b/examples/showcase/custom_logging.lux @@ -1,15 +1,3 @@ -// Custom Logging with Effects -// -// This demonstrates how effects let you abstract side effects. -// The same code can be run with different logging implementations. -// -// Expected output: -// [INFO] Starting computation -// [DEBUG] x = 10 -// [INFO] Processing -// [DEBUG] result = 20 -// Final: 20 - effect Log { fn info(msg: String): Unit fn debug(msg: String): Unit @@ -26,18 +14,22 @@ fn computation(): Int with {Log} = { } handler consoleLogger: Log { - fn info(msg) = { - Console.print("[INFO] " + msg) - resume(()) - } - fn debug(msg) = { - Console.print("[DEBUG] " + msg) - resume(()) - } + fn info(msg) = + { + Console.print("[INFO] " + msg) + resume(()) +} + fn debug(msg) = + { + Console.print("[DEBUG] " + msg) + resume(()) +} } fn main(): Unit with {Console} = { - let result = run computation() with { Log = consoleLogger } + let result = run computation() with { + Log = consoleLogger, +} Console.print("Final: " + toString(result)) } diff --git a/examples/showcase/early_return.lux b/examples/showcase/early_return.lux index d3e33ca..62da5e2 100644 --- a/examples/showcase/early_return.lux +++ b/examples/showcase/early_return.lux @@ -1,37 +1,18 @@ -// Early Return with Fail Effect -// -// The Fail effect provides clean early termination. -// Functions declare their failure modes in the type signature. -// -// Expected output: -// Parsing "42"... -// Result: 42 -// Parsing "100"... -// Result: 100 -// Dividing 100 by 4... -// Result: 25 - fn parsePositive(s: String): Int with {Fail, Console} = { Console.print("Parsing \"" + s + "\"...") - if s == "42" then 42 - else if s == "100" then 100 - else Fail.fail("Invalid number: " + s) + if s == "42" then 42 else if s == "100" then 100 else Fail.fail("Invalid number: " + s) } fn safeDivide(a: Int, b: Int): Int with {Fail, Console} = { Console.print("Dividing " + toString(a) + " by " + toString(b) + "...") - if b == 0 then Fail.fail("Division by zero") - else a / b + if b == 0 then Fail.fail("Division by zero") else a / b } fn main(): Unit with {Console} = { - // These succeed let n1 = run parsePositive("42") with {} Console.print("Result: " + toString(n1)) - let n2 = run parsePositive("100") with {} Console.print("Result: " + toString(n2)) - let n3 = run safeDivide(100, 4) with {} Console.print("Result: " + toString(n3)) } diff --git a/examples/showcase/effect_composition.lux b/examples/showcase/effect_composition.lux index 5bf9b0a..99ead2d 100644 --- a/examples/showcase/effect_composition.lux +++ b/examples/showcase/effect_composition.lux @@ -1,16 +1,3 @@ -// Effect Composition - Combine multiple effects cleanly -// -// Unlike monad transformers (which have ordering issues), -// effects can be freely combined without boilerplate. -// Each handler handles its own effect, ignoring others. -// -// Expected output: -// [LOG] Starting computation -// Generated: 7 -// [LOG] Processing value -// [LOG] Done -// Result: 14 - effect Log { fn log(msg: String): Unit } @@ -30,8 +17,8 @@ handler consoleLog: Log { fn main(): Unit with {Console} = { let result = run computation() with { - Log = consoleLog - } + Log = consoleLog, +} Console.print("Generated: " + toString(result / 2)) Console.print("Result: " + toString(result)) } diff --git a/examples/showcase/higher_order.lux b/examples/showcase/higher_order.lux index 00d4452..5d99480 100644 --- a/examples/showcase/higher_order.lux +++ b/examples/showcase/higher_order.lux @@ -1,38 +1,19 @@ -// Higher-Order Functions and Closures -// -// Functions are first-class values in Lux. -// Closures capture their environment. -// -// Expected output: -// Square of 5: 25 -// Cube of 3: 27 -// Add 10 to 5: 15 -// Add 10 to 20: 30 -// Composed: 15625 (cube(square(5)) = cube(25) = 15625) - fn apply(f: fn(Int): Int, x: Int): Int = f(x) -fn compose(f: fn(Int): Int, g: fn(Int): Int): fn(Int): Int = - fn(x: Int): Int => f(g(x)) +fn compose(f: fn(Int): Int, g: fn(Int): Int): fn(Int): Int = fn(x: Int): Int => f(g(x)) fn square(n: Int): Int = n * n fn cube(n: Int): Int = n * n * n -fn makeAdder(n: Int): fn(Int): Int = - fn(x: Int): Int => x + n +fn makeAdder(n: Int): fn(Int): Int = fn(x: Int): Int => x + n fn main(): Unit with {Console} = { - // Apply functions Console.print("Square of 5: " + toString(apply(square, 5))) Console.print("Cube of 3: " + toString(apply(cube, 3))) - - // Closures let add10 = makeAdder(10) Console.print("Add 10 to 5: " + toString(add10(5))) Console.print("Add 10 to 20: " + toString(add10(20))) - - // Function composition let squareThenCube = compose(cube, square) Console.print("Composed: " + toString(squareThenCube(5))) } diff --git a/examples/showcase/pattern_matching.lux b/examples/showcase/pattern_matching.lux index 593a65b..0042066 100644 --- a/examples/showcase/pattern_matching.lux +++ b/examples/showcase/pattern_matching.lux @@ -1,16 +1,3 @@ -// Algebraic Data Types and Pattern Matching -// -// Lux has powerful ADTs with exhaustive pattern matching. -// The type system ensures all cases are handled. -// -// Expected output: -// Evaluating: (2 + 3) -// Result: 5 -// Evaluating: ((1 + 2) * (3 + 4)) -// Result: 21 -// Evaluating: (10 - (2 * 3)) -// Result: 4 - type Expr = | Num(Int) | Add(Expr, Expr) @@ -19,19 +6,19 @@ type Expr = fn eval(e: Expr): Int = match e { - Num(n) => n, - Add(a, b) => eval(a) + eval(b), - Sub(a, b) => eval(a) - eval(b), - Mul(a, b) => eval(a) * eval(b) - } + Num(n) => n, + Add(a, b) => eval(a) + eval(b), + Sub(a, b) => eval(a) - eval(b), + Mul(a, b) => eval(a) * eval(b), +} fn showExpr(e: Expr): String = match e { - Num(n) => toString(n), - Add(a, b) => "(" + showExpr(a) + " + " + showExpr(b) + ")", - Sub(a, b) => "(" + showExpr(a) + " - " + showExpr(b) + ")", - Mul(a, b) => "(" + showExpr(a) + " * " + showExpr(b) + ")" - } + Num(n) => toString(n), + Add(a, b) => "(" + showExpr(a) + " + " + showExpr(b) + ")", + Sub(a, b) => "(" + showExpr(a) + " - " + showExpr(b) + ")", + Mul(a, b) => "(" + showExpr(a) + " * " + showExpr(b) + ")", +} fn evalAndPrint(e: Expr): Unit with {Console} = { Console.print("Evaluating: " + showExpr(e)) @@ -39,15 +26,10 @@ fn evalAndPrint(e: Expr): Unit with {Console} = { } fn main(): Unit with {Console} = { - // (2 + 3) let e1 = Add(Num(2), Num(3)) evalAndPrint(e1) - - // ((1 + 2) * (3 + 4)) let e2 = Mul(Add(Num(1), Num(2)), Add(Num(3), Num(4))) evalAndPrint(e2) - - // (10 - (2 * 3)) let e3 = Sub(Num(10), Mul(Num(2), Num(3))) evalAndPrint(e3) } diff --git a/examples/standard/factorial.lux b/examples/standard/factorial.lux index b78d7b8..8bd49e6 100644 --- a/examples/standard/factorial.lux +++ b/examples/standard/factorial.lux @@ -1,14 +1,6 @@ -// Factorial - compute n! +fn factorial(n: Int): Int = if n <= 1 then 1 else n * factorial(n - 1) -// Recursive version -fn factorial(n: Int): Int = - if n <= 1 then 1 - else n * factorial(n - 1) - -// Tail-recursive version (optimized) -fn factorialTail(n: Int, acc: Int): Int = - if n <= 1 then acc - else factorialTail(n - 1, n * acc) +fn factorialTail(n: Int, acc: Int): Int = if n <= 1 then acc else factorialTail(n - 1, n * acc) fn factorial2(n: Int): Int = factorialTail(n, 1) diff --git a/examples/standard/fizzbuzz.lux b/examples/standard/fizzbuzz.lux index 621ebbb..1a29e50 100644 --- a/examples/standard/fizzbuzz.lux +++ b/examples/standard/fizzbuzz.lux @@ -1,22 +1,11 @@ -// FizzBuzz - print numbers 1-100, but: -// - multiples of 3: print "Fizz" -// - multiples of 5: print "Buzz" -// - multiples of both: print "FizzBuzz" - -fn fizzbuzz(n: Int): String = - if n % 15 == 0 then "FizzBuzz" - else if n % 3 == 0 then "Fizz" - else if n % 5 == 0 then "Buzz" - else toString(n) +fn fizzbuzz(n: Int): String = if n % 15 == 0 then "FizzBuzz" else if n % 3 == 0 then "Fizz" else if n % 5 == 0 then "Buzz" else toString(n) fn printFizzbuzz(i: Int, max: Int): Unit with {Console} = - if i > max then () - else { - Console.print(fizzbuzz(i)) - printFizzbuzz(i + 1, max) - } + if i > max then () else { + Console.print(fizzbuzz(i)) + printFizzbuzz(i + 1, max) +} -fn main(): Unit with {Console} = - printFizzbuzz(1, 100) +fn main(): Unit with {Console} = printFizzbuzz(1, 100) let output = run main() with {} diff --git a/examples/standard/guessing_game.lux b/examples/standard/guessing_game.lux index 071f4f8..f9b7c17 100644 --- a/examples/standard/guessing_game.lux +++ b/examples/standard/guessing_game.lux @@ -1,42 +1,17 @@ -// Number guessing game - demonstrates Random and Console effects -// -// Expected output: -// Welcome to the Guessing Game! -// Target number: 42 -// Simulating guesses... -// Guess 50: Too high! -// Guess 25: Too low! -// Guess 37: Too low! -// Guess 43: Too high! -// Guess 40: Too low! -// Guess 41: Too low! -// Guess 42: Correct! -// Found in 7 attempts! +fn checkGuess(guess: Int, secret: Int): String = if guess == secret then "Correct" else if guess < secret then "Too low" else "Too high" -// Game logic - check a guess against the secret -fn checkGuess(guess: Int, secret: Int): String = - if guess == secret then "Correct" - else if guess < secret then "Too low" - else "Too high" - -// Binary search simulation to find the number fn binarySearch(low: Int, high: Int, secret: Int, attempts: Int): Int with {Console} = { - let mid = (low + high) / 2 + let mid = low + high / 2 let result = checkGuess(mid, secret) Console.print("Guess " + toString(mid) + ": " + result + "!") - - if result == "Correct" then attempts - else if result == "Too low" then binarySearch(mid + 1, high, secret, attempts + 1) - else binarySearch(low, mid - 1, secret, attempts + 1) + if result == "Correct" then attempts else if result == "Too low" then binarySearch(mid + 1, high, secret, attempts + 1) else binarySearch(low, mid - 1, secret, attempts + 1) } fn main(): Unit with {Console} = { Console.print("Welcome to the Guessing Game!") - // Use a fixed "secret" for reproducible output let secret = 42 Console.print("Target number: " + toString(secret)) Console.print("Simulating guesses...") - let attempts = binarySearch(1, 100, secret, 1) Console.print("Found in " + toString(attempts) + " attempts!") } diff --git a/examples/standard/hello_world.lux b/examples/standard/hello_world.lux index 40c2bc6..2f37a36 100644 --- a/examples/standard/hello_world.lux +++ b/examples/standard/hello_world.lux @@ -1,7 +1,3 @@ -// The classic first program -// Expected output: Hello, World! - -fn main(): Unit with {Console} = - Console.print("Hello, World!") +fn main(): Unit with {Console} = Console.print("Hello, World!") let output = run main() with {} diff --git a/examples/standard/primes.lux b/examples/standard/primes.lux index 748909b..0258aec 100644 --- a/examples/standard/primes.lux +++ b/examples/standard/primes.lux @@ -1,25 +1,14 @@ -// Prime number utilities +fn isPrime(n: Int): Bool = if n < 2 then false else isPrimeHelper(n, 2) -fn isPrime(n: Int): Bool = - if n < 2 then false - else isPrimeHelper(n, 2) +fn isPrimeHelper(n: Int, i: Int): Bool = if i * i > n then true else if n % i == 0 then false else isPrimeHelper(n, i + 1) -fn isPrimeHelper(n: Int, i: Int): Bool = - if i * i > n then true - else if n % i == 0 then false - else isPrimeHelper(n, i + 1) - -// Find first n primes -fn findPrimes(count: Int): Unit with {Console} = - findPrimesHelper(2, count) +fn findPrimes(count: Int): Unit with {Console} = findPrimesHelper(2, count) fn findPrimesHelper(current: Int, remaining: Int): Unit with {Console} = - if remaining <= 0 then () - else if isPrime(current) then { - Console.print(toString(current)) - findPrimesHelper(current + 1, remaining - 1) - } - else findPrimesHelper(current + 1, remaining) + if remaining <= 0 then () else if isPrime(current) then { + Console.print(toString(current)) + findPrimesHelper(current + 1, remaining - 1) +} else findPrimesHelper(current + 1, remaining) fn main(): Unit with {Console} = { Console.print("First 20 prime numbers:") diff --git a/examples/standard/stdlib_demo.lux b/examples/standard/stdlib_demo.lux index 3fc8e66..a1f3028 100644 --- a/examples/standard/stdlib_demo.lux +++ b/examples/standard/stdlib_demo.lux @@ -1,6 +1,3 @@ -// Standard Library Demo -// Demonstrates the built-in modules: List, String, Option, Math - fn main(): Unit with {Console} = { Console.print("=== List Operations ===") let nums = [1, 2, 3, 4, 5] @@ -11,7 +8,6 @@ fn main(): Unit with {Console} = { Console.print("Length: " + toString(List.length(nums))) Console.print("Reversed: " + toString(List.reverse(nums))) Console.print("Range 1-5: " + toString(List.range(1, 6))) - Console.print("") Console.print("=== String Operations ===") let text = " Hello, World! " @@ -22,7 +18,6 @@ fn main(): Unit with {Console} = { Console.print("Contains 'World': " + toString(String.contains(text, "World"))) Console.print("Split by comma: " + toString(String.split("a,b,c", ","))) Console.print("Join with dash: " + String.join(["x", "y", "z"], "-")) - Console.print("") Console.print("=== Option Operations ===") let some_val = Some(42) @@ -31,7 +26,6 @@ fn main(): Unit with {Console} = { Console.print("None mapped: " + toString(Option.map(none_val, fn(x: Int): Int => x * 2))) Console.print("Some(42) getOrElse(0): " + toString(Option.getOrElse(some_val, 0))) Console.print("None getOrElse(0): " + toString(Option.getOrElse(none_val, 0))) - Console.print("") Console.print("=== Math Operations ===") Console.print("abs(-5): " + toString(Math.abs(-5))) diff --git a/examples/statemachine.lux b/examples/statemachine.lux index 867f5a8..32bd595 100644 --- a/examples/statemachine.lux +++ b/examples/statemachine.lux @@ -1,13 +1,3 @@ -// State machine example using algebraic data types -// Demonstrates pattern matching for state transitions -// -// Expected output: -// Initial light: red -// After transition: green -// After two transitions: yellow -// Door: Closed -> Open -> Closed -> Locked - -// Traffic light state machine type TrafficLight = | Red | Yellow @@ -15,26 +5,25 @@ type TrafficLight = fn nextLight(light: TrafficLight): TrafficLight = match light { - Red => Green, - Green => Yellow, - Yellow => Red - } + Red => Green, + Green => Yellow, + Yellow => Red, +} fn canGo(light: TrafficLight): Bool = match light { - Green => true, - Yellow => false, - Red => false - } + Green => true, + Yellow => false, + Red => false, +} fn lightColor(light: TrafficLight): String = match light { - Red => "red", - Yellow => "yellow", - Green => "green" - } + Red => "red", + Yellow => "yellow", + Green => "green", +} -// Door state machine type DoorState = | Open | Closed @@ -48,31 +37,34 @@ type DoorAction = fn applyAction(state: DoorState, action: DoorAction): DoorState = match (state, action) { - (Closed, OpenDoor) => Open, - (Open, CloseDoor) => Closed, - (Closed, LockDoor) => Locked, - (Locked, UnlockDoor) => Closed, - _ => state - } + (Closed, OpenDoor) => Open, + (Open, CloseDoor) => Closed, + (Closed, LockDoor) => Locked, + (Locked, UnlockDoor) => Closed, + _ => state, +} fn doorStateName(state: DoorState): String = match state { - Open => "Open", - Closed => "Closed", - Locked => "Locked" - } + Open => "Open", + Closed => "Closed", + Locked => "Locked", +} -// Test the state machines let light1 = Red + let light2 = nextLight(light1) + let light3 = nextLight(light2) let door1 = Closed + let door2 = applyAction(door1, OpenDoor) + let door3 = applyAction(door2, CloseDoor) + let door4 = applyAction(door3, LockDoor) -// Print results fn printResults(): Unit with {Console} = { Console.print("Initial light: " + lightColor(light1)) Console.print("After transition: " + lightColor(light2)) diff --git a/examples/stress_rc.lux b/examples/stress_rc.lux index 69b2a71..049edf7 100644 --- a/examples/stress_rc.lux +++ b/examples/stress_rc.lux @@ -1,8 +1,4 @@ -// Stress test for RC system with large lists -// Tests FBIP optimization with single-owner chains - fn processChain(n: Int): Int = { - // Single owner chain - FBIP should reuse lists let nums = List.range(1, n) let doubled = List.map(nums, fn(x: Int): Int => x * 2) let filtered = List.filter(doubled, fn(x: Int): Bool => x > n) @@ -12,13 +8,10 @@ fn processChain(n: Int): Int = { fn main(): Unit = { Console.print("=== RC Stress Test ===") - - // Run multiple iterations of list operations let result1 = processChain(100) let result2 = processChain(200) let result3 = processChain(500) let result4 = processChain(1000) - Console.print("Completed 4 chains") Console.print("Sizes: 100, 200, 500, 1000") } diff --git a/examples/stress_shared_rc.lux b/examples/stress_shared_rc.lux index c6e8774..923d605 100644 --- a/examples/stress_shared_rc.lux +++ b/examples/stress_shared_rc.lux @@ -1,12 +1,7 @@ -// Stress test for RC system WITH shared references -// Forces rc>1 path by keeping aliases - fn processWithAlias(n: Int): Int = { let nums = List.range(1, n) - let alias = nums // This increments rc, forcing copy path - let _len = List.length(alias) // Use the alias - - // Now nums has rc>1, so map must allocate new + let alias = nums + let _len = List.length(alias) let doubled = List.map(nums, fn(x: Int): Int => x * 2) let filtered = List.filter(doubled, fn(x: Int): Bool => x > n) let reversed = List.reverse(filtered) @@ -15,12 +10,9 @@ fn processWithAlias(n: Int): Int = { fn main(): Unit = { Console.print("=== RC Stress Test (Shared Refs) ===") - - // Run multiple iterations with shared references let result1 = processWithAlias(100) let result2 = processWithAlias(200) let result3 = processWithAlias(500) let result4 = processWithAlias(1000) - Console.print("Completed 4 chains with shared refs") } diff --git a/examples/tailcall.lux b/examples/tailcall.lux index a325fb7..05e0080 100644 --- a/examples/tailcall.lux +++ b/examples/tailcall.lux @@ -1,45 +1,25 @@ -// Demonstrating tail call optimization (TCO) in Lux -// TCO allows recursive functions to run in constant stack space -// -// Expected output: -// factorial(20) = 2432902008176640000 -// fib(30) = 832040 -// sumTo(1000) = 500500 -// countdown(10000) completed - -// Factorial with accumulator - tail recursive -fn factorialTCO(n: Int, acc: Int): Int = - if n <= 1 then acc - else factorialTCO(n - 1, n * acc) +fn factorialTCO(n: Int, acc: Int): Int = if n <= 1 then acc else factorialTCO(n - 1, n * acc) fn factorial(n: Int): Int = factorialTCO(n, 1) -// Fibonacci with accumulator - tail recursive -fn fibTCO(n: Int, a: Int, b: Int): Int = - if n <= 0 then a - else fibTCO(n - 1, b, a + b) +fn fibTCO(n: Int, a: Int, b: Int): Int = if n <= 0 then a else fibTCO(n - 1, b, a + b) fn fib(n: Int): Int = fibTCO(n, 0, 1) -// Count down - simple tail recursion -fn countdown(n: Int): Int = - if n <= 0 then 0 - else countdown(n - 1) +fn countdown(n: Int): Int = if n <= 0 then 0 else countdown(n - 1) -// Sum with accumulator - tail recursive -fn sumToTCO(n: Int, acc: Int): Int = - if n <= 0 then acc - else sumToTCO(n - 1, acc + n) +fn sumToTCO(n: Int, acc: Int): Int = if n <= 0 then acc else sumToTCO(n - 1, acc + n) fn sumTo(n: Int): Int = sumToTCO(n, 0) -// Test the functions let fact20 = factorial(20) + let fib30 = fib(30) + let sum1000 = sumTo(1000) + let countResult = countdown(10000) -// Print results fn printResults(): Unit with {Console} = { Console.print("factorial(20) = " + toString(fact20)) Console.print("fib(30) = " + toString(fib30)) diff --git a/examples/test_fbip_allocs.lux b/examples/test_fbip_allocs.lux index 0b8fa32..a01e880 100644 --- a/examples/test_fbip_allocs.lux +++ b/examples/test_fbip_allocs.lux @@ -1,17 +1,8 @@ -// This test shows FBIP optimization by comparing allocation counts -// With FBIP (rc=1): lists are reused in-place -// Without FBIP (rc>1): new lists are allocated - fn main(): Unit = { Console.print("=== FBIP Allocation Test ===") - - // Case 1: Single owner (FBIP active) - should reuse list let a = List.range(1, 100) let b = List.map(a, fn(x: Int): Int => x * 2) let c = List.filter(b, fn(x: Int): Bool => x > 50) let d = List.reverse(c) Console.print("Single owner chain done") - - // The allocation count will show FBIP is working - // if allocations are low relative to operations performed } diff --git a/examples/test_fbip_clean.lux b/examples/test_fbip_clean.lux index 108b2dc..c1cf174 100644 --- a/examples/test_fbip_clean.lux +++ b/examples/test_fbip_clean.lux @@ -1,5 +1,4 @@ fn main(): Unit = { - // Test FBIP without string operations let nums = [1, 2, 3, 4, 5] let doubled = List.map(nums, fn(x: Int): Int => x * 2) let filtered = List.filter(doubled, fn(x: Int): Bool => x > 4) diff --git a/examples/test_lists.lux b/examples/test_lists.lux index e5dbfb7..777613b 100644 --- a/examples/test_lists.lux +++ b/examples/test_lists.lux @@ -1,6 +1,3 @@ -// List Operations Test Suite -// Run with: lux test examples/test_lists.lux - fn test_list_length(): Unit with {Test} = { Test.assertEqual(0, List.length([])) Test.assertEqual(1, List.length([1])) diff --git a/examples/test_math.lux b/examples/test_math.lux index b2fc929..01e81c1 100644 --- a/examples/test_math.lux +++ b/examples/test_math.lux @@ -1,6 +1,3 @@ -// Math Test Suite -// Run with: lux test examples/test_math.lux - fn test_addition(): Unit with {Test} = { Test.assertEqual(4, 2 + 2) Test.assertEqual(0, 0 + 0) diff --git a/examples/test_ownership_transfer.lux b/examples/test_ownership_transfer.lux index efa4890..9a31909 100644 --- a/examples/test_ownership_transfer.lux +++ b/examples/test_ownership_transfer.lux @@ -1,21 +1,10 @@ -// Test demonstrating ownership transfer with aliases -// The ownership transfer optimization ensures FBIP still works -// even when variables are aliased, because ownership is transferred -// rather than reference count being incremented. - fn main(): Unit = { Console.print("=== Ownership Transfer Test ===") - let a = List.range(1, 100) - // Ownership transfers from 'a' to 'alias', keeping rc=1 let alias = a let len1 = List.length(alias) - - // Since ownership transferred, 'a' still has rc=1 - // FBIP can still optimize map/filter/reverse let b = List.map(a, fn(x: Int): Int => x * 2) let c = List.filter(b, fn(x: Int): Bool => x > 50) let d = List.reverse(c) - Console.print("Ownership transfer chain done") } diff --git a/examples/test_rc_comparison.lux b/examples/test_rc_comparison.lux index e39f298..314bfbf 100644 --- a/examples/test_rc_comparison.lux +++ b/examples/test_rc_comparison.lux @@ -1,17 +1,13 @@ fn main(): Unit = { Console.print("=== Allocation Comparison ===") - - // FBIP path (rc=1): list is reused Console.print("Test 1: FBIP path") let a1 = List.range(1, 50) let b1 = List.map(a1, fn(x: Int): Int => x * 2) let c1 = List.reverse(b1) Console.print("FBIP done") - - // To show non-FBIP, we need concat which doesn't have FBIP Console.print("Test 2: Non-FBIP path (concat)") let x = List.range(1, 25) let y = List.range(26, 50) - let z = List.concat(x, y) // concat always allocates new + let z = List.concat(x, y) Console.print("Concat done") } diff --git a/examples/traits.lux b/examples/traits.lux index 6aff85a..25b0316 100644 --- a/examples/traits.lux +++ b/examples/traits.lux @@ -1,21 +1,11 @@ -// Demonstrating type classes (traits) in Lux -// -// Expected output: -// RGB color: rgb(255,128,0) -// Red color: red -// Green color: green - -// Define a simple Printable trait trait Printable { fn format(value: Int): String } -// Implement Printable impl Printable for Int { fn format(value: Int): String = "Number: " + toString(value) } -// A Color type with pattern matching type Color = | Red | Green @@ -24,18 +14,18 @@ type Color = fn colorName(c: Color): String = match c { - Red => "red", - Green => "green", - Blue => "blue", - RGB(r, g, b) => "rgb(" + toString(r) + "," + toString(g) + "," + toString(b) + ")" - } + Red => "red", + Green => "green", + Blue => "blue", + RGB(r, g, b) => "rgb(" + toString(r) + "," + toString(g) + "," + toString(b) + ")", +} -// Test let myColor = RGB(255, 128, 0) + let redColor = Red + let greenColor = Green -// Print results fn printResults(): Unit with {Console} = { Console.print("RGB color: " + colorName(myColor)) Console.print("Red color: " + colorName(redColor)) diff --git a/examples/versioning.lux b/examples/versioning.lux index d6c6781..ffb1d59 100644 --- a/examples/versioning.lux +++ b/examples/versioning.lux @@ -1,15 +1,3 @@ -// Demonstrating Schema Evolution in Lux -// -// Lux provides versioned types to help manage data evolution over time. -// The Schema module provides functions for creating and migrating versioned values. -// -// Expected output: -// Created user v1: Alice (age unknown) -// User version: 1 -// Migrated to v2: Alice (age unknown) -// User version after migration: 2 - -// Create a versioned User value at v1 fn createUserV1(name: String): Unit with {Console} = { let user = Schema.versioned("User", 1, { name: name }) let version = Schema.getVersion(user) @@ -17,7 +5,6 @@ fn createUserV1(name: String): Unit with {Console} = { Console.print("User version: " + toString(version)) } -// Migrate a user to v2 fn migrateUserToV2(name: String): Unit with {Console} = { let userV1 = Schema.versioned("User", 1, { name: name }) let userV2 = Schema.migrate(userV1, 2) @@ -26,7 +13,6 @@ fn migrateUserToV2(name: String): Unit with {Console} = { Console.print("User version after migration: " + toString(newVersion)) } -// Main fn main(): Unit with {Console} = { createUserV1("Alice") migrateUserToV2("Alice") diff --git a/examples/web/counter.lux b/examples/web/counter.lux index 9687fb9..dfa8a18 100644 --- a/examples/web/counter.lux +++ b/examples/web/counter.lux @@ -1,62 +1,38 @@ -// Simple Counter for Browser -// Compile with: lux compile examples/web/counter.lux --target js -o examples/web/counter.js +type Model = + | Counter(Int) -// ============================================================================ -// Model -// ============================================================================ - -type Model = | Counter(Int) - -fn getCount(m: Model): Int = match m { Counter(n) => n } +fn getCount(m: Model): Int = + match m { + Counter(n) => n, +} fn init(): Model = Counter(0) -// ============================================================================ -// Messages -// ============================================================================ - -type Msg = | Increment | Decrement | Reset - -// ============================================================================ -// Update -// ============================================================================ +type Msg = + | Increment + | Decrement + | Reset fn update(model: Model, msg: Msg): Model = match msg { - Increment => Counter(getCount(model) + 1), - Decrement => Counter(getCount(model) - 1), - Reset => Counter(0) - } - -// ============================================================================ -// View - Returns HTML string for simplicity -// ============================================================================ + Increment => Counter(getCount(model) + 1), + Decrement => Counter(getCount(model) - 1), + Reset => Counter(0), +} fn view(model: Model): String = { let count = getCount(model) - "
" + - "

Lux Counter

" + - "
" + toString(count) + "
" + - "
" + - "" + - "" + - "" + - "
" + - "
" + "
" + "

Lux Counter

" + "
" + toString(count) + "
" + "
" + "" + "" + "" + "
" + "
" } -// ============================================================================ -// Export for browser runtime -// ============================================================================ - fn luxInit(): Model = init() fn luxUpdate(model: Model, msgName: String): Model = match msgName { - "Increment" => update(model, Increment), - "Decrement" => update(model, Decrement), - "Reset" => update(model, Reset), - _ => model - } + "Increment" => update(model, Increment), + "Decrement" => update(model, Decrement), + "Reset" => update(model, Reset), + _ => model, +} fn luxView(model: Model): String = view(model)