diff --git a/include/serene/environment.h b/include/serene/environment.h new file mode 100644 index 0000000..2692303 --- /dev/null +++ b/include/serene/environment.h @@ -0,0 +1,61 @@ +/* -*- C++ -*- + * Serene programming language. + * + * Copyright (c) 2019-2021 Sameer Rahmani + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef SERENE_ENVIRONMENT_H +#define SERENE_ENVIRONMENT_H + +#include "mlir/Support/LogicalResult.h" +#include "llvm/ADT/DenseMap.h" + +namespace serene { + +template class Environment { + Environment *parent; + llvm::DenseMap pairs; + +public: + Environment() : parent(nullptr) {} + Environment(Environment *parent) : parent(parent){}; + + llvm::Optional lookup(K key) { + if (auto value = pairs.lookup(key)) { + return value; + } + + if (parent) { + return parent->lookup(key); + } + + return llvm::None; + }; + + mlir::LogicalResult insert_symbol(K key, V value) { + pairs.insert(std::pair(key, value)); + return mlir::success(); + }; +}; + +} // namespace serene + +#endif diff --git a/src/serene/CMakeLists.txt b/src/serene/CMakeLists.txt index bc07848..0f18d0a 100644 --- a/src/serene/CMakeLists.txt +++ b/src/serene/CMakeLists.txt @@ -2,6 +2,7 @@ set(HEADER_LIST "${INCLUDE_DIR}/serene/serene.h" "${INCLUDE_DIR}/serene/utils.h" "${INCLUDE_DIR}/serene/context.h" + "${INCLUDE_DIR}/serene/environment.h" "${INCLUDE_DIR}/serene/exprs/expression.h" "${INCLUDE_DIR}/serene/exprs/symbol.h" diff --git a/src/tests/environment_tests.cpp.inc b/src/tests/environment_tests.cpp.inc new file mode 100644 index 0000000..f461725 --- /dev/null +++ b/src/tests/environment_tests.cpp.inc @@ -0,0 +1,65 @@ +/* -*- C++ -*- + * Serene programming language. + * + * Copyright (c) 2019-2021 Sameer Rahmani + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "./test_helpers.cpp.inc" +#include "serene/environment.h" +#include "serene/exprs/expression.h" +#include "serene/exprs/symbol.h" +#include "llvm/ADT/StringRef.h" +#include + +namespace serene { + + +TEST_CASE("Environment tests", "[environment]") { + std::unique_ptr range(dummyLocation()); + + exprs::node sym = exprs::make(*range.get(), llvm::StringRef("example")); + + Environment e; + llvm::Optional result = e.lookup("a"); + + REQUIRE_FALSE(result.hasValue()); + + auto status = e.insert_symbol("a", sym); + + REQUIRE(status.succeeded()); + + result = e.lookup("a"); + + REQUIRE(result.hasValue()); + CHECK(result.getValue() == sym); + + Environment e1(&e); + + result = e1.lookup("b"); + REQUIRE_FALSE(result.hasValue()); + + // It should lookup the value in the parent environment + result = e1.lookup("a"); + REQUIRE(result.hasValue()); + CHECK(result.getValue() == sym); +}; + +} // namespace serene diff --git a/src/tests/serenetests.cpp b/src/tests/serenetests.cpp index 09d0f24..182faef 100644 --- a/src/tests/serenetests.cpp +++ b/src/tests/serenetests.cpp @@ -23,6 +23,7 @@ */ #define CATCH_CONFIG_MAIN +#include "./environment_tests.cpp.inc" #include "./errors/error_tests.cpp.inc" #include "./exprs/expression_tests.cpp.inc" #include "./exprs/list_tests.cpp.inc"