Lake

Branches & patterns

Branches define what a machine does for a given call. Each branch declares a sequence of patterns; when a machine is called, the compiler picks the branch whose patterns match the call's arguments.

§Branch syntax

pattern* -> { body }

A branch has zero or more patterns followed by -> and a body block.

§Three kinds of pattern

§Typed parameter

Binds a value of a given type to a name.

lake
n i64

Matches any i64 argument and makes it available inside the body as n.

§Literal guard

Matches only when the argument equals a specific literal. The literal carries the type.

lake
0 i64
"hello" str

A literal guard does not introduce a binding — it filters the dispatch. Use a typed parameter for the catch-all.

§Wildcard

The lone underscore matches a no-argument branch. There is no type.

lake
_

This is how the entry point is written: main is { _ -> { ... } }. Once you have arguments to bind, use a typed parameter (or a literal guard).

§Putting them together

A branch may mix literal guards and typed parameters. Patterns are read left-to-right and separated by spaces.

@rt(rt_write)

answer is {
  0 i64 -> { rt_write(1 "zero\n" 5) }
  1 i64 -> { rt_write(1 "one\n" 4) }
  n i64 -> { rt_write(1 "many\n" 5) }
}

main is {
  _ -> {
    answer(0)
    answer(1)
    answer(7)
  }
}

Three branches share the same arity and type signature (i64). The compiler picks the matching one in O(1) by hashing the argument's type and literal value.

§Multiple parameters

Patterns are space-separated.

lake
sum is {
  0 i64 acc i64 -> { rt_write(1 "done\n" 5) }
  n i64 acc i64 -> { self(n-1 acc+n) }
}

sum(0 acc) matches the first branch; everything else matches the second and recurses.

§Strings

String literals work as guards too.

@rt(rt_write)

reply is {
  "hello" str -> { rt_write(1 "world\n" 6) }
  "ping"  str -> { rt_write(1 "pong\n" 5) }
   s     str  -> { rt_write(1 "?\n" 2) }
}

main is {
  _ -> {
    reply("hello")
    reply("ping")
    reply("???")
  }
}

§Scope

Each branch has its own scope. Variables introduced by typed parameters or by let are visible only inside that branch's body.