plum
git clone https://git.pyrossh.dev/plum
A statically typed, imperative programming language inspired by rust, python
plum-examples/functions.plum
| b7071c9 | 1 | import std/Str |
| 73b5e55 | 2 | import std/Bool |
| ca5fd6f | 3 | import std/Number |
| b7071c9 | 4 | |
| 0fe3528 | 5 | fun addInts(a: Int, b: Int) -> Int = |
| 0e1801a | 6 | a + b |
| 0e1801a | 7 | |
| 0fe3528 | 8 | fun greet() = |
| 0e1801a | 9 | todo |
| 0e1801a | 10 | |
| 0fe3528 | 11 | fun withDefault(a: Int, step: Int = 1) -> Int = |
| 0e1801a | 12 | a + step |
| 0e1801a | 13 | |
| 0fe3528 | 14 | fun sumAll(nums: ...Int) -> Int = |
| a271f34 | 15 | total := 0 |
| a271f34 | 16 | for v := range nums |
| da1c377 | 17 | total = total + v |
| da1c377 | 18 | total |
| 0e1801a | 19 | |
| 0fe3528 | 20 | fun wrap(value: T) -> Bool = |
| 0e1801a | 21 | True |
| 0e1801a | 22 | |
| 0fe3528 | 23 | fun pair(first: T, second: U) -> Bool = |
| 0e1801a | 24 | True |
| 2e28ecc | 25 | |
| 0fe3528 | 26 | fun useWrap() -> Bool = |
| 2e28ecc | 27 | wrap(5) |
| 2e28ecc | 28 | |
| 0fe3528 | 29 | fun usePair() -> Bool = |
| 2e28ecc | 30 | pair(1, "x") |
| a43f3af | 31 | |
| a43f3af | 32 | # ---- generics, variadics, and misc regression tests ---- |
| a43f3af | 33 | |
| a43f3af | 34 | fun factorial(x: Int) -> Int = |
| a43f3af | 35 | if x < 2 |
| a43f3af | 36 | return 1 |
| a43f3af | 37 | return x * factorial(x - 1) |
| a43f3af | 38 | |
| a43f3af | 39 | # Regression test: `double(...)` (an all-lowercase, no-uppercase, no-underscore |
| a43f3af | 40 | # callee) used to fail to parse at all — `var_identifier` and `fn_identifier` |
| a43f3af | 41 | # both matched its text and the grammar's lexer would nondeterministically |
| a43f3af | 42 | # commit to `var_identifier`, breaking every such call site. |
| a43f3af | 43 | fun double(n: Int) -> Int = |
| a43f3af | 44 | n * 2 |
| a43f3af | 45 | |
| 5f2f962 | 46 | enum GenericBox[T] = |
| 5f2f962 | 47 | | GenericBox(value: T) |
| a43f3af | 48 | |
| a43f3af | 49 | fun getIntValue() -> Int = |
| a43f3af | 50 | self.value |
| a43f3af | 51 | |
| a43f3af | 52 | fun useGenericBox() -> Int = |
| a43f3af | 53 | b := GenericBox(value: 7) |
| a43f3af | 54 | b.getIntValue() |
| a43f3af | 55 | |
| a43f3af | 56 | fun identity(value: T) -> T = |
| a43f3af | 57 | value |
| a43f3af | 58 | |
| 5f2f962 | 59 | enum GenericBox2[T] = |
| 5f2f962 | 60 | | GenericBox2(value: T) |
| a43f3af | 61 | |
| a43f3af | 62 | fun getValue() -> Int = |
| a43f3af | 63 | self.value |
| a43f3af | 64 | |
| a43f3af | 65 | fun doubled(value: T) -> Int = |
| a43f3af | 66 | identity(value) + identity(value) |
| a43f3af | 67 | |
| 287b97c | 68 | enum FnOption[T] = |
| 287b97c | 69 | | FnSome(T) |
| a43f3af | 70 | | FnNone |
| a43f3af | 71 | |
| a43f3af | 72 | fun unwrapFnOptionOr(o: FnOption, default: Int) -> Int = |
| a43f3af | 73 | match o |
| 3a2119e | 74 | FnSome(v) => v |
| 3a2119e | 75 | FnNone => default |
| a43f3af | 76 | |
| a43f3af | 77 | # `Str.length()` is not a real, working method — the point of this test is |
| a43f3af | 78 | # that `FnOption$Str` coexists with `FnOption$Int` and both run correctly, not |
| a43f3af | 79 | # string processing, so the Str arm returns a fixed literal. |
| a43f3af | 80 | fun unwrapFnOptionIntOr(o: FnOption, default: Int) -> Int = |
| a43f3af | 81 | match o |
| 3a2119e | 82 | FnSome(v) => v |
| 3a2119e | 83 | FnNone => default |
| a43f3af | 84 | |
| a43f3af | 85 | fun unwrapFnOptionStrOr(o: FnOption, default: Int) -> Int = |
| a43f3af | 86 | match o |
| 3a2119e | 87 | FnSome(v) => 4 |
| 3a2119e | 88 | FnNone => default |
| a43f3af | 89 | |
| 5f2f962 | 90 | enum GenericBox3[T] = |
| 5f2f962 | 91 | | GenericBox3(value: T) |
| a43f3af | 92 | |
| a43f3af | 93 | fun getBoxValue() -> Int = |
| a43f3af | 94 | self.value |
| a43f3af | 95 | |
| a43f3af | 96 | fun sumBox(b: GenericBox3) -> Int = |
| a43f3af | 97 | b.getBoxValue() |
| a43f3af | 98 | |
| a43f3af | 99 | fun combineVariadic(prefix: Int, rest: ...Int) -> Int = |
| a43f3af | 100 | prefix |
| a43f3af | 101 | |
| 8de13fd | 102 | test "factorial runs correctly" |
| 8de13fd | 103 | assert factorial(5) == 120 |
| 8de13fd | 104 | |
| 8de13fd | 105 | test "lowercase single word function call runs correctly" |
| 8de13fd | 106 | assert double(21) == 42 |
| 8de13fd | 107 | |
| 8de13fd | 108 | test "generic class specialized at two types does not alias" |
| 8de13fd | 109 | assert useGenericBox() == 7 |
| 8de13fd | 110 | |
| 8de13fd | 111 | test "generic function called at multiple concrete types runs correctly" |
| 8de13fd | 112 | assert identity(5) + identity(37) == 42 |
| 8de13fd | 113 | |
| 8de13fd | 114 | test "generic method on generic class runs correctly" |
| 8de13fd | 115 | b := GenericBox2(value: 9) |
| 8de13fd | 116 | assert b.getValue() == 9 |
| 8de13fd | 117 | |
| 8de13fd | 118 | test "transitively generic call chain runs correctly" |
| 8de13fd | 119 | assert doubled(21) == 42 |
| 8de13fd | 120 | |
| 8de13fd | 121 | test "generic enum specialized and matched runs correctly" |
| 8de13fd | 122 | assert unwrapFnOptionOr(FnSome(13), 0) == 13 |
| 8de13fd | 123 | |
| 8de13fd | 124 | test "generic enum multiple instantiations coexist and run correctly" |
| 8de13fd | 125 | assert unwrapFnOptionIntOr(FnSome(13), 0) + unwrapFnOptionStrOr(FnSome("abcd"), 0) == 17 |
| 8de13fd | 126 | |
| 8de13fd | 127 | test "same bare generic enum param function called multiple times runs correctly" |
| 8de13fd | 128 | assert unwrapFnOptionOr(FnSome(5), 0) + unwrapFnOptionOr(FnSome(37), 0) == 42 |
| 8de13fd | 129 | |
| 8de13fd | 130 | test "ordinary function with bare generic class param runs correctly" |
| 8de13fd | 131 | assert sumBox(GenericBox3(value: 11)) == 11 |
| 8de13fd | 132 | |
| a43f3af | 133 | test "variadic call with varying trailing arg counts runs correctly" |
| a43f3af | 134 | a := combineVariadic(10) |
| a43f3af | 135 | b := combineVariadic(20, 1) |
| a43f3af | 136 | c := combineVariadic(30, 1, 2, 3) |
| a9a0147 | 137 | assert a + b + c == 60 |
| a43f3af | 138 | |
| a43f3af | 139 | test "sum all variadic int runs correctly" |
| a9a0147 | 140 | assert sumAll(1, 2, 3, 4) == 10 |
| a43f3af | 141 | |
| a43f3af | 142 | test "sum all variadic int with zero args runs correctly" |
| a9a0147 | 143 | assert sumAll() == 0 |