Skip to content
This repository was archived by the owner on Nov 11, 2021. It is now read-only.

Commit f61ecc5

Browse files
committed
print1 - prints an integer
- improves on the built-in print by handling negative integers in compiled code "properly" -- with a leading minus sign the same as in the simulator. - currently expands inline due to macros being the only code abstraction we have - perhaps useful as a basis of a native print written in porth at some point - the built-in print is derived from compiling a similar conversion in C - uses a temporary area within mem (32 bytes) to accumulate the characters of the output string from back to front. - a scratch buffer like this might make sense as a peer to mem, str, argv - alternatively, being able to allocate this temp buffer on the stack seems like it would be useful in avoiding contention for a global buffer - uses `rot` which is a basic stack word from ANS forth - without it, it was not convenient to use the third item on the stack
1 parent c662f8d commit f61ecc5

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

examples/native-print.porth

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
include "std.porth"
2+
3+
// print1 - prints an integer
4+
//
5+
// - improves on the built-in print by handling negative integers in compiled
6+
// code "properly" -- with a leading minus sign the same as in the simulator.
7+
// - currently expands inline due to macros being the only code abstraction
8+
// we have
9+
// - perhaps useful as a basis of a native print written in porth at some point
10+
// - the built-in print is derived from compiling a similar conversion in C
11+
// - uses a temporary area within mem (32 bytes) to accumulate the characters
12+
// of the output string from back to front.
13+
// - a scratch buffer like this might make sense as a peer to mem, str, argv
14+
// - alternatively, being able to allocate this temp buffer on the stack seems
15+
// like it would be useful in avoiding contention for a global buffer
16+
// - uses `rot` which is a basic stack word from ANS forth
17+
// - without it, it was not convenient to use the third item on the stack
18+
19+
// --------------------------------------------------------------------------------
20+
// possibly generally useful function, maybe a std.porth candidate
21+
22+
// (num:int -- neg?:bool mag:int)
23+
// converts num to sign-magnitude form
24+
macro signmag
25+
dup 0 <
26+
dup if
27+
swap 0 swap - swap
28+
end
29+
swap
30+
end
31+
n
32+
// --------------------------------------------------------------------------------
33+
// temporary buffer
34+
35+
macro printbuf-start
36+
mem 10000 +
37+
end
38+
39+
macro printbuf-end
40+
printbuf-start 31 +
41+
end
42+
43+
// --------------------------------------------------------------------------------
44+
// helpers for the main print1 word
45+
46+
// (ptr:addr mag:int -- ptr(-1):addr mag(/10):int)
47+
// stores the character code for the least significant
48+
// decimal digit of non-negative mag to ptr,
49+
// decrements ptr, divs mag by 10.
50+
51+
macro buffer-digit!
52+
10 divmod // ptr div mod
53+
rot dup // div mod ptr ptr
54+
rot // div ptr ptr mod
55+
'0' + . 1 - // div ptr(-1)
56+
swap // ptr div
57+
end
58+
59+
// (ptr:addr mag:int -- ptr(-n):addr)
60+
// stores the character codes for the decimal digits
61+
// of mag in reverse order starting at ptr. decrements
62+
// ptr by the number of characters stored.
63+
macro buffer-mag!
64+
buffer-digit! // ptr(-1) mag(/10)
65+
while dup 0 > do
66+
buffer-digit! // ptr(-1) mag(/10)
67+
end // ptr 0
68+
drop // ptr
69+
end
70+
71+
// --------------------------------------------------------------------------------
72+
// (int --)
73+
// prints an int to stdout followed by a newline
74+
// overwrites printbuf, accumulating characters backward from its end
75+
macro print1
76+
signmag printbuf-end // neg? mag ptr
77+
78+
dup '\n' . 1 - // neg? mag ptr(-1)
79+
swap buffer-mag! // neg? ptr
80+
swap // ptr neg?
81+
if // ptr
82+
dup '-' . 1 - // ptr(-1)
83+
end
84+
85+
dup printbuf-end swap - // ptr len
86+
swap 1 + // len ptr(+1)
87+
stdout write drop
88+
end
89+
90+
// --------------------------------------------------------------------------------
91+
// tests
92+
93+
350 signmag print print
94+
95+
-350 signmag print print
96+
97+
"stack ends up empty check\n"
98+
99+
0 print1
100+
101+
123 print1
102+
103+
-123 print1
104+
105+
stdout write

examples/native-print.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
:i argc 0
2+
:b stdin 0
3+
4+
:i returncode 0
5+
:b stdout 49
6+
350
7+
0
8+
350
9+
1
10+
0
11+
123
12+
-123
13+
stack ends up empty check
14+
15+
:b stderr 0
16+

0 commit comments

Comments
 (0)