1
1
mirror of https://github.com/kanaka/mal.git synced 2024-10-26 14:22:25 +03:00

Convert to Swift 1.2:

* Change "Array" to "ArraySlice"
* Change "as" keyword to "as!"
* Use count(str.utf16) rather than str.utf16count)
* Add "combine:" parameter label to call to slice.reduce
This commit is contained in:
Keith Rollin 2015-04-08 14:35:33 -07:00
parent 3829ee8cb4
commit 1c76df7dc6
15 changed files with 278 additions and 278 deletions

View File

@ -413,8 +413,8 @@ scala -classpath target/scala*/classes stepX_YYY
*The Swift implementation was created by [Keith Rollin](https://github.com/keith-rollin)*
The Swift implemenation of mal requires the Swift compiler (XCode) to
build.
The Swift implemenation of mal requires the Swift 1.2 compiler (XCode
6.3) to build.
```
cd swift

View File

@ -4,7 +4,7 @@
import Foundation
typealias MalVarArgs = Slice<MalVal>
typealias MalVarArgs = ArraySlice<MalVal>
func fn_eq(obj1: MalVal, obj2: MalVal) -> Bool {
return obj1 == obj2
@ -39,7 +39,7 @@ func fn_keyword(s: MalVal) -> MalVal {
return s
}
if is_string(s) {
return MalKeyword(keyword: (s as MalString).value)
return MalKeyword(keyword: (s as! MalString).value)
}
return MalError(message: "expected string or keyword")
}
@ -177,13 +177,13 @@ func fn_dissoc(hash: MalHashMap, args: MalVarArgs) -> MalVal {
func fn_get(obj: MalVal, key: MalVal) -> MalVal {
if is_vector(obj) {
if !is_integer(key) { return MalError(message: "expected integer key for get(vector), got \(key)") }
let as_vector = obj as MalVector
let index = key as MalInteger
let as_vector = obj as! MalVector
let index = key as! MalInteger
if Int(index.value) >= as_vector.count { return MalError(message: "index out of range: \(index) >= \(as_vector.count)") }
return as_vector[Int(index.value)]
}
if is_hashmap(obj) {
let as_hash = obj as MalHashMap
let as_hash = obj as! MalHashMap
if let value = as_hash[key] { return value }
return MalNil()
}
@ -196,12 +196,12 @@ func fn_get(obj: MalVal, key: MalVal) -> MalVal {
func fn_containsQ(obj: MalVal, key: MalVal) -> MalVal {
if is_vector(obj) {
if !is_integer(key) { return MalError(message: "expected integer key for contains(vector), got \(key)") }
let as_vector = obj as MalVector
let index = key as MalInteger
let as_vector = obj as! MalVector
let index = key as! MalInteger
return Int(index.value) < as_vector.count ? MalTrue() : MalFalse()
}
if is_hashmap(obj) {
let as_hash = obj as MalHashMap
let as_hash = obj as! MalHashMap
return as_hash[key] != nil ? MalTrue() : MalFalse()
}
return MalError(message: "contains? called on unsupported type: \(obj)")
@ -229,7 +229,7 @@ func fn_concat(args: MalVarArgs) -> MalVal {
var result = [MalVal]()
for arg in args {
if !is_sequence(arg) { return MalError(message: "expected list, got \(arg)") }
result.extend((arg as MalSequence).slice)
result.extend((arg as! MalSequence).slice)
}
return MalList(array: result)
}
@ -243,7 +243,7 @@ func fn_first(arg: MalVal) -> MalVal {
return arg
}
if is_sequence(arg) {
let list = arg as MalSequence
let list = arg as! MalSequence
return list.first()
}
return MalError(message: "expected list, got \(arg)")
@ -255,7 +255,7 @@ func fn_rest(list: MalSequence) -> MalVal {
func fn_emptyQ(obj: MalVal) -> Bool {
if is_sequence(obj) {
let list = obj as MalSequence
let list = obj as! MalSequence
return list.isEmpty
}
return true
@ -266,16 +266,16 @@ func fn_count(obj: MalVal) -> Int64 {
return 0
}
if is_sequence(obj) {
let as_seq = obj as MalSequence
let as_seq = obj as! MalSequence
return Int64(as_seq.count)
}
if is_hashmap(obj) {
let hash = obj as MalHashMap
let hash = obj as! MalHashMap
return Int64(hash.count)
}
if is_string(obj) {
let string = obj as MalString
return Int64(string.value.utf16Count)
let string = obj as! MalString
return Int64(count(string.value.utf16))
}
return 0
}
@ -287,8 +287,8 @@ func fn_apply(args: MalVarArgs) -> MalVal {
let last = args[args.count - 1]
if !is_function(first) { return MalError(message: "expected function for first argument to apply, got \(first)") }
if !is_sequence(last) { return MalError(message: "expected sequence for last argument to apply, got \(last)") }
middle.extend((last as MalSequence).slice)
return (first as MalFunction).apply(MalList(slice: middle))
middle.extend((last as! MalSequence).slice)
return (first as! MalFunction).apply(MalList(slice: middle))
}
func fn_map(fn: MalFunction, list: MalSequence) -> MalVal {
@ -338,7 +338,7 @@ func fn_atomQ(obj: MalVal) -> Bool {
func fn_deref(form:MalVal) -> MalVal {
if !is_atom(form) { return MalError(message: "expected atom, got \(form)") }
return (form as MalAtom).value
return (form as! MalAtom).value
}
func fn_resetBang(atom: MalAtom, obj: MalVal) -> MalVal {
@ -405,7 +405,7 @@ func unwrap(args: MalSequence, fn: () -> MalVal) -> MalVal {
func unwrap(args: MalSequence, fn: (MalHashMap) -> MalVal) -> MalVal {
return with_one_parameter(args) { (arg1) -> MalVal in
if !is_hashmap(arg1) { return MalError(message: "expected hashmap, got \(arg1)") }
return fn(arg1 as MalHashMap)
return fn(arg1 as! MalHashMap)
}
}
@ -414,7 +414,7 @@ func unwrap(args: MalSequence, fn: (MalHashMap) -> MalVal) -> MalVal {
func unwrap(args: MalSequence, fn: (MalSequence) -> MalVal) -> MalVal {
return with_one_parameter(args) { (arg1) -> MalVal in
if !is_sequence(arg1) { return MalError(message: "expected list, got \(arg1)") }
return fn(arg1 as MalSequence)
return fn(arg1 as! MalSequence)
}
}
@ -447,7 +447,7 @@ func unwrap(args: MalSequence, fn: (MalVal) -> MalVal) -> MalVal {
func unwrap(args: MalSequence, fn: (String) -> MalVal) -> MalVal {
return with_one_parameter(args) { (arg1) -> MalVal in
if !is_string(arg1) { return MalError(message: "expected string, got \(arg1)") }
return fn((arg1 as MalString).value)
return fn((arg1 as! MalString).value)
}
}
@ -456,7 +456,7 @@ func unwrap(args: MalSequence, fn: (String) -> MalVal) -> MalVal {
func unwrap(args: MalSequence, fn: (String) -> MalVal?) -> MalVal {
return with_one_parameter(args) { (arg1) -> MalVal in
if !is_string(arg1) { return MalError(message: "expected string, got \(arg1)") }
let res = fn((arg1 as MalString).value)
let res = fn((arg1 as! MalString).value)
return res != nil ? res! : MalNil()
}
}
@ -466,7 +466,7 @@ func unwrap(args: MalSequence, fn: (String) -> MalVal?) -> MalVal {
func unwrap(args: MalSequence, fn: (String) -> String) -> MalVal {
return with_one_parameter(args) { (arg1) -> MalVal in
if !is_string(arg1) { return MalError(message: "expected string, got \(arg1)") }
return MalString(unescaped: fn((arg1 as MalString).value))
return MalString(unescaped: fn((arg1 as! MalString).value))
}
}
@ -475,7 +475,7 @@ func unwrap(args: MalSequence, fn: (String) -> String) -> MalVal {
func unwrap(args: MalSequence, fn: (String) -> String?) -> MalVal {
return with_one_parameter(args) { (arg1) -> MalVal in
if !is_string(arg1) { return MalError(message: "expected string, got \(arg1)") }
let res = fn((arg1 as MalString).value)
let res = fn((arg1 as! MalString).value)
return res != nil ? MalString(unescaped:res!) : MalNil()
}
}
@ -488,7 +488,7 @@ func unwrap(args: MalSequence, fn: (Int64, Int64) -> Bool) -> MalVal {
return with_two_parameters(args) { (arg1, arg2) -> MalVal in
if !is_integer(arg1) { return MalError(message: "expected number, got \(arg1)") }
if !is_integer(arg2) { return MalError(message: "expected number, got \(arg2)") }
return fn((arg1 as MalInteger).value, (arg2 as MalInteger).value) ? MalTrue() : MalFalse()
return fn((arg1 as! MalInteger).value, (arg2 as! MalInteger).value) ? MalTrue() : MalFalse()
}
}
@ -498,7 +498,7 @@ func unwrap(args: MalSequence, fn: (Int64, Int64) -> Int64) -> MalVal {
return with_two_parameters(args) { (arg1, arg2) -> MalVal in
if !is_integer(arg1) { return MalError(message: "expected number, got \(arg1)") }
if !is_integer(arg2) { return MalError(message: "expected number, got \(arg2)") }
return MalInteger(value: fn((arg1 as MalInteger).value, (arg2 as MalInteger).value))
return MalInteger(value: fn((arg1 as! MalInteger).value, (arg2 as! MalInteger).value))
}
}
@ -507,7 +507,7 @@ func unwrap(args: MalSequence, fn: (Int64, Int64) -> Int64) -> MalVal {
func unwrap(args: MalSequence, fn: (MalAtom, MalVal) -> MalVal) -> MalVal {
return with_two_parameters(args) { (arg1, arg2) -> MalVal in
if !is_atom(arg1) { return MalError(message: "expected atom, got \(arg1)") }
return fn((arg1 as MalAtom), arg2)
return fn((arg1 as! MalAtom), arg2)
}
}
@ -517,7 +517,7 @@ func unwrap(args: MalSequence, fn: (MalFunction, MalSequence) -> MalVal) -> MalV
return with_two_parameters(args) { (arg1, arg2) -> MalVal in
if !is_function(arg1) { return MalError(message: "expected function, got \(arg1)") }
if !is_sequence(arg2) { return MalError(message: "expected sequence, got \(arg2)") }
return fn((arg1 as MalFunction), (arg2 as MalSequence))
return fn((arg1 as! MalFunction), (arg2 as! MalSequence))
}
}
@ -527,7 +527,7 @@ func unwrap(args: MalSequence, fn: (MalSequence, Int) -> MalVal) -> MalVal {
return with_two_parameters(args) { (arg1, arg2) -> MalVal in
if !is_sequence(arg1) { return MalError(message: "expected sequence, got \(arg1)") }
if !is_integer(arg2) { return MalError(message: "expected number, got \(arg2)") }
return fn((arg1 as MalSequence), Int((arg2 as MalInteger).value))
return fn((arg1 as! MalSequence), Int((arg2 as! MalInteger).value))
}
}
@ -536,7 +536,7 @@ func unwrap(args: MalSequence, fn: (MalSequence, Int) -> MalVal) -> MalVal {
func unwrap(args: MalSequence, fn: (MalVal, MalSequence) -> MalVal) -> MalVal {
return with_two_parameters(args) { (arg1, arg2) -> MalVal in
if !is_sequence(arg2) { return MalError(message: "expected sequence, got \(arg2)") }
return fn(arg1, (arg2 as MalSequence))
return fn(arg1, (arg2 as! MalSequence))
}
}
@ -583,7 +583,7 @@ func unwrap(args: MalSequence, fn: (MalAtom, MalFunction, MalVarArgs) -> MalVal)
return with_two_parameters(args) { (arg1, arg2) -> MalVal in
if !is_atom(arg1) { return MalError(message: "expected atom, got \(arg1)") }
if !is_function(arg2) { return MalError(message: "expected function, got \(arg2)") }
return fn((arg1 as MalAtom), (arg2 as MalFunction), args[2..<args.count])
return fn((arg1 as! MalAtom), (arg2 as! MalFunction), args[2..<args.count])
}
}
@ -592,7 +592,7 @@ func unwrap(args: MalSequence, fn: (MalAtom, MalFunction, MalVarArgs) -> MalVal)
func unwrap(args: MalSequence, fn: (MalHashMap, MalVarArgs) -> MalVal) -> MalVal {
return with_one_parameter(args) { (arg1) -> MalVal in
if !is_hashmap(arg1) { return MalError(message: "expected hashmap, got \(arg1)") }
return fn((arg1 as MalHashMap), args[1..<args.count])
return fn((arg1 as! MalHashMap), args[1..<args.count])
}
}
@ -601,7 +601,7 @@ func unwrap(args: MalSequence, fn: (MalHashMap, MalVarArgs) -> MalVal) -> MalVal
func unwrap(args: MalSequence, fn: (MalSequence, MalVarArgs) -> MalVal) -> MalVal {
return with_one_parameter(args) { (arg1) -> MalVal in
if !is_sequence(arg1) { return MalError(message: "expected sequence, got \(arg1)") }
return fn((arg1 as MalSequence), args[1..<args.count])
return fn((arg1 as! MalSequence), args[1..<args.count])
}
}

View File

@ -18,7 +18,7 @@ class Environment {
func set_bindings(binds: MalSequence, with_exprs exprs: MalSequence) -> MalVal {
for var index = 0; index < binds.count; ++index {
if !is_symbol(binds[index]) { return MalError(message: "an entry in binds was not a symbol: index=\(index), binds[index]=\(binds[index])") }
let sym = binds[index] as MalSymbol
let sym = binds[index] as! MalSymbol
if sym != kSymbolAmpersand {
if index < exprs.count {
set(sym, exprs[index])
@ -41,7 +41,7 @@ class Environment {
// later decrement it to get to (a b c d e ...)
if ++index >= binds.count { return MalError(message: "found & but no symbol") }
if !is_symbol(binds[index]) { return MalError(message: "& was not followed by a symbol: index=\(index), binds[index]=\(binds[index])") }
let rest_sym = binds[index--] as MalSymbol
let rest_sym = binds[index--] as! MalSymbol
let rest = exprs[index..<exprs.count]
set(rest_sym, MalList(slice: rest))
break

View File

@ -73,9 +73,9 @@ class Reader {
func tokenizer(s: String) -> [String] {
var tokens = [String]()
let range = NSMakeRange(0, s.utf16Count)
let range = NSMakeRange(0, count(s.utf16))
let matches = token_regex.matchesInString(s, options:.allZeros, range:range)
for match in matches as [NSTextCheckingResult] {
for match in matches as! [NSTextCheckingResult] {
if match.range.length > 0 {
let token = (s as NSString).substringWithRange(match.rangeAtIndex(1))
tokens.append(token)
@ -89,9 +89,9 @@ private func have_match_at(match: NSTextCheckingResult, index:Int) -> Bool {
}
func read_atom(token: String) -> MalVal {
let range = NSMakeRange(0, token.utf16Count)
let range = NSMakeRange(0, count(token.utf16))
let matches = atom_regex.matchesInString(token, options:.allZeros, range:range)
for match in matches as [NSTextCheckingResult] {
for match in matches as! [NSTextCheckingResult] {
if have_match_at(match, 1) { // Comment
return MalComment(comment: token)
} else if have_match_at(match, 2) { // Integer

View File

@ -23,13 +23,13 @@ func READ(str: String) -> MalVal {
func eval_ast(ast: MalVal, env: Environment) -> MalVal {
switch ast.type {
case .TypeSymbol:
let symbol = ast as MalSymbol
let symbol = ast as! MalSymbol
if let val = env.get(symbol) {
return val
}
return MalError(message: "'\(symbol)' not found") // Specific text needed to match MAL unit tests
case .TypeList:
let list = ast as MalList
let list = ast as! MalList
var result = [MalVal]()
result.reserveCapacity(list.count)
for item in list {
@ -39,7 +39,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalList(array: result)
case .TypeVector:
let vec = ast as MalVector
let vec = ast as! MalVector
var result = [MalVal]()
result.reserveCapacity(vec.count)
for item in vec {
@ -49,7 +49,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalVector(array: result)
case .TypeHashMap:
let hash = ast as MalHashMap
let hash = ast as! MalHashMap
var result = [MalVal]()
result.reserveCapacity(hash.count * 2)
for (k, v) in hash {
@ -80,7 +80,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// Special handling if it's a list.
var list = ast as MalList
var list = ast as! MalList
if list.isEmpty {
return list
@ -93,7 +93,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// The result had better be a list and better be non-empty.
let eval_list = eval as MalList
let eval_list = eval as! MalList
if eval_list.isEmpty {
return eval_list
}
@ -104,7 +104,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let rest = eval_list.rest()
if is_builtin(first) {
let fn = first as MalBuiltin
let fn = first as! MalBuiltin
let answer = fn.apply(rest)
return answer
}

View File

@ -28,13 +28,13 @@ func READ(str: String) -> MalVal {
func eval_ast(ast: MalVal, env: Environment) -> MalVal {
switch ast.type {
case .TypeSymbol:
let symbol = ast as MalSymbol
let symbol = ast as! MalSymbol
if let val = env.get(symbol) {
return val
}
return MalError(message: "'\(symbol)' not found") // Specific text needed to match MAL unit tests
case .TypeList:
let list = ast as MalList
let list = ast as! MalList
var result = [MalVal]()
result.reserveCapacity(list.count)
for item in list {
@ -44,7 +44,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalList(array: result)
case .TypeVector:
let vec = ast as MalVector
let vec = ast as! MalVector
var result = [MalVal]()
result.reserveCapacity(vec.count)
for item in vec {
@ -54,7 +54,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalVector(array: result)
case .TypeHashMap:
let hash = ast as MalHashMap
let hash = ast as! MalHashMap
var result = [MalVal]()
result.reserveCapacity(hash.count * 2)
for (k, v) in hash {
@ -80,7 +80,7 @@ func eval_def(list: MalSequence, env: Environment) -> MalVal {
if !is_symbol(arg1) {
return MalError(message: "expected symbol for first argument to def!")
}
let sym = arg1 as MalSymbol
let sym = arg1 as! MalSymbol
let value = EVAL(arg2, env)
if is_error(value) { return value }
return env.set(sym, value)
@ -97,7 +97,7 @@ func eval_let(list: MalSequence, env: Environment) -> MalVal {
if !is_sequence(arg1) {
return MalError(message: "expected list for first argument to let*")
}
let bindings = arg1 as MalSequence
let bindings = arg1 as! MalSequence
if bindings.count % 2 == 1 {
return MalError(message: "expected even number of elements in bindings to let*, got \(bindings.count)")
}
@ -109,7 +109,7 @@ func eval_let(list: MalSequence, env: Environment) -> MalVal {
if !is_symbol(binding_name) {
return MalError(message: "expected symbol for first element in binding pair")
}
let binding_symbol = binding_name as MalSymbol
let binding_symbol = binding_name as! MalSymbol
let evaluated_value = EVAL(binding_value, new_env)
if is_error(evaluated_value) { return evaluated_value }
new_env.set(binding_symbol, evaluated_value)
@ -133,7 +133,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// Special handling if it's a list.
var list = ast as MalList
var list = ast as! MalList
if list.isEmpty {
return list
@ -144,7 +144,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let arg0 = list.first()
if is_symbol(arg0) {
let fn_symbol = arg0 as MalSymbol
let fn_symbol = arg0 as! MalSymbol
switch fn_symbol {
case kSymbolDef: return eval_def(list, env)
@ -160,7 +160,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// The result had better be a list and better be non-empty.
let eval_list = eval as MalList
let eval_list = eval as! MalList
if eval_list.isEmpty {
return eval_list
}
@ -171,7 +171,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let rest = eval_list.rest()
if is_builtin(first) {
let fn = first as MalBuiltin
let fn = first as! MalBuiltin
let answer = fn.apply(rest)
return answer
}

View File

@ -31,13 +31,13 @@ func READ(str: String) -> MalVal {
func eval_ast(ast: MalVal, env: Environment) -> MalVal {
switch ast.type {
case .TypeSymbol:
let symbol = ast as MalSymbol
let symbol = ast as! MalSymbol
if let val = env.get(symbol) {
return val
}
return MalError(message: "'\(symbol)' not found") // Specific text needed to match MAL unit tests
case .TypeList:
let list = ast as MalList
let list = ast as! MalList
var result = [MalVal]()
result.reserveCapacity(list.count)
for item in list {
@ -47,7 +47,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalList(array: result)
case .TypeVector:
let vec = ast as MalVector
let vec = ast as! MalVector
var result = [MalVal]()
result.reserveCapacity(vec.count)
for item in vec {
@ -57,7 +57,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalVector(array: result)
case .TypeHashMap:
let hash = ast as MalHashMap
let hash = ast as! MalHashMap
var result = [MalVal]()
result.reserveCapacity(hash.count * 2)
for (k, v) in hash {
@ -83,7 +83,7 @@ func eval_def(list: MalSequence, env: Environment) -> MalVal {
if !is_symbol(arg1) {
return MalError(message: "expected symbol for first argument to def!")
}
let sym = arg1 as MalSymbol
let sym = arg1 as! MalSymbol
let value = EVAL(arg2, env)
if is_error(value) { return value }
return env.set(sym, value)
@ -100,7 +100,7 @@ func eval_let(list: MalSequence, env: Environment) -> MalVal {
if !is_sequence(arg1) {
return MalError(message: "expected list for first argument to let*")
}
let bindings = arg1 as MalSequence
let bindings = arg1 as! MalSequence
if bindings.count % 2 == 1 {
return MalError(message: "expected even number of elements in bindings to let*, got \(bindings.count)")
}
@ -112,7 +112,7 @@ func eval_let(list: MalSequence, env: Environment) -> MalVal {
if !is_symbol(binding_name) {
return MalError(message: "expected symbol for first element in binding pair")
}
let binding_symbol = binding_name as MalSymbol
let binding_symbol = binding_name as! MalSymbol
let evaluated_value = EVAL(binding_value, new_env)
if is_error(evaluated_value) { return evaluated_value }
new_env.set(binding_symbol, evaluated_value)
@ -125,7 +125,7 @@ func eval_let(list: MalSequence, env: Environment) -> MalVal {
func eval_do(list: MalSequence, env: Environment) -> MalVal {
let evaluated_ast = eval_ast(list.rest(), env)
if is_error(evaluated_ast) { return evaluated_ast }
let evaluated_seq = evaluated_ast as MalSequence
let evaluated_seq = evaluated_ast as! MalSequence
return evaluated_seq.last()
}
@ -156,7 +156,7 @@ func eval_fn(list: MalSequence, env: Environment) -> MalVal {
if !is_sequence(list[1]) {
return MalError(message: "expected list or vector for first argument to fn*")
}
return MalClosure(eval: EVAL, args:list[1] as MalSequence, body:list[2], env:env)
return MalClosure(eval: EVAL, args:list[1] as! MalSequence, body:list[2], env:env)
}
// Walk the AST and completely evaluate it, handling macro expansions, special
@ -175,7 +175,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// Special handling if it's a list.
var list = ast as MalList
var list = ast as! MalList
if list.isEmpty {
return list
@ -186,7 +186,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let arg0 = list.first()
if is_symbol(arg0) {
let fn_symbol = arg0 as MalSymbol
let fn_symbol = arg0 as! MalSymbol
switch fn_symbol {
case kSymbolDef: return eval_def(list, env)
@ -205,7 +205,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// The result had better be a list and better be non-empty.
let eval_list = eval as MalList
let eval_list = eval as! MalList
if eval_list.isEmpty {
return eval_list
}
@ -216,11 +216,11 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let rest = eval_list.rest()
if is_builtin(first) {
let fn = first as MalBuiltin
let fn = first as! MalBuiltin
let answer = fn.apply(rest)
return answer
} else if is_closure(first) {
let fn = first as MalClosure
let fn = first as! MalClosure
var new_env = Environment(outer: fn.env)
let result = new_env.set_bindings(fn.args, with_exprs:rest)
if is_error(result) { return result }

View File

@ -84,13 +84,13 @@ func READ(str: String) -> MalVal {
func eval_ast(ast: MalVal, env: Environment) -> MalVal {
switch ast.type {
case .TypeSymbol:
let symbol = ast as MalSymbol
let symbol = ast as! MalSymbol
if let val = env.get(symbol) {
return val
}
return MalError(message: "'\(symbol)' not found") // Specific text needed to match MAL unit tests
case .TypeList:
let list = ast as MalList
let list = ast as! MalList
var result = [MalVal]()
result.reserveCapacity(list.count)
for item in list {
@ -100,7 +100,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalList(array: result)
case .TypeVector:
let vec = ast as MalVector
let vec = ast as! MalVector
var result = [MalVal]()
result.reserveCapacity(vec.count)
for item in vec {
@ -110,7 +110,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalVector(array: result)
case .TypeHashMap:
let hash = ast as MalHashMap
let hash = ast as! MalHashMap
var result = [MalVal]()
result.reserveCapacity(hash.count * 2)
for (k, v) in hash {
@ -147,7 +147,7 @@ func eval_def(list: MalSequence, env: Environment) -> TCOVal {
if !is_symbol(arg1) {
return TCOVal("expected symbol for first argument to def!")
}
let sym = arg1 as MalSymbol
let sym = arg1 as! MalSymbol
let value = EVAL(arg2, env)
if is_error(value) { return TCOVal(value) }
return TCOVal(env.set(sym, value))
@ -164,7 +164,7 @@ func eval_let(list: MalSequence, env: Environment) -> TCOVal {
if !is_sequence(arg1) {
return TCOVal("expected list for first argument to let*")
}
let bindings = arg1 as MalSequence
let bindings = arg1 as! MalSequence
if bindings.count % 2 == 1 {
return TCOVal("expected even number of elements in bindings to let*, got \(bindings.count)")
}
@ -176,7 +176,7 @@ func eval_let(list: MalSequence, env: Environment) -> TCOVal {
if !is_symbol(binding_name) {
return TCOVal("expected symbol for first element in binding pair")
}
let binding_symbol = binding_name as MalSymbol
let binding_symbol = binding_name as! MalSymbol
let evaluated_value = EVAL(binding_value, new_env)
if is_error(evaluated_value) { return TCOVal(evaluated_value) }
new_env.set(binding_symbol, evaluated_value)
@ -198,7 +198,7 @@ func eval_do(list: MalSequence, env: Environment) -> TCOVal {
let evaluated_ast = eval_ast(list.rest(), env)
if is_error(evaluated_ast) { return TCOVal(evaluated_ast) }
let evaluated_seq = evaluated_ast as MalSequence
let evaluated_seq = evaluated_ast as! MalSequence
return TCOVal(evaluated_seq.last())
}
@ -232,7 +232,7 @@ func eval_fn(list: MalSequence, env: Environment) -> TCOVal {
if !is_sequence(list[1]) {
return TCOVal("expected list or vector for first argument to fn*")
}
return TCOVal(MalClosure(eval: EVAL, args:list[1] as MalSequence, body:list[2], env:env))
return TCOVal(MalClosure(eval: EVAL, args:list[1] as! MalSequence, body:list[2], env:env))
}
// Walk the AST and completely evaluate it, handling macro expansions, special
@ -263,7 +263,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// Special handling if it's a list.
var list = ast as MalList
var list = ast as! MalList
if DEBUG_EVAL { println("\(indent)>. \(list)") }
if list.isEmpty {
@ -276,7 +276,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let arg0 = list.first()
if is_symbol(arg0) {
var res: TCOVal
let fn_symbol = arg0 as MalSymbol
let fn_symbol = arg0 as! MalSymbol
switch fn_symbol {
case kSymbolDef: res = eval_def(list, env)
@ -300,7 +300,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// The result had better be a list and better be non-empty.
let eval_list = eval as MalList
let eval_list = eval as! MalList
if eval_list.isEmpty {
return eval_list
}
@ -313,12 +313,12 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let rest = eval_list.rest()
if is_builtin(first) {
let fn = first as MalBuiltin
let fn = first as! MalBuiltin
let answer = fn.apply(rest)
if DEBUG_EVAL { println("\(indent)>>> \(answer)") }
return answer
} else if is_closure(first) {
let fn = first as MalClosure
let fn = first as! MalClosure
var new_env = Environment(outer: fn.env)
let result = new_env.set_bindings(fn.args, with_exprs:rest)
if is_error(result) { return result }

View File

@ -86,13 +86,13 @@ func READ(str: String) -> MalVal {
func eval_ast(ast: MalVal, env: Environment) -> MalVal {
switch ast.type {
case .TypeSymbol:
let symbol = ast as MalSymbol
let symbol = ast as! MalSymbol
if let val = env.get(symbol) {
return val
}
return MalError(message: "'\(symbol)' not found") // Specific text needed to match MAL unit tests
case .TypeList:
let list = ast as MalList
let list = ast as! MalList
var result = [MalVal]()
result.reserveCapacity(list.count)
for item in list {
@ -102,7 +102,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalList(array: result)
case .TypeVector:
let vec = ast as MalVector
let vec = ast as! MalVector
var result = [MalVal]()
result.reserveCapacity(vec.count)
for item in vec {
@ -112,7 +112,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalVector(array: result)
case .TypeHashMap:
let hash = ast as MalHashMap
let hash = ast as! MalHashMap
var result = [MalVal]()
result.reserveCapacity(hash.count * 2)
for (k, v) in hash {
@ -149,7 +149,7 @@ func eval_def(list: MalSequence, env: Environment) -> TCOVal {
if !is_symbol(arg1) {
return TCOVal("expected symbol for first argument to def!")
}
let sym = arg1 as MalSymbol
let sym = arg1 as! MalSymbol
let value = EVAL(arg2, env)
if is_error(value) { return TCOVal(value) }
return TCOVal(env.set(sym, value))
@ -166,7 +166,7 @@ func eval_let(list: MalSequence, env: Environment) -> TCOVal {
if !is_sequence(arg1) {
return TCOVal("expected list for first argument to let*")
}
let bindings = arg1 as MalSequence
let bindings = arg1 as! MalSequence
if bindings.count % 2 == 1 {
return TCOVal("expected even number of elements in bindings to let*, got \(bindings.count)")
}
@ -178,7 +178,7 @@ func eval_let(list: MalSequence, env: Environment) -> TCOVal {
if !is_symbol(binding_name) {
return TCOVal("expected symbol for first element in binding pair")
}
let binding_symbol = binding_name as MalSymbol
let binding_symbol = binding_name as! MalSymbol
let evaluated_value = EVAL(binding_value, new_env)
if is_error(evaluated_value) { return TCOVal(evaluated_value) }
new_env.set(binding_symbol, evaluated_value)
@ -200,7 +200,7 @@ func eval_do(list: MalSequence, env: Environment) -> TCOVal {
let evaluated_ast = eval_ast(list.rest(), env)
if is_error(evaluated_ast) { return TCOVal(evaluated_ast) }
let evaluated_seq = evaluated_ast as MalSequence
let evaluated_seq = evaluated_ast as! MalSequence
return TCOVal(evaluated_seq.last())
}
@ -234,7 +234,7 @@ func eval_fn(list: MalSequence, env: Environment) -> TCOVal {
if !is_sequence(list[1]) {
return TCOVal("expected list or vector for first argument to fn*")
}
return TCOVal(MalClosure(eval: EVAL, args:list[1] as MalSequence, body:list[2], env:env))
return TCOVal(MalClosure(eval: EVAL, args:list[1] as! MalSequence, body:list[2], env:env))
}
// Walk the AST and completely evaluate it, handling macro expansions, special
@ -265,7 +265,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// Special handling if it's a list.
var list = ast as MalList
var list = ast as! MalList
if DEBUG_EVAL { println("\(indent)>. \(list)") }
if list.isEmpty {
@ -278,7 +278,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let arg0 = list.first()
if is_symbol(arg0) {
var res: TCOVal
let fn_symbol = arg0 as MalSymbol
let fn_symbol = arg0 as! MalSymbol
switch fn_symbol {
case kSymbolDef: res = eval_def(list, env)
@ -302,7 +302,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// The result had better be a list and better be non-empty.
let eval_list = eval as MalList
let eval_list = eval as! MalList
if eval_list.isEmpty {
return eval_list
}
@ -315,12 +315,12 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let rest = eval_list.rest()
if is_builtin(first) {
let fn = first as MalBuiltin
let fn = first as! MalBuiltin
let answer = fn.apply(rest)
if DEBUG_EVAL { println("\(indent)>>> \(answer)") }
return answer
} else if is_closure(first) {
let fn = first as MalClosure
let fn = first as! MalClosure
var new_env = Environment(outer: fn.env)
let result = new_env.set_bindings(fn.args, with_exprs:rest)
if is_error(result) { return result }

View File

@ -88,7 +88,7 @@ func READ(str: String) -> MalVal {
//
func is_pair(val:MalVal) -> Bool {
if !is_sequence(val) { return false }
let list = val as MalSequence
let list = val as! MalSequence
return !list.isEmpty
}
@ -146,9 +146,9 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
//
// Return: item
let qq_list = qq_arg as MalSequence
let qq_list = qq_arg as! MalSequence
if is_symbol(qq_list.first()) {
let sym = qq_list.first() as MalSymbol
let sym = qq_list.first() as! MalSymbol
if sym == kSymbolUnquote {
return qq_list.count >= 2 ? qq_list[1] : MalNil()
}
@ -160,9 +160,9 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
// Return: (concat item quasiquote(rest...))
if is_pair(qq_list.first()) {
let qq_list_item0 = qq_list.first() as MalSequence
let qq_list_item0 = qq_list.first() as! MalSequence
if is_symbol(qq_list_item0.first()) {
let sym = qq_list_item0.first() as MalSymbol
let sym = qq_list_item0.first() as! MalSymbol
if sym == kSymbolSpliceUnquote {
let result = quasiquote(qq_list.rest())
if is_error(result) { return result }
@ -192,13 +192,13 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
func eval_ast(ast: MalVal, env: Environment) -> MalVal {
switch ast.type {
case .TypeSymbol:
let symbol = ast as MalSymbol
let symbol = ast as! MalSymbol
if let val = env.get(symbol) {
return val
}
return MalError(message: "'\(symbol)' not found") // Specific text needed to match MAL unit tests
case .TypeList:
let list = ast as MalList
let list = ast as! MalList
var result = [MalVal]()
result.reserveCapacity(list.count)
for item in list {
@ -208,7 +208,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalList(array: result)
case .TypeVector:
let vec = ast as MalVector
let vec = ast as! MalVector
var result = [MalVal]()
result.reserveCapacity(vec.count)
for item in vec {
@ -218,7 +218,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalVector(array: result)
case .TypeHashMap:
let hash = ast as MalHashMap
let hash = ast as! MalHashMap
var result = [MalVal]()
result.reserveCapacity(hash.count * 2)
for (k, v) in hash {
@ -255,7 +255,7 @@ func eval_def(list: MalSequence, env: Environment) -> TCOVal {
if !is_symbol(arg1) {
return TCOVal("expected symbol for first argument to def!")
}
let sym = arg1 as MalSymbol
let sym = arg1 as! MalSymbol
let value = EVAL(arg2, env)
if is_error(value) { return TCOVal(value) }
return TCOVal(env.set(sym, value))
@ -272,7 +272,7 @@ func eval_let(list: MalSequence, env: Environment) -> TCOVal {
if !is_sequence(arg1) {
return TCOVal("expected list for first argument to let*")
}
let bindings = arg1 as MalSequence
let bindings = arg1 as! MalSequence
if bindings.count % 2 == 1 {
return TCOVal("expected even number of elements in bindings to let*, got \(bindings.count)")
}
@ -284,7 +284,7 @@ func eval_let(list: MalSequence, env: Environment) -> TCOVal {
if !is_symbol(binding_name) {
return TCOVal("expected symbol for first element in binding pair")
}
let binding_symbol = binding_name as MalSymbol
let binding_symbol = binding_name as! MalSymbol
let evaluated_value = EVAL(binding_value, new_env)
if is_error(evaluated_value) { return TCOVal(evaluated_value) }
new_env.set(binding_symbol, evaluated_value)
@ -306,7 +306,7 @@ func eval_do(list: MalSequence, env: Environment) -> TCOVal {
let evaluated_ast = eval_ast(list.rest(), env)
if is_error(evaluated_ast) { return TCOVal(evaluated_ast) }
let evaluated_seq = evaluated_ast as MalSequence
let evaluated_seq = evaluated_ast as! MalSequence
return TCOVal(evaluated_seq.last())
}
@ -340,7 +340,7 @@ func eval_fn(list: MalSequence, env: Environment) -> TCOVal {
if !is_sequence(list[1]) {
return TCOVal("expected list or vector for first argument to fn*")
}
return TCOVal(MalClosure(eval: EVAL, args:list[1] as MalSequence, body:list[2], env:env))
return TCOVal(MalClosure(eval: EVAL, args:list[1] as! MalSequence, body:list[2], env:env))
}
// EVALuate "quote".
@ -392,7 +392,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// Special handling if it's a list.
var list = ast as MalList
var list = ast as! MalList
if DEBUG_EVAL { println("\(indent)>. \(list)") }
if list.isEmpty {
@ -405,7 +405,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let arg0 = list.first()
if is_symbol(arg0) {
var res: TCOVal
let fn_symbol = arg0 as MalSymbol
let fn_symbol = arg0 as! MalSymbol
switch fn_symbol {
case kSymbolDef: res = eval_def(list, env)
@ -431,7 +431,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// The result had better be a list and better be non-empty.
let eval_list = eval as MalList
let eval_list = eval as! MalList
if eval_list.isEmpty {
return eval_list
}
@ -444,12 +444,12 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let rest = eval_list.rest()
if is_builtin(first) {
let fn = first as MalBuiltin
let fn = first as! MalBuiltin
let answer = fn.apply(rest)
if DEBUG_EVAL { println("\(indent)>>> \(answer)") }
return answer
} else if is_closure(first) {
let fn = first as MalClosure
let fn = first as! MalClosure
var new_env = Environment(outer: fn.env)
let result = new_env.set_bindings(fn.args, with_exprs:rest)
if is_error(result) { return result }

View File

@ -90,7 +90,7 @@ func READ(str: String) -> MalVal {
//
func is_pair(val:MalVal) -> Bool {
if !is_sequence(val) { return false }
let list = val as MalSequence
let list = val as! MalSequence
return !list.isEmpty
}
@ -99,15 +99,15 @@ func is_pair(val:MalVal) -> Bool {
func macroexpand(var ast:MalVal, env:Environment) -> MalVal {
while true {
if !is_list(ast) { break }
let ast_as_list = ast as MalList
let ast_as_list = ast as! MalList
if ast_as_list.isEmpty { break }
let first = ast_as_list.first()
if !is_symbol(first) { break }
let macro_name = first as MalSymbol
let macro_name = first as! MalSymbol
let obj = env.get(macro_name)
if obj == nil { break }
if !is_closure(obj!) { break }
let macro = obj! as MalClosure
let macro = obj! as! MalClosure
if !macro.is_macro { break }
var new_env = Environment(outer: macro.env)
let rest = ast_as_list.rest()
@ -172,9 +172,9 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
//
// Return: item
let qq_list = qq_arg as MalSequence
let qq_list = qq_arg as! MalSequence
if is_symbol(qq_list.first()) {
let sym = qq_list.first() as MalSymbol
let sym = qq_list.first() as! MalSymbol
if sym == kSymbolUnquote {
return qq_list.count >= 2 ? qq_list[1] : MalNil()
}
@ -186,9 +186,9 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
// Return: (concat item quasiquote(rest...))
if is_pair(qq_list.first()) {
let qq_list_item0 = qq_list.first() as MalSequence
let qq_list_item0 = qq_list.first() as! MalSequence
if is_symbol(qq_list_item0.first()) {
let sym = qq_list_item0.first() as MalSymbol
let sym = qq_list_item0.first() as! MalSymbol
if sym == kSymbolSpliceUnquote {
let result = quasiquote(qq_list.rest())
if is_error(result) { return result }
@ -218,13 +218,13 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
func eval_ast(ast: MalVal, env: Environment) -> MalVal {
switch ast.type {
case .TypeSymbol:
let symbol = ast as MalSymbol
let symbol = ast as! MalSymbol
if let val = env.get(symbol) {
return val
}
return MalError(message: "'\(symbol)' not found") // Specific text needed to match MAL unit tests
case .TypeList:
let list = ast as MalList
let list = ast as! MalList
var result = [MalVal]()
result.reserveCapacity(list.count)
for item in list {
@ -234,7 +234,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalList(array: result)
case .TypeVector:
let vec = ast as MalVector
let vec = ast as! MalVector
var result = [MalVal]()
result.reserveCapacity(vec.count)
for item in vec {
@ -244,7 +244,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalVector(array: result)
case .TypeHashMap:
let hash = ast as MalHashMap
let hash = ast as! MalHashMap
var result = [MalVal]()
result.reserveCapacity(hash.count * 2)
for (k, v) in hash {
@ -276,18 +276,18 @@ func eval_def(list: MalSequence, env: Environment) -> TCOVal {
if list.count != 3 {
return TCOVal("expected 2 arguments to def!, got \(list.count - 1)")
}
let arg0 = list[0] as MalSymbol
let arg0 = list[0] as! MalSymbol
let arg1 = list[1]
let arg2 = list[2]
if !is_symbol(arg1) {
return TCOVal("expected symbol for first argument to def!")
}
let sym = arg1 as MalSymbol
let sym = arg1 as! MalSymbol
let value = EVAL(arg2, env)
if is_error(value) { return TCOVal(value) }
if arg0 == kSymbolDefMacro {
if is_closure(value) {
let as_closure = value as MalClosure
let as_closure = value as! MalClosure
as_closure.is_macro = true
} else {
return TCOVal("expected closure, got \(value)")
@ -307,7 +307,7 @@ func eval_let(list: MalSequence, env: Environment) -> TCOVal {
if !is_sequence(arg1) {
return TCOVal("expected list for first argument to let*")
}
let bindings = arg1 as MalSequence
let bindings = arg1 as! MalSequence
if bindings.count % 2 == 1 {
return TCOVal("expected even number of elements in bindings to let*, got \(bindings.count)")
}
@ -319,7 +319,7 @@ func eval_let(list: MalSequence, env: Environment) -> TCOVal {
if !is_symbol(binding_name) {
return TCOVal("expected symbol for first element in binding pair")
}
let binding_symbol = binding_name as MalSymbol
let binding_symbol = binding_name as! MalSymbol
let evaluated_value = EVAL(binding_value, new_env)
if is_error(evaluated_value) { return TCOVal(evaluated_value) }
new_env.set(binding_symbol, evaluated_value)
@ -341,7 +341,7 @@ func eval_do(list: MalSequence, env: Environment) -> TCOVal {
let evaluated_ast = eval_ast(list.rest(), env)
if is_error(evaluated_ast) { return TCOVal(evaluated_ast) }
let evaluated_seq = evaluated_ast as MalSequence
let evaluated_seq = evaluated_ast as! MalSequence
return TCOVal(evaluated_seq.last())
}
@ -375,7 +375,7 @@ func eval_fn(list: MalSequence, env: Environment) -> TCOVal {
if !is_sequence(list[1]) {
return TCOVal("expected list or vector for first argument to fn*")
}
return TCOVal(MalClosure(eval: EVAL, args:list[1] as MalSequence, body:list[2], env:env))
return TCOVal(MalClosure(eval: EVAL, args:list[1] as! MalSequence, body:list[2], env:env))
}
// EVALuate "quote".
@ -436,10 +436,10 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// Special handling if it's a list.
var list = ast as MalList
var list = ast as! MalList
ast = macroexpand(ast, env)
if !is_list(ast) { return ast }
list = ast as MalList
list = ast as! MalList
if DEBUG_EVAL { println("\(indent)>. \(list)") }
@ -453,7 +453,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let arg0 = list.first()
if is_symbol(arg0) {
var res: TCOVal
let fn_symbol = arg0 as MalSymbol
let fn_symbol = arg0 as! MalSymbol
switch fn_symbol {
case kSymbolDef: res = eval_def(list, env)
@ -481,7 +481,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// The result had better be a list and better be non-empty.
let eval_list = eval as MalList
let eval_list = eval as! MalList
if eval_list.isEmpty {
return eval_list
}
@ -494,12 +494,12 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let rest = eval_list.rest()
if is_builtin(first) {
let fn = first as MalBuiltin
let fn = first as! MalBuiltin
let answer = fn.apply(rest)
if DEBUG_EVAL { println("\(indent)>>> \(answer)") }
return answer
} else if is_closure(first) {
let fn = first as MalClosure
let fn = first as! MalClosure
var new_env = Environment(outer: fn.env)
let result = new_env.set_bindings(fn.args, with_exprs:rest)
if is_error(result) { return result }

View File

@ -92,7 +92,7 @@ func READ(str: String) -> MalVal {
//
func is_pair(val:MalVal) -> Bool {
if !is_sequence(val) { return false }
let list = val as MalSequence
let list = val as! MalSequence
return !list.isEmpty
}
@ -101,15 +101,15 @@ func is_pair(val:MalVal) -> Bool {
func macroexpand(var ast:MalVal, env:Environment) -> MalVal {
while true {
if !is_list(ast) { break }
let ast_as_list = ast as MalList
let ast_as_list = ast as! MalList
if ast_as_list.isEmpty { break }
let first = ast_as_list.first()
if !is_symbol(first) { break }
let macro_name = first as MalSymbol
let macro_name = first as! MalSymbol
let obj = env.get(macro_name)
if obj == nil { break }
if !is_closure(obj!) { break }
let macro = obj! as MalClosure
let macro = obj! as! MalClosure
if !macro.is_macro { break }
var new_env = Environment(outer: macro.env)
let rest = ast_as_list.rest()
@ -174,9 +174,9 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
//
// Return: item
let qq_list = qq_arg as MalSequence
let qq_list = qq_arg as! MalSequence
if is_symbol(qq_list.first()) {
let sym = qq_list.first() as MalSymbol
let sym = qq_list.first() as! MalSymbol
if sym == kSymbolUnquote {
return qq_list.count >= 2 ? qq_list[1] : MalNil()
}
@ -188,9 +188,9 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
// Return: (concat item quasiquote(rest...))
if is_pair(qq_list.first()) {
let qq_list_item0 = qq_list.first() as MalSequence
let qq_list_item0 = qq_list.first() as! MalSequence
if is_symbol(qq_list_item0.first()) {
let sym = qq_list_item0.first() as MalSymbol
let sym = qq_list_item0.first() as! MalSymbol
if sym == kSymbolSpliceUnquote {
let result = quasiquote(qq_list.rest())
if is_error(result) { return result }
@ -220,13 +220,13 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
func eval_ast(ast: MalVal, env: Environment) -> MalVal {
switch ast.type {
case .TypeSymbol:
let symbol = ast as MalSymbol
let symbol = ast as! MalSymbol
if let val = env.get(symbol) {
return val
}
return MalError(message: "'\(symbol)' not found") // Specific text needed to match MAL unit tests
case .TypeList:
let list = ast as MalList
let list = ast as! MalList
var result = [MalVal]()
result.reserveCapacity(list.count)
for item in list {
@ -236,7 +236,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalList(array: result)
case .TypeVector:
let vec = ast as MalVector
let vec = ast as! MalVector
var result = [MalVal]()
result.reserveCapacity(vec.count)
for item in vec {
@ -246,7 +246,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalVector(array: result)
case .TypeHashMap:
let hash = ast as MalHashMap
let hash = ast as! MalHashMap
var result = [MalVal]()
result.reserveCapacity(hash.count * 2)
for (k, v) in hash {
@ -278,18 +278,18 @@ func eval_def(list: MalSequence, env: Environment) -> TCOVal {
if list.count != 3 {
return TCOVal("expected 2 arguments to def!, got \(list.count - 1)")
}
let arg0 = list[0] as MalSymbol
let arg0 = list[0] as! MalSymbol
let arg1 = list[1]
let arg2 = list[2]
if !is_symbol(arg1) {
return TCOVal("expected symbol for first argument to def!")
}
let sym = arg1 as MalSymbol
let sym = arg1 as! MalSymbol
let value = EVAL(arg2, env)
if is_error(value) { return TCOVal(value) }
if arg0 == kSymbolDefMacro {
if is_closure(value) {
let as_closure = value as MalClosure
let as_closure = value as! MalClosure
as_closure.is_macro = true
} else {
return TCOVal("expected closure, got \(value)")
@ -309,7 +309,7 @@ func eval_let(list: MalSequence, env: Environment) -> TCOVal {
if !is_sequence(arg1) {
return TCOVal("expected list for first argument to let*")
}
let bindings = arg1 as MalSequence
let bindings = arg1 as! MalSequence
if bindings.count % 2 == 1 {
return TCOVal("expected even number of elements in bindings to let*, got \(bindings.count)")
}
@ -321,7 +321,7 @@ func eval_let(list: MalSequence, env: Environment) -> TCOVal {
if !is_symbol(binding_name) {
return TCOVal("expected symbol for first element in binding pair")
}
let binding_symbol = binding_name as MalSymbol
let binding_symbol = binding_name as! MalSymbol
let evaluated_value = EVAL(binding_value, new_env)
if is_error(evaluated_value) { return TCOVal(evaluated_value) }
new_env.set(binding_symbol, evaluated_value)
@ -343,7 +343,7 @@ func eval_do(list: MalSequence, env: Environment) -> TCOVal {
let evaluated_ast = eval_ast(list.rest(), env)
if is_error(evaluated_ast) { return TCOVal(evaluated_ast) }
let evaluated_seq = evaluated_ast as MalSequence
let evaluated_seq = evaluated_ast as! MalSequence
return TCOVal(evaluated_seq.last())
}
@ -377,7 +377,7 @@ func eval_fn(list: MalSequence, env: Environment) -> TCOVal {
if !is_sequence(list[1]) {
return TCOVal("expected list or vector for first argument to fn*")
}
return TCOVal(MalClosure(eval: EVAL, args:list[1] as MalSequence, body:list[2], env:env))
return TCOVal(MalClosure(eval: EVAL, args:list[1] as! MalSequence, body:list[2], env:env))
}
// EVALuate "quote".
@ -431,7 +431,7 @@ func eval_try(list: MalSequence, env: Environment) -> TCOVal {
println("try*: second parameter to 'try' is not a sequence")
return TCOVal(MalNil()) // Second parameter to 'try' is not a sequence
}
let catch_list = list[2] as MalSequence
let catch_list = list[2] as! MalSequence
if catch_list.count < 3 {
println("try*: not enough catch parameters")
return TCOVal(MalNil()) // Not enough catch parameters
@ -440,7 +440,7 @@ func eval_try(list: MalSequence, env: Environment) -> TCOVal {
println("try*: first parameter in catch list is not a symbol")
return TCOVal(MalNil()) // First parameter in catch list is not a symbol
}
let catch_symbol = catch_list[0] as MalSymbol
let catch_symbol = catch_list[0] as! MalSymbol
if catch_symbol != kSymbolCatch {
println("try*: first parameter in catch list is not 'catch'")
return TCOVal(MalNil()) // First parameter in catch list is not 'catch'
@ -449,10 +449,10 @@ func eval_try(list: MalSequence, env: Environment) -> TCOVal {
println("try*: first parameter to 'catch' is not a symbol")
return TCOVal(MalNil()) // First parameter to 'catch' is not a symbol
}
let catch_name = catch_list[1] as MalSymbol
let catch_name = catch_list[1] as! MalSymbol
let catch_expr = catch_list[2]
let catch_env = Environment(outer: env)
let error = res as MalError
let error = res as! MalError
catch_env.set_bindings(MalList(objects: catch_name), with_exprs: MalList(objects: error.value))
return TCOVal(EVAL(catch_expr, catch_env))
}
@ -485,10 +485,10 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// Special handling if it's a list.
var list = ast as MalList
var list = ast as! MalList
ast = macroexpand(ast, env)
if !is_list(ast) { return ast }
list = ast as MalList
list = ast as! MalList
if DEBUG_EVAL { println("\(indent)>. \(list)") }
@ -502,7 +502,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let arg0 = list.first()
if is_symbol(arg0) {
var res: TCOVal
let fn_symbol = arg0 as MalSymbol
let fn_symbol = arg0 as! MalSymbol
switch fn_symbol {
case kSymbolDef: res = eval_def(list, env)
@ -531,7 +531,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// The result had better be a list and better be non-empty.
let eval_list = eval as MalList
let eval_list = eval as! MalList
if eval_list.isEmpty {
return eval_list
}
@ -544,12 +544,12 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let rest = eval_list.rest()
if is_builtin(first) {
let fn = first as MalBuiltin
let fn = first as! MalBuiltin
let answer = fn.apply(rest)
if DEBUG_EVAL { println("\(indent)>>> \(answer)") }
return answer
} else if is_closure(first) {
let fn = first as MalClosure
let fn = first as! MalClosure
var new_env = Environment(outer: fn.env)
let result = new_env.set_bindings(fn.args, with_exprs:rest)
if is_error(result) { return result }

View File

@ -92,7 +92,7 @@ func READ(str: String) -> MalVal {
//
func is_pair(val:MalVal) -> Bool {
if !is_sequence(val) { return false }
let list = val as MalSequence
let list = val as! MalSequence
return !list.isEmpty
}
@ -101,15 +101,15 @@ func is_pair(val:MalVal) -> Bool {
func macroexpand(var ast:MalVal, env:Environment) -> MalVal {
while true {
if !is_list(ast) { break }
let ast_as_list = ast as MalList
let ast_as_list = ast as! MalList
if ast_as_list.isEmpty { break }
let first = ast_as_list.first()
if !is_symbol(first) { break }
let macro_name = first as MalSymbol
let macro_name = first as! MalSymbol
let obj = env.get(macro_name)
if obj == nil { break }
if !is_closure(obj!) { break }
let macro = obj! as MalClosure
let macro = obj! as! MalClosure
if !macro.is_macro { break }
var new_env = Environment(outer: macro.env)
let rest = ast_as_list.rest()
@ -174,9 +174,9 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
//
// Return: item
let qq_list = qq_arg as MalSequence
let qq_list = qq_arg as! MalSequence
if is_symbol(qq_list.first()) {
let sym = qq_list.first() as MalSymbol
let sym = qq_list.first() as! MalSymbol
if sym == kSymbolUnquote {
return qq_list.count >= 2 ? qq_list[1] : MalNil()
}
@ -188,9 +188,9 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
// Return: (concat item quasiquote(rest...))
if is_pair(qq_list.first()) {
let qq_list_item0 = qq_list.first() as MalSequence
let qq_list_item0 = qq_list.first() as! MalSequence
if is_symbol(qq_list_item0.first()) {
let sym = qq_list_item0.first() as MalSymbol
let sym = qq_list_item0.first() as! MalSymbol
if sym == kSymbolSpliceUnquote {
let result = quasiquote(qq_list.rest())
if is_error(result) { return result }
@ -220,13 +220,13 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
func eval_ast(ast: MalVal, env: Environment) -> MalVal {
switch ast.type {
case .TypeSymbol:
let symbol = ast as MalSymbol
let symbol = ast as! MalSymbol
if let val = env.get(symbol) {
return val
}
return MalError(message: "'\(symbol)' not found") // Specific text needed to match MAL unit tests
case .TypeList:
let list = ast as MalList
let list = ast as! MalList
var result = [MalVal]()
result.reserveCapacity(list.count)
for item in list {
@ -236,7 +236,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalList(array: result)
case .TypeVector:
let vec = ast as MalVector
let vec = ast as! MalVector
var result = [MalVal]()
result.reserveCapacity(vec.count)
for item in vec {
@ -246,7 +246,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
}
return MalVector(array: result)
case .TypeHashMap:
let hash = ast as MalHashMap
let hash = ast as! MalHashMap
var result = [MalVal]()
result.reserveCapacity(hash.count * 2)
for (k, v) in hash {
@ -278,18 +278,18 @@ func eval_def(list: MalSequence, env: Environment) -> TCOVal {
if list.count != 3 {
return TCOVal("expected 2 arguments to def!, got \(list.count - 1)")
}
let arg0 = list[0] as MalSymbol
let arg0 = list[0] as! MalSymbol
let arg1 = list[1]
let arg2 = list[2]
if !is_symbol(arg1) {
return TCOVal("expected symbol for first argument to def!")
}
let sym = arg1 as MalSymbol
let sym = arg1 as! MalSymbol
let value = EVAL(arg2, env)
if is_error(value) { return TCOVal(value) }
if arg0 == kSymbolDefMacro {
if is_closure(value) {
let as_closure = value as MalClosure
let as_closure = value as! MalClosure
as_closure.is_macro = true
} else {
return TCOVal("expected closure, got \(value)")
@ -309,7 +309,7 @@ func eval_let(list: MalSequence, env: Environment) -> TCOVal {
if !is_sequence(arg1) {
return TCOVal("expected list for first argument to let*")
}
let bindings = arg1 as MalSequence
let bindings = arg1 as! MalSequence
if bindings.count % 2 == 1 {
return TCOVal("expected even number of elements in bindings to let*, got \(bindings.count)")
}
@ -321,7 +321,7 @@ func eval_let(list: MalSequence, env: Environment) -> TCOVal {
if !is_symbol(binding_name) {
return TCOVal("expected symbol for first element in binding pair")
}
let binding_symbol = binding_name as MalSymbol
let binding_symbol = binding_name as! MalSymbol
let evaluated_value = EVAL(binding_value, new_env)
if is_error(evaluated_value) { return TCOVal(evaluated_value) }
new_env.set(binding_symbol, evaluated_value)
@ -343,7 +343,7 @@ func eval_do(list: MalSequence, env: Environment) -> TCOVal {
let evaluated_ast = eval_ast(list.rest(), env)
if is_error(evaluated_ast) { return TCOVal(evaluated_ast) }
let evaluated_seq = evaluated_ast as MalSequence
let evaluated_seq = evaluated_ast as! MalSequence
return TCOVal(evaluated_seq.last())
}
@ -377,7 +377,7 @@ func eval_fn(list: MalSequence, env: Environment) -> TCOVal {
if !is_sequence(list[1]) {
return TCOVal("expected list or vector for first argument to fn*")
}
return TCOVal(MalClosure(eval: EVAL, args:list[1] as MalSequence, body:list[2], env:env))
return TCOVal(MalClosure(eval: EVAL, args:list[1] as! MalSequence, body:list[2], env:env))
}
// EVALuate "quote".
@ -431,7 +431,7 @@ func eval_try(list: MalSequence, env: Environment) -> TCOVal {
println("try*: second parameter to 'try' is not a sequence")
return TCOVal(MalNil()) // Second parameter to 'try' is not a sequence
}
let catch_list = list[2] as MalSequence
let catch_list = list[2] as! MalSequence
if catch_list.count < 3 {
println("try*: not enough catch parameters")
return TCOVal(MalNil()) // Not enough catch parameters
@ -440,7 +440,7 @@ func eval_try(list: MalSequence, env: Environment) -> TCOVal {
println("try*: first parameter in catch list is not a symbol")
return TCOVal(MalNil()) // First parameter in catch list is not a symbol
}
let catch_symbol = catch_list[0] as MalSymbol
let catch_symbol = catch_list[0] as! MalSymbol
if catch_symbol != kSymbolCatch {
println("try*: first parameter in catch list is not 'catch'")
return TCOVal(MalNil()) // First parameter in catch list is not 'catch'
@ -449,10 +449,10 @@ func eval_try(list: MalSequence, env: Environment) -> TCOVal {
println("try*: first parameter to 'catch' is not a symbol")
return TCOVal(MalNil()) // First parameter to 'catch' is not a symbol
}
let catch_name = catch_list[1] as MalSymbol
let catch_name = catch_list[1] as! MalSymbol
let catch_expr = catch_list[2]
let catch_env = Environment(outer: env)
let error = res as MalError
let error = res as! MalError
catch_env.set_bindings(MalList(objects: catch_name), with_exprs: MalList(objects: error.value))
return TCOVal(EVAL(catch_expr, catch_env))
}
@ -485,10 +485,10 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// Special handling if it's a list.
var list = ast as MalList
var list = ast as! MalList
ast = macroexpand(ast, env)
if !is_list(ast) { return ast }
list = ast as MalList
list = ast as! MalList
if DEBUG_EVAL { println("\(indent)>. \(list)") }
@ -502,7 +502,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let arg0 = list.first()
if is_symbol(arg0) {
var res: TCOVal
let fn_symbol = arg0 as MalSymbol
let fn_symbol = arg0 as! MalSymbol
switch fn_symbol {
case kSymbolDef: res = eval_def(list, env)
@ -531,7 +531,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// The result had better be a list and better be non-empty.
let eval_list = eval as MalList
let eval_list = eval as! MalList
if eval_list.isEmpty {
return eval_list
}
@ -544,12 +544,12 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let rest = eval_list.rest()
if is_builtin(first) {
let fn = first as MalBuiltin
let fn = first as! MalBuiltin
let answer = fn.apply(rest)
if DEBUG_EVAL { println("\(indent)>>> \(answer)") }
return answer
} else if is_closure(first) {
let fn = first as MalClosure
let fn = first as! MalClosure
var new_env = Environment(outer: fn.env)
let result = new_env.set_bindings(fn.args, with_exprs:rest)
if is_error(result) { return result }

View File

@ -161,7 +161,7 @@ func READ(str: String) -> MalVal {
// // malstep(7,8,9,A)
func is_pair(val:MalVal) -> Bool { // malstep(7,8,9,A)
if !is_sequence(val) { return false } // malstep(7,8,9,A)
let list = val as MalSequence // malstep(7,8,9,A)
let list = val as! MalSequence // malstep(7,8,9,A)
return !list.isEmpty // malstep(7,8,9,A)
} // malstep(7,8,9,A)
// malstep(7,8,9,A)
@ -170,15 +170,15 @@ func is_pair(val:MalVal) -> Bool {
func macroexpand(var ast:MalVal, env:Environment) -> MalVal { // malstep(8,9,A)
while true { // malstep(8,9,A)
if !is_list(ast) { break } // malstep(8,9,A)
let ast_as_list = ast as MalList // malstep(8,9,A)
let ast_as_list = ast as! MalList // malstep(8,9,A)
if ast_as_list.isEmpty { break } // malstep(8,9,A)
let first = ast_as_list.first() // malstep(8,9,A)
if !is_symbol(first) { break } // malstep(8,9,A)
let macro_name = first as MalSymbol // malstep(8,9,A)
let macro_name = first as! MalSymbol // malstep(8,9,A)
let obj = env.get(macro_name) // malstep(8,9,A)
if obj == nil { break } // malstep(8,9,A)
if !is_closure(obj!) { break } // malstep(8,9,A)
let macro = obj! as MalClosure // malstep(8,9,A)
let macro = obj! as! MalClosure // malstep(8,9,A)
if !macro.is_macro { break } // malstep(8,9,A)
var new_env = Environment(outer: macro.env) // malstep(8,9,A)
let rest = ast_as_list.rest() // malstep(8,9,A)
@ -243,9 +243,9 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
// // malstep(7,8,9,A)
// Return: item // malstep(7,8,9,A)
// malstep(7,8,9,A)
let qq_list = qq_arg as MalSequence // malstep(7,8,9,A)
let qq_list = qq_arg as! MalSequence // malstep(7,8,9,A)
if is_symbol(qq_list.first()) { // malstep(7,8,9,A)
let sym = qq_list.first() as MalSymbol // malstep(7,8,9,A)
let sym = qq_list.first() as! MalSymbol // malstep(7,8,9,A)
if sym == kSymbolUnquote { // malstep(7,8,9,A)
return qq_list.count >= 2 ? qq_list[1] : MalNil() // malstep(7,8,9,A)
} // malstep(7,8,9,A)
@ -257,9 +257,9 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
// Return: (concat item quasiquote(rest...)) // malstep(7,8,9,A)
// malstep(7,8,9,A)
if is_pair(qq_list.first()) { // malstep(7,8,9,A)
let qq_list_item0 = qq_list.first() as MalSequence // malstep(7,8,9,A)
let qq_list_item0 = qq_list.first() as! MalSequence // malstep(7,8,9,A)
if is_symbol(qq_list_item0.first()) { // malstep(7,8,9,A)
let sym = qq_list_item0.first() as MalSymbol // malstep(7,8,9,A)
let sym = qq_list_item0.first() as! MalSymbol // malstep(7,8,9,A)
if sym == kSymbolSpliceUnquote { // malstep(7,8,9,A)
let result = quasiquote(qq_list.rest()) // malstep(7,8,9,A)
if is_error(result) { return result } // malstep(7,8,9,A)
@ -289,13 +289,13 @@ func quasiquote(qq_arg:MalVal) -> MalVal {
func eval_ast(ast: MalVal, env: Environment) -> MalVal { // malstep(2,3,4,5,6,7,8,9,A)
switch ast.type { // malstep(2,3,4,5,6,7,8,9,A)
case .TypeSymbol: // malstep(2,3,4,5,6,7,8,9,A)
let symbol = ast as MalSymbol // malstep(2,3,4,5,6,7,8,9,A)
let symbol = ast as! MalSymbol // malstep(2,3,4,5,6,7,8,9,A)
if let val = env.get(symbol) { // malstep(2,3,4,5,6,7,8,9,A)
return val // malstep(2,3,4,5,6,7,8,9,A)
} // malstep(2,3,4,5,6,7,8,9,A)
return MalError(message: "'\(symbol)' not found") // Specific text needed to match MAL unit tests // malstep(2,3,4,5,6,7,8,9,A)
case .TypeList: // malstep(2,3,4,5,6,7,8,9,A)
let list = ast as MalList // malstep(2,3,4,5,6,7,8,9,A)
let list = ast as! MalList // malstep(2,3,4,5,6,7,8,9,A)
var result = [MalVal]() // malstep(2,3,4,5,6,7,8,9,A)
result.reserveCapacity(list.count) // malstep(2,3,4,5,6,7,8,9,A)
for item in list { // malstep(2,3,4,5,6,7,8,9,A)
@ -305,7 +305,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
} // malstep(2,3,4,5,6,7,8,9,A)
return MalList(array: result) // malstep(2,3,4,5,6,7,8,9,A)
case .TypeVector: // malstep(2,3,4,5,6,7,8,9,A)
let vec = ast as MalVector // malstep(2,3,4,5,6,7,8,9,A)
let vec = ast as! MalVector // malstep(2,3,4,5,6,7,8,9,A)
var result = [MalVal]() // malstep(2,3,4,5,6,7,8,9,A)
result.reserveCapacity(vec.count) // malstep(2,3,4,5,6,7,8,9,A)
for item in vec { // malstep(2,3,4,5,6,7,8,9,A)
@ -315,7 +315,7 @@ func eval_ast(ast: MalVal, env: Environment) -> MalVal {
} // malstep(2,3,4,5,6,7,8,9,A)
return MalVector(array: result) // malstep(2,3,4,5,6,7,8,9,A)
case .TypeHashMap: // malstep(2,3,4,5,6,7,8,9,A)
let hash = ast as MalHashMap // malstep(2,3,4,5,6,7,8,9,A)
let hash = ast as! MalHashMap // malstep(2,3,4,5,6,7,8,9,A)
var result = [MalVal]() // malstep(2,3,4,5,6,7,8,9,A)
result.reserveCapacity(hash.count * 2) // malstep(2,3,4,5,6,7,8,9,A)
for (k, v) in hash { // malstep(2,3,4,5,6,7,8,9,A)
@ -350,20 +350,20 @@ func eval_def(list: MalSequence, env: Environment) -> TCOVal {
return MalError(message: "expected 2 arguments to def!, got \(list.count - 1)") // malstep(3,4)
return TCOVal("expected 2 arguments to def!, got \(list.count - 1)") // malstep(5,6,7,8,9,A)
} // malstep(3,4,5,6,7,8,9,A)
let arg0 = list[0] as MalSymbol // malstep(8,9,A)
let arg0 = list[0] as! MalSymbol // malstep(8,9,A)
let arg1 = list[1] // malstep(3,4,5,6,7,8,9,A)
let arg2 = list[2] // malstep(3,4,5,6,7,8,9,A)
if !is_symbol(arg1) { // malstep(3,4,5,6,7,8,9,A)
return MalError(message: "expected symbol for first argument to def!") // malstep(3,4)
return TCOVal("expected symbol for first argument to def!") // malstep(5,6,7,8,9,A)
} // malstep(3,4,5,6,7,8,9,A)
let sym = arg1 as MalSymbol // malstep(3,4,5,6,7,8,9,A)
let sym = arg1 as! MalSymbol // malstep(3,4,5,6,7,8,9,A)
let value = EVAL(arg2, env) // malstep(3,4,5,6,7,8,9,A)
if is_error(value) { return value } // malstep(3,4)
if is_error(value) { return TCOVal(value) } // malstep(5,6,7,8,9,A)
if arg0 == kSymbolDefMacro { // malstep(8,9,A)
if is_closure(value) { // malstep(8,9,A)
let as_closure = value as MalClosure // malstep(8,9,A)
let as_closure = value as! MalClosure // malstep(8,9,A)
as_closure.is_macro = true // malstep(8,9,A)
} else { // malstep(8,9,A)
return TCOVal("expected closure, got \(value)") // malstep(8,9,A)
@ -387,7 +387,7 @@ func eval_let(list: MalSequence, env: Environment) -> TCOVal {
return MalError(message: "expected list for first argument to let*") // malstep(3,4)
return TCOVal("expected list for first argument to let*") // malstep(5,6,7,8,9,A)
} // malstep(3,4,5,6,7,8,9,A)
let bindings = arg1 as MalSequence // malstep(3,4,5,6,7,8,9,A)
let bindings = arg1 as! MalSequence // malstep(3,4,5,6,7,8,9,A)
if bindings.count % 2 == 1 { // malstep(3,4,5,6,7,8,9,A)
return MalError(message: "expected even number of elements in bindings to let*, got \(bindings.count)") // malstep(3,4)
return TCOVal("expected even number of elements in bindings to let*, got \(bindings.count)") // malstep(5,6,7,8,9,A)
@ -401,7 +401,7 @@ func eval_let(list: MalSequence, env: Environment) -> TCOVal {
return MalError(message: "expected symbol for first element in binding pair") // malstep(3,4)
return TCOVal("expected symbol for first element in binding pair") // malstep(5,6,7,8,9,A)
} // malstep(3,4,5,6,7,8,9,A)
let binding_symbol = binding_name as MalSymbol // malstep(3,4,5,6,7,8,9,A)
let binding_symbol = binding_name as! MalSymbol // malstep(3,4,5,6,7,8,9,A)
let evaluated_value = EVAL(binding_value, new_env) // malstep(3,4,5,6,7,8,9,A)
if is_error(evaluated_value) { return evaluated_value } // malstep(3,4)
if is_error(evaluated_value) { return TCOVal(evaluated_value) } // malstep(5,6,7,8,9,A)
@ -427,7 +427,7 @@ func eval_do(list: MalSequence, env: Environment) -> TCOVal {
let evaluated_ast = eval_ast(list.rest(), env) // malstep(4,5,6,7,8,9,A)
if is_error(evaluated_ast) { return evaluated_ast } // malstep(4)
if is_error(evaluated_ast) { return TCOVal(evaluated_ast) } // malstep(5,6,7,8,9,A)
let evaluated_seq = evaluated_ast as MalSequence // malstep(4,5,6,7,8,9,A)
let evaluated_seq = evaluated_ast as! MalSequence // malstep(4,5,6,7,8,9,A)
return evaluated_seq.last() // malstep(4)
return TCOVal(evaluated_seq.last()) // malstep(5,6,7,8,9,A)
} // malstep(4,5,6,7,8,9,A)
@ -469,8 +469,8 @@ func eval_fn(list: MalSequence, env: Environment) -> TCOVal {
return MalError(message: "expected list or vector for first argument to fn*") // malstep(4)
return TCOVal("expected list or vector for first argument to fn*") // malstep(5,6,7,8,9,A)
} // malstep(4,5,6,7,8,9,A)
return MalClosure(eval: EVAL, args:list[1] as MalSequence, body:list[2], env:env) // malstep(4)
return TCOVal(MalClosure(eval: EVAL, args:list[1] as MalSequence, body:list[2], env:env)) // malstep(5,6,7,8,9,A)
return MalClosure(eval: EVAL, args:list[1] as! MalSequence, body:list[2], env:env) // malstep(4)
return TCOVal(MalClosure(eval: EVAL, args:list[1] as! MalSequence, body:list[2], env:env)) // malstep(5,6,7,8,9,A)
} // malstep(4,5,6,7,8,9,A)
// malstep(4,5,6,7,8,9,A)
// EVALuate "quote". // malstep(7,8,9,A)
@ -524,7 +524,7 @@ func eval_try(list: MalSequence, env: Environment) -> TCOVal {
println("try*: second parameter to 'try' is not a sequence") // malstep(9,A)
return TCOVal(MalNil()) // Second parameter to 'try' is not a sequence // malstep(9,A)
} // malstep(9,A)
let catch_list = list[2] as MalSequence // malstep(9,A)
let catch_list = list[2] as! MalSequence // malstep(9,A)
if catch_list.count < 3 { // malstep(9,A)
println("try*: not enough catch parameters") // malstep(9,A)
return TCOVal(MalNil()) // Not enough catch parameters // malstep(9,A)
@ -533,7 +533,7 @@ func eval_try(list: MalSequence, env: Environment) -> TCOVal {
println("try*: first parameter in catch list is not a symbol") // malstep(9,A)
return TCOVal(MalNil()) // First parameter in catch list is not a symbol // malstep(9,A)
} // malstep(9,A)
let catch_symbol = catch_list[0] as MalSymbol // malstep(9,A)
let catch_symbol = catch_list[0] as! MalSymbol // malstep(9,A)
if catch_symbol != kSymbolCatch { // malstep(9,A)
println("try*: first parameter in catch list is not 'catch'") // malstep(9,A)
return TCOVal(MalNil()) // First parameter in catch list is not 'catch' // malstep(9,A)
@ -542,10 +542,10 @@ func eval_try(list: MalSequence, env: Environment) -> TCOVal {
println("try*: first parameter to 'catch' is not a symbol") // malstep(9,A)
return TCOVal(MalNil()) // First parameter to 'catch' is not a symbol // malstep(9,A)
} // malstep(9,A)
let catch_name = catch_list[1] as MalSymbol // malstep(9,A)
let catch_name = catch_list[1] as! MalSymbol // malstep(9,A)
let catch_expr = catch_list[2] // malstep(9,A)
let catch_env = Environment(outer: env) // malstep(9,A)
let error = res as MalError // malstep(9,A)
let error = res as! MalError // malstep(9,A)
catch_env.set_bindings(MalList(objects: catch_name), with_exprs: MalList(objects: error.value)) // malstep(9,A)
return TCOVal(EVAL(catch_expr, catch_env)) // malstep(9,A)
} // malstep(9,A)
@ -592,10 +592,10 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// malstep(2,3,4,5,6,7,8,9,A)
// Special handling if it's a list. // malstep(2,3,4,5,6,7,8,9,A)
// malstep(2,3,4,5,6,7,8,9,A)
var list = ast as MalList // malstep(2,3,4,5,6,7,8,9,A)
var list = ast as! MalList // malstep(2,3,4,5,6,7,8,9,A)
ast = macroexpand(ast, env) // malstep(8,9,A)
if !is_list(ast) { return ast } // malstep(8,9,A)
list = ast as MalList // malstep(8,9,A)
list = ast as! MalList // malstep(8,9,A)
// malstep(8,9,A)
if DEBUG_EVAL { println("\(indent)>. \(list)") } // malstep(5,6,7,8,9,A)
// malstep(2,3,4,5,6,7,8,9,A)
@ -609,7 +609,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let arg0 = list.first() // malstep(3,4,5,6,7,8,9,A)
if is_symbol(arg0) { // malstep(3,4,5,6,7,8,9,A)
var res: TCOVal // malstep(5,6,7,8,9,A)
let fn_symbol = arg0 as MalSymbol // malstep(3,4,5,6,7,8,9,A)
let fn_symbol = arg0 as! MalSymbol // malstep(3,4,5,6,7,8,9,A)
// malstep(3,4,5,6,7,8,9,A)
switch fn_symbol { // malstep(3,4,5,6,7,8,9,A)
case kSymbolDef: return eval_def(list, env) // malstep(3,4)
@ -644,7 +644,7 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
// malstep(2,3,4,5,6,7,8,9,A)
// The result had better be a list and better be non-empty. // malstep(2,3,4,5,6,7,8,9,A)
// malstep(2,3,4,5,6,7,8,9,A)
let eval_list = eval as MalList // malstep(2,3,4,5,6,7,8,9,A)
let eval_list = eval as! MalList // malstep(2,3,4,5,6,7,8,9,A)
if eval_list.isEmpty { // malstep(2,3,4,5,6,7,8,9,A)
return eval_list // malstep(2,3,4,5,6,7,8,9,A)
} // malstep(2,3,4,5,6,7,8,9,A)
@ -657,12 +657,12 @@ func EVAL(var ast: MalVal, var env: Environment) -> MalVal {
let rest = eval_list.rest() // malstep(2,3,4,5,6,7,8,9,A)
// malstep(2,3,4,5,6,7,8,9,A)
if is_builtin(first) { // malstep(2,3,4,5,6,7,8,9,A)
let fn = first as MalBuiltin // malstep(2,3,4,5,6,7,8,9,A)
let fn = first as! MalBuiltin // malstep(2,3,4,5,6,7,8,9,A)
let answer = fn.apply(rest) // malstep(2,3,4,5,6,7,8,9,A)
if DEBUG_EVAL { println("\(indent)>>> \(answer)") } // malstep(5,6,7,8,9,A)
return answer // malstep(2,3,4,5,6,7,8,9,A)
} else if is_closure(first) { // malstep(4,5,6,7,8,9,A)
let fn = first as MalClosure // malstep(4,5,6,7,8,9,A)
let fn = first as! MalClosure // malstep(4,5,6,7,8,9,A)
var new_env = Environment(outer: fn.env) // malstep(4,5,6,7,8,9,A)
let result = new_env.set_bindings(fn.args, with_exprs:rest) // malstep(4,5,6,7,8,9,A)
if is_error(result) { return result } // malstep(4,5,6,7,8,9,A)

View File

@ -88,8 +88,8 @@ func == (left: MalVal, right: MalVal) -> Bool {
// Special case lists/vectors, since they are different types that are
// nonetheless comparable.
if is_sequence(left) && is_sequence(right) {
let left_seq = left as MalSequence
let right_seq = right as MalSequence
let left_seq = left as! MalSequence
let right_seq = right as! MalSequence
return left_seq == right_seq
}
@ -99,22 +99,22 @@ func == (left: MalVal, right: MalVal) -> Bool {
switch left.type {
case .TypeUnknown: return false
case .TypeNil: return (left as MalNil) == (right as MalNil)
case .TypeTrue: return (left as MalTrue) == (right as MalTrue)
case .TypeFalse: return (left as MalFalse) == (right as MalFalse)
case .TypeInteger: return (left as MalInteger) == (right as MalInteger)
case .TypeFloat: return (left as MalFloat) == (right as MalFloat)
case .TypeSymbol: return (left as MalSymbol) == (right as MalSymbol)
case .TypeKeyword: return (left as MalKeyword) == (right as MalKeyword)
case .TypeString: return (left as MalString) == (right as MalString)
case .TypeList: return (left as MalList) == (right as MalList)
case .TypeVector: return (left as MalVector) == (right as MalVector)
case .TypeHashMap: return (left as MalHashMap) == (right as MalHashMap)
case .TypeAtom: return (left as MalAtom) == (right as MalAtom)
case .TypeClosure: return (left as MalClosure) == (right as MalClosure)
case .TypeBuiltin: return (left as MalBuiltin) == (right as MalBuiltin)
case .TypeComment: return (left as MalComment) == (right as MalComment)
case .TypeError: return (left as MalError) == (right as MalError)
case .TypeNil: return (left as! MalNil) == (right as! MalNil)
case .TypeTrue: return (left as! MalTrue) == (right as! MalTrue)
case .TypeFalse: return (left as! MalFalse) == (right as! MalFalse)
case .TypeInteger: return (left as! MalInteger) == (right as! MalInteger)
case .TypeFloat: return (left as! MalFloat) == (right as! MalFloat)
case .TypeSymbol: return (left as! MalSymbol) == (right as! MalSymbol)
case .TypeKeyword: return (left as! MalKeyword) == (right as! MalKeyword)
case .TypeString: return (left as! MalString) == (right as! MalString)
case .TypeList: return (left as! MalList) == (right as! MalList)
case .TypeVector: return (left as! MalVector) == (right as! MalVector)
case .TypeHashMap: return (left as! MalHashMap) == (right as! MalHashMap)
case .TypeAtom: return (left as! MalAtom) == (right as! MalAtom)
case .TypeClosure: return (left as! MalClosure) == (right as! MalClosure)
case .TypeBuiltin: return (left as! MalBuiltin) == (right as! MalBuiltin)
case .TypeComment: return (left as! MalComment) == (right as! MalComment)
case .TypeError: return (left as! MalError) == (right as! MalError)
}
}
@ -178,28 +178,28 @@ func == (left: MalFloat, right: MalFloat) -> Bool { return left.value == right.v
var symbolHash = [String:Int]()
var symbolArray = [String]()
private func indexForSymbol(s: String) -> Int {
if let i = symbolHash[s] {
return i
}
symbolArray.append(s)
symbolHash[s] = symbolArray.count - 1
return symbolArray.count - 1
}
private func symbolForIndex(i: Int) -> String {
return symbolArray[i]
}
class MalSymbol: MalVal, Hashable {
init(symbol: String, meta: MalVal? = nil) { self.index = -1; super.init(meta: meta); self.index = indexForSymbol(symbol) }
init(symbol: String, meta: MalVal? = nil) { self.index = indexForSymbol(symbol); super.init(meta: meta) }
init(other: MalSymbol) { self.index = other.index; super.init(other: other) }
override func clone() -> MalVal { return MalSymbol(other:self) }
override var type: MalType { return .TypeSymbol }
override var description: String { return self.symbolForIndex(self.index) }
override var description: String { return symbolForIndex(self.index) }
override var hashValue: Int { return self.index }
let index: Int
private func indexForSymbol(s: String) -> Int {
if let i = symbolHash[s] {
return i
}
symbolArray.append(s)
symbolHash[s] = symbolArray.count - 1
return symbolArray.count - 1
}
private func symbolForIndex(i: Int) -> String {
return symbolArray[i]
}
}
func == (left: MalSymbol, right: MalSymbol) -> Bool { return left.index == right.index }
@ -232,7 +232,7 @@ class MalString: MalVal {
var prev_is_escape = false
var str = ""
for ch in s {
if index == s.utf16Count - 1 { continue }
if index == count(s.utf16) - 1 { continue }
if index++ == 0 { continue }
if prev_is_escape {
prev_is_escape = false;
@ -267,25 +267,25 @@ func == (left: MalString, right: MalString) -> Bool { return left.value == right
// ===== MalSequence =====
class MalSequence: MalVal, SequenceType {
init(slice: Slice<MalVal>, meta: MalVal? = nil) { self.slice = slice; super.init(meta: meta) }
init(slice: ArraySlice<MalVal>, meta: MalVal? = nil) { self.slice = slice; super.init(meta: meta) }
init(other: MalSequence) { self.slice = other.slice; super.init(other: other) }
override var type: MalType { return .TypeUnknown }
override var description: String { return "" }
func first() -> MalVal { return !isEmpty ? slice[0] : MalNil() }
func last() -> MalVal { return !isEmpty ? slice[slice.count - 1] : MalNil() }
func rest() -> MalSequence { return MalSequence(slice: Slice<MalVal>()) }
func map<U>(transform: (MalVal) -> U) -> Slice<U> { return slice.map(transform) }
func reduce<U>(initial: U, combine: (U, MalVal) -> U) -> U { return slice.reduce(initial, combine) }
func rest() -> MalSequence { return MalSequence(slice: ArraySlice<MalVal>()) }
func map<U>(transform: (MalVal) -> U) -> ArraySlice<U> { return slice.map(transform) }
func reduce<U>(initial: U, combine: (U, MalVal) -> U) -> U { return slice.reduce(initial, combine: combine) }
var count: Int { return slice.count }
var isEmpty: Bool { return slice.isEmpty }
subscript(index: Int) -> MalVal { return index < slice.count ? slice[index] : MalError(message: "index (\(index)) out of range (\(slice.count))") }
subscript(subRange: Range<Int>) -> Slice<MalVal> { return slice[subRange] }
subscript(subRange: Range<Int>) -> ArraySlice<MalVal> { return slice[subRange] }
// SequenceType
func generate() -> Slice<MalVal>.Generator { return slice.generate() }
func generate() -> ArraySlice<MalVal>.Generator { return slice.generate() }
let slice: Slice<MalVal>
let slice: ArraySlice<MalVal>
}
func == (left: MalSequence, right: MalSequence) -> Bool {
if left.count != right.count { return false }
@ -296,7 +296,7 @@ func == (left: MalSequence, right: MalSequence) -> Bool {
// ===== MalList =====
class MalList: MalSequence {
override init(slice: Slice<MalVal>, meta: MalVal? = nil) { super.init(slice: slice, meta: meta) }
override init(slice: ArraySlice<MalVal>, meta: MalVal? = nil) { super.init(slice: slice, meta: meta) }
convenience init(array: [MalVal], meta: MalVal? = nil) { self.init(slice: array[0..<array.count], meta: meta) }
convenience init(objects: MalVal...) { self.init(array: objects) }
init(other: MalList) { super.init(other: other) }
@ -312,7 +312,7 @@ func == (left: MalList, right: MalList) -> Bool {
// ===== MalVector =====
class MalVector: MalSequence {
override init(slice: Slice<MalVal>, meta: MalVal? = nil) { super.init(slice: slice, meta: meta) }
override init(slice: ArraySlice<MalVal>, meta: MalVal? = nil) { super.init(slice: slice, meta: meta) }
convenience init(array: [MalVal], meta: MalVal? = nil) { self.init(slice: array[0..<array.count], meta: meta) }
convenience init(objects: MalVal...) { self.init(array: objects) }
init(other: MalVector) { super.init(other: other) }
@ -330,7 +330,7 @@ func == (left: MalVector, right: MalVector) -> Bool {
class MalHashMap: MalVal, SequenceType {
convenience override init(meta: MalVal? = nil) { self.init(hash: [MalVal:MalVal](), meta:meta) }
init(hash: [MalVal:MalVal], meta: MalVal? = nil) { self.hash = hash; super.init(meta: meta) }
convenience init(slice: Slice<MalVal>, meta: MalVal? = nil) { var hash = [MalVal:MalVal](); for var index = 0; index < slice.count; index += 2 { hash[slice[index]] = slice[index + 1] }; self.init(hash: hash, meta: meta) }
convenience init(slice: ArraySlice<MalVal>, meta: MalVal? = nil) { var hash = [MalVal:MalVal](); for var index = 0; index < slice.count; index += 2 { hash[slice[index]] = slice[index + 1] }; self.init(hash: hash, meta: meta) }
convenience init(array: Array<MalVal>, meta: MalVal? = nil) { var hash = [MalVal:MalVal](); for var index = 0; index < array.count; index += 2 { hash[array[index]] = array[index + 1] }; self.init(hash: hash, meta: meta) }
init(other: MalHashMap) { self.hash = other.hash; super.init(other: other) }
override func clone() -> MalVal { return MalHashMap(other:self) }