Merge branch 'master' into dart
[jackhill/mal.git] / vimscript / types.vim
CommitLineData
50a964ce
DM
1" types module
2
3function ObjNewWithMeta(obj_type, obj_val, obj_meta)
4 return {"type": a:obj_type, "val": a:obj_val, "meta": a:obj_meta}
5endfunction
6
7function ObjNew(obj_type, obj_val)
8 return {"type": a:obj_type, "val": a:obj_val}
9endfunction
10
50a964ce 11function ObjHasMeta(obj)
b628a220 12 return has_key(a:obj, "meta")
50a964ce
DM
13endfunction
14
15function ObjMeta(obj)
16 return ObjHasMeta(a:obj) ? a:obj["meta"] : g:MalNil
17endfunction
18
19function ObjSetValue(obj, newval)
20 let a:obj["val"] = a:newval
21 return a:newval
22endfunction
23
24function ObjSetMeta(obj, newmeta)
25 let a:obj["meta"] = a:newmeta
26 return a:newmeta
27endfunction
28
50a964ce 29function SymbolQ(obj)
b628a220 30 return a:obj.type == "symbol"
50a964ce
DM
31endfunction
32
33function StringQ(obj)
b628a220 34 return a:obj.type == "string"
50a964ce
DM
35endfunction
36
37function KeywordQ(obj)
b628a220 38 return a:obj.type == "keyword"
50a964ce
DM
39endfunction
40
41function AtomQ(obj)
b628a220 42 return a:obj.type == "atom"
50a964ce
DM
43endfunction
44
45function NilQ(obj)
b628a220 46 return a:obj.type == "nil"
50a964ce
DM
47endfunction
48
49function TrueQ(obj)
b628a220 50 return a:obj.type == "true"
50a964ce
DM
51endfunction
52
53function FalseQ(obj)
b628a220 54 return a:obj.type == "false"
50a964ce
DM
55endfunction
56
57function IntegerQ(obj)
b628a220 58 return a:obj.type == "integer"
50a964ce
DM
59endfunction
60
61function FloatQ(obj)
b628a220 62 return a:obj.type == "float"
50a964ce
DM
63endfunction
64
65function ListQ(obj)
b628a220 66 return a:obj.type == "list"
50a964ce
DM
67endfunction
68
69function VectorQ(obj)
b628a220 70 return a:obj.type == "vector"
50a964ce
DM
71endfunction
72
73function SequentialQ(obj)
b628a220 74 return ListQ(a:obj) || VectorQ(a:obj)
50a964ce
DM
75endfunction
76
77function HashQ(obj)
b628a220 78 return a:obj.type == "hash"
50a964ce
DM
79endfunction
80
81function FunctionQ(obj)
b628a220 82 return a:obj.type == "function" && !a:obj.val.is_macro
50a964ce
DM
83endfunction
84
85function MacroQ(obj)
b628a220 86 return a:obj.type == "function" && a:obj.val.is_macro
50a964ce
DM
87endfunction
88
89function NativeFunctionQ(obj)
b628a220 90 return a:obj.type == "nativefunction"
50a964ce
DM
91endfunction
92
93function NilNew()
94 return ObjNew("nil", "")
95endfunction
96
97function TrueNew()
98 return ObjNew("true", "")
99endfunction
100
101function FalseNew()
102 return ObjNew("false", "")
103endfunction
104
105function BoolNew(bool)
106 return a:bool ? g:MalTrue : g:MalFalse
107endfunction
108
109function KeywordNew(val)
110 return ObjNew("keyword", a:val)
111endfunction
112
113function AtomNew(val)
114 return ObjNewWithMeta("atom", a:val, g:MalNil)
115endfunction
116
117function SymbolNew(val)
118 return ObjNew("symbol", a:val)
119endfunction
120
121function StringNew(val)
122 return ObjNew("string", a:val)
123endfunction
124
125function IntegerNew(val)
126 return ObjNew("integer", a:val)
127endfunction
128
129function FloatNew(val)
130 return ObjNew("float", a:val)
131endfunction
132
133function ListNew(val)
134 return ObjNewWithMeta("list", a:val, g:MalNil)
135endfunction
136
137function VectorNew(val)
138 return ObjNewWithMeta("vector", a:val, g:MalNil)
139endfunction
140
141function HashNew(val)
142 return ObjNewWithMeta("hash", a:val, g:MalNil)
143endfunction
144
145function HashMakeKey(obj)
146 if !StringQ(a:obj) && !KeywordQ(a:obj)
b0b1e169 147 throw "expected hash-map key string, got: " . a:obj.type);
50a964ce 148 endif
b0b1e169 149 return a:obj.type . "#" . a:obj.val
50a964ce
DM
150endfunction
151
152function HashParseKey(str)
153 if a:str =~ "^string#"
154 return StringNew(a:str[7:])
155 elseif a:str =~ "^keyword#"
156 return KeywordNew(a:str[8:])
157 endif
158endfunction
159
160function HashBuild(elements)
161 if (len(a:elements) % 2) != 0
162 throw "Odd number of hash-map arguments"
163 endif
164 let i = 0
165 let hash = {}
166 while i < len(a:elements)
167 let key = a:elements[i]
168 let val = a:elements[i + 1]
169 let keystring = HashMakeKey(key)
170 let hash[keystring] = val
171 let i = i + 2
172 endwhile
173 return HashNew(hash)
174endfunction
175
176function HashEqualQ(x, y)
82641edb 177 if len(a:x.val) != len(a:y.val)
50a964ce
DM
178 return 0
179 endif
82641edb
DM
180 for k in keys(a:x.val)
181 let vx = a:x.val[k]
182 let vy = a:y.val[k]
50a964ce
DM
183 if empty(vy) || !EqualQ(vx, vy)
184 return 0
185 endif
186 endfor
187 return 1
188endfunction
189
190function SequentialEqualQ(x, y)
82641edb 191 if len(a:x.val) != len(a:y.val)
50a964ce
DM
192 return 0
193 endif
194 let i = 0
82641edb
DM
195 while i < len(a:x.val)
196 let ex = a:x.val[i]
197 let ey = a:y.val[i]
50a964ce
DM
198 if !EqualQ(ex, ey)
199 return 0
200 endif
201 let i = i +1
202 endwhile
203 return 1
204endfunction
205
206function EqualQ(x, y)
207 if SequentialQ(a:x) && SequentialQ(a:y)
208 return SequentialEqualQ(a:x, a:y)
209 elseif HashQ(a:x) && HashQ(a:y)
210 return HashEqualQ(a:x, a:y)
b0b1e169 211 elseif a:x.type != a:y.type
50a964ce
DM
212 return 0
213 else
82641edb 214 return a:x.val == a:y.val
50a964ce
DM
215 endif
216endfunction
217
218function EmptyQ(list)
82641edb 219 return empty(a:list.val)
50a964ce
DM
220endfunction
221
222function ListCount(list)
82641edb 223 return len(a:list.val)
50a964ce
DM
224endfunction
225
226function ListNth(list, index)
82641edb 227 if a:index >= len(a:list.val)
50a964ce
DM
228 throw "nth: index out of range"
229 endif
82641edb 230 return a:list.val[a:index]
50a964ce
DM
231endfunction
232
233function ListFirst(list)
82641edb 234 return get(a:list.val, 0, g:MalNil)
50a964ce
DM
235endfunction
236
237function ListDrop(list, drop_elements)
82641edb 238 return ListNew(a:list.val[a:drop_elements :])
50a964ce
DM
239endfunction
240
241function ListRest(list)
242 return ListDrop(a:list, 1)
243endfunction
244
245function FuncInvoke(funcobj, args)
82641edb 246 let fn = a:funcobj.val
50a964ce
DM
247 let funcenv = NewEnvWithBinds(fn.env, fn.params, a:args)
248 return EVAL(fn.ast, funcenv)
249endfunction
250
251function NativeFuncInvoke(funcobj, argslist)
82641edb
DM
252 let fn = a:funcobj.val
253 return fn.Func(a:argslist.val)
50a964ce
DM
254endfunction
255
256function MarkAsMacro(funcobj)
82641edb 257 let fn = a:funcobj.val
50a964ce
DM
258 let fn.is_macro = 1
259 return a:funcobj
260endfunction
261
262function NewFn(ast, env, params)
263 let fn = {"ast": a:ast, "env": a:env, "params": a:params, "is_macro": 0}
264 return ObjNewWithMeta("function", fn, g:MalNil)
265endfunction
266
267function NewNativeFn(funcname)
268 let fn = {"Func": function(a:funcname), "name": a:funcname}
269 return ObjNewWithMeta("nativefunction", fn, g:MalNil)
270endfunction
271
aa62cbda
DM
272function NewNativeFnLambda(lambdaexpr)
273 let fn = {"Func": a:lambdaexpr, "name": "inline"}
274 return ObjNewWithMeta("nativefunction", fn, g:MalNil)
275endfunction
276
50a964ce
DM
277let g:MalNil = NilNew()
278let g:MalTrue = TrueNew()
279let g:MalFalse = FalseNew()