return bool_to_mal(s.is_keyword());
}
+static MalType mal_fn_q(MalType[] a ...)
+{
+ verify_args_count(a, 1);
+ auto builtinfn = cast(MalBuiltinFunc) a[0];
+ if (builtinfn !is null) return mal_true;
+ auto malfunc = cast(MalFunc) a[0];
+ if (malfunc !is null) return bool_to_mal(!malfunc.is_macro);
+ return mal_false;
+}
+
+static MalType mal_macro_q(MalType[] a ...)
+{
+ verify_args_count(a, 1);
+ auto malfunc = cast(MalFunc) a[0];
+ if (malfunc !is null) return bool_to_mal(malfunc.is_macro);
+ return mal_false;
+}
+
static MalType mal_pr_str(MalType[] a ...)
{
auto items_strs = a.map!(e => pr_str(e, true));
"string?": &mal_string_q,
"keyword": &mal_keyword,
"keyword?": &mal_keyword_q,
+ "number?": (a ...) => mal_type_q!MalInteger(a),
+ "fn?": &mal_fn_q,
+ "macro?": &mal_macro_q,
"pr-str": &mal_pr_str,
"str": &mal_str,
"symbol?": fun symbol_q,
"keyword": fun keyword,
"keyword?": fun keyword_q,
+ "number?": fun number_q,
+ "fn?": fun fn_q,
+ "macro?": fun macro_q,
"with-meta": fun with_meta,
"meta": fun meta,
proc is_macro_call(ast: MalType, env: Env): bool =
ast.kind == List and ast.list[0].kind == Symbol and
- env.find(ast.list[0].str) != nil and env.get(ast.list[0].str).macro_q
+ env.find(ast.list[0].str) != nil and env.get(ast.list[0].str).fun_is_macro
proc macroexpand(ast: MalType, env: Env): MalType =
result = ast
proc is_macro_call(ast: MalType, env: Env): bool =
ast.kind == List and ast.list[0].kind == Symbol and
- env.find(ast.list[0].str) != nil and env.get(ast.list[0].str).macro_q
+ env.find(ast.list[0].str) != nil and env.get(ast.list[0].str).fun_is_macro
proc macroexpand(ast: MalType, env: Env): MalType =
result = ast
proc is_macro_call(ast: MalType, env: Env): bool =
ast.kind == List and ast.list.len > 0 and ast.list[0].kind == Symbol and
- env.find(ast.list[0].str) != nil and env.get(ast.list[0].str).macro_q
+ env.find(ast.list[0].str) != nil and env.get(ast.list[0].str).fun_is_macro
proc macroexpand(ast: MalType, env: Env): MalType =
result = ast
else: xs[i].str
result.hash_map[s] = xs[i+1]
-proc macro_q*(x: MalType): bool =
+proc fun_is_macro*(x: MalType): bool =
if x.kind == Fun: result = x.is_macro
elif x.kind == MalFun: result = x.malfun.is_macro
else: raise newException(ValueError, "no function")
proc keyword_q*(xs: varargs[MalType]): MalType {.procvar.} =
boolObj(xs[0].kind == String and xs[0].str[0] == '\xff')
+proc number_q*(xs: varargs[MalType]): MalType {.procvar.} =
+ boolObj xs[0].kind == Number
+
+proc fn_q*(xs: varargs[MalType]): MalType {.procvar.} =
+ boolObj((xs[0].kind == MalFun or xs[0].kind == Fun) and not xs[0].fun_is_macro)
+
+proc macro_q*(xs: varargs[MalType]): MalType {.procvar.} =
+ boolObj((xs[0].kind == MalFun or xs[0].kind == Fun) and xs[0].fun_is_macro)
+
proc atom*(xs: varargs[MalType]): MalType {.procvar.} =
atom(xs[0])