Skip to content

Instantly share code, notes, and snippets.

@antmd
Created August 15, 2014 09:50
Show Gist options
  • Save antmd/ff4f72f91cd7bd4f9b5d to your computer and use it in GitHub Desktop.
Save antmd/ff4f72f91cd7bd4f9b5d to your computer and use it in GitHub Desktop.
import Foundation
//
// Box.swift
// swiftz_core
//
// Created by Andrew Cobb on 6/9/14.
// Copyright (c) 2014 Maxwell Swadling. All rights reserved.
//
// https://github.com/maxpow4h/swiftz/blob/master/swiftz_core/swiftz_core/Box.swift
// An immutable box, necessary for recursive datatypes (such as List) to avoid compiler crashes
public final class Box<T> {
private let _value : () -> T
public init(_ value : T) {
self._value = { value }
}
public var value: T {
return _value()
}
public func map<U>(f: T -> U) -> Box<U> {
return Box<U>(f(value)) // TODO: file rdar, type inf fails without <U>
}
}
enum Term {
case TmTrue
case TmFalse
case TmIf(Box<Term>, Box<Term>, Box<Term>)
case TmZero
case TmSucc(Box<Term>)
case TmPred(Box<Term>)
case TmIsZero(Box<Term>)
// We use Rob Rix’s Destructurable idea to be able to pattern match with boxed recursive enums.
// See the destructure() method below — converting this to an extension seems a good idea.
// https://github.com/robrix/Hammer.swift/blob/master/Hammer/Destructurable.swift
enum DestructuredTerm {
case TmTrue
case TmFalse
case TmIf(Term, Term, Term)
case TmZero
case TmSucc(Term)
case TmPred(Term)
case TmIsZero(Term)
}
func isnumericval () -> Bool {
switch (self) {
case TmZero: return true
case let TmSucc(t1): return t1.value.isnumericval()
default: return false
}
}
func isval () -> Bool {
switch (self) {
case TmTrue: return true
case TmFalse: return true
case let t where t.isnumericval(): return true
default: return false
}
}
func eval () -> Term {
switch self.destructure() {
case let .TmIf(t1, t2, t3):
return TmIf(Box(t1.eval()), Box(t2), Box(t3))
case let .TmIf(.TmTrue, t2, _):
return t2
case let .TmIf(.TmFalse, _, t3):
return t3
case let .TmSucc(t1):
return TmSucc(Box(t1.eval()))
case let .TmPred(.TmZero):
return TmZero
case let .TmPred(TmSucc(nv1)) where nv1.value.isnumericval():
return nv1.value
case let .TmPred(t1):
return TmPred(Box(t1.eval()))
case let .TmIsZero(TmZero):
return TmTrue
case let .TmIsZero(TmSucc(nv1)) where nv1.value.isnumericval():
return TmFalse
case let .TmIsZero(t1):
return TmIsZero(Box(t1.eval()))
default:
fatalError("End of the line")
}
}
func destructure () -> DestructuredTerm {
switch self {
case TmTrue: return .TmTrue
case TmFalse: return .TmFalse
case TmZero: return .TmZero
case let TmSucc(t1): return .TmSucc(t1.value)
case let TmPred(t1): return .TmPred(t1.value)
case let TmIsZero(t1): return .TmIsZero(t1.value)
case let TmIf(t1, t2, t3): return .TmIf(t1.value, t2.value, t3.value)
}
}
}
/* Not needed anymore! :D
func ==(lhs: Term, rhs: Term) -> Bool {
switch (lhs, rhs) {
case (.TmTrue, .TmTrue): return true
case (.TmFalse, .TmFalse): return true
case (.TmZero, .TmZero): return true
case let (.TmSucc(l), .TmSucc(r)): return l.value == r.value
case let (.TmPred(l), .TmPred(r)): return l.value == r.value
case let (.TmIsZero(l), .TmIsZero(r)): return l.value == r.value
case let (.TmIf(l1, l2, l3), .TmIf(r1, r2, r3)): return l1.value == r1.value && l2.value == r2.value && l3.value == r3.value
default: return false
}
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment