<commit_before>//
//  CalculatorBrain.swift
//  Calculator
//
//  Created by <NAME> on 18/03/17.
//  Copyright © 2017 <NAME>. All rights reserved.
//

import Foundation

struct CalculatorBrain {
    
    // MARK: - Internal
    
    private enum ExpressionLiteral {
        case operand(Double)
        case operation(String)
        case variable(String)
    }
    
    private var sequence = [ExpressionLiteral]()
    
    private enum Operation {
        case constant(Double)
        case nullaryOperation(() -> Double, () -> String)
        case unaryOperation((Double) -> Double, (String) -> String)
        case binaryOperation((Double,Double) -> Double, (String,String) -> String)
        case equals
    }

    private var operations: Dictionary<String,Operation> = [
        "π" : Operation.constant(Double.pi),
        "e" : Operation.constant(M_E),
        "Rand" : Operation.nullaryOperation({Double(arc4random()) / 0xFFFFFFFF}, {"Rand"}),
        "√" : Operation.unaryOperation(sqrt, {"√(\($0))"}),
        "cos" : Operation.unaryOperation(cos, {"cos(\($0))"}),
        "sin" : Operation.unaryOperation(sin, {"sin(\($0))"}),
        "tan" : Operation.unaryOperation(tan, {"tan(\($0))"}),
        "x²" : Operation.unaryOperation({ $0 * $0 }, {"(\($0))²"}),
        "x⁻¹" : Operation.unaryOperation({ 1 / $0 }, {"(\($0))⁻¹"}),
        "±" : Operation.unaryOperation({ -$0 }, {"-\($0)"}),
        "×" : Operation.binaryOperation({ $0 * $1 }, {"\($0) × \($1)"}),
        "÷" : Operation.binaryOperation({ $0 / $1 }, {"\($0) ÷ \($1)"}),
        "+" : Operation.binaryOperation({ $0 + $1 }, {"\($0) + \($1)"}),
        "−" : Operation.binaryOperation({ $0 - $1 }, {"\($0) − \($1)"}),
        "=" : Operation.equals
    ]
    
    mutating func performOperation(_ symbol: String) {
        sequence.append(ExpressionLiteral.operation(symbol))
    }
    
    // MARK: - API
    
    mutating func setOperand(_ operand: Double) {
        sequence.append(ExpressionLiteral.operand(operand))
    }
    
    var result: Double? {
        get {
            return evaluate().result
        }
    }
    
    var resultIsPending: Bool {
        get {
            return evaluate().isPending
        }
    }
    
    var description: String? {
        get {
            return evaluate().description
        }
    }
    
    mutating func setOperand(variable named: String) {
        sequence.append(ExpressionLiteral.variable(named))
    }

    func evaluate(using variables: Dictionary<String,Double>? = nil) -> (result: Double?, isPending: Bool, description: String) {
        var accumulator: Double?
        var accumulatorString: String? // todo tuple
        var pendingBinaryOperation: PendingBinaryOperation?

        // Old functions are moved into this one as nested functionality
        func setOperand(_ operand: Double) {
            accumulator = operand
            
            let numberFormatter = NumberFormatter()
            numberFormatter.numberStyle = .decimal
            numberFormatter.usesGroupingSeparator = false
            numberFormatter.maximumFractionDigits = Constants.numberOfDigitsAfterDecimalPoint
            accumulatorString = numberFormatter.string(from: NSNumber(value: operand))
        }
        
        func setOperand(variable named: String) {
            accumulator = variables?[named] ?? 0<commit_msg>Completes task 5 (closes #3)<commit_after>//
//  CalculatorBrain.swift
//  Calculator
//
//  Created by <NAME> on 18/03/17.
//  Copyright © 2017 <NAME>. All rights reserved.
//

import Foundation

struct CalculatorBrain {
    
    // MARK: - Internal
    
    private enum ExpressionLiteral {
        case operand(Double)
        case operation(String)
        case variable(String)
    }
    
    private var sequence = [ExpressionLiteral]()
    
    private enum Operation {
        case constant(Double)
        case nullaryOperation(() -> Double, () -> String)
        case unaryOperation((Double) -> Double, (String) -> String)
        case binaryOperation((Double,Double) -> Double, (String,String) -> String)
        case equals
    }

    private var operations: Dictionary<String,Operation> = [
        "π" : Operation.constant(Double.pi),
        "e" : Operation.constant(M_E),
        "Rand" : Operation.nullaryOperation({Double(arc4random()) / 0xFFFFFFFF}, {"Rand"}),
        "√" : Operation.unaryOperation(sqrt, {"√(\($0))"}),
        "cos" : Operation.unaryOperation(cos, {"cos(\($0))"}),
        "sin" : Operation.unaryOperation(sin, {"sin(\($0))"}),
        "tan" : Operation.unaryOperation(tan, {"tan(\($0))"}),
        "x²" : Operation.unaryOperation({ $0 * $0 }, {"(\($0))²"}),
        "x⁻¹" : Operation.unaryOperation({ 1 / $0 }, {"(\($0))⁻¹"}),
        "±" : Operation.unaryOperation({ -$0 }, {"-\($0)"}),
        "×" : Operation.binaryOperation({ $0 * $1 }, {"\($0) × \($1)"}),
        "÷" : Operation.binaryOperation({ $0 / $1 }, {"\($0) ÷ \($1)"}),
        "+" : Operation.binaryOperation({ $0 + $1 }, {"\($0) + \($1)"}),
        "−" : Operation.binaryOperation({ $0 - $1 }, {"\($0) − \($1)"}),
        "=" : Operation.equals
    ]
    
    mutating func performOperation(_ symbol: String) {
        sequence.append(ExpressionLiteral.operation(symbol))
    }
    
    // MARK: - API
    
    mutating func setOperand(_ operand: Double) {
        sequence.append(ExpressionLiteral.operand(operand))
    }
    
    @available(*, deprecated, message: "Use evaluate instead")
    var result: Double? {
        get {
            return evaluate().result
        }
    }
    
    @available(*, deprecated, message: "Use evaluate instead")
    var resultIsPending: Bool {
        get {
            return evaluate().isPending
        }
    }
    
    @available(*, deprecated, message: "Use evaluate instead")
    var description: String? {
        get {
            return evaluate().description
        }
    }
    
    mutating func setOperand(variable named: String) {
        sequence.append(ExpressionLiteral.variable(named))
    }

    func evaluate(using variables: Dictionary<String,Double>? = nil) -> (result: Double?, isPending: Bool, description: String) {
        var accumulator: Double?
        var accumulatorString: String? // todo tuple
        var pendingBinaryOperation: PendingBinaryOperation?

        // Old functions are moved into this one as nested functionality
        func setOperand(_ operand: Double) {
            accumulator = operand
            
            let numberFormatter = NumberFormatter()
            numberFormatter.numberStyle = .decimal
            numberFormatter.usesGroupingSeparator = false
            numberFormatter.maximumFractionDigits = Constants.numberOfDigitsAfterDecimalPoint
            accumulatorString = numberFormatter.string(from: NSNumber(value: operand))
        }
        
        func setOperand(variable named: String) {
            accumulator = variables?[named] ?? 0
{'fraction_non_alphanumeric': 0.1516642547033285, 'fraction_numerical': 0.01215629522431259, 'mean_word_length': 2.3894065718489457, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3821740', 'n_tokens_mistral': 1994, 'n_tokens_neox': 1952, 'n_words': 453}