#print("EVAL %s" % printer._pr_str(ast))
if not types._list_Q(ast):
return eval_ast(ast, env)
+ if len(ast) == 0: return ast
# apply list
ast = macroexpand(ast, env)
#print("EVAL %s" % printer._pr_str(ast))
if not types._list_Q(ast):
return eval_ast(ast, env)
+ if len(ast) == 0: return ast
# apply list
ast = macroexpand(ast, env)
#print("EVAL %s" % printer._pr_str(ast))
if not types._list_Q(ast):
return eval_ast(ast, env)
+ if len(ast) == 0: return ast
# apply list
ast = macroexpand(ast, env)
ret = match ast.clone() {
List(l,_) => {
+ if l.len() == 0 { return Ok(ast); }
match macroexpand(ast.clone(), &env) {
(true, Ok(new_ast)) => {
ast = new_ast;
ret = match ast.clone() {
List(l,_) => {
+ if l.len() == 0 { return Ok(ast); }
match macroexpand(ast.clone(), &env) {
(true, Ok(new_ast)) => {
ast = new_ast;
ret = match ast.clone() {
List(l,_) => {
+ if l.len() == 0 { return Ok(ast); }
match macroexpand(ast.clone(), &env) {
(true, Ok(new_ast)) => {
ast = new_ast;
}
@discardableResult func rep(_ input: String, env: Env) throws -> String {
-
+
return try PRINT(EVAL(READ(input), env: env))
}
let fn = {(params: [MalData]) -> MalData in
let newEnv = Env(binds: (list[1].listForm as! [Symbol]), exprs: params, outer: env)
return try EVAL(list[2], env: newEnv)
- }
+ }
return Function(ast: list[2], params: (list[1].listForm as! [Symbol]), env:env , fn: fn)
-
+
default:
break
}
}
}
}
-
+
func PRINT(_ input: MalData) -> String {
return pr_str(input, print_readably: true)
}
@discardableResult func rep(_ input: String, env: Env) throws -> String {
-
return try PRINT(EVAL(READ(input), env: env))
}
let fn = {(params: [MalData]) -> MalData in
let newEnv = Env(binds: (list[1].listForm as! [Symbol]), exprs: params, outer: env)
return try EVAL(list[2], env: newEnv)
- }
+ }
return Function(ast: list[2], params: (list[1].listForm as! [Symbol]), env:env , fn: fn)
-
+
default:
break
}
ast = list[2]
}
continue
- case "fn*":
+ case "fn*":
let fn = {(params: [MalData]) -> MalData in
let newEnv = Env(binds: (list[1].listForm as! [Symbol]), exprs: params, outer: env)
return try EVAL(list[2], env: newEnv)
- }
+ }
return Function(ast: list[2], params: (list[1].listForm as! [Symbol]), env:env , fn: fn)
case "quote":
return list[1]
while true {
switch ast.dataType {
case .List:
+ if (ast as! [MalData]).isEmpty { return ast }
ast = try macroexpand(ast, env: env)
guard let list = ast as? [MalData] else { return try eval_ast(ast, env: env) }
guard !list.isEmpty else { return list }
ast = list[2]
}
continue
- case "fn*":
+ case "fn*":
let fn = {(params: [MalData]) -> MalData in
let newEnv = Env(binds: (list[1].listForm as! [Symbol]), exprs: params, outer: env)
return try EVAL(list[2], env: newEnv)
while true {
switch ast.dataType {
case .List:
+ if (ast as! [MalData]).isEmpty { return ast }
ast = try macroexpand(ast, env: env)
guard let list = ast as? [MalData] else { return try eval_ast(ast, env: env) }
guard !list.isEmpty else { return list }
ast = list[2]
}
continue
- case "fn*":
+ case "fn*":
let fn = {(params: [MalData]) -> MalData in
let newEnv = Env(binds: (list[1].listForm as! [Symbol]), exprs: params, outer: env)
return try EVAL(list[2], env: newEnv)
continue
case "macroexpand":
return try macroexpand(list[1], env: env)
-// (try* A (catch* B C))
case "try*":
do {
return try EVAL(list[1], env: env)
while true {
switch ast.dataType {
case .List:
+ if (ast as! [MalData]).isEmpty { return ast }
ast = try macroexpand(ast, env: env)
guard let list = ast as? [MalData] else { return try eval_ast(ast, env: env) }
guard !list.isEmpty else { return list }
(let* (a 123) (identity a))
;=>123
+;; Test that macros do not break empty list
+()
+;=>()
+
;>>> deferrable=True
;;
if (ast.type !== Node.List) {
return evalAST(ast, env);
}
+ if (ast.list.length === 0) {
+ return ast;
+ }
ast = macroexpand(ast, env);
if (!isSeq(ast)) {
if (ast.type !== Node.List) {
return evalAST(ast, env);
}
+ if (ast.list.length === 0) {
+ return ast;
+ }
ast = macroexpand(ast, env);
if (!isSeq(ast)) {
if (ast.type !== Node.List) {
return evalAST(ast, env);
}
+ if (ast.list.length === 0) {
+ return ast;
+ }
ast = macroexpand(ast, env);
if (!isSeq(ast)) {