plum

#treesitter#compiler#wasm

git clone https://git.pyrossh.dev/plum

A statically typed, imperative programming language inspired by rust, python


plum-examples/safe_navigation.plum
import std/Option
import std/Result
import std/Bool
import std/Number
import std/Str
# `obj?.field` / `obj?.method(args)` — Groovy/Kotlin-style safe navigation.
# Reaches into a `Result`'s `Ok`/an `Option`'s `Some` without unwrapping it,
# mapping the field/method access over the inner value and re-wrapping the
# result; `Err`/`None` passes through untouched. Pure sugar for
# `obj.map(|v| v.field)` — desugared entirely in the parser (see
# `plum-core`'s `parseSafeAttribute`), so nothing past it needs to know this
# syntax exists.

enum Person =
  | Person(name: Str, age: Int)
  fun birthday(self) -> Int =
    self.age + 1

fun personName(p: Option[Person]) -> Option[Str] =
  p?.name

fun personBirthday(p: Option[Person]) -> Option[Int] =
  p?.birthday()

fun personNameResult(p: Result[Person, Str]) -> Result[Str, Str] =
  p?.name

fun somePerson() -> Option[Person] =
  Some(Person(name: "Ann", age: 3))

fun noPerson() -> Option[Person] =
  None

fun okPerson() -> Result[Person, Str] =
  Ok(Person(name: "Ann", age: 3))

fun errPerson() -> Result[Person, Str] =
  Err("missing")

test "safe navigation maps a field access over Some, passes None through unchanged"
  a := personName(somePerson())
  assert a.isSome()
  assert a.unwrap() == "Ann"
  b := personName(noPerson())
  assert b.isNone()

test "safe navigation maps a method call over Some"
  a := personBirthday(somePerson())
  assert a.isSome()
  assert a.unwrap() == 4

test "safe navigation maps a field access over Ok, passes Err through unchanged"
  a := personNameResult(okPerson())
  assert a.isOk()
  assert a.unwrap() == "Ann"
  b := personNameResult(errPerson())
  assert b.isErr()
  assert b.unwrapErr() == "missing"