-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathprintf.singeli
89 lines (75 loc) · 2.55 KB
/
printf.singeli
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
# printf: Print a list of values at runtime, C backend
# lprintf: Same, with trailing newline
local {
include 'arch/c' # load{}
include 'skin/c'
include 'skin/cext'
include 'util/kind'
include 'util/tup'
}
require{'stdio.h', 'inttypes.h'}
def lprintf{...vs} = printf_impl{...vs, '\n'}
def printf{...vs} = printf_impl{...vs, ''}
def printf_impl{...vs0} = {
def nsym = ~each{ksym, vs0}
def vs = join{each{
{a,b} => if (b) tup{' ', a} else tup{a},
vs0, nsym & shiftright{0, nsym}
}}
def lit{s} = tup{s, tup{}}
def lit1{s} = tup{lit{s}}
def listfmt{hex, open, close, vs} = {
def f = each{runfmt{hex, .}, vs}
def d = each{lit1, tup{open, ', ', close}}
merge{...each{merge, select{d, 0 != inds{f}}, f}, select{d,2}}
}
def listfmt{hex, open, close, {}} = lit{merge{open, close}}
def runfmt{hex, x} = match(x) {
{_ if ksym{x}} => lit1{x}
{{'x0', y}} => runfmt{2, y}
{{'x', y}} => runfmt{1, y}
{{}} => lit1{'{}'}
{{...vs}} => listfmt{hex, '{', '}', vs}
{_:*E} => tup{tup{'%p', tup{x}}}
{_:V=[l]E} => {
tmp:*V = undefined{V, 1}
tmp <- x
listfmt{hex, '[', ']', each{load{*E~~tmp,.}, range{l}}}
}
{_:T if typekind{T}=='primitive'} => {
def q = quality{T}
def w = width{T}
def u = w>1 and q=='u'
def spec = {
if (q=='f') (if (w==32) '%.8g' else '%.17g')
else merge{
if (hex!=0) '0x' else '',
'%',
if (hex==2) merge{'0', fmtnat{w/4}} else '',
if (w==64) '"SCN' else '',
if (hex!=0) 'x' else if (u) 'u' else 'd',
if (w==64) '64"' else ''
}
}
tup{tup{spec, tup{if (q=='i' and hex!=0) reinterpret{primtype{'u', w}, x} else x}}}
}
{_ if knum{x}} => {
if ((x>>0) == x) {
if (x >= -(1<<63) and x < 1<<63) runfmt{hex, i64~~x}
else if (x >= 0 and x < 1<<64) runfmt{hex, u64~~x}
else lit1{fmtnat{x}}
} else runfmt{hex, f64~~x}
}
{T if kind{T}=='type'} => match(typekind{T}) {
{'primitive'} => lit1{merge{quality{T}, fmtnat{width{T}}}}
{'vector'} => join{flip{tup{lit1{merge{'[', fmtnat{vcount{T}}, ']'}}, runfmt{hex, eltype{T}}}}}
{_} => lit1{merge{'(unhandled type typekind: ', typekind{x}, ')'}}
}
{_:T} => lit1{merge{'(unhandled value typekind: ', typekind{x}, ')'}}
{_} => lit1{merge{'(unhandled kind: ', kind{x}, ')'}}
}
def fs = flip{join{each{runfmt{0,.}, vs}}}
def {strs, args} = each{join, fs}
emit{void, 'printf', merge{'"', strs, '"'}, ...args}
match(vs0) { {{r, _}} => r; {_} => {} }
}