diff --git a/examples/modules/main.lux b/examples/modules/main.lux new file mode 100644 index 0000000..1e20fef --- /dev/null +++ b/examples/modules/main.lux @@ -0,0 +1,20 @@ +// 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)) +} + +let output = run main() with {} diff --git a/examples/modules/main_selective.lux b/examples/modules/main_selective.lux new file mode 100644 index 0000000..e20ccda --- /dev/null +++ b/examples/modules/main_selective.lux @@ -0,0 +1,17 @@ +// 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")) +} + +let output = run main() with {} diff --git a/examples/modules/main_wildcard.lux b/examples/modules/main_wildcard.lux new file mode 100644 index 0000000..5edcfc4 --- /dev/null +++ b/examples/modules/main_wildcard.lux @@ -0,0 +1,14 @@ +// 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))) + Console.print("sumRange(1, 4) = " + toString(sumRange(1, 4))) +} + +let output = run main() with {} diff --git a/examples/modules/math_utils.lux b/examples/modules/math_utils.lux new file mode 100644 index 0000000..0970c2b --- /dev/null +++ b/examples/modules/math_utils.lux @@ -0,0 +1,14 @@ +// Math utilities module +// Exports: square, cube, factorial + +pub fn square(n: Int): Int = n * n + +pub fn cube(n: Int): Int = n * n * n + +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) diff --git a/examples/modules/string_utils.lux b/examples/modules/string_utils.lux new file mode 100644 index 0000000..72f5b88 --- /dev/null +++ b/examples/modules/string_utils.lux @@ -0,0 +1,11 @@ +// String utilities module +// Exports: repeat, exclaim + +pub fn repeat(s: String, n: Int): String = + if n <= 0 then "" + else s + repeat(s, n - 1) + +pub fn exclaim(s: String): String = s + "!" + +pub fn greet(name: String): String = + "Hello, " + name + "!" diff --git a/examples/modules/use_stdlib.lux b/examples/modules/use_stdlib.lux new file mode 100644 index 0000000..9af692a --- /dev/null +++ b/examples/modules/use_stdlib.lux @@ -0,0 +1,23 @@ +// 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))) + Console.print("isNone(None) = " + toString(opt.isNone(y))) + Console.print("unwrapOr(Some(10), 0) = " + toString(opt.unwrapOr(x, 0))) + Console.print("unwrapOr(None, 0) = " + toString(opt.unwrapOr(y, 0))) +} + +let output = run main() with {} diff --git a/std/io.lux b/std/io.lux new file mode 100644 index 0000000..7b83cd5 --- /dev/null +++ b/std/io.lux @@ -0,0 +1,28 @@ +// Standard I/O utilities +// Wraps Console effect with convenient functions + +/// Print a line with a newline +pub fn println(s: String): Unit with {Console} = + Console.print(s) + +/// Print without newline (if supported) +pub fn print(s: String): Unit with {Console} = + Console.print(s) + +/// Read a line from input +pub fn readLine(): String with {Console} = + Console.readLine() + +/// Read an integer from input +pub fn readInt(): Int with {Console} = + Console.readInt() + +/// Print a debug representation of any value +pub fn debug(label: String, value: T): T with {Console} = { + Console.print(label + ": " + toString(value)) + value +} + +/// Print multiple strings on separate lines +pub fn printAll(lines: List): Unit with {Console} = + List.fold(lines, (), fn(acc: Unit, line: String): Unit with {Console} => Console.print(line)) diff --git a/std/option.lux b/std/option.lux new file mode 100644 index 0000000..ff1cf85 --- /dev/null +++ b/std/option.lux @@ -0,0 +1,57 @@ +// Option type utilities +// For working with optional values + +/// Wrap a value in Some +pub fn some(value: T): Option = Some(value) + +/// The None value +pub fn none(): Option = None + +/// Check if option has a value +pub fn isSome(opt: Option): Bool = + match opt { + Some(_) => true, + None => false + } + +/// Check if option is empty +pub fn isNone(opt: Option): Bool = + match opt { + Some(_) => false, + None => true + } + +/// Get value or default +pub fn unwrapOr(opt: Option, default: T): T = + match opt { + Some(v) => v, + None => default + } + +/// Map over the value if present +pub fn map(opt: Option, f: fn(T): U): Option = + match opt { + Some(v) => Some(f(v)), + None => None + } + +/// FlatMap (bind) for options +pub fn flatMap(opt: Option, f: fn(T): Option): Option = + match opt { + Some(v) => f(v), + None => None + } + +/// Filter option by predicate +pub fn filter(opt: Option, pred: fn(T): Bool): Option = + match opt { + Some(v) => if pred(v) then Some(v) else None, + None => None + } + +/// Convert Option to List (empty or singleton) +pub fn toList(opt: Option): List = + match opt { + Some(v) => [v], + None => [] + } diff --git a/std/prelude.lux b/std/prelude.lux new file mode 100644 index 0000000..2ddcac2 --- /dev/null +++ b/std/prelude.lux @@ -0,0 +1,37 @@ +// Standard Prelude - commonly used functions and types +// This module can be imported to get essential utilities + +/// Identity function - returns its argument unchanged +pub fn identity(x: T): T = x + +/// Constant function - returns first argument, ignores second +pub fn const(a: A, b: B): A = a + +/// Function composition +pub fn compose(f: fn(B): C, g: fn(A): B): fn(A): C = + fn(x: A): C => f(g(x)) + +/// Flip argument order of a binary function +pub fn flip(f: fn(A, B): C): fn(B, A): C = + fn(b: B, a: A): C => f(a, b) + +/// Apply a function to a value (useful for pipelines) +pub fn apply(f: fn(A): B, x: A): B = f(x) + +/// Check if two integers are equal +pub fn eq(a: Int, b: Int): Bool = a == b + +/// Check if first is less than second +pub fn lt(a: Int, b: Int): Bool = a < b + +/// Check if first is greater than second +pub fn gt(a: Int, b: Int): Bool = a > b + +/// Negate a boolean +pub fn not(b: Bool): Bool = if b then false else true + +/// Logical and +pub fn and(a: Bool, b: Bool): Bool = if a then b else false + +/// Logical or +pub fn or(a: Bool, b: Bool): Bool = if a then true else b diff --git a/std/result.lux b/std/result.lux new file mode 100644 index 0000000..e9b8742 --- /dev/null +++ b/std/result.lux @@ -0,0 +1,43 @@ +// Result type utilities +// For working with computations that may fail + +/// Wrap a value in Ok +pub fn ok(value: T): Result = Ok(value) + +/// Wrap an error in Err +pub fn err(error: E): Result = Err(error) + +/// Check if result is Ok +pub fn isOk(r: Result): Bool = + match r { + Ok(_) => true, + Err(_) => false + } + +/// Check if result is Err +pub fn isErr(r: Result): Bool = + match r { + Ok(_) => false, + Err(_) => true + } + +/// Get value or default +pub fn unwrapOr(r: Result, default: T): T = + match r { + Ok(v) => v, + Err(_) => default + } + +/// Map over the success value +pub fn mapOk(r: Result, f: fn(T): U): Result = + match r { + Ok(v) => Ok(f(v)), + Err(e) => Err(e) + } + +/// Map over the error value +pub fn mapErr(r: Result, f: fn(E): F): Result = + match r { + Ok(v) => Ok(v), + Err(e) => Err(f(e)) + }