<commit_before>import Syft

protocol Expr {
    func evaluate() -> Int
}

struct Num: Expr {
    let value: Int
    
    func evaluate() -> Int {
        return value
    }
}

struct Plus: Expr {
    let first: Expr
    let second: Expr

    func evaluate() -> Int {
        return first.evaluate() + second.evaluate()
    }
}

struct Minus: Expr {
    let first: Expr
    let second: Expr

    func evaluate() -> Int {
        return first.evaluate() - second.evaluate()
    }
}

struct Times: Expr {
    let first: Expr
    let second: Expr

    func evaluate() -> Int {
        return first.evaluate() * second.evaluate()
    }
}

func arithmetic() -> Pipeline<Expr> {
    return Pipeline(defaultInput: "+ 1 2", parser: makeArithmeticParser(), transformer: makeArithmeticTransformer()) { ast in
        let result = ast.evaluate()
        return "\(result)"
    }
}

func makeArithmeticParser() -> ParserProtocol {

    let space = " ".match
    let skip = space.some.maybe
    let digit = (0...9).match
    let op = skip >>> "+-*".match.tag("op") >>> skip
    let numeral = skip >>> digit.some.tag("n") >>> skip
    let expression = Deferred()
    let compound = op >>> expression.tag("a") >>> expression.tag("b")
    expression.parser = compound | numeral
    return expression
}

enum ExprError: Error {
    case notAConstant
    case unexpectedRemainder
}

func makeArithmeticTransformer() -> Transformer<Expr> {

    let transformer = Transformer<Expr>()

    transformer.rule(["n": .simple("n")]) {
        guard let int = Int(try $0.val("n")) else { throw ExprError.notAConstant }
        return Num(value: int)
    }
    
    transformer.rule(["a": .simple("a"), "b": .simple("b"), "op": .literal("+")]) {
        try Plus(first: $0.val("a"), second: $0.val("b"))
    }
    
    transformer.rule(["a": .simple("a"), "b": .simple("b"), "op": .literal("-")]) {
        try Minus(first: $0.val("a"), second: $0.val("b"))
    }
    
    transformer.rule(["a": .simple("a"), "b": .simple("b"), "op": .literal("*")]) {
        try Times(first: $0.val("a"), second: $0.val("b"))
    }
    
    return transformer
}<commit_msg>Add division to arithmetic example.<commit_after>import Syft

protocol Expr {
    func evaluate() -> Double
}

struct Num: Expr {
    let value: Double
    
    func evaluate() -> Double {
        return value
    }
}

struct Plus: Expr {
    let first: Expr
    let second: Expr

    func evaluate() -> Double {
        return first.evaluate() + second.evaluate()
    }
}

struct Minus: Expr {
    let first: Expr
    let second: Expr

    func evaluate() -> Double {
        return first.evaluate() - second.evaluate()
    }
}

struct Times: Expr {
    let first: Expr
    let second: Expr

    func evaluate() -> Double {
        return first.evaluate() * second.evaluate()
    }
}

struct Divide: Expr {
    let first: Expr
    let second: Expr

    func evaluate() -> Double {
        return first.evaluate() / second.evaluate()
    }
}

func arithmetic() -> Pipeline<Expr> {
    return Pipeline(defaultInput: "+ 1 2", parser: makeArithmeticParser(), transformer: makeArithmeticTransformer()) { ast in
        let result = ast.evaluate()
        return "\(result)"
    }
}

func makeArithmeticParser() -> ParserProtocol {

    let space = " ".match
    let skip = space.some.maybe
    let digit = (0...9).match
    let op = skip >>> "+-*/".match.tag("op") >>> skip
    let numeral = skip >>> digit.some.tag("n") >>> skip
    let expression = Deferred()
    let compound = op >>> expression.tag("a") >>> expression.tag("b")
    expression.parser = compound | numeral
    return expression
}

enum ExprError: Error {
    case notAConstant
}

func makeArithmeticTransformer() -> Transformer<Expr> {

    let transformer = Transformer<Expr>()

    transformer.rule(["n": .simple("n")]) {
        guard let value = Double(try $0.val("n")) else { throw ExprError.notAConstant }
        return Num(value: value)
    }
    
    transformer.rule(["a": .simple("a"), "b": .simple("b"), "op": .literal("+")]) {
        try Plus(first: $0.val("a"), second: $0.val("b"))
    }
    
    transformer.rule(["a": .simple("a"), "b": .simple("b"), "op": .literal("-")]) {
        try Minus(first: $0.val("a"), second: $0.val("b"))
    }

    transformer.rule(["a": .simple("a"), "b": .simple("b"), "op": .literal("*")]) {
        try Times(first: $0.val("a"), second: $0.val("b"))
    }

    transformer.rule(["a": .simple("a"), "b": .simple("b"), "op": .literal("/")]) {
        try Divide(first: $0.val("a"), second: $0.val("b"))
    }

    return transformer
}
{'fraction_non_alphanumeric': 0.18104389604717186, 'fraction_numerical': 0.0052413190652981, 'mean_word_length': 2.66693354683747, 'pattern_counts': {'":': 23, '<': 9, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, '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': '201397', 'n_tokens_mistral': 1527, 'n_tokens_neox': 1470, 'n_words': 382}