/* * Copyright (C) 2023 Riyyi * * SPDX-License-Identifier: MIT */ #include // int64_t #include // std::function #include // std::static_pointer_cast #include "ast.h" #include "env/macro.h" #include "util.h" namespace blaze { void Environment::loadCompare() { #define NUMBER_COMPARE(operator) \ { \ bool result = true; \ \ CHECK_ARG_COUNT_AT_LEAST(#operator, SIZE(), 2); \ \ /* Start with the first number */ \ VALUE_CAST(number_node, Number, (*begin)); \ int64_t number = number_node->number(); \ \ /* Skip the first node */ \ for (auto it = begin + 1; it != end; ++it) { \ VALUE_CAST(current_number_node, Number, (*it)); \ int64_t current_number = current_number_node->number(); \ if (!(number operator current_number)) { \ result = false; \ break; \ } \ number = current_number; \ } \ \ return makePtr((result) ? Constant::True : Constant::False); \ } ADD_FUNCTION("<", "", "", NUMBER_COMPARE(<)); ADD_FUNCTION("<=", "", "", NUMBER_COMPARE(<=)); ADD_FUNCTION(">", "", "", NUMBER_COMPARE(>)); ADD_FUNCTION(">=", "", "", NUMBER_COMPARE(>=)); // ----------------------------------------- // (= 1 1) -> true // (= "foo" "foo") -> true ADD_FUNCTION( "=", "", "", { CHECK_ARG_COUNT_AT_LEAST("=", SIZE(), 2); std::function equal = [&equal](ValuePtr lhs, ValuePtr rhs) -> bool { if ((is(lhs.get()) || is(lhs.get())) && (is(rhs.get()) || is(rhs.get()))) { auto lhs_collection = std::static_pointer_cast(lhs); auto rhs_collection = std::static_pointer_cast(rhs); if (lhs_collection->size() != rhs_collection->size()) { return false; } auto lhs_it = lhs_collection->begin(); auto rhs_it = rhs_collection->begin(); for (; lhs_it != lhs_collection->end(); ++lhs_it, ++rhs_it) { if (!equal(*lhs_it, *rhs_it)) { return false; } } return true; } if (is(lhs.get()) && is(rhs.get())) { const auto& lhs_nodes = std::static_pointer_cast(lhs)->elements(); const auto& rhs_nodes = std::static_pointer_cast(rhs)->elements(); if (lhs_nodes.size() != rhs_nodes.size()) { return false; } for (const auto& [key, value] : lhs_nodes) { auto it = rhs_nodes.find(key); if (it == rhs_nodes.cend() || !equal(value, it->second)) { return false; } } return true; } if (is(lhs.get()) && is(rhs.get()) && std::static_pointer_cast(lhs)->data() == std::static_pointer_cast(rhs)->data()) { return true; } if (is(lhs.get()) && is(rhs.get()) && std::static_pointer_cast(lhs)->keyword() == std::static_pointer_cast(rhs)->keyword()) { return true; } if (is(lhs.get()) && is(rhs.get()) && std::static_pointer_cast(lhs)->number() == std::static_pointer_cast(rhs)->number()) { return true; } if (is(lhs.get()) && is(rhs.get()) && std::static_pointer_cast(lhs)->state() == std::static_pointer_cast(rhs)->state()) { return true; } if (is(lhs.get()) && is(rhs.get()) && std::static_pointer_cast(lhs)->symbol() == std::static_pointer_cast(rhs)->symbol()) { return true; } return false; }; bool result = true; auto it = begin; auto it_next = begin + 1; for (; it_next != end; ++it, ++it_next) { if (!equal(*it, *it_next)) { result = false; break; } } return makePtr((result) ? Constant::True : Constant::False); }); } } // namespace blaze