Besides parameterized modules, Cwerg supports a limited form of (ad-hoc) polymorphism for functions. There is no dynamic dispatch as everything is resolved at compile-time.
Example:
poly fun SysRender(v u8, out span!(u8)) uint:
return FmtDecU8(v, out)
Note the poly atttribute indicates that a function is polymorphic.
This example has two effects:
- It defines a function that renders an
u8value in decimal into the bufferoutand returns the number of characters written. - It registers a family of functions named
SysRenderthat must differ in their first argument.
Functions can be added to this family by re-using the name like so
poly fun SysRender(v u32, out span!(u8)) uint:
return FmtDecU32(v, out)
Note, this function has a different first parameter type for the first argument while the other stay the same, though tthat is not a requirement. Cwerg's polymorphism applieds to the first argument only!
Printing in hex instead of decimal could be accomplished like so:
pub wrapped type u32_hex = u32
poly fun SysRender(v u32_hex, out span!(u8)) uint:
return FmtHexU32(unwrap(v), out)
Assuming the functions above are defined in a module named fmt they can be called like so:
...
ref let! buf_raw = [1024]u8{}
let! buf span!(u8) = buf_raw
set buf = IncSpan(buf, fmt\SysRender@(666_u32, buf))
set buf = IncSpan(buf, fmt\SysRender@(66_u8, buf))
set buf = IncSpan(buf, fmt\SysRender@(
wrap_as(666, fmt\ u32_hex), buf))
...
Defining SysRender for a data type in another module can be accomplished like so:
rec Point:
x u32
y u32
poly fun fmt\SysRender(v Point, out span!(u8)) uint:
let! buf = out
set buf = IncSpan(buf, fmt\SysRender@(v.x, buf))
set buf = IncSpan(buf, fmt\SysRender@(", ", buf))
set buf = IncSpan(buf, fmt\SysRender@(v.y, buf))
return len(out) - len(buf)
Note, that the definition uses a qualified name referencing the family of
polymorphic function we want to add to. This is the only situation where a qualified is
used at a defiition of a global object.