plum

#treesitter#compiler#wasm

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