Skip to content

Commit

Permalink
Added Control and modify/ update
Browse files Browse the repository at this point in the history
  • Loading branch information
Zach Eriksen committed Sep 29, 2020
1 parent 9e2fd46 commit 696f9f0
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 4 deletions.
49 changes: 49 additions & 0 deletions Sources/E.num/Control.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// Control.swift
// E.num
//
// Created by Zach Eriksen on 9/29/20.
//

enum Control {
case `if`(Bool, Function)
case `else`(Bool, Function)
case ifElse(Bool, Function, Function)
case loop(ClosedRange<Int>, Function)
case forEach([Variable], Function)
case forever(Function)
}

extension Control {
func run() {
switch self {
case .if(let condition, let function):
if condition {
function()
}
case .else(let condition, let function):
if !condition {
function()
}
case .ifElse(let condition, let trueFunction, let falseFunction):
if condition {
trueFunction()
} else {
falseFunction()
}
case .loop(let range, let function):
for value in range {
function.run(.int(value))
}
case .forEach(let values, let function):
for value in values {
function.run(value)
}
case .forever(let function):
while true {
function()
}
}
}
}

3 changes: 1 addition & 2 deletions Sources/E.num/Function.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
// Created by Zach Eriksen on 9/29/20.
//

import Foundation

@dynamicCallable
public enum Function {
case void(() -> ())
case `in`((Variable) -> ())
case out(() -> Variable)
case `inout`((Variable) -> Variable)

@discardableResult
func dynamicallyCall(withArguments args: [Variable]) -> Variable? {
guard args.isEmpty else {
return run()
Expand Down
47 changes: 45 additions & 2 deletions Sources/E.num/Variable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
// Created by Zach Eriksen on 9/29/20.
//

import Foundation

public enum Variable: Equatable, Hashable {
case void
case bool(Bool)
Expand All @@ -19,6 +17,51 @@ public enum Variable: Equatable, Hashable {
case dictionary([Variable: Variable])
}

public extension Variable {
/// Update the Variable's Value
/// - Returns: A new Variable with the type of T
func update<T>(_ closure: (T) -> Variable) -> Self {
guard let value = value(as: T.self) else {
print("[E.num] ERROR (\(#function): Could not modify value \(self) as \(T.self)...")
return self
}

return closure(value)
}

/// Modify the Variable to be any type of Variable
/// - Returns: A new Variable of any type
func modify<T>(_ closure: (T?) -> Variable) -> Self {
guard let value = value(as: T.self) else {
return closure(nil)
}

return closure(value)
}

func value<T>(as type: T.Type? = nil) -> T? {
if case .bool(let value) = self {
return value as? T
} else if case .int(let value) = self {
return value as? T
} else if case .float(let value) = self {
return value as? T
} else if case .double(let value) = self {
return value as? T
} else if case .string(let value) = self {
return value as? T
} else if case .set(let value) = self {
return value as? T
} else if case .array(let value) = self {
return value as? T
} else if case .dictionary(let value) = self {
return value as? T
} else {
return nil
}
}
}

extension Variable: ExpressibleByBooleanLiteral {
public init(booleanLiteral value: Bool) {
self = .bool(value)
Expand Down
23 changes: 23 additions & 0 deletions Tests/E.numTests/E_numTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,29 @@ final class E_numTests: XCTestCase {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct
// results.
var count: Variable = .int(0)

let stillIntValue = count
.update { .string($0 ?? "Hello, World!") } // returns .int(0)
.update { .int($0 + 27) }

let defaultedStringValue = count.modify { value in
.string(value ?? "Hello, World!")
}

XCTAssertEqual(count, 0)
XCTAssertEqual(stillIntValue, 27)
XCTAssertEqual(defaultedStringValue, "Hello, World!")

Control.loop(0 ... 5,
.in { index in
count = count.update { value in
.int(value + (index.value() ?? 0))
}
})
.run()

XCTAssertEqual(count, 15)
XCTAssertEqual(E_num().text, "Hello, World!")
}

Expand Down

0 comments on commit 696f9f0

Please sign in to comment.