aboutsummaryrefslogtreecommitdiff
path: root/forth/printer.fs
blob: 85f88a0fb64b991a567a015371fc199d12ffcb57 (plain)
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
require str.fs
require types.fs

\ === printer protocol and implementations === /

def-protocol-method pr-buf ( readably? str-addr str-len this -- str-addr str-len )
def-protocol-method pr-seq-buf ( readably? str-addr str-len this -- str-addr str-len )

: pr-str { obj }
    true new-str obj pr-buf rot drop ;

\ Examples of extending existing protocol methods to existing type
MalDefault
  extend pr-buf
    { this }
    s" #<" str-append
    this mal-type @ type-name str-append
    a-space
    this int>str str-append
    s" >" str-append ;;
drop

MalNil   extend pr-buf drop s" nil"   str-append ;; drop
MalTrue  extend pr-buf drop s" true"  str-append ;; drop
MalFalse extend pr-buf drop s" false" str-append ;; drop

MalList
  extend pr-buf
    -rot s" (" str-append ( list str-addr str-len )
    rot pr-seq-buf
    s" )" str-append ;;
  extend pr-seq-buf { list }
    list MalList/count @ 0 > if
        list MalList/start @ { start }
        start @ pr-buf
        list MalList/count @ 1 ?do
            a-space
            start i cells + @ pr-buf
        loop
    endif ;;
drop

MalVector
  extend pr-buf
    MalVector/list @
    -rot s" [" str-append ( list str-addr str-len )
    rot pr-seq-buf
    s" ]" str-append ;;
drop

MalMap
  extend pr-buf
    MalMap/list @
    -rot s" {" str-append ( list str-addr str-len )
    rot { list }
    list MalList/count @ { count }
    count 0 > if
        list MalList/start @ { start }
        start @ pr-buf a-space start cell+ @ pr-buf
        count 2 / 1 ?do
            s" , " str-append
            start i 2 * cells + @ pr-buf a-space
            start i 2 * 1+ cells + @ pr-buf
        loop
    endif
    s" }" str-append ;;
drop

MalInt
  extend pr-buf
    MalInt/int @ int>str str-append ;;
drop

MalSymbol
  extend pr-buf
    unpack-sym str-append ;;
drop

MalKeyword
  extend pr-buf { kw }
    s" :" str-append
    kw unpack-keyword str-append ;;
drop

: escape-str { addr len }
    s\" \"" str-append
    addr len +  addr  ?do
        i c@ case
            [char] " of s\" \\\"" str-append endof
            [char] \ of s\" \\\\" str-append endof
            10 of s\" \\n" str-append endof
            13 of s\" \\r" str-append endof
            -rot i 1 str-append rot
        endcase
    loop
    s\" \"" str-append ;

MalString
  extend pr-buf
    dup MalString/str-addr @
    swap MalString/str-len @
    4 pick if
        escape-str
    else
        str-append
    endif ;;
drop

Atom
  extend pr-buf { this }
    s" (atom " str-append
    this Atom/val @ pr-buf
    s" )" str-append ;;
drop