Skip to content

Commit

Permalink
swift[34]: merge eval_ast and macroexpand into EVAL, add DEBUG-EVAL
Browse files Browse the repository at this point in the history
swift3: merge env.find and env.get, take a string as parameter,
  return nil instead of throwing an exception
swift3/stepA: print *host-language*
swift4: reduce differences between steps in spacing, ordering and so on.
swift4/step5: remove a large comment containing non-printable characters
  • Loading branch information
asarhaddon committed Nov 9, 2024
1 parent dfc67ee commit 55c1039
Show file tree
Hide file tree
Showing 19 changed files with 473 additions and 824 deletions.
28 changes: 2 additions & 26 deletions impls/swift3/Sources/env.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,32 +48,8 @@ class Env {
}
}

func find(_ key: MalVal) throws -> Env? {
switch key {
case MalVal.MalSymbol(let str):
if data[str] != nil {
return self
} else if outer != nil {
return try outer!.find(key)
} else {
return nil
}
default:
throw MalError.General(msg: "invalid Env.find call")
}
}

func get(_ key: MalVal) throws -> MalVal {
switch key {
case MalVal.MalSymbol(let str):
let env = try self.find(key)
if env == nil {
throw MalError.General(msg: "'\(str)' not found")
}
return env!.data[str]!
default:
throw MalError.General(msg: "invalid Env.find call")
}
func get(_ str: String) -> MalVal? {
return data[str] ?? outer?.get(str)
}

@discardableResult
Expand Down
40 changes: 16 additions & 24 deletions impls/swift3/Sources/step2_eval/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,37 @@ func READ(_ str: String) throws -> MalVal {
}

// eval
func eval_ast(_ ast: MalVal, _ env: Dictionary<String, MalVal>) throws -> MalVal {
func EVAL(_ ast: MalVal, _ env: Dictionary<String, MalVal>) throws -> MalVal {
/* print("EVAL: " + PRINT(ast)) */
switch ast {
case MalVal.MalSymbol(let sym):
if env[sym] == nil {
if let value = env[sym] {
return value
} else {
throw MalError.General(msg: "'\(sym)' not found")
}
return env[sym]!
case MalVal.MalList(let lst, _):
return list(try lst.map { try EVAL($0, env) })
case MalVal.MalVector(let lst, _):
return vector(try lst.map { try EVAL($0, env) })
case MalVal.MalHashMap(let dict, _):
var new_dict = Dictionary<String,MalVal>()
for (k,v) in dict { new_dict[k] = try EVAL(v, env) }
return hash_map(new_dict)
case MalVal.MalList(let lst, _):
if lst.count == 0 { return ast }

let raw_args = lst[1..<lst.count]
switch try EVAL(lst[0], env) {
case MalVal.MalFunc(let fn, nil, _, _, _, _):
let args = try raw_args.map { try EVAL($0, env) }
return try fn(args)
default:
throw MalError.General(msg: "Cannot apply on '\(lst[0])'")
}
default:
return ast
}
}

func EVAL(_ ast: MalVal, _ env: Dictionary<String, MalVal>) throws -> MalVal {
switch ast {
case MalVal.MalList(let lst, _): if lst.count == 0 { return ast }
default: return try eval_ast(ast, env)
}

switch try eval_ast(ast, env) {
case MalVal.MalList(let elst, _):
switch elst[0] {
case MalVal.MalFunc(let fn,_,_,_,_,_):
let args = Array(elst[1..<elst.count])
return try fn(args)
default:
throw MalError.General(msg: "Cannot apply on '\(elst[0])'")
}
default: throw MalError.General(msg: "Invalid apply")
}
}

// print
func PRINT(_ exp: MalVal) -> String {
return pr_str(exp, true)
Expand Down
46 changes: 20 additions & 26 deletions impls/swift3/Sources/step3_env/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,28 @@ func READ(_ str: String) throws -> MalVal {
}

// eval
func eval_ast(_ ast: MalVal, _ env: Env) throws -> MalVal {
func EVAL(_ ast: MalVal, _ env: Env) throws -> MalVal {
if let dbgeval = env.get("DEBUG-EVAL") {
switch dbgeval {
case MalVal.MalFalse, MalVal.MalNil: break
default: print("EVAL: " + PRINT(ast))
}
}
switch ast {
case MalVal.MalSymbol:
return try env.get(ast)
case MalVal.MalList(let lst, _):
return list(try lst.map { try EVAL($0, env) })
case MalVal.MalSymbol(let sym):
if let value = env.get(sym) {
return value
} else {
throw MalError.General(msg: "'\(sym)' not found")
}
case MalVal.MalVector(let lst, _):
return vector(try lst.map { try EVAL($0, env) })
case MalVal.MalHashMap(let dict, _):
var new_dict = Dictionary<String,MalVal>()
for (k,v) in dict { new_dict[k] = try EVAL(v, env) }
return hash_map(new_dict)
default:
return ast
}
}

func EVAL(_ ast: MalVal, _ env: Env) throws -> MalVal {
switch ast {
case MalVal.MalList(let lst, _): if lst.count == 0 { return ast }
default: return try eval_ast(ast, env)
}

switch ast {
case MalVal.MalList(let lst, _):
if lst.count == 0 { return ast }
switch lst[0] {
case MalVal.MalSymbol("def!"):
return try env.set(lst[1], try EVAL(lst[2], env))
Expand All @@ -51,20 +48,17 @@ func EVAL(_ ast: MalVal, _ env: Env) throws -> MalVal {
}
return try EVAL(lst[2], let_env)
default:
switch try eval_ast(ast, env) {
case MalVal.MalList(let elst, _):
switch elst[0] {
case MalVal.MalFunc(let fn,_,_,_,_,_):
let args = Array(elst[1..<elst.count])
let raw_args = lst[1..<lst.count]
switch try EVAL(lst[0], env) {
case MalVal.MalFunc(let fn, nil, _, _, _, _):
let args = try raw_args.map { try EVAL($0, env) }
return try fn(args)
default:
throw MalError.General(msg: "Cannot apply on '\(elst[0])'")
throw MalError.General(msg: "Cannot apply on '\(lst[0])'")
}
default: throw MalError.General(msg: "Invalid apply")
}
}
default:
throw MalError.General(msg: "Invalid apply")
return ast
}
}

Expand Down
56 changes: 24 additions & 32 deletions impls/swift3/Sources/step4_if_fn_do/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,28 @@ func READ(_ str: String) throws -> MalVal {
}

// eval
func eval_ast(_ ast: MalVal, _ env: Env) throws -> MalVal {
func EVAL(_ ast: MalVal, _ env: Env) throws -> MalVal {
if let dbgeval = env.get("DEBUG-EVAL") {
switch dbgeval {
case MalVal.MalFalse, MalVal.MalNil: break
default: print("EVAL: " + PRINT(ast))
}
}
switch ast {
case MalVal.MalSymbol:
return try env.get(ast)
case MalVal.MalList(let lst, _):
return list(try lst.map { try EVAL($0, env) })
case MalVal.MalSymbol(let sym):
if let value = env.get(sym) {
return value
} else {
throw MalError.General(msg: "'\(sym)' not found")
}
case MalVal.MalVector(let lst, _):
return vector(try lst.map { try EVAL($0, env) })
case MalVal.MalHashMap(let dict, _):
var new_dict = Dictionary<String,MalVal>()
for (k,v) in dict { new_dict[k] = try EVAL(v, env) }
return hash_map(new_dict)
default:
return ast
}
}

func EVAL(_ ast: MalVal, _ env: Env) throws -> MalVal {
switch ast {
case MalVal.MalList(let lst, _): if lst.count == 0 { return ast }
default: return try eval_ast(ast, env)
}

switch ast {
case MalVal.MalList(let lst, _):
if lst.count == 0 { return ast }
switch lst[0] {
case MalVal.MalSymbol("def!"):
return try env.set(lst[1], try EVAL(lst[2], env))
Expand All @@ -51,13 +48,11 @@ func EVAL(_ ast: MalVal, _ env: Env) throws -> MalVal {
}
return try EVAL(lst[2], let_env)
case MalVal.MalSymbol("do"):
let slc = lst[lst.index(after: lst.startIndex)..<lst.endIndex]
switch try eval_ast(list(Array(slc)), env) {
case MalVal.MalList(let elst, _):
return elst[elst.index(before: elst.endIndex)]
default:
throw MalError.General(msg: "Invalid do form")
let slc = lst[1..<lst.index(before: lst.endIndex)]
for item in slc {
_ = try EVAL(item, env)
}
return try EVAL(lst[lst.index(before: lst.endIndex)], env)
case MalVal.MalSymbol("if"):
switch try EVAL(lst[1], env) {
case MalVal.MalFalse, MalVal.MalNil:
Expand All @@ -75,20 +70,17 @@ func EVAL(_ ast: MalVal, _ env: Env) throws -> MalVal {
exprs: list($0)))
})
default:
switch try eval_ast(ast, env) {
case MalVal.MalList(let elst, _):
switch elst[0] {
case MalVal.MalFunc(let fn,_,_,_,_,_):
let args = Array(elst[1..<elst.count])
let raw_args = lst[1..<lst.count]
switch try EVAL(lst[0], env) {
case MalVal.MalFunc(let fn, nil, _, _, _, _):
let args = try raw_args.map { try EVAL($0, env) }
return try fn(args)
default:
throw MalError.General(msg: "Cannot apply on '\(elst[0])'")
throw MalError.General(msg: "Cannot apply on '\(lst[0])'")
}
default: throw MalError.General(msg: "Invalid apply")
}
}
default:
throw MalError.General(msg: "Invalid apply")
return ast
}
}

Expand Down
54 changes: 25 additions & 29 deletions impls/swift3/Sources/step5_tco/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,30 @@ func READ(_ str: String) throws -> MalVal {
}

// eval
func eval_ast(_ ast: MalVal, _ env: Env) throws -> MalVal {
func EVAL(_ orig_ast: MalVal, _ orig_env: Env) throws -> MalVal {
var ast = orig_ast, env = orig_env
while true {
if let dbgeval = env.get("DEBUG-EVAL") {
switch dbgeval {
case MalVal.MalFalse, MalVal.MalNil: break
default: print("EVAL: " + PRINT(ast))
}
}
switch ast {
case MalVal.MalSymbol:
return try env.get(ast)
case MalVal.MalList(let lst, _):
return list(try lst.map { try EVAL($0, env) })
case MalVal.MalSymbol(let sym):
if let value = env.get(sym) {
return value
} else {
throw MalError.General(msg: "'\(sym)' not found")
}
case MalVal.MalVector(let lst, _):
return vector(try lst.map { try EVAL($0, env) })
case MalVal.MalHashMap(let dict, _):
var new_dict = Dictionary<String,MalVal>()
for (k,v) in dict { new_dict[k] = try EVAL(v, env) }
return hash_map(new_dict)
default:
return ast
}
}

func EVAL(_ orig_ast: MalVal, _ orig_env: Env) throws -> MalVal {
var ast = orig_ast, env = orig_env
while true {
switch ast {
case MalVal.MalList(let lst, _): if lst.count == 0 { return ast }
default: return try eval_ast(ast, env)
}

switch ast {
case MalVal.MalList(let lst, _):
if lst.count == 0 { return ast }
switch lst[0] {
case MalVal.MalSymbol("def!"):
return try env.set(lst[1], try EVAL(lst[2], env))
Expand All @@ -55,7 +52,9 @@ func EVAL(_ orig_ast: MalVal, _ orig_env: Env) throws -> MalVal {
ast = lst[2] // TCO
case MalVal.MalSymbol("do"):
let slc = lst[1..<lst.index(before: lst.endIndex)]
try _ = eval_ast(list(Array(slc)), env)
for item in slc {
_ = try EVAL(item, env)
}
ast = lst[lst.index(before: lst.endIndex)] // TCO
case MalVal.MalSymbol("if"):
switch try EVAL(lst[1], env) {
Expand All @@ -74,25 +73,22 @@ func EVAL(_ orig_ast: MalVal, _ orig_env: Env) throws -> MalVal {
exprs: list($0)))
}, ast:[lst[2]], env:env, params:[lst[1]])
default:
switch try eval_ast(ast, env) {
case MalVal.MalList(let elst, _):
switch elst[0] {
let raw_args = lst[1..<lst.count]
switch try EVAL(lst[0], env) {
case MalVal.MalFunc(let fn, nil, _, _, _, _):
let args = Array(elst[1..<elst.count])
let args = try raw_args.map { try EVAL($0, env) }
return try fn(args)
case MalVal.MalFunc(_, let a, let e, let p, _, _):
let args = Array(elst[1..<elst.count])
let args = try raw_args.map { try EVAL($0, env) }
env = try Env(e, binds: p![0],
exprs: list(args)) // TCO
ast = a![0] // TCO
default:
throw MalError.General(msg: "Cannot apply on '\(elst[0])'")
throw MalError.General(msg: "Cannot apply on '\(lst[0])'")
}
default: throw MalError.General(msg: "Invalid apply")
}
}
default:
throw MalError.General(msg: "Invalid apply")
return ast
}
}
}
Expand Down
Loading

0 comments on commit 55c1039

Please sign in to comment.