Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Swift has MixFix operators, right?
// Colin Barrett - @cbarrett
// turning a big dial taht says "Mixfix operators like Agda" on it
// and constantly looking back at the audience for approval
// like a contestant on the price is right
// https://twitter.com/cbarrett/status/1137113289593413633
// Here define a mixfix interpreter operator spelled: _ ⊢ ⟦_⟧
prefix operator
postfix operator
infix operator : CastingPrecedence
struct ToEval1 { let ast: Ast }
struct ToEval2 { let ast: ToEval1 }
postfix func (ast: Ast) -> ToEval1 {
return ToEval1(ast: ast)
}
prefix func (ast: ToEval1) -> ToEval2 {
return ToEval2(ast: ast)
}
func (env: [Int], ast: ToEval2) -> Int {
return ast.ast.ast.eval(env: env) // :3
}
// This is a nice collection extension that I use very often
extension Collection {
subscript(safe index: Index) -> Element? {
if indices.contains(index) {
return self[index]
} else {
return nil
}
}
}
indirect enum Ast: ExpressibleByIntegerLiteral {
init(integerLiteral value: Int) {
self = .int(value)
}
typealias IntegerLiteralType = Int
case int(Int)
case `var`(Int)
case `let`(Ast, Ast)
case add(Ast, Ast), sub(Ast, Ast), mul(Ast, Ast), div(Ast, Ast), rem(Ast, Ast)
func eval(env: [Int]) -> Int {
switch self {
case .int(let val): return val
case .var(let name): return env[safe: name] ?? 0
case .let(let bind, let body): return ([env bind] + env) body
case .add(let lhs, let rhs): return (env lhs) + (env rhs)
case .sub(let lhs, let rhs): return (env lhs) - (env rhs)
case .mul(let lhs, let rhs): return (env lhs) * (env rhs)
case .div(let lhs, let rhs): return (env lhs) / (env rhs)
case .rem(let lhs, let rhs): return (env lhs) % (env rhs)
}
}
}
func + (lhs: Ast, rhs: Ast) -> Ast { return .add(lhs, rhs) }
func - (lhs: Ast, rhs: Ast) -> Ast { return .sub(lhs, rhs) }
func * (lhs: Ast, rhs: Ast) -> Ast { return .mul(lhs, rhs) }
func / (lhs: Ast, rhs: Ast) -> Ast { return .div(lhs, rhs) }
func % (lhs: Ast, rhs: Ast) -> Ast { return .rem(lhs, rhs) }
let (x, y) = (Ast.var(0), Ast.var(1))
let expr = Ast.let(20 / 2, x * x * 4 + (2 * y) - 1)
print(expr)
print([7] expr)
assert([7] expr == 413)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.