*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
import Foundation
-typealias MalVarArgs = Slice<MalVal>
+typealias MalVarArgs = ArraySlice<MalVal>
func fn_eq(obj1: MalVal, obj2: MalVal) -> Bool {
return obj1 == obj2
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")
}
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()
}
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)")
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)
}
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)")
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
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
}
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 {
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 {
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)
}
}
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)
}
}
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)
}
}
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()
}
}
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))
}
}
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()
}
}
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()
}
}
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))
}
}
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)
}
}
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))
}
}
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))
}
}
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))
}
}
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])
}
}
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])
}
}
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])
}
}
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])
// 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
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)
}
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
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 {
}
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 {
}
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 {
// Special handling if it's a list.
- var list = ast as MalList
+ var list = ast as! MalList
if list.isEmpty {
return list
// 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
}
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
}
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 {
}
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 {
}
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 {
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)
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)")
}
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)
// Special handling if it's a list.
- var list = ast as MalList
+ var list = ast as! MalList
if list.isEmpty {
return list
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)
// 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
}
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
}
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 {
}
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 {
}
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 {
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)
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)")
}
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)
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()
}
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
// Special handling if it's a list.
- var list = ast as MalList
+ var list = ast as! MalList
if list.isEmpty {
return list
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)
// 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
}
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 }
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 {
}
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 {
}
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 {
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))
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)")
}
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)
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())
}
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
// 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 {
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)
// 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
}
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 }
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 {
}
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 {
}
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 {
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))
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)")
}
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)
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())
}
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
// 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 {
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)
// 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
}
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 }
//
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
}
//
// 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()
}
// 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 }
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 {
}
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 {
}
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 {
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))
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)")
}
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)
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())
}
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".
// 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 {
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)
// 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
}
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 }
//
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
}
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()
//
// 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()
}
// 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 }
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 {
}
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 {
}
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 {
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)")
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)")
}
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)
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())
}
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".
// 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)") }
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)
// 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
}
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 }
//
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
}
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()
//
// 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()
}
// 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 }
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 {
}
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 {
}
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 {
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)")
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)")
}
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)
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())
}
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".
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
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'
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))
}
// 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)") }
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)
// 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
}
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 }
//
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
}
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()
//
// 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()
}
// 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 }
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 {
}
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 {
}
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 {
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)")
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)")
}
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)
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())
}
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".
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
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'
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))
}
// 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)") }
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)
// 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
}
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 }
// // 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)
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)
// // 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)
// 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)
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)
} // 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)
} // 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)
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)
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)
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)
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)
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)
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)
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)
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)
// 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)
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)
// 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)
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)
// 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
}
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)
}
}
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 }
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;
// ===== 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 }
// ===== 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) }
// ===== 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) }
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) }