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:
parent
3829ee8cb4
commit
1c76df7dc6
@ -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
|
||||
|
@ -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])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 }
|
||||
|
@ -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 }
|
||||
|
@ -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 }
|
||||
|
@ -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 }
|
||||
|
@ -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 }
|
||||
|
@ -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 }
|
||||
|
@ -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 }
|
||||
|
@ -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)
|
||||
|
@ -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) }
|
||||
|
Loading…
Reference in New Issue
Block a user