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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
(import-macros {: fn* : fn&} :macros.fn)
(local core {})
(local unpack (or table.unpack _G.unpack))
(local insert table.insert)
(fn -check-bindings [bindings]
(and (assert-compile (sequence? bindings) "expected binding table" [])
(assert-compile (= (length bindings) 2) "expected exactly two forms in binding vector." bindings)))
(fn* core.if-let
([bindings then]
(if-let bindings then nil))
([bindings then else]
(-check-bindings bindings)
(let [[form test] bindings]
`(let [tmp# ,test]
(if tmp#
(let [,form tmp#]
,then)
,else)))))
(fn* core.when-let
[bindings & body]
(-check-bindings bindings)
(let [[form test] bindings]
`(let [tmp# ,test]
(if tmp#
(let [,form tmp#]
,(unpack body))))))
(fn* core.if-some
([bindings then]
(if-some bindings then nil))
([bindings then else]
(-check-bindings bindings)
(let [[form test] bindings]
`(let [tmp# ,test]
(if (= tmp# nil)
,else
(let [,form tmp#]
,then))))))
(fn* core.when-some
[bindings & body]
(-check-bindings bindings)
(let [[form test] bindings]
`(let [tmp# ,test]
(if (= tmp# nil)
nil
(let [,form tmp#]
,(unpack body))))))
(fn -table-type [tbl]
(if (sequence? tbl) :seq
(table? tbl) :table
:else))
(fn -table-type-fn []
`(fn [tbl#]
(let [t# (type tbl#)]
(if (= t# :table)
(let [(k# _#) (next tbl#)]
(if (and (= (type k#) :number) (= k# 1)) :seq
(= k# nil) :empty
:table))
:else))))
(fn -seq-fn []
`(fn [tbl#]
(var assoc# false)
(let [res# []
insert# table.insert]
(each [k# v# (pairs tbl#)]
(if (and (not assoc#)
(not (= (type k#) :number)))
(set assoc# true))
(insert# res# [k# v#]))
(if assoc# res# tbl#))))
(fn& core.into [to from]
(let [to-type (-table-type to)
from-type (-table-type from)]
(if (and (= to-type :seq) (= from-type :seq))
`(let [to# ,to
insert# table.insert]
(each [_# v# (ipairs ,from)]
(insert# to# v#))
to#)
(= to-type :seq)
`(let [to# ,to
seq# ,(-seq-fn)
insert# table.insert]
(each [_# v# (ipairs (seq# ,from))]
(insert# to# v#))
to#)
(and (= to-type :table) (= from-type :seq))
`(let [to# ,to]
(each [_# [k# v#] (ipairs ,from)]
(tset to# k# v#))
to#)
(and (= to-type :table) (= from-type :table))
`(let [to# ,to
from# ,from]
(each [k# v# (pairs from#)]
(tset to# k# v#))
to#)
(= to-type :table)
`(let [to# ,to
from# ,from]
(match (,(-table-type-fn) from#)
:seq (each [_# [k# v#] (ipairs from#)]
(tset to# k# v#))
:table (each [k# v# (pairs from#)]
(tset to# k# v#))
:else (error "expected table as second argument"))
to#)
`(let [to# ,to
from# ,from
insert# table.insert
table-type# ,(-table-type-fn)
seq# ,(-seq-fn)]
(match (table-type# to#)
:seq (each [_# v# (ipairs (seq# from#))]
(insert# to# v#))
:table (match (table-type# from#)
:seq (each [_# [k# v#] (ipairs from#)]
(tset to# k# v#))
:table (each [k# v# (pairs from#)]
(tset to# k# v#))
:else (error "expected table as second argument"))
;; If we could not deduce type, it means that
;; we've got empty table. We use will default
;; to sequential table, because it will never
;; break when converting into
:empty (each [_# v# (ipairs (seq# from#))]
(insert# to# v#))
:else (error "expected table as first argument"))
to#))))
core
|