<commit_before>//
//  Environment.swift
//  slox
//
//  Created by <NAME> on 01/06/2017.
//
//

import Foundation
import Result

// This is a hack to make Swift useful when working with Any and Optional.
// You can't know, not even at runtime, if an Any is an Optional (it always says yes).
// So to store Any (including nil) in the enviornment we just use Any instead of Any? and use this value
// to denote nil.
// Otherwise you start having Optional nested many times that will break the stringify output and probably
// any other execution that tries to use it.
let NilAny: Any = Optional<Any>.none as Any

final class Environment {

    var enclosing: Environment?

    // Any is optional because uninitialized variables are nil.
    private var values = Dictionary<String, Any>()

    init() {
        enclosing = nil
    }

    init(enclosing: Environment) {
        self.enclosing = enclosing
    }

    /// Pass any value, but for nil use `NilAny`
    func define(name: String, value: Any) {
        assert((value is Result<Any, InterpreterError>) == false, "Trying to store a Result instead of the value?")
        values[name] = value
    }

    func valueFor(name: Token) throws -> Any {
        if values.contains(where: { key, value in key == name.lexeme }) {
            if let unwrapped = values[name.lexeme] {
                return unwrapped
            }
            return NilAny
        }

        if let enclosing = enclosing {
            return try enclosing.valueFor(name: name)
        }

        throw InterpreterError.runtime(name, "Undefined variable '\(name.lexeme)'.")
    }

    func assign(name: Token, value: Any) throws {
        if values.contains(where: { key, value in key == name.lexeme }) {
            values[name.lexeme] = value
            return
        }

        if let enclosing = enclosing {
            try enclosing.assign(name: name, value: value)
        }

        throw InterpreterError.runtime(name, "Undefined variable '\(name.lexeme)'.")
    }
}
<commit_msg>Fixed bug in Environment throwing an undefined variable even when it was defined in an outser scope<commit_after>//
//  Environment.swift
//  slox
//
//  Created by <NAME> on 01/06/2017.
//
//

import Foundation
import Result

// This is a hack to make Swift useful when working with Any and Optional.
// You can't know, not even at runtime, if an Any is an Optional (it always says yes).
// So to store Any (including nil) in the enviornment we just use Any instead of Any? and use this value
// to denote nil.
// Otherwise you start having Optional nested many times that will break the stringify output and probably
// any other execution that tries to use it.
let NilAny: Any = Optional<Any>.none as Any

final class Environment {

    var enclosing: Environment?

    // Any is optional because uninitialized variables are nil.
    private var values = Dictionary<String, Any>()

    init() {
        enclosing = nil
    }

    init(enclosing: Environment) {
        self.enclosing = enclosing
    }

    /// Pass any value, but for nil use `NilAny`
    func define(name: String, value: Any) {
        assert((value is Result<Any, InterpreterError>) == false, "Trying to store a Result instead of the value?")
        values[name] = value
    }

    func valueFor(name: Token) throws -> Any {
        if values.contains(where: { key, value in key == name.lexeme }) {
            if let unwrapped = values[name.lexeme] {
                return unwrapped
            }
            return NilAny
        }

        if let enclosing = enclosing {
            return try enclosing.valueFor(name: name)
        }

        throw InterpreterError.runtime(name, "Undefined variable '\(name.lexeme)'.")
    }

    func assign(name: Token, value: Any) throws {
        if values.contains(where: { key, value in key == name.lexeme }) {
            values[name.lexeme] = value
            return
        }

        if let enclosing = enclosing {
            try enclosing.assign(name: name, value: value)
            return
        }

        throw InterpreterError.runtime(name, "Undefined variable '\(name.lexeme)'.")
    }
}

{'fraction_non_alphanumeric': 0.09480048367593712, 'fraction_numerical': 0.0038694074969770256, 'mean_word_length': 2.303514376996805, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, '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': '7128575', 'n_tokens_mistral': 1185, 'n_tokens_neox': 1118, 'n_words': 445}