1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-21 02:27:10 +03:00
mal/forth/printer.fs

182 lines
4.3 KiB
Forth
Raw Normal View History

require types.fs
: safe-type ( str-addr str-len -- )
dup 256 > if
2015-02-13 03:27:00 +03:00
drop 256 type ." ...<lots more>"
else
type
endif ;
\ === mutable string buffer === /
\ string buffer that maintains an allocation larger than the current
\ string size. When appending would cause the string size exceed the
\ current allocation, resize is used to double the allocation. The
\ current allocation is not stored anywhere, but computed based on
\ current string size or str-base-size, whichever is larger.
64 constant str-base-size
: new-str ( -- addr length )
str-base-size allocate throw 0 ;
: round-up ( n -- n )
2
begin
1 lshift 2dup <
until
2015-02-06 10:38:58 +03:00
nip ;
: str-append { buf-addr buf-str-len str-addr str-len }
buf-str-len str-len +
{ new-len }
new-len str-base-size > if
buf-str-len new-len xor buf-str-len > if
buf-addr new-len round-up resize throw
to buf-addr
endif
endif
str-addr buf-addr buf-str-len + str-len cmove
buf-addr new-len ;
\ define a-space, to append a space char to a string
bl c,
here constant space-str
: a-space space-str 1 str-append ;
: str-append-char ( buf-addr buf-str-len char -- buf-addr buf-str-len )
2015-02-06 10:38:58 +03:00
pad ! pad 1 str-append ;
: int>str ( num -- str-addr str-len )
s>d <# #s #> ;
\ === printer protocol and implementations === /
def-protocol-method pr-buf ( str-addr str-len this -- str-addr str-len )
2015-02-13 03:27:00 +03:00
def-protocol-method pr-seq-buf ( str-addr str-len this -- str-addr str-len )
def-protocol-method pr-pairs-buf ( str-addr str-len this -- str-addr str-len )
: pr-str { obj }
new-str obj pr-buf ;
\ Examples of extending existing protocol methods to existing type
MalDefault
extend pr-buf
{ this }
s" #<MalObject" str-append a-space
this int>str str-append
s" >" str-append ;;
drop
2015-02-15 21:33:44 +03:00
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
2015-02-13 03:27:00 +03:00
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 }
2015-02-15 21:33:44 +03:00
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 ;;
extend pr-pairs-buf { list }
list MalList/start @ { start }
2015-02-13 03:27:00 +03:00
start @ pr-buf a-space start cell+ @ pr-buf
list MalList/count @ 2 / 1 ?do
2015-02-13 03:27:00 +03:00
s" , " str-append
a-space
start i 2 * cells + @ pr-buf a-space
start i 2 * 1+ cells + @ pr-buf
loop ;;
2015-02-07 07:58:41 +03:00
drop
MalVector
extend pr-buf
MalVector/list @
-rot s" [" str-append ( list str-addr str-len )
2015-02-13 03:27:00 +03:00
rot pr-seq-buf
2015-02-07 07:58:41 +03:00
s" ]" str-append ;;
drop
2015-02-07 18:01:31 +03:00
MalMap
extend pr-buf
MalMap/list @
-rot s" {" str-append ( list str-addr str-len )
2015-02-13 03:27:00 +03:00
rot pr-pairs-buf
2015-02-07 18:01:31 +03:00
s" }" str-append ;;
drop
MalInt
extend pr-buf
MalInt/int @ int>str str-append ;;
drop
2015-02-13 03:27:00 +03:00
MalFn
extend pr-buf
drop s" #<fn>" str-append ;;
drop
2015-02-14 21:40:07 +03:00
SpecialOp
extend pr-buf
drop s" #<op>" str-append ;;
drop
MalSymbol
extend pr-buf
2015-02-13 03:27:00 +03:00
unpack-sym str-append ;;
drop
MalKeyword
extend pr-buf { kw }
s" :" str-append
kw unpack-keyword str-append ;;
drop
2015-02-06 10:38:58 +03:00
: insert-\ ( str-addr str-len insert-idx -- str-addr str-len )
-rot 0 str-append-char { addr len }
dup dup addr + dup 1+ ( i i from to )
rot len swap - cmove> ( i ) \ shift " etc to the right
addr + [char] \ swap c! \ escape it!
addr len
;
MalString
extend pr-buf
dup MalString/str-addr @
swap MalString/str-len @
{ addr len }
s\" \"" str-append
0 ( i )
begin
2015-02-07 07:58:41 +03:00
dup len <
while
2015-02-06 10:38:58 +03:00
dup addr + c@ ( i char )
dup [char] " = over [char] \ = or if ( i char )
drop dup addr len rot insert-\ to len to addr
1+
else
2015-02-07 07:58:41 +03:00
dup 10 = if ( i ) \ newline?
drop dup addr len rot insert-\ to len to addr
2015-02-06 10:38:58 +03:00
dup addr + 1+ [char] n swap c!
1+
2015-02-07 07:58:41 +03:00
else
13 = if ( i ) \ return?
dup addr len rot insert-\ to len to addr
dup addr + 1+ [char] r swap c!
1+
endif
2015-02-06 10:38:58 +03:00
endif
endif
1+
2015-02-07 07:58:41 +03:00
repeat
2015-02-06 10:38:58 +03:00
drop addr len str-append
s\" \"" str-append ;;
drop