3 function ObjNewWithMeta(obj_type, obj_val, obj_meta)
4 return {"type": a:obj_type, "val": a:obj_val, "meta": a:obj_meta}
7 function ObjNew(obj_type, obj_val)
8 return {"type": a:obj_type, "val": a:obj_val}
11 function ObjHasMeta(obj)
12 return has_key(a:obj, "meta")
16 return ObjHasMeta(a:obj) ? a:obj["meta"] : g:MalNil
19 function ObjSetValue(obj, newval)
20 let a:obj["val"] = a:newval
24 function ObjSetMeta(obj, newmeta)
25 let a:obj["meta"] = a:newmeta
30 return a:obj.type == "symbol"
34 return a:obj.type == "string"
37 function KeywordQ(obj)
38 return a:obj.type == "keyword"
42 return a:obj.type == "atom"
46 return a:obj.type == "nil"
50 return a:obj.type == "true"
54 return a:obj.type == "false"
57 function IntegerQ(obj)
58 return a:obj.type == "integer"
62 return a:obj.type == "float"
66 return a:obj.type == "list"
70 return a:obj.type == "vector"
73 function SequentialQ(obj)
74 return ListQ(a:obj) || VectorQ(a:obj)
78 return a:obj.type == "hash"
81 function FunctionQ(obj)
82 return a:obj.type == "function" && !a:obj.val.is_macro
86 return a:obj.type == "function" && a:obj.val.is_macro
89 function NativeFunctionQ(obj)
90 return a:obj.type == "nativefunction"
94 return ObjNew("nil", "")
98 return ObjNew("true", "")
102 return ObjNew("false", "")
105 function BoolNew(bool)
106 return a:bool ? g:MalTrue : g:MalFalse
109 function KeywordNew(val)
110 return ObjNew("keyword", a:val)
113 function AtomNew(val)
114 return ObjNewWithMeta("atom", a:val, g:MalNil)
117 function SymbolNew(val)
118 return ObjNew("symbol", a:val)
121 function StringNew(val)
122 return ObjNew("string", a:val)
125 function IntegerNew(val)
126 return ObjNew("integer", a:val)
129 function FloatNew(val)
130 return ObjNew("float", a:val)
133 function ListNew(val)
134 return ObjNewWithMeta("list", a:val, g:MalNil)
137 function VectorNew(val)
138 return ObjNewWithMeta("vector", a:val, g:MalNil)
141 function HashNew(val)
142 return ObjNewWithMeta("hash", a:val, g:MalNil)
145 function HashMakeKey(obj)
146 if !StringQ(a:obj) && !KeywordQ(a:obj)
147 throw "expected hash-map key string, got: " . a:obj.type);
149 return a:obj.type . "#" . a:obj.val
152 function HashParseKey(str)
153 if a:str =~ "^string#"
154 return StringNew(a:str[7:])
155 elseif a:str =~ "^keyword#"
156 return KeywordNew(a:str[8:])
160 function HashBuild(elements)
161 if (len(a:elements) % 2) != 0
162 throw "Odd number of hash-map arguments"
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
176 function HashEqualQ(x, y)
177 if len(a:x.val) != len(a:y.val)
180 for k in keys(a:x.val)
183 if empty(vy) || !EqualQ(vx, vy)
190 function SequentialEqualQ(x, y)
191 if len(a:x.val) != len(a:y.val)
195 while i < len(a:x.val)
206 function 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)
211 elseif a:x.type != a:y.type
214 return a:x.val == a:y.val
218 function EmptyQ(list)
219 return empty(a:list.val)
222 function ListCount(list)
223 return len(a:list.val)
226 function ListNth(list, index)
227 if a:index >= len(a:list.val)
228 throw "nth: index out of range"
230 return a:list.val[a:index]
233 function ListFirst(list)
234 return get(a:list.val, 0, g:MalNil)
237 function ListDrop(list, drop_elements)
238 return ListNew(a:list.val[a:drop_elements :])
241 function ListRest(list)
242 return ListDrop(a:list, 1)
245 function FuncInvoke(funcobj, args)
246 let fn = a:funcobj.val
247 let funcenv = NewEnvWithBinds(fn.env, fn.params, a:args)
248 return EVAL(fn.ast, funcenv)
251 function NativeFuncInvoke(funcobj, argslist)
252 let fn = a:funcobj.val
253 return fn.Func(a:argslist.val)
256 function MarkAsMacro(funcobj)
257 let fn = a:funcobj.val
262 function 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)
267 function NewNativeFn(funcname)
268 let fn = {"Func": function(a:funcname), "name": a:funcname}
269 return ObjNewWithMeta("nativefunction", fn, g:MalNil)
272 function NewNativeFnLambda(lambdaexpr)
273 let fn = {"Func": a:lambdaexpr, "name": "inline"}
274 return ObjNewWithMeta("nativefunction", fn, g:MalNil)
277 let g:MalNil = NilNew()
278 let g:MalTrue = TrueNew()
279 let g:MalFalse = FalseNew()