aboutsummaryrefslogtreecommitdiff
path: root/std/prelude/format.pk
blob: 6fc7c9938ab482482a6d6df7a79f31869134df36 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
## std.format: Niceties around printing and debugging.
## This module is imported by default.

## The Display class. Any type implementing `str` is printable.
## Any type that is Display must necessarily also implement Debug.
pub type Display = class
  str(Self): str
  dbg(Self): str

## The Debug class. Broadly implemented for every type with compiler magic.
## Types can (and should) override the generic implementations.
pub type Debug = class
  dbg(Self): str

## Prints all of its arguments to the command line.
pub func print(params: varargs[Display]) =
  stdout.write(params.map(x => x.str).join(" "), "\n")

## Prints all of its arguments to the command line, in Debug form.
##
## Note: this function is special! It does not count as a side effect.
## This breaks effect tracking, of course: but `dbg` is for debugging.
## It will produce a warning in code compiled for release.
@[no_side_effect]
pub func dbg(params: varargs[Debug]) =
  stdout.write(params.map(x => x.dbg).join(" "), "\n")

## A dummy implementation of the Display class for strings.
pub func str(self: str): str = self
## An implementation of the Debug class for strings.
pub func dbg(self: str): str = "\"" & self & "\""

## An implementation of the Debug class for all structs.
## Uses the special `struct` typeclass.
pub func dbg[T: Debug](self: struct[T]): str =
  "{{}}".fmt(self.fields.map((key, val) => key & ":" & val.dbg))

## An implementation of the Debug class for all tuples.
## Uses the special `tuple` typeclass.
pub func dbg[T: Debug](self: tuple[T]): str =
  "({})".fmt(self.fields.map((key, val) =>
    key.map(x => x & ":").get_or("") & val.dbg).join(", "))

## An implementation of the Debug class for all arrays and lists.
pub func dbg[T: Debug](self: Iter[T]): str =
  "[{}]".fmt(self.map(x => x.dbg).join(", "))

## The fmt macro. Builds a formatted string from its arguments.
pub macro fmt(self: static[str], args: varargs[Display]): str =
  let parts = self.split("{}")
  if parts.len != args.len + 1 then
    macro_error("wrong number of arguments")
  use std.ast
  var res = parts.get(0)!
  for i, arg in args do
    res &= quote(`parts` & str(`arg`) &) # fixme
  res &= parts.last()!
  res