Files
kraken/koka_bench/swift/cfold.swift
2022-05-19 00:43:27 -04:00

104 lines
2.5 KiB
Swift

indirect enum Expr {
case Var(UInt64)
case Val(UInt64)
case Add(Expr, Expr)
case Mul(Expr, Expr)
}
func mk_expr(_ n: UInt64, _ v: UInt64) -> Expr {
if n == 0 {
return v == 0 ? .Var(1) : .Val(v)
} else {
return .Add(mk_expr(n - 1, v+1), mk_expr(n - 1, v == 0 ? 0 : v - 1))
}
}
func append_add(_ e: Expr, _ e: Expr) -> Expr {
switch e {
case let .Add(e, e):
return .Add(e, append_add(e, e))
default:
return .Add(e, e)
}
}
func append_mul(_ e: Expr, _ e: Expr) -> Expr {
switch e {
case let .Mul(e, e):
return .Mul(e, append_mul(e, e))
default:
return .Mul(e, e)
}
}
func reassoc(_ e: Expr) -> Expr {
switch e {
case let .Add(e, e):
let e = reassoc(e)
let e = reassoc(e)
return append_add(e, e)
case let .Mul(e, e):
let e = reassoc(e)
let e = reassoc(e)
return append_mul(e, e)
default:
return e
}
}
func const_folding(_ e: Expr) -> Expr {
switch e {
case let .Add(e, e):
let e = const_folding(e)
let e = const_folding(e)
switch (e, e) {
case let (.Val(a), .Val(b)):
return .Val(a+b)
case let (.Val(a), .Add(e, .Val(b))):
return .Add(.Val(a+b), e)
case let (.Val(a), .Add(.Val(b), e)):
return .Add(.Val(a+b), e)
default:
return .Add(e, e)
}
case let .Mul(e, e):
let e = const_folding(e)
let e = const_folding(e)
switch (e, e) {
case let (.Val(a), .Val(b)):
return .Val(a*b)
case let (.Val(a), .Mul(e, .Val(b))):
return .Mul(.Val(a*b), e)
case let (.Val(a), .Mul(.Val(b), e)):
return .Mul(.Val(a*b), e)
default:
return .Mul(e, e)
}
default:
return e
}
}
func eval(_ e: Expr) -> UInt64 {
switch e {
case .Var(_):
return 0
case let .Val(v):
return v
case let .Add(l, r):
return eval(l) + eval(r)
case let .Mul(l, r):
return eval(l) * eval(r)
}
}
var num: UInt64? = 20
if CommandLine.arguments.count >= 2 {
num = UInt64(CommandLine.arguments[1])
}
let e = mk_expr(num!, 1)
let v = eval(e)
let v = eval(const_folding(reassoc(e)))
print(v, v)