From dfca529319e1f7ff68962b9c677949d4f7f69e47 Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 16 Oct 2025 12:55:17 -0700 Subject: [PATCH 001/122] Explicitly set bdwgc debug flags --- compiler+runtime/cmake/dependency/bdwgc.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler+runtime/cmake/dependency/bdwgc.cmake b/compiler+runtime/cmake/dependency/bdwgc.cmake index fff5b9cba..26706a9f1 100644 --- a/compiler+runtime/cmake/dependency/bdwgc.cmake +++ b/compiler+runtime/cmake/dependency/bdwgc.cmake @@ -11,11 +11,15 @@ set(CMAKE_CXX_CLANG_TIDY_OLD ${CMAKE_CXX_CLANG_TIDY}) set(enable_docs OFF CACHE BOOL "Enable docs") set(enable_large_config ON CACHE BOOL "Optimize for large heap or root set") set(enable_throw_bad_alloc_library ON CACHE BOOL "Enable C++ gctba library build") + set(enable_gc_debug OFF CACHE BOOL "Support for pointer back-tracing") add_subdirectory(third-party/bdwgc EXCLUDE_FROM_ALL) unset(enable_cplusplus) unset(build_cord) unset(enable_docs) + unset(enable_large_config) + unset(enable_throw_bad_alloc_library) + unset(enable_gc_debug) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_OLD}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_OLD}") set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_OLD}) From bf31860d7106b98ed02c4bb27c7983e73fb77387 Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 16 Oct 2025 12:56:30 -0700 Subject: [PATCH 002/122] Move reusable_context to jtl::ref --- .../cpp/jank/codegen/llvm_processor.hpp | 2 +- .../src/cpp/jank/codegen/llvm_processor.cpp | 39 ++++++------------- 2 files changed, 12 insertions(+), 29 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/codegen/llvm_processor.hpp b/compiler+runtime/include/cpp/jank/codegen/llvm_processor.hpp index c2bb669c6..123969dc1 100644 --- a/compiler+runtime/include/cpp/jank/codegen/llvm_processor.hpp +++ b/compiler+runtime/include/cpp/jank/codegen/llvm_processor.hpp @@ -94,7 +94,7 @@ namespace jank::codegen compilation_target target); /* For this ctor, we're inheriting the context from another function, which means * we're building a nested function. */ - llvm_processor(analyze::expr::function_ref expr, std::unique_ptr ctx); + llvm_processor(analyze::expr::function_ref expr, jtl::ref ctx); llvm_processor(llvm_processor const &) = delete; llvm_processor(llvm_processor &&) noexcept = default; diff --git a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp index 05eef930f..c55e2f48e 100644 --- a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp @@ -88,7 +88,7 @@ namespace jank::codegen compilation_target target); /* For this ctor, we're inheriting the context from another function, which means * we're building a nested function. */ - impl(analyze::expr::function_ref expr, std::unique_ptr ctx); + impl(analyze::expr::function_ref expr, jtl::ref ctx); jtl::string_result gen(); llvm::Value *gen(analyze::expression_ref, analyze::expr::function_arity const &); @@ -181,10 +181,9 @@ namespace jank::codegen compilation_target target{}; analyze::expr::function_ref root_fn; jtl::ptr fn{}; - std::unique_ptr ctx; + jtl::ref ctx; native_unordered_map> locals; - /* TODO: Use gc allocator to avoid leaks. */ - std::list deferred_inits{}; + native_list deferred_inits{}; jtl::ref llvm_ctx; jtl::ref llvm_module; jtl::ptr current_loop; @@ -479,9 +478,8 @@ namespace jank::codegen /* Whenever we have an object in an `alloca`, we need to load it before using. This fn only * makes sense to use with jank objects, as opposed to native values. */ - static llvm::Value *load_if_needed(std::unique_ptr const &ctx, - llvm::Value *arg, - jtl::ptr const type) + static llvm::Value * + load_if_needed(jtl::ref const ctx, llvm::Value *arg, jtl::ptr const type) { if(!arg) { @@ -495,8 +493,7 @@ namespace jank::codegen return arg; } - static llvm::Value * - load_if_needed(std::unique_ptr const &ctx, llvm::Value * const arg) + static llvm::Value *load_if_needed(jtl::ref const ctx, llvm::Value * const arg) { return load_if_needed(ctx, arg, cpp_util::untyped_object_ptr_type()); } @@ -576,8 +573,8 @@ namespace jank::codegen } llvm_processor::llvm_processor(expr::function_ref const expr, - std::unique_ptr ctx) - : _impl{ make_ref(expr, jtl::move(ctx)) } + jtl::ref const ctx) + : _impl{ make_ref(expr, ctx) } { } @@ -586,13 +583,13 @@ namespace jank::codegen compilation_target const target) : target{ target } , root_fn{ expr } - , ctx{ std::make_unique(module_name, std::make_unique()) } + , ctx{ make_ref(module_name, std::make_unique()) } , llvm_ctx{ extract_context(ctx->module) } , llvm_module{ ctx->module.getModuleUnlocked() } { } - llvm_processor::impl::impl(expr::function_ref const expr, std::unique_ptr ctx) + llvm_processor::impl::impl(expr::function_ref const expr, jtl::ref ctx) : target{ compilation_target::function } , root_fn{ expr } , ctx{ std::move(ctx) } @@ -1147,27 +1144,13 @@ namespace jank::codegen { llvm::IRBuilder<>::InsertPointGuard const guard{ *ctx->builder }; - llvm_processor nested{ expr, std::move(ctx) }; - - /* We need to make sure to transfer ownership of the context back, even if an exception - * is thrown. */ - util::scope_exit const finally{ [&]() { - if(nested._impl->ctx) - { - ctx = std::move(nested._impl->ctx); - } - } }; - + llvm_processor nested{ expr, ctx }; auto const res{ nested.gen() }; if(res.is_err()) { /* TODO: Return error. */ res.expect_ok(); } - - /* This is covered by finally, but clang-tidy can't figure that out, so we have - * to make this more clear. */ - ctx = std::move(nested._impl->ctx); } auto const fn_obj(gen_function_instance(expr, fn_arity)); From b8f24b53e4e955692fddbd8f73c3ff6f4b3ddcdc Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 16 Oct 2025 12:57:06 -0700 Subject: [PATCH 003/122] Use gc allocator and remove thread_local usage --- .../include/cpp/jank/read/parse.hpp | 2 +- .../include/cpp/jank/runtime/context.hpp | 5 ++--- .../src/cpp/jank/analyze/processor.cpp | 2 +- .../src/cpp/jank/runtime/context.cpp | 17 ++++++----------- compiler+runtime/src/cpp/jank/runtime/var.cpp | 2 +- 5 files changed, 11 insertions(+), 17 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/read/parse.hpp b/compiler+runtime/include/cpp/jank/read/parse.hpp index 8de1c5e14..e42d364d4 100644 --- a/compiler+runtime/include/cpp/jank/read/parse.hpp +++ b/compiler+runtime/include/cpp/jank/read/parse.hpp @@ -117,7 +117,7 @@ namespace jank::read::parse * token, we should check this list to see if there's already a form we should pull out. * This is needed because parse iteration works one form at a time and splicing potentially * turns one form into many. */ - std::list pending_forms; + native_list pending_forms; lex::token latest_token; jtl::option shorthand; /* Whether or not the next form is considered quoted. */ diff --git a/compiler+runtime/include/cpp/jank/runtime/context.hpp b/compiler+runtime/include/cpp/jank/runtime/context.hpp index 353b17fcf..d6661e10e 100644 --- a/compiler+runtime/include/cpp/jank/runtime/context.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/context.hpp @@ -43,7 +43,6 @@ namespace jank::runtime context(); context(context const &) = delete; context(context &&) noexcept = delete; - ~context(); ns_ref intern_ns(jtl::immutable_string const &); ns_ref intern_ns(obj::symbol_ref const &); @@ -162,8 +161,8 @@ namespace jank::runtime /* Hold onto the CLI Options for use at runtime */ util::cli::options opts; - /* TODO: Remove this map. Just use the list. */ - static thread_local native_unordered_map> + /* XXX: We can't use thread_local here, due to bdwgc not supporting it. */ + static native_unordered_map> thread_binding_frames; /* This must go last, since it'll try to access other bits in the runtime context during diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index 1ece62ee9..e0408cf1a 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -1632,7 +1632,7 @@ namespace jank::analyze native_vector param_symbols; param_symbols.reserve(params->data.size()); - std::set unique_param_symbols; + native_set unique_param_symbols; bool is_variadic{}; for(auto it(params->data.begin()); it != params->data.end(); ++it) diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 4eea03e64..4af42365a 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -34,7 +34,7 @@ namespace jank::runtime { /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ - thread_local decltype(context::thread_binding_frames) context::thread_binding_frames{}; + decltype(context::thread_binding_frames) context::thread_binding_frames{}; /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ context *__rt_ctx{}; @@ -93,11 +93,6 @@ namespace jank::runtime .expect_ok(); } - context::~context() - { - thread_binding_frames.erase(this); - } - obj::symbol_ref context::qualify_symbol(obj::symbol_ref const &sym) const { obj::symbol_ref qualified_sym{ sym }; @@ -708,7 +703,7 @@ namespace jank::runtime jtl::string_result context::push_thread_bindings() { auto bindings(obj::persistent_hash_map::empty()); - auto &tbfs(thread_binding_frames[this]); + auto &tbfs(thread_binding_frames[std::this_thread::get_id()]); if(!tbfs.empty()) { bindings = tbfs.front().bindings; @@ -737,7 +732,7 @@ namespace jank::runtime context::push_thread_bindings(obj::persistent_hash_map_ref const bindings) { thread_binding_frame frame{ obj::persistent_hash_map::empty() }; - auto &tbfs(thread_binding_frames[this]); + auto &tbfs(thread_binding_frames[std::this_thread::get_id()]); if(!tbfs.empty()) { frame.bindings = tbfs.front().bindings; @@ -780,7 +775,7 @@ namespace jank::runtime jtl::string_result context::pop_thread_bindings() { - auto &tbfs(thread_binding_frames[this]); + auto &tbfs(thread_binding_frames[std::this_thread::get_id()]); if(tbfs.empty()) { return err("Mismatched thread binding pop"); @@ -793,7 +788,7 @@ namespace jank::runtime obj::persistent_hash_map_ref context::get_thread_bindings() const { - auto const &tbfs(thread_binding_frames[this]); + auto const &tbfs(thread_binding_frames[std::this_thread::get_id()]); if(tbfs.empty()) { return obj::persistent_hash_map::empty(); @@ -803,7 +798,7 @@ namespace jank::runtime jtl::option context::current_thread_binding_frame() { - auto &tbfs(thread_binding_frames[this]); + auto &tbfs(thread_binding_frames[std::this_thread::get_id()]); if(tbfs.empty()) { return none; diff --git a/compiler+runtime/src/cpp/jank/runtime/var.cpp b/compiler+runtime/src/cpp/jank/runtime/var.cpp index 44f739671..aea909fc9 100644 --- a/compiler+runtime/src/cpp/jank/runtime/var.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/var.cpp @@ -150,7 +150,7 @@ namespace jank::runtime return {}; } - auto &tbfs(__rt_ctx->thread_binding_frames[__rt_ctx]); + auto &tbfs(__rt_ctx->thread_binding_frames[std::this_thread::get_id()]); if(tbfs.empty()) { return {}; From c538cd5582f124e2b39aa2053046afa43e4c9b8e Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 16 Oct 2025 16:58:02 -0700 Subject: [PATCH 004/122] Upgrade bdwgc and use malloc redirection This currently doesn't work with ASan, but I have an open issue for this here: https://github.com/bdwgc/bdwgc/issues/772 --- compiler+runtime/CMakeLists.txt | 1 + compiler+runtime/cmake/dependency/bdwgc.cmake | 11 +++++++++-- compiler+runtime/src/cpp/jank/c_api.cpp | 1 - compiler+runtime/src/cpp/jank/read/lex.cpp | 2 +- compiler+runtime/src/cpp/jank/read/parse.cpp | 12 ++++++------ compiler+runtime/src/cpp/jank/runtime/context.cpp | 2 +- .../cpp/jank/runtime/obj/native_vector_sequence.cpp | 6 +++--- compiler+runtime/third-party/bdwgc | 2 +- 8 files changed, 22 insertions(+), 15 deletions(-) diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index 4eefdd793..1272533a2 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -42,6 +42,7 @@ option(jank_coverage "Enable code coverage measurement" OFF) option(jank_analyze "Enable static analysis" OFF) option(jank_test "Enable jank's test suite" OFF) option(jank_unity_build "Optimize translation unit compilation for the number of cores" OFF) +option(jank_debug_gc "Enable GC debug assertions" OFF) set(jank_sanitize "none" CACHE STRING "The type of Clang sanitization to use (or none)") set(jank_resource_dir "../lib/jank/${CMAKE_PROJECT_VERSION}" diff --git a/compiler+runtime/cmake/dependency/bdwgc.cmake b/compiler+runtime/cmake/dependency/bdwgc.cmake index 26706a9f1..a0b897c78 100644 --- a/compiler+runtime/cmake/dependency/bdwgc.cmake +++ b/compiler+runtime/cmake/dependency/bdwgc.cmake @@ -2,8 +2,8 @@ set(CMAKE_C_FLAGS_OLD "${CMAKE_C_FLAGS}") set(CMAKE_CXX_FLAGS_OLD "${CMAKE_CXX_FLAGS}") set(BUILD_SHARED_LIBS_OLD ${BUILD_SHARED_LIBS}) set(CMAKE_CXX_CLANG_TIDY_OLD ${CMAKE_CXX_CLANG_TIDY}) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w -DREDIRECT_MALLOC=GC_malloc_uncollectable") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w -DREDIRECT_MALLOC=GC_malloc_uncollectable") set(BUILD_SHARED_LIBS OFF) set(CMAKE_CXX_CLANG_TIDY "") set(enable_cplusplus ON CACHE BOOL "Enable C++") @@ -12,6 +12,13 @@ set(CMAKE_CXX_CLANG_TIDY_OLD ${CMAKE_CXX_CLANG_TIDY}) set(enable_large_config ON CACHE BOOL "Optimize for large heap or root set") set(enable_throw_bad_alloc_library ON CACHE BOOL "Enable C++ gctba library build") set(enable_gc_debug OFF CACHE BOOL "Support for pointer back-tracing") + + if(jank_debug_gc) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGC_ASSERTIONS") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGC_ASSERTIONS") + set(enable_gc_debug ON CACHE BOOL "Support for pointer back-tracing") + endif() + add_subdirectory(third-party/bdwgc EXCLUDE_FROM_ALL) unset(enable_cplusplus) diff --git a/compiler+runtime/src/cpp/jank/c_api.cpp b/compiler+runtime/src/cpp/jank/c_api.cpp index b6f317a33..ac766ee0c 100644 --- a/compiler+runtime/src/cpp/jank/c_api.cpp +++ b/compiler+runtime/src/cpp/jank/c_api.cpp @@ -1017,7 +1017,6 @@ extern "C" /* The GC needs to enabled even before arg parsing, since our native types, * like strings, use the GC for allocations. It can still be configured later. */ GC_set_all_interior_pointers(1); - GC_enable(); GC_init(); llvm::llvm_shutdown_obj const Y{}; diff --git a/compiler+runtime/src/cpp/jank/read/lex.cpp b/compiler+runtime/src/cpp/jank/read/lex.cpp index dd71dab54..1e8339cce 100644 --- a/compiler+runtime/src/cpp/jank/read/lex.cpp +++ b/compiler+runtime/src/cpp/jank/read/lex.cpp @@ -1081,7 +1081,7 @@ namespace jank::read::lex return error::lex_invalid_number( util::format( "Characters '{}' are invalid for a base {} number.", - jtl::immutable_string_view{ invalid_digits.begin(), invalid_digits.end() }, + jtl::immutable_string_view{ invalid_digits.data(), invalid_digits.size() }, radix), { token_start, pos }); } diff --git a/compiler+runtime/src/cpp/jank/read/parse.cpp b/compiler+runtime/src/cpp/jank/read/parse.cpp index 4ca0535b8..40f2cdc20 100644 --- a/compiler+runtime/src/cpp/jank/read/parse.cpp +++ b/compiler+runtime/src/cpp/jank/read/parse.cpp @@ -409,7 +409,7 @@ namespace jank::read::parse parsed_keys.insert({ key.ptr, key }); - if constexpr(std::same_as) + if constexpr(jtl::is_same) { map.insert_or_assign(key.ptr, value.unwrap().ptr); } @@ -435,7 +435,7 @@ namespace jank::read::parse return object_source_info{ make_box( source_to_meta(start_token.start, latest_token.end), - std::move(map)), + jtl::move(map)), start_token, latest_token }; } @@ -453,7 +453,7 @@ namespace jank::read::parse return object_source_info{ make_box( source_to_meta(start_token.start, latest_token.end), - std::move(map)), + jtl::move(map)), start_token, latest_token }; } @@ -538,7 +538,7 @@ namespace jank::read::parse auto meta_result(visit_object( [&](auto const typed_val) -> processor::object_result { using T = typename decltype(typed_val)::value_type; - if constexpr(std::same_as) + if constexpr(jtl::is_same) { return object_source_info{ obj::persistent_array_map::create_unique(typed_val, jank_true), start_token, @@ -683,7 +683,7 @@ namespace jank::read::parse expected_closer = prev_expected_closer; return object_source_info{ make_box( source_to_meta(start_token.start, latest_token.end), - std::move(ret).persistent()), + jtl::move(ret).persistent()), start_token, latest_token }; } @@ -1285,7 +1285,7 @@ namespace jank::read::parse [&](auto const typed_form) -> jtl::result { using T = typename decltype(typed_form)::value_type; - if constexpr(std::same_as) + if constexpr(jtl::is_same) { auto const seq(typed_form->seq()); if(seq.is_nil()) diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 4af42365a..24bb7c1dc 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -186,7 +186,7 @@ namespace jank::runtime auto const name{ module::module_to_load_function(module) }; auto const form{ runtime::conj( - runtime::conj(runtime::conj(make_box(std::move(forms)), + runtime::conj(runtime::conj(make_box(jtl::move(forms)), obj::persistent_vector::empty()), make_box(name)), make_box("fn*")) }; diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/native_vector_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/native_vector_sequence.cpp index 7603e8e3e..cea169687 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/native_vector_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/native_vector_sequence.cpp @@ -12,13 +12,13 @@ namespace jank::runtime::obj } native_vector_sequence::native_vector_sequence(native_vector &&data) - : data{ std::move(data) } + : data{ jtl::move(data) } { jank_debug_assert(!this->data.empty()); } native_vector_sequence::native_vector_sequence(native_vector &&data, usize index) - : data{ std::move(data) } + : data{ jtl::move(data) } , index{ index } { jank_debug_assert(!this->data.empty()); @@ -26,7 +26,7 @@ namespace jank::runtime::obj native_vector_sequence::native_vector_sequence(jtl::option const &meta, native_vector &&data) - : data{ std::move(data) } + : data{ jtl::move(data) } , meta{ meta } { } diff --git a/compiler+runtime/third-party/bdwgc b/compiler+runtime/third-party/bdwgc index 88a61fc6f..19a7f495c 160000 --- a/compiler+runtime/third-party/bdwgc +++ b/compiler+runtime/third-party/bdwgc @@ -1 +1 @@ -Subproject commit 88a61fc6f2688d8e1ea94f3f810c23db89a3f30b +Subproject commit 19a7f495cd7c48cdf6f56c593c6dd57187afa079 From 238cfdbee3ca9161e6d0f4fcd9021955fdc650e0 Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 16 Oct 2025 17:56:16 -0700 Subject: [PATCH 005/122] Fix clang-tidy issues --- compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp | 2 +- compiler+runtime/src/cpp/jank/runtime/var.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp index c55e2f48e..1f4666a6d 100644 --- a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp @@ -1144,7 +1144,7 @@ namespace jank::codegen { llvm::IRBuilder<>::InsertPointGuard const guard{ *ctx->builder }; - llvm_processor nested{ expr, ctx }; + llvm_processor const nested{ expr, ctx }; auto const res{ nested.gen() }; if(res.is_err()) { diff --git a/compiler+runtime/src/cpp/jank/runtime/var.cpp b/compiler+runtime/src/cpp/jank/runtime/var.cpp index aea909fc9..8894d37e8 100644 --- a/compiler+runtime/src/cpp/jank/runtime/var.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/var.cpp @@ -150,7 +150,7 @@ namespace jank::runtime return {}; } - auto &tbfs(__rt_ctx->thread_binding_frames[std::this_thread::get_id()]); + auto &tbfs(runtime::context::thread_binding_frames[std::this_thread::get_id()]); if(tbfs.empty()) { return {}; From 0c6bfe16d242cda64e5f50358be3fcf3837ad2d6 Mon Sep 17 00:00:00 2001 From: jeaye Date: Wed, 5 Nov 2025 11:41:01 -0800 Subject: [PATCH 006/122] Remove BppTree It leaks, leads to premature GC, takes too long to compile, and doesn't support runtime sorting functions. We'll need a new solution. For now, we're deep copying standard containers, which isn't going to last us very long. --- .../include/cpp/jank/runtime/detail/type.hpp | 27 ++++++------------- .../jank/runtime/obj/transient_sorted_map.hpp | 3 +-- .../jank/runtime/obj/transient_sorted_set.hpp | 3 +-- compiler+runtime/include/cpp/jank/type.hpp | 2 +- .../src/cpp/jank/analyze/processor.cpp | 17 +----------- .../src/cpp/jank/runtime/detail/type.cpp | 8 ------ .../runtime/obj/persistent_sorted_map.cpp | 12 +++++---- .../runtime/obj/persistent_sorted_set.cpp | 18 +++++++------ .../jank/runtime/obj/transient_sorted_map.cpp | 15 ++++------- .../jank/runtime/obj/transient_sorted_set.cpp | 26 +++++++----------- compiler+runtime/third-party/bpptree | 1 - 11 files changed, 44 insertions(+), 88 deletions(-) delete mode 160000 compiler+runtime/third-party/bpptree diff --git a/compiler+runtime/include/cpp/jank/runtime/detail/type.hpp b/compiler+runtime/include/cpp/jank/runtime/detail/type.hpp index 8eab57d00..a115e6602 100644 --- a/compiler+runtime/include/cpp/jank/runtime/detail/type.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/detail/type.hpp @@ -8,9 +8,6 @@ #include #include -#include -#include - #include #include @@ -36,15 +33,6 @@ namespace immer jank::memory_policy>; } -namespace bpptree::detail -{ - extern template struct BppTreeSet; - extern template struct BppTreeMap; -} - namespace jank::runtime::detail { using native_persistent_vector = immer::vector; @@ -54,11 +42,10 @@ namespace jank::runtime::detail set, std::equal_to, memory_policy>; using native_transient_hash_set = native_persistent_hash_set::transient_type; - /* TODO: These BppTree types will leak until we get them GC allocated. */ + /* TODO: Bring in proper immutable sorted maps/sets. */ using native_persistent_sorted_set - = bpptree::BppTreeSet::Persistent; - using native_transient_sorted_set - = bpptree::BppTreeSet::Transient; + = std::set>; + using native_transient_sorted_set = native_persistent_sorted_set; using native_persistent_hash_map = immer::map::Persistent; - using native_transient_sorted_map - = bpptree::BppTreeMap::Transient; + = std::map>>; + using native_transient_sorted_map = native_persistent_sorted_map; /* If an object requires this in its constructor, use your runtime context to intern * it instead. */ diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp index 97e3fdcc1..5b77e1145 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp @@ -18,8 +18,7 @@ namespace jank::runtime::obj transient_sorted_map() = default; transient_sorted_map(transient_sorted_map &&) noexcept = default; transient_sorted_map(transient_sorted_map const &) = default; - transient_sorted_map(runtime::detail::native_persistent_sorted_map const &d); - transient_sorted_map(runtime::detail::native_persistent_sorted_map &&d); + transient_sorted_map(value_type const &d); transient_sorted_map(value_type &&d); static transient_sorted_map_ref empty(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp index e2d679eaf..1f05fab0b 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp @@ -18,8 +18,7 @@ namespace jank::runtime::obj transient_sorted_set() = default; transient_sorted_set(transient_sorted_set &&) noexcept = default; transient_sorted_set(transient_sorted_set const &) = default; - transient_sorted_set(runtime::detail::native_persistent_sorted_set const &d); - transient_sorted_set(runtime::detail::native_persistent_sorted_set &&d); + transient_sorted_set(value_type const &d); transient_sorted_set(value_type &&d); static transient_sorted_set_ref empty(); diff --git a/compiler+runtime/include/cpp/jank/type.hpp b/compiler+runtime/include/cpp/jank/type.hpp index dbd3eef3a..0fb35c802 100644 --- a/compiler+runtime/include/cpp/jank/type.hpp +++ b/compiler+runtime/include/cpp/jank/type.hpp @@ -43,7 +43,7 @@ namespace jank template using native_list = std::list>; template - using native_map = std::map>>; + using native_map = std::map, native_allocator>>; template using native_set = std::set, native_allocator>; diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index aba6ec9af..95ddfe3ff 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -2884,27 +2884,12 @@ namespace jank::analyze /* TODO: Detect literal and act accordingly. */ return visit_map_like( [&](auto const typed_o) -> processor::expression_result { - using T = typename decltype(typed_o)::value_type; - native_vector> exprs; exprs.reserve(typed_o->data.size()); for(auto const &kv : typed_o->data) { - /* The two maps (hash and sorted) have slightly different iterators, so we need to - * pull out the entries differently. */ - object_ref first{}, second{}; - if constexpr(std::same_as) - { - auto const &entry(kv.get()); - first = entry.first; - second = entry.second; - } - else - { - first = kv.first; - second = kv.second; - } + object_ref const first{ kv.first }, second{ kv.second }; auto k_expr(analyze(first, current_frame, expression_position::value, fn_ctx, true)); if(k_expr.is_err()) diff --git a/compiler+runtime/src/cpp/jank/runtime/detail/type.cpp b/compiler+runtime/src/cpp/jank/runtime/detail/type.cpp index cd8a24c82..b8c4abafd 100644 --- a/compiler+runtime/src/cpp/jank/runtime/detail/type.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/detail/type.cpp @@ -22,11 +22,3 @@ namespace immer std::equal_to, jank::memory_policy>; } - -namespace bpptree::detail -{ - template struct BppTreeSet; - template struct BppTreeMap; -} diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp index 23fbbea2d..212a26131 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp @@ -56,9 +56,9 @@ namespace jank::runtime::obj typed_seq->to_string()) }; } auto const val(*it); - transient.insert_or_assign(key, val); + transient[key] = val; } - return transient.persistent(); + return transient; } else { @@ -100,19 +100,21 @@ namespace jank::runtime::obj bool persistent_sorted_map::contains(object_ref const key) const { - return data.find(key) != data.end(); + return data.contains(key); } persistent_sorted_map_ref persistent_sorted_map::assoc(object_ref const key, object_ref const val) const { - auto copy(data.insert_or_assign(key, val)); + auto copy(data); + copy[key] = val; return make_box(meta, std::move(copy)); } persistent_sorted_map_ref persistent_sorted_map::dissoc(object_ref const key) const { - auto copy(data.erase_key(key)); + auto copy(data); + copy.erase(key); return make_box(meta, std::move(copy)); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp index 2516fc267..283d1bef3 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp @@ -41,9 +41,9 @@ namespace jank::runtime::obj runtime::detail::native_transient_sorted_set transient; for(auto const e : make_sequence_range(typed_seq)) { - transient.insert_v(e); + transient.insert(e); } - return transient.persistent(); + return transient; }, seq)); } @@ -130,8 +130,9 @@ namespace jank::runtime::obj persistent_sorted_set_ref persistent_sorted_set::conj(object_ref const head) const { - auto set(data.insert_v(head)); - auto ret(make_box(meta, std::move(set))); + auto copy(data); + copy.insert(head); + auto ret(make_box(meta, std::move(copy))); return ret; } @@ -140,7 +141,7 @@ namespace jank::runtime::obj auto const found(data.find(o)); if(found != data.end()) { - return found.get(); + return *found; } return jank_nil; } @@ -152,13 +153,14 @@ namespace jank::runtime::obj bool persistent_sorted_set::contains(object_ref const o) const { - return data.find(o) != data.end(); + return data.contains(o); } persistent_sorted_set_ref persistent_sorted_set::disj(object_ref const o) const { - auto set(data.erase_key(o)); - auto ret(make_box(meta, std::move(set))); + auto copy(data); + copy.erase(o); + auto ret(make_box(meta, std::move(copy))); return ret; } } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp index 7fbb68553..0629d1c22 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp @@ -9,17 +9,12 @@ namespace jank::runtime::obj { - transient_sorted_map::transient_sorted_map(runtime::detail::native_persistent_sorted_map &&d) - : data{ std::move(d).transient() } - { - } - transient_sorted_map::transient_sorted_map(runtime::detail::native_persistent_sorted_map const &d) - : data{ d.transient() } + : data{ d } { } - transient_sorted_map::transient_sorted_map(runtime::detail::native_transient_sorted_map &&d) + transient_sorted_map::transient_sorted_map(runtime::detail::native_persistent_sorted_map &&d) : data{ std::move(d) } { } @@ -107,14 +102,14 @@ namespace jank::runtime::obj transient_sorted_map::assoc_in_place(object_ref const key, object_ref const val) { assert_active(); - data.insert_or_assign(key, val); + data[key] = val; return this; } transient_sorted_map_ref transient_sorted_map::dissoc_in_place(object_ref const key) { assert_active(); - data.erase_key(key); + data.erase(key); return this; } @@ -151,7 +146,7 @@ namespace jank::runtime::obj { assert_active(); active = false; - return make_box(std::move(data).persistent()); + return make_box(std::move(data)); } object_ref transient_sorted_map::call(object_ref const o) const diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp index 0e92a615a..1aa04f45b 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp @@ -6,17 +6,12 @@ namespace jank::runtime::obj { - transient_sorted_set::transient_sorted_set(runtime::detail::native_persistent_sorted_set &&d) - : data{ std::move(d).transient() } - { - } - transient_sorted_set::transient_sorted_set(runtime::detail::native_persistent_sorted_set const &d) - : data{ d.transient() } + : data{ d } { } - transient_sorted_set::transient_sorted_set(runtime::detail::native_transient_sorted_set &&d) + transient_sorted_set::transient_sorted_set(runtime::detail::native_persistent_sorted_set &&d) : data{ std::move(d) } { } @@ -64,7 +59,7 @@ namespace jank::runtime::obj transient_sorted_set_ref transient_sorted_set::conj_in_place(object_ref const elem) { assert_active(); - data.insert_v(elem); + data.insert(elem); return this; } @@ -72,7 +67,7 @@ namespace jank::runtime::obj { assert_active(); active = false; - return make_box(data.persistent()); + return make_box(data); } object_ref transient_sorted_set::call(object_ref const elem) @@ -81,7 +76,7 @@ namespace jank::runtime::obj auto const found(data.find(elem)); if(found != data.end()) { - return found.get(); + return *found; } return jank_nil; } @@ -92,7 +87,7 @@ namespace jank::runtime::obj auto const found(data.find(elem)); if(found != data.end()) { - return found.get(); + return *found; } return fallback; } @@ -109,11 +104,10 @@ namespace jank::runtime::obj object_ref transient_sorted_set::get_entry(object_ref const elem) { - auto const found = call(elem); - auto const nil(jank_nil); - if(found == nil) + auto const found{ call(elem) }; + if(found == jank_nil) { - return nil; + return found; } return make_box(std::in_place, found, found); @@ -128,7 +122,7 @@ namespace jank::runtime::obj transient_sorted_set_ref transient_sorted_set::disjoin_in_place(object_ref const elem) { assert_active(); - data.erase_key(elem); + data.erase(elem); return this; } diff --git a/compiler+runtime/third-party/bpptree b/compiler+runtime/third-party/bpptree deleted file mode 160000 index addf92b02..000000000 --- a/compiler+runtime/third-party/bpptree +++ /dev/null @@ -1 +0,0 @@ -Subproject commit addf92b029bef74ae07f4ebb7e82312a6950ae8c From c561a8533307ff51d4828ccc529064a0e8207180 Mon Sep 17 00:00:00 2001 From: jeaye Date: Wed, 5 Nov 2025 14:39:31 -0800 Subject: [PATCH 007/122] Remove direct std::set usages --- compiler+runtime/src/cpp/jank/ui/highlight.cpp | 2 +- compiler+runtime/src/cpp/jank/util/try.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/ui/highlight.cpp b/compiler+runtime/src/cpp/jank/ui/highlight.cpp index 7c70d3812..b22afcf11 100644 --- a/compiler+runtime/src/cpp/jank/ui/highlight.cpp +++ b/compiler+runtime/src/cpp/jank/ui/highlight.cpp @@ -10,7 +10,7 @@ namespace jank::ui using namespace ftxui; /* TODO: Also support core fns? */ - static std::set const specials{ + static native_set const specials{ "def", "fn*", "fn", "let*", "let", "loop*", "loop", "do", "if", "quote", "var", "try", "catch", "finally", "throw", "letfn*", }; diff --git a/compiler+runtime/src/cpp/jank/util/try.cpp b/compiler+runtime/src/cpp/jank/util/try.cpp index 0a4430917..c50e77d98 100644 --- a/compiler+runtime/src/cpp/jank/util/try.cpp +++ b/compiler+runtime/src/cpp/jank/util/try.cpp @@ -47,7 +47,7 @@ namespace jank::util * at the start/end of each stack trace. */ static bool filter_frame(cpptrace::stacktrace_frame const &frame) { - static std::set const symbols_to_ignore{ + static native_set const symbols_to_ignore{ /* (Top) Linux exception pipework. */ "get_adjusted_ptr", "__gxx_personality_v0", From c7e6d39d7a4900def1fc5597bc29fdf9dc9ad7f7 Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 6 Nov 2025 12:46:49 -0800 Subject: [PATCH 008/122] Hack in some cpp gen fixes --- .../jank/runtime/obj/persistent_hash_map.hpp | 6 +- .../include/cpp/jank/runtime/oref.hpp | 9 +- .../src/cpp/jank/analyze/processor.cpp | 2 +- .../src/cpp/jank/codegen/processor.cpp | 116 +++++++++++++----- .../jank/runtime/obj/persistent_hash_map.cpp | 6 + 5 files changed, 103 insertions(+), 36 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp index 770ac4542..b511a8ecd 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp @@ -48,11 +48,7 @@ namespace jank::runtime::obj this->meta = meta; } - static persistent_hash_map_ref empty() - { - static auto const ret(make_box()); - return ret; - } + static persistent_hash_map_ref empty(); using base_persistent_map::base_persistent_map; diff --git a/compiler+runtime/include/cpp/jank/runtime/oref.hpp b/compiler+runtime/include/cpp/jank/runtime/oref.hpp index 5c1f24e9e..9b09341c5 100644 --- a/compiler+runtime/include/cpp/jank/runtime/oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/oref.hpp @@ -100,6 +100,14 @@ namespace jank::runtime constexpr oref &operator=(oref const &rhs) noexcept = default; constexpr oref &operator=(oref &&rhs) noexcept = default; + template + requires behavior::object_like + constexpr oref &operator=(oref const &rhs) noexcept + { + data = &rhs->base; + return *this; + } + constexpr bool operator==(oref const &rhs) const noexcept { return data == rhs.data; @@ -499,5 +507,4 @@ namespace jank::runtime { return static_cast(ptr.data); } - } diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index b219a91ee..d47c5484b 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -3597,7 +3597,7 @@ namespace jank::analyze for(usize i{}; i < arg_count; ++i, it = it.rest()) { auto arg_expr{ - analyze(it.first().unwrap(), current_frame, expression_position::value, fn_ctx, needs_box) + analyze(it.first().unwrap(), current_frame, expression_position::value, fn_ctx, true) }; if(arg_expr.is_err()) { diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 6fba00c93..c01fd29e1 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -347,7 +347,7 @@ namespace jank::codegen static jtl::immutable_string boxed_local_name(jtl::immutable_string const &local_name) { - return local_name + "__boxed"; + return local_name; // + "__boxed"; } } @@ -399,20 +399,21 @@ namespace jank::codegen } } - jtl::immutable_string handle::str(bool const needs_box) const + jtl::immutable_string handle::str([[maybe_unused]] bool const needs_box) const { - if(needs_box) - { - if(boxed_name.empty()) - { - throw std::runtime_error{ util::format("Missing boxed name for handle {}", unboxed_name) }; - } - return boxed_name; - } - else - { - return unboxed_name; - } + return boxed_name; + //if(needs_box) + //{ + // if(boxed_name.empty()) + // { + // throw std::runtime_error{ util::format("Missing boxed name for handle {}", unboxed_name) }; + // } + // return boxed_name; + //} + //else + //{ + // return unboxed_name; + //} } processor::processor(analyze::expr::function_ref const expr, @@ -1296,12 +1297,40 @@ namespace jank::codegen } auto arg_tmp_it(arg_tmps.begin()); - for(auto const ¶m : fn_arity.params) + if(expr->loop_target.is_some()) { - util::format_to(body_buffer, "{} = {};", runtime::munge(param->name), arg_tmp_it->str(true)); - ++arg_tmp_it; + auto const let{ expr->loop_target.unwrap() }; + for(usize i{}; i < expr->arg_exprs.size(); ++i) + { + auto const &pair{ let->pairs[i] }; + auto const local(expr->frame->find_local_or_capture(pair.first)); + if(local.is_none()) + { + throw std::runtime_error{ util::format("ICE: unable to find local: {}", + pair.first->to_string()) }; + } + + auto const &munged_name(runtime::munge(local.unwrap().binding->native_name)); + + util::format_to(body_buffer, "{} = {};", munged_name, arg_tmp_it->str(true)); + ++arg_tmp_it; + } + + util::format_to(body_buffer, "continue;"); + } + else + { + for(auto const ¶m : fn_arity.params) + { + util::format_to(body_buffer, + "{} = {};", + runtime::munge(param->name), + arg_tmp_it->str(true)); + ++arg_tmp_it; + } + util::format_to(body_buffer, "continue;"); } - util::format_to(body_buffer, "continue;"); + return none; } @@ -1398,21 +1427,45 @@ namespace jank::codegen auto const &val_tmp(gen(pair.second, fn_arity, pair.second->needs_box)); auto const &munged_name(runtime::munge(local.unwrap().binding->native_name)); + /* Every binding is wrapped in its own scope, to allow shadowing. * * Also, bindings are references to their value expression, rather than a copy. * This is important for C++ interop, since the we don't want to, and we may not - * be able to, just copy stack-allocated C++ objects around willy nillly. */ - util::format_to(body_buffer, "{ auto &&{}({}); ", munged_name, val_tmp.unwrap().str(false)); - - auto const binding(local.unwrap().binding); - if(!binding->needs_box && binding->has_boxed_usage) + * be able to, just copy stack-allocated C++ objects around willy nilly. */ + if(expr->is_loop) { - util::format_to(body_buffer, - "auto const {}({});", - detail::boxed_local_name(munged_name), - val_tmp.unwrap().str(true)); + auto const local_type{ cpp_util::expression_type(pair.second) }; + if(cpp_util::is_any_object(local_type)) + { + util::format_to(body_buffer, + "{ object_ref {}({}); ", + munged_name, + val_tmp.unwrap().str(true)); + } + else + { + util::format_to(body_buffer, "{ auto {}({}); ", munged_name, val_tmp.unwrap().str(true)); + } } + else + { + util::format_to(body_buffer, "{ auto &&{}({}); ", munged_name, val_tmp.unwrap().str(false)); + } + + //auto const binding(local.unwrap().binding); + //if(!binding->needs_box && binding->has_boxed_usage) + //{ + // util::format_to(body_buffer, + // "auto const {}({});", + // detail::boxed_local_name(munged_name), + // val_tmp.unwrap().str(true)); + //} + } + + if(expr->is_loop) + { + util::format_to(body_buffer, "while(true){"); } for(auto it(expr->body->values.begin()); it != expr->body->values.end();) @@ -1442,6 +1495,11 @@ namespace jank::codegen util::format_to(body_buffer, "}"); } + if(expr->is_loop) + { + util::format_to(body_buffer, "}"); + } + if(expr->needs_box) { util::format_to(body_buffer, "}"); @@ -1727,7 +1785,7 @@ namespace jank::codegen arg_tmps.reserve(expr->arg_exprs.size()); for(auto const &arg_expr : expr->arg_exprs) { - arg_tmps.emplace_back(gen(arg_expr, arity, false).unwrap()); + arg_tmps.emplace_back(gen(arg_expr, arity, true).unwrap()); } util::format_to(body_buffer, @@ -1742,7 +1800,7 @@ namespace jank::codegen { util::format_to(body_buffer, ", "); } - util::format_to(body_buffer, "{}", arg_tmp.str(false)); + util::format_to(body_buffer, "{}", arg_tmp.str(true)); need_comma = true; } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp index 406a1deec..793e95923 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp @@ -40,6 +40,12 @@ namespace jank::runtime::obj { } + persistent_hash_map_ref persistent_hash_map::empty() + { + static auto const ret(make_box()); + return ret; + } + persistent_hash_map_ref persistent_hash_map::create_from_seq(object_ref const seq) { return make_box(visit_seqable( From 5679cf84761cf8f7562db7c6d0381b815c481db4 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 11 Nov 2025 09:54:50 -0800 Subject: [PATCH 009/122] Just adding everything so I can have it on my mac --- .gitignore | 1 - compiler+runtime/cmake/dependency/bdwgc.cmake | 6 +- compiler+runtime/cmake/summary.cmake | 1 + .../include/cpp/jank/analyze/cpp_util.hpp | 1 + .../include/cpp/jank/codegen/processor.hpp | 103 +-- .../include/cpp/jank/util/cli.hpp | 2 +- .../src/cpp/jank/analyze/cpp_util.cpp | 14 + .../src/cpp/jank/codegen/llvm_processor.cpp | 1 + .../src/cpp/jank/codegen/processor.cpp | 803 +++++------------- compiler+runtime/src/cpp/jank/evaluate.cpp | 2 +- compiler+runtime/src/cpp/jank/util/cli.cpp | 6 +- .../src/cpp/jtl/string_builder.cpp | 9 +- 12 files changed, 271 insertions(+), 678 deletions(-) diff --git a/.gitignore b/.gitignore index 66bce157b..454712591 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,6 @@ a.out .jank-repl-history .envrc .direnv -/notes # Vim files /.ycm_extra_conf.py* diff --git a/compiler+runtime/cmake/dependency/bdwgc.cmake b/compiler+runtime/cmake/dependency/bdwgc.cmake index a0b897c78..034bab9c6 100644 --- a/compiler+runtime/cmake/dependency/bdwgc.cmake +++ b/compiler+runtime/cmake/dependency/bdwgc.cmake @@ -2,13 +2,14 @@ set(CMAKE_C_FLAGS_OLD "${CMAKE_C_FLAGS}") set(CMAKE_CXX_FLAGS_OLD "${CMAKE_CXX_FLAGS}") set(BUILD_SHARED_LIBS_OLD ${BUILD_SHARED_LIBS}) set(CMAKE_CXX_CLANG_TIDY_OLD ${CMAKE_CXX_CLANG_TIDY}) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w -DREDIRECT_MALLOC=GC_malloc_uncollectable") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w -DREDIRECT_MALLOC=GC_malloc_uncollectable") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w -DREDIRECT_MALLOC=GC_malloc_uncollectable -DREDIR_MALLOC_AND_LINUX_THREADS") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w -DREDIRECT_MALLOC=GC_malloc_uncollectable -DREDIR_MALLOC_AND_LINUX_THREADS") set(BUILD_SHARED_LIBS OFF) set(CMAKE_CXX_CLANG_TIDY "") set(enable_cplusplus ON CACHE BOOL "Enable C++") set(build_cord OFF CACHE BOOL "Build cord") set(enable_docs OFF CACHE BOOL "Enable docs") + set(enable_threads ON CACHE BOOL "Enable multi-threading support") set(enable_large_config ON CACHE BOOL "Optimize for large heap or root set") set(enable_throw_bad_alloc_library ON CACHE BOOL "Enable C++ gctba library build") set(enable_gc_debug OFF CACHE BOOL "Support for pointer back-tracing") @@ -24,6 +25,7 @@ set(CMAKE_CXX_CLANG_TIDY_OLD ${CMAKE_CXX_CLANG_TIDY}) unset(enable_cplusplus) unset(build_cord) unset(enable_docs) + unset(enable_threads) unset(enable_large_config) unset(enable_throw_bad_alloc_library) unset(enable_gc_debug) diff --git a/compiler+runtime/cmake/summary.cmake b/compiler+runtime/cmake/summary.cmake index d5000b845..8477b6e01 100644 --- a/compiler+runtime/cmake/summary.cmake +++ b/compiler+runtime/cmake/summary.cmake @@ -11,6 +11,7 @@ jank_message("│ jank analyze : ${jank_analyze}") jank_message("│ jank sanitize : ${jank_sanitize}") jank_message("│ jank unity build : ${jank_unity_build}") jank_message("│ jank resource dir : ${jank_resource_dir}") +jank_message("│ jank debug gc : ${jank_debug_gc}") jank_message("│ clang version : ${LLVM_PACKAGE_VERSION}") jank_message("│ clang prefix : ${CLANG_INSTALL_PREFIX}") jank_message("│ clang resource dir : ${clang_resource_dir}") diff --git a/compiler+runtime/include/cpp/jank/analyze/cpp_util.hpp b/compiler+runtime/include/cpp/jank/analyze/cpp_util.hpp index 8cd03e655..9d8ec82ac 100644 --- a/compiler+runtime/include/cpp/jank/analyze/cpp_util.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/cpp_util.hpp @@ -28,6 +28,7 @@ namespace jank::analyze::cpp_util native_vector> find_adl_scopes(native_vector> const &starters); jtl::immutable_string get_qualified_name(jtl::ptr scope); + jtl::immutable_string get_qualified_type_name(jtl::ptr type); void register_rtti(jtl::ptr type); jtl::ptr expression_type(expression_ref expr); diff --git a/compiler+runtime/include/cpp/jank/codegen/processor.hpp b/compiler+runtime/include/cpp/jank/codegen/processor.hpp index 048215b59..f3f73d4eb 100644 --- a/compiler+runtime/include/cpp/jank/codegen/processor.hpp +++ b/compiler+runtime/include/cpp/jank/codegen/processor.hpp @@ -92,104 +92,69 @@ namespace jank::codegen processor(processor const &) = delete; processor(processor &&) noexcept = delete; + jtl::option gen(analyze::expression_ref const, analyze::expr::function_arity const &); + jtl::option gen(analyze::expr::def_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expression_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::var_deref_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::def_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::var_ref_ref const, analyze::expr::function_arity const &); + jtl::option gen(analyze::expr::call_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::var_deref_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::primitive_literal_ref const, analyze::expr::function_arity const &); + jtl::option gen(analyze::expr::vector_ref const, analyze::expr::function_arity const &); + jtl::option gen(analyze::expr::map_ref const, analyze::expr::function_arity const &); + jtl::option gen(analyze::expr::set_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::var_ref_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::local_reference_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::call_ref const, analyze::expr::function_arity const &, bool box_needed); - jtl::option gen(analyze::expr::primitive_literal_ref const, - analyze::expr::function_arity const &, - bool box_needed); + gen(analyze::expr::function_ref const, analyze::expr::function_arity const &); + jtl::option gen(analyze::expr::recur_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::vector_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::recursion_reference_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::map_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::named_recursion_ref const, analyze::expr::function_arity const &); + jtl::option gen(analyze::expr::let_ref const, analyze::expr::function_arity const &); + jtl::option gen(analyze::expr::letfn_ref const, analyze::expr::function_arity const &); + jtl::option gen(analyze::expr::do_ref const, analyze::expr::function_arity const &); + jtl::option gen(analyze::expr::if_ref const, analyze::expr::function_arity const &); + jtl::option gen(analyze::expr::throw_ref const, analyze::expr::function_arity const &); + jtl::option gen(analyze::expr::try_ref const, analyze::expr::function_arity const &); + jtl::option gen(analyze::expr::case_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::set_ref const, analyze::expr::function_arity const &, bool box_needed); - jtl::option gen(analyze::expr::local_reference_ref const, - analyze::expr::function_arity const &, - bool box_needed); + gen(analyze::expr::cpp_raw_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::function_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::cpp_type_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::recur_ref const, analyze::expr::function_arity const &, bool box_needed); - jtl::option gen(analyze::expr::recursion_reference_ref const, - analyze::expr::function_arity const &, - bool box_needed); - jtl::option gen(analyze::expr::named_recursion_ref const, - analyze::expr::function_arity const &, - bool box_needed); + gen(analyze::expr::cpp_value_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::let_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::cpp_cast_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::letfn_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::cpp_call_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::do_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::cpp_constructor_call_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::if_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::cpp_member_call_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::throw_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::cpp_member_access_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::try_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::cpp_builtin_operator_call_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::case_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::cpp_box_ref const, analyze::expr::function_arity const &); jtl::option - gen(analyze::expr::cpp_raw_ref const, analyze::expr::function_arity const &, bool box_needed); - jtl::option - gen(analyze::expr::cpp_type_ref const, analyze::expr::function_arity const &, bool box_needed); - jtl::option - gen(analyze::expr::cpp_value_ref const, analyze::expr::function_arity const &, bool box_needed); - jtl::option - gen(analyze::expr::cpp_cast_ref const, analyze::expr::function_arity const &, bool box_needed); - jtl::option - gen(analyze::expr::cpp_call_ref const, analyze::expr::function_arity const &, bool box_needed); - jtl::option gen(analyze::expr::cpp_constructor_call_ref const, - analyze::expr::function_arity const &, - bool box_needed); - jtl::option gen(analyze::expr::cpp_member_call_ref const, - analyze::expr::function_arity const &, - bool box_needed); - jtl::option gen(analyze::expr::cpp_member_access_ref const, - analyze::expr::function_arity const &, - bool box_needed); - jtl::option gen(analyze::expr::cpp_builtin_operator_call_ref const, - analyze::expr::function_arity const &, - bool box_needed); - jtl::option - gen(analyze::expr::cpp_box_ref const, analyze::expr::function_arity const &, bool box_needed); - jtl::option - gen(analyze::expr::cpp_unbox_ref const, analyze::expr::function_arity const &, bool box_needed); + gen(analyze::expr::cpp_unbox_ref const, analyze::expr::function_arity const &); jtl::immutable_string declaration_str(); void build_header(); void build_body(); void build_footer(); - jtl::immutable_string expression_str(bool box_needed); + jtl::immutable_string expression_str(); jtl::immutable_string module_init_str(jtl::immutable_string const &module); - void format_elided_var(jtl::immutable_string const &start, - jtl::immutable_string const &end, - jtl::immutable_string const &ret_tmp, - native_vector const &arg_exprs, - analyze::expr::function_arity const &fn_arity, - bool arg_box_needed, - bool ret_box_needed); - void format_direct_call(jtl::immutable_string const &source_tmp, - jtl::immutable_string const &ret_tmp, - native_vector const &arg_exprs, - analyze::expr::function_arity const &fn_arity, - bool arg_box_needed); void format_dynamic_call(jtl::immutable_string const &source_tmp, jtl::immutable_string const &ret_tmp, native_vector const &arg_exprs, - analyze::expr::function_arity const &fn_arity, - bool arg_box_needed); + analyze::expr::function_arity const &fn_arity); analyze::expr::function_ref root_fn; jtl::immutable_string module; diff --git a/compiler+runtime/include/cpp/jank/util/cli.hpp b/compiler+runtime/include/cpp/jank/util/cli.hpp index 8e792b4eb..defa3e09a 100644 --- a/compiler+runtime/include/cpp/jank/util/cli.hpp +++ b/compiler+runtime/include/cpp/jank/util/cli.hpp @@ -29,7 +29,7 @@ namespace jank::util::cli bool profiler_enabled{}; bool perf_profiling_enabled{}; bool gc_incremental{}; - codegen_type codegen{ codegen_type::llvm_ir }; + codegen_type codegen{ codegen_type::cpp }; /* Native dependencies. */ native_vector include_dirs; diff --git a/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp b/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp index aac12ebaa..fc08303c9 100644 --- a/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp @@ -292,6 +292,20 @@ namespace jank::analyze::cpp_util return res; } + jtl::immutable_string get_qualified_type_name(jtl::ptr const type) + { + if(auto const scope{ Cpp::GetScopeFromType(type) }; scope) + { + auto name{ get_qualified_name(scope) }; + if(Cpp::IsPointerType(type)) + { + name = name + "*"; + } + return name; + } + return Cpp::GetTypeAsString(type); + } + /* This is a quick and dirty helper to get the RTTI for a given QualType. We need * this for exception catching. */ void register_rtti(jtl::ptr const type) diff --git a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp index d60e82064..4266f59c2 100644 --- a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp @@ -729,6 +729,7 @@ namespace jank::codegen jtl::string_result llvm_processor::impl::gen() { + throw "no IR gen allowed!"; profile::timer const timer{ "ir gen" }; if(target != compilation_target::function) { diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index c01fd29e1..d7244e8a7 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -216,6 +216,12 @@ namespace jank::codegen typed_o->sym->ns, typed_o->sym->name); } + else if constexpr(std::same_as) + { + util::format_to(buffer, + R"(jank::runtime::make_box({}))", + typed_o->to_code_string().substr(1)); + } else if constexpr(std::same_as) { util::format_to(buffer, @@ -427,18 +433,16 @@ namespace jank::codegen assert(root_fn->frame.data); } - jtl::option processor::gen(analyze::expression_ref const ex, - analyze::expr::function_arity const &fn_arity, - bool const box_needed) + jtl::option + processor::gen(analyze::expression_ref const ex, analyze::expr::function_arity const &fn_arity) { jtl::option ret; - visit_expr([&, this](auto const typed_ex) { ret = gen(typed_ex, fn_arity, box_needed); }, ex); + visit_expr([&, this](auto const typed_ex) { ret = gen(typed_ex, fn_arity); }, ex); return ret; } - jtl::option processor::gen(analyze::expr::def_ref const expr, - analyze::expr::function_arity const &fn_arity, - bool const) + jtl::option + processor::gen(analyze::expr::def_ref const expr, analyze::expr::function_arity const &fn_arity) { auto const &var(expr->frame->find_lifted_var(expr->name).unwrap().get()); auto const &munged_name(runtime::munge(var.native_name)); @@ -469,7 +473,7 @@ namespace jank::codegen } } - auto const val(gen(expr->value.unwrap(), fn_arity, true).unwrap()); + auto const val(gen(expr->value.unwrap(), fn_arity).unwrap()); switch(expr->position) { case analyze::expression_position::value: @@ -521,9 +525,8 @@ namespace jank::codegen } } - jtl::option processor::gen(analyze::expr::var_deref_ref const expr, - analyze::expr::function_arity const &, - bool const) + jtl::option + processor::gen(analyze::expr::var_deref_ref const expr, analyze::expr::function_arity const &) { auto const &var(expr->frame->find_lifted_var(expr->qualified_name).unwrap().get()); switch(expr->position) @@ -541,9 +544,8 @@ namespace jank::codegen } } - jtl::option processor::gen(analyze::expr::var_ref_ref const expr, - analyze::expr::function_arity const &, - bool const) + jtl::option + processor::gen(analyze::expr::var_ref_ref const expr, analyze::expr::function_arity const &) { auto const &var(expr->frame->find_lifted_var(expr->qualified_name).unwrap().get()); switch(expr->position) @@ -561,74 +563,10 @@ namespace jank::codegen } } - void processor::format_elided_var(jtl::immutable_string const &start, - jtl::immutable_string const &end, - jtl::immutable_string const &ret_tmp, - native_vector const &arg_exprs, - analyze::expr::function_arity const &fn_arity, - bool const arg_box_needed, - bool const ret_box_needed) - { - /* TODO: Assert arg count when we know it. */ - native_vector arg_tmps; - arg_tmps.reserve(arg_exprs.size()); - for(auto const &arg_expr : arg_exprs) - { - arg_tmps.emplace_back(gen(arg_expr, fn_arity, arg_box_needed).unwrap()); - } - - jtl::immutable_string ret_box; - if(ret_box_needed) - { - ret_box = "jank::runtime::make_box("; - } - util::format_to(body_buffer, "auto const {}({}{}", ret_tmp, ret_box, start); - bool need_comma{}; - for(size_t i{}; i < runtime::max_params && i < arg_tmps.size(); ++i) - { - if(need_comma) - { - util::format_to(body_buffer, ", "); - } - util::format_to(body_buffer, "{}", arg_tmps[i].str(arg_box_needed)); - need_comma = true; - } - util::format_to(body_buffer, "{}{});", end, (ret_box_needed ? ")" : "")); - } - - void processor::format_direct_call(jtl::immutable_string const &source_tmp, - jtl::immutable_string const &ret_tmp, - native_vector const &arg_exprs, - analyze::expr::function_arity const &fn_arity, - bool const arg_box_needed) - { - native_vector arg_tmps; - arg_tmps.reserve(arg_exprs.size()); - for(auto const &arg_expr : arg_exprs) - { - arg_tmps.emplace_back(gen(arg_expr, fn_arity, arg_box_needed).unwrap()); - } - - util::format_to(body_buffer, "auto const {}({}.call(", ret_tmp, source_tmp); - - bool need_comma{}; - for(size_t i{}; i < runtime::max_params && i < arg_tmps.size(); ++i) - { - if(need_comma) - { - util::format_to(body_buffer, ", "); - } - util::format_to(body_buffer, "{}", arg_tmps[i].str(true)); - need_comma = true; - } - util::format_to(body_buffer, "));"); - } - void processor::format_dynamic_call(jtl::immutable_string const &source_tmp, jtl::immutable_string const &ret_tmp, native_vector const &arg_exprs, - analyze::expr::function_arity const &fn_arity, - bool const arg_box_needed) + analyze::expr::function_arity const &fn_arity) { //util::println("format_dynamic_call source {}", source_tmp); native_vector arg_tmps; @@ -637,7 +575,7 @@ namespace jank::codegen { //util::println("\tformat_dynamic_call arg {}", // runtime::to_code_string(arg_expr->to_runtime_data())); - arg_tmps.emplace_back(gen(arg_expr, fn_arity, arg_box_needed).unwrap()); + arg_tmps.emplace_back(gen(arg_expr, fn_arity).unwrap()); } util::format_to(body_buffer, @@ -663,374 +601,18 @@ namespace jank::codegen util::format_to(body_buffer, "));"); } - jtl::option processor::gen(analyze::expr::call_ref const expr, - analyze::expr::function_arity const &fn_arity, - bool const box_needed) + jtl::option + processor::gen(analyze::expr::call_ref const expr, analyze::expr::function_arity const &fn_arity) { - /* TODO: Doesn't take into account boxing. */ handle ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("call")) }; - /* Clojure's codegen actually skips vars for certain calls to clojure.core - * fns; this is not the same as direct linking, which uses `invokeStatic` - * instead. Rather, this makes calls to `get` become `RT.get`, calls to `+` become - * `Numbers.add`, and so on. We do the same thing here. */ - bool elided{}; - /* TODO: Use the actual var meta to do this, not a hard-coded set of if checks. */ - if(auto const * const ref = dynamic_cast(expr->source_expr.data)) - { - auto const &name{ ref->var->name->name }; - if(ref->var->n->name->name != "clojure.core") - { - } - else if(name == "get") - { - format_elided_var("jank::runtime::get(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - true, - false); - elided = true; - } - else if(expr->arg_exprs.empty()) - { - if(name == "rand") - { - format_elided_var("jank::runtime::rand(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - } - else if(expr->arg_exprs.size() == 1) - { - //if(name == "print") - //{ - // format_elided_var("jank::runtime::print(", - // ")", - // ret_tmp.str(false), - // expr->arg_exprs, - // fn_arity, - // true, - // false); - // elided = true; - //} - if(name == "abs") - { - format_elided_var("jank::runtime::abs(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - else if(name == "sqrt") - { - format_elided_var("jank::runtime::sqrt(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - else if(name == "int") - { - format_elided_var("jank::runtime::to_int(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - else if(name == "seq") - { - format_elided_var("jank::runtime::seq(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - true, - false); - elided = true; - } - else if(name == "fresh-seq") - { - format_elided_var("jank::runtime::fresh_seq(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - true, - false); - elided = true; - } - else if(name == "first") - { - format_elided_var("jank::runtime::first(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - true, - false); - elided = true; - } - else if(name == "next") - { - format_elided_var("jank::runtime::next(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - true, - false); - elided = true; - } - else if(name == "next-in-place") - { - format_elided_var("jank::runtime::next_in_place(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - true, - false); - elided = true; - } - else if(name == "nil?") - { - format_elided_var("jank::runtime::is_nil(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - true, - box_needed); - elided = true; - } - else if(name == "some?") - { - format_elided_var("jank::runtime::is_some(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - true, - box_needed); - elided = true; - } - } - else if(expr->arg_exprs.size() == 2) - { - if(name == "+") - { - format_elided_var("jank::runtime::add(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - else if(name == "-") - { - format_elided_var("jank::runtime::sub(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - else if(name == "*") - { - format_elided_var("jank::runtime::mul(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - else if(name == "/") - { - format_elided_var("jank::runtime::div(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - else if(name == "<") - { - format_elided_var("jank::runtime::lt(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - else if(name == "<=") - { - format_elided_var("jank::runtime::lte(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - else if(name == ">") - { - format_elided_var("jank::runtime::lt(", - ")", - ret_tmp.str(false), - { expr->arg_exprs.rbegin(), expr->arg_exprs.rend() }, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - else if(name == ">=") - { - format_elided_var("jank::runtime::lte(", - ")", - ret_tmp.str(false), - { expr->arg_exprs.rbegin(), expr->arg_exprs.rend() }, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - else if(name == "min") - { - format_elided_var("jank::runtime::min(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - else if(name == "max") - { - format_elided_var("jank::runtime::max(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - else if(name == "pow") - { - format_elided_var("jank::runtime::pow(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - false, - box_needed); - elided = true; - ret_tmp = { ret_tmp.unboxed_name, box_needed }; - } - else if(name == "conj") - { - format_elided_var("jank::runtime::conj(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - true, - false); - elided = true; - } - } - else if(expr->arg_exprs.size() == 3) - { - if(name == "assoc") - { - format_elided_var("jank::runtime::assoc(", - ")", - ret_tmp.str(false), - expr->arg_exprs, - fn_arity, - true, - false); - elided = true; - } - } - } - else if(auto const * const fn = dynamic_cast(expr->source_expr.data)) - { - bool variadic{}; - for(auto const &arity : fn->arities) - { - if(arity.fn_ctx->is_variadic) - { - variadic = true; - } - } - if(!variadic) - { - auto const &source_tmp(gen(expr->source_expr, fn_arity, false)); - format_direct_call(source_tmp.unwrap().str(false), - ret_tmp.str(true), - expr->arg_exprs, - fn_arity, - true); - elided = true; - } - } - - if(!elided) - { - auto const &source_tmp(gen(expr->source_expr, fn_arity, false)); - format_dynamic_call(source_tmp.unwrap().str(true), - ret_tmp.str(true), - expr->arg_exprs, - fn_arity, - true); - } + auto const &source_tmp(gen(expr->source_expr, fn_arity)); + format_dynamic_call(source_tmp.unwrap().str(true), + ret_tmp.str(true), + expr->arg_exprs, + fn_arity); if(expr->position == analyze::expression_position::tail) { - /* TODO: Box here, not in the calls above. Using false when we mean true is not good. */ - /* No need for extra boxing on this, since the boxing was done on the call above. */ util::format_to(body_buffer, "return {};", ret_tmp.str(false)); return none; } @@ -1039,8 +621,7 @@ namespace jank::codegen } jtl::option processor::gen(analyze::expr::primitive_literal_ref const expr, - analyze::expr::function_arity const &, - bool const) + analyze::expr::function_arity const &) { auto const &constant(expr->frame->find_lifted_constant(expr->data).unwrap().get()); @@ -1067,14 +648,13 @@ namespace jank::codegen } jtl::option processor::gen(analyze::expr::vector_ref const expr, - analyze::expr::function_arity const &fn_arity, - bool const) + analyze::expr::function_arity const &fn_arity) { native_vector data_tmps; data_tmps.reserve(expr->data_exprs.size()); for(auto const &data_expr : expr->data_exprs) { - data_tmps.emplace_back(gen(data_expr, fn_arity, true).unwrap()); + data_tmps.emplace_back(gen(data_expr, fn_arity).unwrap()); } auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("vec"))); @@ -1103,16 +683,15 @@ namespace jank::codegen return ret_tmp; } - jtl::option processor::gen(analyze::expr::map_ref const expr, - analyze::expr::function_arity const &fn_arity, - bool const) + jtl::option + processor::gen(analyze::expr::map_ref const expr, analyze::expr::function_arity const &fn_arity) { native_vector> data_tmps; data_tmps.reserve(expr->data_exprs.size()); for(auto const &data_expr : expr->data_exprs) { - data_tmps.emplace_back(gen(data_expr.first, fn_arity, true).unwrap(), - gen(data_expr.second, fn_arity, true).unwrap()); + data_tmps.emplace_back(gen(data_expr.first, fn_arity).unwrap(), + gen(data_expr.second, fn_arity).unwrap()); } auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("map"))); @@ -1183,15 +762,14 @@ namespace jank::codegen return ret_tmp; } - jtl::option processor::gen(analyze::expr::set_ref const expr, - analyze::expr::function_arity const &fn_arity, - bool const) + jtl::option + processor::gen(analyze::expr::set_ref const expr, analyze::expr::function_arity const &fn_arity) { native_vector data_tmps; data_tmps.reserve(expr->data_exprs.size()); for(auto const &data_expr : expr->data_exprs) { - data_tmps.emplace_back(gen(data_expr, fn_arity, true).unwrap()); + data_tmps.emplace_back(gen(data_expr, fn_arity).unwrap()); } auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("set"))); @@ -1222,8 +800,7 @@ namespace jank::codegen } jtl::option processor::gen(analyze::expr::local_reference_ref const expr, - analyze::expr::function_arity const &, - bool const) + analyze::expr::function_arity const &) { auto const munged_name(runtime::munge(expr->binding->native_name)); @@ -1252,22 +829,16 @@ namespace jank::codegen } } - jtl::option processor::gen(analyze::expr::function_ref const expr, - analyze::expr::function_arity const &, - bool const box_needed) + jtl::option + processor::gen(analyze::expr::function_ref const expr, analyze::expr::function_arity const &) { auto const compiling(truthy(__rt_ctx->compile_files_var->deref())); /* Since each codegen proc handles one callable struct, we create a new one for this fn. */ processor prc{ expr, module, - //runtime::module::nest_module(module, runtime::munge(expr->unique_name)), compiling ? compilation_target::function : compilation_target::eval }; - /* If we're compiling, we'll create a separate file for this. */ - //if(target != compilation_target::module) - { - util::format_to(deps_buffer, "{}", prc.declaration_str()); - } + util::format_to(deps_buffer, "{}", prc.declaration_str()); switch(expr->position) { @@ -1275,25 +846,24 @@ namespace jank::codegen case analyze::expression_position::value: /* TODO: Return a handle. */ { - return prc.expression_str(box_needed); + return prc.expression_str(); } case analyze::expression_position::tail: { - util::format_to(body_buffer, "return {};", prc.expression_str(box_needed)); + util::format_to(body_buffer, "return {};", prc.expression_str()); return none; } } } - jtl::option processor::gen(analyze::expr::recur_ref const expr, - analyze::expr::function_arity const &fn_arity, - bool const) + jtl::option + processor::gen(analyze::expr::recur_ref const expr, analyze::expr::function_arity const &fn_arity) { native_vector arg_tmps; arg_tmps.reserve(expr->arg_exprs.size()); for(auto const &arg_expr : expr->arg_exprs) { - arg_tmps.emplace_back(gen(arg_expr, fn_arity, true).unwrap()); + arg_tmps.emplace_back(gen(arg_expr, fn_arity).unwrap()); } auto arg_tmp_it(arg_tmps.begin()); @@ -1310,9 +880,13 @@ namespace jank::codegen pair.first->to_string()) }; } - auto const &munged_name(runtime::munge(local.unwrap().binding->native_name)); + auto const &local_name(runtime::munge(local.unwrap().binding->native_name)); + auto const &val_name(arg_tmp_it->str(true)); - util::format_to(body_buffer, "{} = {};", munged_name, arg_tmp_it->str(true)); + if(local_name != val_name) + { + util::format_to(body_buffer, "{} = {};", local_name, val_name); + } ++arg_tmp_it; } @@ -1336,8 +910,7 @@ namespace jank::codegen /* NOLINTNEXTLINE(readability-make-member-function-const): Can't be const, due to overload resolution. */ jtl::option processor::gen(analyze::expr::recursion_reference_ref const expr, - analyze::expr::function_arity const &, - bool const) + analyze::expr::function_arity const &) { if(expr->position == analyze::expression_position::tail) { @@ -1348,18 +921,16 @@ namespace jank::codegen } jtl::option processor::gen(analyze::expr::named_recursion_ref const expr, - analyze::expr::function_arity const &fn_arity, - bool const) + analyze::expr::function_arity const &fn_arity) { handle ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("named_recursion")) }; auto const &source_tmp( - gen(jtl::ref{ &expr->recursion_ref }, fn_arity, false)); + gen(jtl::ref{ &expr->recursion_ref }, fn_arity)); format_dynamic_call(source_tmp.unwrap().str(true), ret_tmp.str(true), expr->arg_exprs, - fn_arity, - true); + fn_arity); if(expr->position == analyze::expression_position::tail) { @@ -1370,9 +941,8 @@ namespace jank::codegen return ret_tmp; } - jtl::option processor::gen(analyze::expr::let_ref const expr, - analyze::expr::function_arity const &fn_arity, - bool const) + jtl::option + processor::gen(analyze::expr::let_ref const expr, analyze::expr::function_arity const &fn_arity) { handle const ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("let")), expr->needs_box }; @@ -1425,7 +995,7 @@ namespace jank::codegen pair.first->to_string()) }; } - auto const &val_tmp(gen(pair.second, fn_arity, pair.second->needs_box)); + auto const &val_tmp(gen(pair.second, fn_arity)); auto const &munged_name(runtime::munge(local.unwrap().binding->native_name)); /* Every binding is wrapped in its own scope, to allow shadowing. @@ -1470,7 +1040,7 @@ namespace jank::codegen for(auto it(expr->body->values.begin()); it != expr->body->values.end();) { - auto const &val_tmp(gen(*it, fn_arity, true)); + auto const &val_tmp(gen(*it, fn_arity)); /* We ignore all values but the last. */ if(++it == expr->body->values.end() && val_tmp.is_some()) @@ -1482,6 +1052,11 @@ namespace jank::codegen "{} = std::move({});", ret_tmp.str(true), val_tmp.unwrap().str(expr->needs_box)); + + if(expr->is_loop) + { + util::format_to(body_buffer, " break;"); + } } else { @@ -1522,19 +1097,18 @@ namespace jank::codegen } jtl::option - processor::gen(analyze::expr::letfn_ref const, analyze::expr::function_arity const &, bool const) + processor::gen(analyze::expr::letfn_ref const, analyze::expr::function_arity const &) { return none; } - jtl::option processor::gen(analyze::expr::do_ref const expr, - analyze::expr::function_arity const &arity, - bool const) + jtl::option + processor::gen(analyze::expr::do_ref const expr, analyze::expr::function_arity const &arity) { jtl::option last; for(auto const &form : expr->values) { - last = gen(form, arity, true); + last = gen(form, arity); } switch(expr->position) @@ -1559,18 +1133,17 @@ namespace jank::codegen } } - jtl::option processor::gen(analyze::expr::if_ref const expr, - analyze::expr::function_arity const &fn_arity, - bool const) + jtl::option + processor::gen(analyze::expr::if_ref const expr, analyze::expr::function_arity const &fn_arity) { /* TODO: Handle unboxed results! */ auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("if"))); util::format_to(body_buffer, "object_ref {}{ };", ret_tmp); - auto const &condition_tmp(gen(expr->condition, fn_arity, false)); + auto const &condition_tmp(gen(expr->condition, fn_arity)); util::format_to(body_buffer, "if(jank::runtime::truthy({})) {", condition_tmp.unwrap().str(false)); - auto const &then_tmp(gen(expr->then, fn_arity, true)); + auto const &then_tmp(gen(expr->then, fn_arity)); if(then_tmp.is_some()) { util::format_to(body_buffer, "{} = {}; }", ret_tmp, then_tmp.unwrap().str(expr->needs_box)); @@ -1583,7 +1156,7 @@ namespace jank::codegen if(expr->else_.is_some()) { util::format_to(body_buffer, "else {"); - auto const &else_tmp(gen(expr->else_.unwrap(), fn_arity, true)); + auto const &else_tmp(gen(expr->else_.unwrap(), fn_arity)); if(else_tmp.is_some()) { util::format_to(body_buffer, "{} = {}; }", ret_tmp, else_tmp.unwrap().str(expr->needs_box)); @@ -1603,11 +1176,10 @@ namespace jank::codegen return ret_tmp; } - jtl::option processor::gen(analyze::expr::throw_ref const expr, - analyze::expr::function_arity const &fn_arity, - bool const) + jtl::option + processor::gen(analyze::expr::throw_ref const expr, analyze::expr::function_arity const &fn_arity) { - auto const &value_tmp(gen(expr->value, fn_arity, true)); + auto const &value_tmp(gen(expr->value, fn_arity)); /* We static_cast to object_ref here, since we'll be trying to catch an object_ref in any * try/catch forms. This loses us our type info, but C++ doesn't do implicit conversions * when catching and we're not using inheritance. */ @@ -1617,9 +1189,8 @@ namespace jank::codegen return none; } - jtl::option processor::gen(analyze::expr::try_ref const expr, - analyze::expr::function_arity const &fn_arity, - bool const box_needed) + jtl::option + processor::gen(analyze::expr::try_ref const expr, analyze::expr::function_arity const &fn_arity) { auto const has_catch{ expr->catch_body.is_some() }; auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("try"))); @@ -1629,17 +1200,17 @@ namespace jank::codegen if(expr->finally_body.is_some()) { util::format_to(body_buffer, "jank::util::scope_exit const finally{ [&](){ "); - gen(expr->finally_body.unwrap(), fn_arity, box_needed); + gen(expr->finally_body.unwrap(), fn_arity); util::format_to(body_buffer, "} };"); } if(has_catch) { util::format_to(body_buffer, "try {"); - auto const &body_tmp(gen(expr->body, fn_arity, box_needed)); + auto const &body_tmp(gen(expr->body, fn_arity)); if(body_tmp.is_some()) { - util::format_to(body_buffer, "{} = {};", ret_tmp, body_tmp.unwrap().str(box_needed)); + util::format_to(body_buffer, "{} = {};", ret_tmp, body_tmp.unwrap().str(true)); } if(expr->position == analyze::expression_position::tail) { @@ -1648,20 +1219,20 @@ namespace jank::codegen util::format_to(body_buffer, "}"); /* There's a gotcha here, tied to how we throw exceptions. We're catching an object_ref, which - * means we need to be throwing an object_ref. Since we're not using inheritance, we can't - * rely on a catch-all and C++ doesn't do implicit conversions into catch types. So, if we - * throw a persistent_string_ref, for example, it will not be caught as an object_ref. - * - * We mitigate this by ensuring during the codegen for throw that we type-erase to - * an object_ref. - */ + * means we need to be throwing an object_ref. Since we're not using inheritance, we can't + * rely on a catch-all and C++ doesn't do implicit conversions into catch types. So, if we + * throw a persistent_string_ref, for example, it will not be caught as an object_ref. + * + * We mitigate this by ensuring during the codegen for throw that we type-erase to + * an object_ref. + */ util::format_to(body_buffer, "catch(jank::runtime::object_ref const {}) {", runtime::munge(expr->catch_body.unwrap().sym->name)); - auto const &catch_tmp(gen(expr->catch_body.unwrap().body, fn_arity, box_needed)); + auto const &catch_tmp(gen(expr->catch_body.unwrap().body, fn_arity)); if(catch_tmp.is_some()) { - util::format_to(body_buffer, "{} = {};", ret_tmp, catch_tmp.unwrap().str(box_needed)); + util::format_to(body_buffer, "{} = {};", ret_tmp, catch_tmp.unwrap().str(true)); } if(expr->position == analyze::expression_position::tail) { @@ -1671,10 +1242,10 @@ namespace jank::codegen } else { - auto const &body_tmp(gen(expr->body, fn_arity, box_needed)); + auto const &body_tmp(gen(expr->body, fn_arity)); if(body_tmp.is_some()) { - util::format_to(body_buffer, "{} = {};", ret_tmp, body_tmp.unwrap().str(box_needed)); + util::format_to(body_buffer, "{} = {};", ret_tmp, body_tmp.unwrap().str(true)); } if(expr->position == analyze::expression_position::tail) { @@ -1688,15 +1259,14 @@ namespace jank::codegen } jtl::option - processor::gen(analyze::expr::case_ref const, analyze::expr::function_arity const &, bool) + processor::gen(analyze::expr::case_ref const, analyze::expr::function_arity const &) { return none; } - jtl::option - processor::gen(expr::cpp_raw_ref const expr, expr::function_arity const &, bool) + jtl::option processor::gen(expr::cpp_raw_ref const expr, expr::function_arity const &) { - util::format_to(deps_buffer, "{}", expr->code); + util::format_to(deps_buffer, "{}\n", expr->code); if(expr->position == analyze::expression_position::tail) { @@ -1707,14 +1277,13 @@ namespace jank::codegen } jtl::option - processor::gen(analyze::expr::cpp_type_ref const, analyze::expr::function_arity const &, bool) + processor::gen(analyze::expr::cpp_type_ref const, analyze::expr::function_arity const &) { throw std::runtime_error{ "cpp_type has no codegen" }; } - jtl::option processor::gen(analyze::expr::cpp_value_ref const expr, - analyze::expr::function_arity const &, - bool) + jtl::option + processor::gen(analyze::expr::cpp_value_ref const expr, analyze::expr::function_arity const &) { if(expr->val_kind == expr::cpp_value::value_kind::null) { @@ -1748,20 +1317,25 @@ namespace jank::codegen return tmp; } - jtl::option processor::gen(analyze::expr::cpp_cast_ref const expr, - analyze::expr::function_arity const &arity, - bool const box_needed) + jtl::option + processor::gen(analyze::expr::cpp_cast_ref const expr, analyze::expr::function_arity const &arity) { auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("cpp_cast"))); - auto const value_tmp{ gen(expr->value_expr, arity, box_needed) }; + auto const value_tmp{ gen(expr->value_expr, arity) }; + + if(Cpp::IsVoid(expr->conversion_type)) + { + return "jank::runtime::jank_nil"; + } util::format_to( body_buffer, - "auto const {}{ jank::runtime::convert<{}>::{}({}) };", + "auto const {}{ jank::runtime::convert<{}>::{}({}{}) };", ret_tmp, - Cpp::GetTypeAsString(expr->conversion_type), + cpp_util::get_qualified_type_name(expr->conversion_type), (expr->policy == conversion_policy::into_object ? "into_object" : "from_object"), - value_tmp.unwrap().str(true)); + value_tmp.unwrap().str(true), + (expr->policy == conversion_policy::into_object ? "" : ".data")); if(expr->position == expression_position::tail) { @@ -1772,9 +1346,8 @@ namespace jank::codegen return ret_tmp; } - jtl::option processor::gen(analyze::expr::cpp_call_ref const expr, - analyze::expr::function_arity const &arity, - bool const) + jtl::option + processor::gen(analyze::expr::cpp_call_ref const expr, analyze::expr::function_arity const &arity) { if(expr->source_expr->kind == expression_kind::cpp_value) { @@ -1785,13 +1358,21 @@ namespace jank::codegen arg_tmps.reserve(expr->arg_exprs.size()); for(auto const &arg_expr : expr->arg_exprs) { - arg_tmps.emplace_back(gen(arg_expr, arity, true).unwrap()); + arg_tmps.emplace_back(gen(arg_expr, arity).unwrap()); } - util::format_to(body_buffer, - "auto const {}{ {}(", - ret_tmp, - Cpp::GetQualifiedCompleteName(source->scope)); + auto const is_void{ Cpp::IsVoid(Cpp::GetFunctionReturnType(source->scope)) }; + + if(is_void) + { + util::format_to(body_buffer, "object_ref const {};", ret_tmp); + } + else + { + util::format_to(body_buffer, "auto const &{}{ ", ret_tmp); + } + + util::format_to(body_buffer, "{}(", Cpp::GetQualifiedCompleteName(source->scope)); bool need_comma{}; for(auto const &arg_tmp : arg_tmps) @@ -1804,7 +1385,16 @@ namespace jank::codegen need_comma = true; } - util::format_to(body_buffer, ") };"); + util::format_to(body_buffer, ")"); + + if(!is_void) + { + util::format_to(body_buffer, "};"); + } + else + { + util::format_to(body_buffer, ";"); + } if(expr->position == expression_position::tail) { @@ -1822,8 +1412,7 @@ namespace jank::codegen } jtl::option processor::gen(analyze::expr::cpp_constructor_call_ref const expr, - analyze::expr::function_arity const &arity, - bool const) + analyze::expr::function_arity const &arity) { auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("cpp_ctor"))); @@ -1831,26 +1420,43 @@ namespace jank::codegen arg_tmps.reserve(expr->arg_exprs.size()); for(auto const &arg_expr : expr->arg_exprs) { - arg_tmps.emplace_back(gen(arg_expr, arity, false).unwrap()); + arg_tmps.emplace_back(gen(arg_expr, arity).unwrap()); } if(expr->arg_exprs.empty()) { - util::format_to(body_buffer, "{} {}{ };", Cpp::GetTypeAsString(expr->type), ret_tmp); + util::format_to(body_buffer, + "{} {}{ };", + cpp_util::get_qualified_type_name(expr->type), + ret_tmp); return ret_tmp; } - util::format_to(body_buffer, "{} {}( ", Cpp::GetTypeAsString(expr->type), ret_tmp); + util::format_to(body_buffer, "{} {}( ", cpp_util::get_qualified_type_name(expr->type), ret_tmp); - bool need_comma{}; - for(auto const &arg_tmp : arg_tmps) + auto const is_primitive{ cpp_util::is_primitive(expr->type) }; + auto const arg_type{ cpp_util::expression_type(expr->arg_exprs[0]) }; + auto const needs_conversion{ !Cpp::IsConstructible(expr->type, arg_type) }; + if(is_primitive && needs_conversion) { - if(need_comma) + util::format_to(body_buffer, + "jank::runtime::convert<{}>::{}({}.get())", + cpp_util::get_qualified_type_name(expr->type), + "from_object", + arg_tmps[0].str(false)); + } + else + { + bool need_comma{}; + for(auto const &arg_tmp : arg_tmps) { - util::format_to(body_buffer, ", "); + if(need_comma) + { + util::format_to(body_buffer, ", "); + } + util::format_to(body_buffer, "{}", arg_tmp.str(false)); + need_comma = true; } - util::format_to(body_buffer, "{}", arg_tmp.str(false)); - need_comma = true; } util::format_to(body_buffer, " );"); @@ -1864,8 +1470,7 @@ namespace jank::codegen } jtl::option processor::gen(analyze::expr::cpp_member_call_ref const expr, - analyze::expr::function_arity const &arity, - bool) + analyze::expr::function_arity const &arity) { auto const fn_name{ Cpp::GetName(expr->fn) }; auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string(fn_name))); @@ -1874,16 +1479,31 @@ namespace jank::codegen arg_tmps.reserve(expr->arg_exprs.size()); for(auto const &arg_expr : expr->arg_exprs) { - arg_tmps.emplace_back(gen(arg_expr, arity, false).unwrap()); + arg_tmps.emplace_back(gen(arg_expr, arity).unwrap()); } - util::format_to( - body_buffer, - "auto &&{}{ {}{}{}(", - ret_tmp, - arg_tmps[0].str(false), - (Cpp::IsPointerType(cpp_util::expression_type(expr->arg_exprs[0])) ? "->" : "."), - fn_name); + auto const is_void{ Cpp::IsVoid(Cpp::GetFunctionReturnType(expr->fn)) }; + + if(is_void) + { + util::format_to(body_buffer, "jank::runtime::object_ref {}{ };", ret_tmp); + util::format_to( + body_buffer, + "{}{}{}(", + arg_tmps[0].str(false), + (Cpp::IsPointerType(cpp_util::expression_type(expr->arg_exprs[0])) ? "->" : "."), + fn_name); + } + else + { + util::format_to( + body_buffer, + "auto &&{}{ {}{}{}(", + ret_tmp, + arg_tmps[0].str(false), + (Cpp::IsPointerType(cpp_util::expression_type(expr->arg_exprs[0])) ? "->" : "."), + fn_name); + } bool need_comma{}; for(auto it{ arg_tmps.begin() + 1 }; it != arg_tmps.end(); ++it) @@ -1896,7 +1516,14 @@ namespace jank::codegen need_comma = true; } - util::format_to(body_buffer, ") };"); + if(is_void) + { + util::format_to(body_buffer, ");"); + } + else + { + util::format_to(body_buffer, ") };"); + } if(expr->position == expression_position::tail) { @@ -1908,11 +1535,10 @@ namespace jank::codegen } jtl::option processor::gen(analyze::expr::cpp_member_access_ref const expr, - analyze::expr::function_arity const &arity, - bool) + analyze::expr::function_arity const &arity) { auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string(expr->name))); - auto obj_tmp(gen(expr->obj_expr, arity, false)); + auto obj_tmp(gen(expr->obj_expr, arity)); util::format_to(body_buffer, "auto &&{}{ {}{}{} };", @@ -1931,8 +1557,7 @@ namespace jank::codegen } jtl::option processor::gen(analyze::expr::cpp_builtin_operator_call_ref const expr, - analyze::expr::function_arity const &arity, - bool) + analyze::expr::function_arity const &arity) { auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("cpp_operator"))); @@ -1940,7 +1565,7 @@ namespace jank::codegen arg_tmps.reserve(expr->arg_exprs.size()); for(auto const &arg_expr : expr->arg_exprs) { - arg_tmps.emplace_back(gen(arg_expr, arity, false).unwrap()); + arg_tmps.emplace_back(gen(arg_expr, arity).unwrap()); } if(expr->arg_exprs.size() == 1) @@ -1970,12 +1595,11 @@ namespace jank::codegen return ret_tmp; } - jtl::option processor::gen(analyze::expr::cpp_box_ref const expr, - analyze::expr::function_arity const &arity, - bool) + jtl::option + processor::gen(analyze::expr::cpp_box_ref const expr, analyze::expr::function_arity const &arity) { auto ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("cpp_box")) }; - auto value_tmp{ gen(expr->value_expr, arity, false) }; + auto value_tmp{ gen(expr->value_expr, arity) }; util::format_to(body_buffer, "auto {}{ jank::runtime::make_box({}) };", @@ -1992,11 +1616,10 @@ namespace jank::codegen } jtl::option processor::gen(analyze::expr::cpp_unbox_ref const expr, - analyze::expr::function_arity const &arity, - bool) + analyze::expr::function_arity const &arity) { auto ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("cpp_unbox")) }; - auto value_tmp{ gen(expr->value_expr, arity, false) }; + auto value_tmp{ gen(expr->value_expr, arity) }; util::format_to(body_buffer, "auto {}{ " @@ -2267,7 +1890,7 @@ namespace jank::codegen for(auto const &form : arity.body->values) { - gen(form, arity, true); + gen(form, arity); } if(arity.body->values.empty()) @@ -2324,28 +1947,16 @@ namespace jank::codegen } } - jtl::immutable_string processor::expression_str(bool const box_needed) + jtl::immutable_string processor::expression_str() { auto const module_ns(runtime::module::module_to_native_ns(module)); if(!generated_expression) { jtl::immutable_string close = ")"; - if(box_needed) - { - util::format_to( - expression_buffer, - "jank::runtime::make_box<{}>(", - runtime::module::nest_native_ns(module_ns, runtime::munge(struct_name.name))); - } - else - { - util::format_to( - expression_buffer, - "{}{ ", - runtime::module::nest_native_ns(module_ns, runtime::munge(struct_name.name))); - close = "}"; - } + util::format_to(expression_buffer, + "jank::runtime::make_box<{}>(", + runtime::module::nest_native_ns(module_ns, runtime::munge(struct_name.name))); native_set used_captures; bool need_comma{}; diff --git a/compiler+runtime/src/cpp/jank/evaluate.cpp b/compiler+runtime/src/cpp/jank/evaluate.cpp index cfe9c7b9c..909749420 100644 --- a/compiler+runtime/src/cpp/jank/evaluate.cpp +++ b/compiler+runtime/src/cpp/jank/evaluate.cpp @@ -607,7 +607,7 @@ namespace jank::evaluate codegen::processor cg_prc{ expr, module, codegen::compilation_target::eval }; util::println("{}\n", util::format_cpp_source(cg_prc.declaration_str()).expect_ok()); __rt_ctx->jit_prc.eval_string(cg_prc.declaration_str()); - auto const expr_str{ cg_prc.expression_str(true) + ".erase()" }; + auto const expr_str{ cg_prc.expression_str() + ".erase()" }; clang::Value v; auto res( __rt_ctx->jit_prc.interpreter->ParseAndExecute({ expr_str.data(), expr_str.size() }, &v)); diff --git a/compiler+runtime/src/cpp/jank/util/cli.cpp b/compiler+runtime/src/cpp/jank/util/cli.cpp index e48405128..c68cfd118 100644 --- a/compiler+runtime/src/cpp/jank/util/cli.cpp +++ b/compiler+runtime/src/cpp/jank/util/cli.cpp @@ -47,12 +47,12 @@ namespace jank::util::cli ->check(CLI::Range(0, 3)); std::map const codegen_types{ - { "llvm_ir", codegen_type::llvm_ir }, + { "llvm-ir", codegen_type::llvm_ir }, { "cpp", codegen_type::cpp } }; cli.add_option("--codegen", opts.codegen, "The type of code generation to use.") - ->transform(CLI::CheckedTransformer(codegen_types).description("{llvm_ir,cpp}")) - ->default_str(make_default("llvm_ir")); + ->transform(CLI::CheckedTransformer(codegen_types).description("{llvm-ir,cpp}")) + ->default_str(make_default("cpp")); /* Native dependencies. */ cli.add_option("-I,--include-dir", diff --git a/compiler+runtime/src/cpp/jtl/string_builder.cpp b/compiler+runtime/src/cpp/jtl/string_builder.cpp index ef7de4a32..369ec23b4 100644 --- a/compiler+runtime/src/cpp/jtl/string_builder.cpp +++ b/compiler+runtime/src/cpp/jtl/string_builder.cpp @@ -13,15 +13,14 @@ namespace jtl using allocator_traits = std::allocator_traits; /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ - static allocator_type allocator; + //static allocator_type allocator; static void realloc(string_builder &sb, usize const required) { auto const new_capacity{ std::bit_ceil(required) }; - /* TODO: Pointer-free GC alloc. */ - auto const new_data{ allocator_traits::allocate(allocator, new_capacity) }; + auto const new_data{ reinterpret_cast(GC_malloc(new_capacity)) }; string_builder::traits_type::copy(new_data, sb.buffer, sb.pos); - allocator_traits::deallocate(allocator, sb.buffer, sb.pos); + GC_free(sb.buffer); sb.buffer = new_data; sb.capacity = new_capacity; } @@ -103,7 +102,7 @@ namespace jtl string_builder::~string_builder() { - allocator_traits::deallocate(allocator, buffer, pos); + GC_free(buffer); } string_builder &string_builder::operator()(bool const d) & From 278f7cb12b35b046282553d32b96961981e29df0 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 18 Nov 2025 10:58:05 -0800 Subject: [PATCH 010/122] Address some tidy issues --- .../src/cpp/jank/runtime/obj/transient_sorted_map.cpp | 2 +- .../src/cpp/jank/runtime/obj/transient_sorted_set.cpp | 2 +- compiler+runtime/src/cpp/jtl/string_builder.cpp | 5 +---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp index 0629d1c22..530c8e4cb 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp @@ -95,7 +95,7 @@ namespace jank::runtime::obj bool transient_sorted_map::contains(object_ref const key) const { assert_active(); - return data.find(key) != data.end(); + return data.contains(key); } transient_sorted_map_ref diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp index 1aa04f45b..cba4ce9af 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp @@ -116,7 +116,7 @@ namespace jank::runtime::obj bool transient_sorted_set::contains(object_ref const elem) const { assert_active(); - return data.find(elem) != data.end(); + return data.contains(elem); } transient_sorted_set_ref transient_sorted_set::disjoin_in_place(object_ref const elem) diff --git a/compiler+runtime/src/cpp/jtl/string_builder.cpp b/compiler+runtime/src/cpp/jtl/string_builder.cpp index 369ec23b4..3c683c534 100644 --- a/compiler+runtime/src/cpp/jtl/string_builder.cpp +++ b/compiler+runtime/src/cpp/jtl/string_builder.cpp @@ -12,13 +12,10 @@ namespace jtl using allocator_type = jank::native_allocator; using allocator_traits = std::allocator_traits; - /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ - //static allocator_type allocator; - static void realloc(string_builder &sb, usize const required) { auto const new_capacity{ std::bit_ceil(required) }; - auto const new_data{ reinterpret_cast(GC_malloc(new_capacity)) }; + auto const new_data{ reinterpret_cast(GC_malloc_atomic(new_capacity)) }; string_builder::traits_type::copy(new_data, sb.buffer, sb.pos); GC_free(sb.buffer); sb.buffer = new_data; From 69418a2eab87901218e09e673da2d3f7201ad774 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 18 Nov 2025 14:33:26 -0800 Subject: [PATCH 011/122] Generate stack save/restore during loop IR gen This addresses a GC crash we were seeing, as documented here: https://github.com/bdwgc/bdwgc/issues/800#issuecomment-3495453933 --- .../include/cpp/jank/util/cli.hpp | 15 +- .../src/cpp/jank/codegen/llvm_processor.cpp | 128 +++++++++++++----- compiler+runtime/src/cpp/jank/util/cli.cpp | 2 +- 3 files changed, 112 insertions(+), 33 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/util/cli.hpp b/compiler+runtime/include/cpp/jank/util/cli.hpp index defa3e09a..0d63837e3 100644 --- a/compiler+runtime/include/cpp/jank/util/cli.hpp +++ b/compiler+runtime/include/cpp/jank/util/cli.hpp @@ -21,6 +21,19 @@ namespace jank::util::cli cpp }; + constexpr char const *codegen_type_str(codegen_type const type) + { + switch(type) + { + case codegen_type::llvm_ir: + return "llvm-ir"; + case codegen_type::cpp: + return "cpp"; + default: + return "unknown"; + } + } + struct options { /* Runtime. */ @@ -29,7 +42,7 @@ namespace jank::util::cli bool profiler_enabled{}; bool perf_profiling_enabled{}; bool gc_incremental{}; - codegen_type codegen{ codegen_type::cpp }; + codegen_type codegen{ codegen_type::llvm_ir }; /* Native dependencies. */ native_vector include_dirs; diff --git a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp index 4266f59c2..e39af6c3b 100644 --- a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp @@ -173,6 +173,11 @@ namespace jank::codegen llvm::StructType *get_or_insert_struct_type(std::string const &name, std::vector const &fields) const; + util::scope_exit gen_stack_save(); + void gen_stack_restore(); + jtl::ptr gen_ret(jtl::ptr const value); + jtl::ptr gen_ret(); + compilation_target target{}; analyze::expr::function_ref root_fn; jtl::ptr llvm_fn{}; @@ -195,6 +200,7 @@ namespace jank::codegen * We don't use this within the current fn, but it's passed upward to * the fn gen which is above us, all the way up to the module level. */ native_unordered_map global_rtti; + native_vector> stack_saves; }; struct llvm_type_info @@ -729,7 +735,6 @@ namespace jank::codegen jtl::string_result llvm_processor::impl::gen() { - throw "no IR gen allowed!"; profile::timer const timer{ "ir gen" }; if(target != compilation_target::function) { @@ -757,7 +762,7 @@ namespace jank::codegen continue; } - ctx->builder->CreateRet(gen_global(jank_nil)); + gen_ret(gen_global(jank_nil)); } if(target != compilation_target::function) @@ -775,7 +780,7 @@ namespace jank::codegen { gen_c_string(util::format("global ctor for {}", root_fn->name)) }); } - ctx->builder->CreateRetVoid(); + gen_ret(); } /* For modules, we need to make sure to define RTTI symbols manually. Since @@ -857,7 +862,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(ref); + return gen_ret(ref); } return ref; @@ -898,7 +903,7 @@ namespace jank::codegen } if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(call); + return gen_ret(call); } return call; @@ -911,7 +916,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(var); + return gen_ret(var); } return var; @@ -988,7 +993,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(call); + return gen_ret(call); } return call; @@ -1035,7 +1040,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(ret); + return gen_ret(ret); } return ret; @@ -1062,7 +1067,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(call); + return gen_ret(call); } return call; @@ -1089,7 +1094,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(call); + return gen_ret(call); } return call; @@ -1117,7 +1122,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(call); + return gen_ret(call); } return call; @@ -1144,7 +1149,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(call); + return gen_ret(call); } return call; @@ -1161,7 +1166,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(load_if_needed(ctx, ret)); + return gen_ret(load_if_needed(ctx, ret)); } return ret; @@ -1188,7 +1193,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(fn_obj); + return gen_ret(fn_obj); } return fn_obj; @@ -1230,6 +1235,7 @@ namespace jank::codegen ctx->builder->CreateStore(store.first, store.second); } + gen_stack_restore(); return ctx->builder->CreateBr(current_loop.data); } else @@ -1279,7 +1285,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(call); + return gen_ret(call); } return call; @@ -1299,7 +1305,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(fn_obj); + return gen_ret(fn_obj); } return fn_obj; @@ -1377,7 +1383,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(call); + return gen_ret(call); } return call; @@ -1431,6 +1437,8 @@ namespace jank::codegen ctx->builder->CreateBr(loop_block); ctx->builder->SetInsertPoint(loop_block); + auto const stack_save{ gen_stack_save() }; + auto const ret(gen(expr->body, arity)); locals = std::move(old_locals); @@ -1440,6 +1448,7 @@ namespace jank::codegen auto const postloop_block(llvm::BasicBlock::Create(*llvm_ctx, "postloop", current_fn)); if(!ctx->builder->GetInsertBlock()->getTerminator()) { + gen_stack_restore(); ctx->builder->CreateBr(postloop_block); } ctx->builder->SetInsertPoint(postloop_block); @@ -1574,7 +1583,7 @@ namespace jank::codegen else_ = gen_global(jank_nil); if(expr->position == expression_position::tail) { - else_ = ctx->builder->CreateRet(else_); + else_ = gen_ret(else_); } } @@ -1648,7 +1657,7 @@ namespace jank::codegen auto const ret{ gen_global(jank_nil) }; if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(ret); + return gen_ret(ret); } return ret; } @@ -2055,7 +2064,7 @@ namespace jank::codegen if(is_return) { - ctx->builder->CreateRet(final_val); + gen_ret(final_val); } return final_val; } @@ -2142,7 +2151,7 @@ namespace jank::codegen auto const ret{ gen_global(jank_nil) }; if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(ret); + return gen_ret(ret); } return ret; } @@ -2166,7 +2175,7 @@ namespace jank::codegen ctx->builder->CreateStore(null, alloc); if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(alloc); + return gen_ret(alloc); } return alloc; } @@ -2181,7 +2190,7 @@ namespace jank::codegen ctx->builder->CreateStore(ir_val, alloc); if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(alloc); + return gen_ret(alloc); } return alloc; } @@ -2199,7 +2208,7 @@ namespace jank::codegen ctx->builder->CreateStore(ir_val, alloc); if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(alloc); + return gen_ret(alloc); } return alloc; } @@ -2227,7 +2236,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(alloc); + return gen_ret(alloc); } return alloc; @@ -2248,7 +2257,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(load_if_needed(ctx, converted)); + return gen_ret(load_if_needed(ctx, converted)); } return converted; @@ -2424,11 +2433,11 @@ namespace jank::codegen { if(is_void) { - return ctx->builder->CreateRet(gen_global(jank_nil)); + return gen_ret(gen_global(jank_nil)); } auto const ret_load{ ctx->builder->CreateLoad(ctx->builder->getPtrTy(), ret_alloc, "ret") }; - return ctx->builder->CreateRet(ret_load); + return gen_ret(ret_load); } if(is_void) @@ -2693,7 +2702,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(call); + return gen_ret(call); } return call; @@ -2720,7 +2729,7 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(call); + return gen_ret(call); } return alloc; @@ -2818,7 +2827,7 @@ namespace jank::codegen auto const ret{ gen_global(jank_nil) }; if(expr->position == expression_position::tail) { - return ctx->builder->CreateRet(ret); + return gen_ret(ret); } return ret; @@ -3723,6 +3732,63 @@ namespace jank::codegen return struct_type; } + util::scope_exit llvm_processor::impl::gen_stack_save() + { + /* In some cases, such as loops, we use LLVM's stack preservation intrinsics. + * These will help us reset the stack on each iteration so that each new alloc + * doesn't actually keep grabbing more stack space. + * + * However, there is some tricky logic in balancing each save/restore, since we + * can have multiple terminators in an IR function and we need to make sure that + * each of them gets a restore. Also, we can have nested saves and we need to + * make sure they get restored in the correct order. */ + auto const stack_ptr{ ctx->builder->CreateStackSave() }; + stack_saves.emplace_back(stack_ptr); + + /* The main logic here is to pop the back of the stack, but we add some error handling + * as well, to detect cases where we're not restoring in the correct order. */ + return { [stack_ptr, this]() { + ssize found{ -1 }; + for(ssize i{}; i != static_cast(stack_saves.size()); ++i) + { + if(stack_saves[i].data == stack_ptr) + { + found = i; + } + } + + jank_debug_assert(found == -1 || found == static_cast(stack_saves.size()) - 1); + if(found != -1) + { + stack_saves.erase(stack_saves.begin() + found); + } + } }; + } + + void llvm_processor::impl::gen_stack_restore() + { + jank_debug_assert(!stack_saves.empty()); + ctx->builder->CreateStackRestore(stack_saves.back()); + } + + jtl::ptr llvm_processor::impl::gen_ret(jtl::ptr const value) + { + for(auto it{ stack_saves.rbegin() }; it != stack_saves.rend(); ++it) + { + ctx->builder->CreateStackRestore(*it); + } + return ctx->builder->CreateRet(value); + } + + jtl::ptr llvm_processor::impl::gen_ret() + { + for(auto it{ stack_saves.rbegin() }; it != stack_saves.rend(); ++it) + { + ctx->builder->CreateStackRestore(*it); + } + return ctx->builder->CreateRetVoid(); + } + void llvm_processor::optimize() const { jtl::immutable_string_view const print_settings{ getenv("JANK_PRINT_IR") ?: "" }; diff --git a/compiler+runtime/src/cpp/jank/util/cli.cpp b/compiler+runtime/src/cpp/jank/util/cli.cpp index c68cfd118..8752374d4 100644 --- a/compiler+runtime/src/cpp/jank/util/cli.cpp +++ b/compiler+runtime/src/cpp/jank/util/cli.cpp @@ -52,7 +52,7 @@ namespace jank::util::cli }; cli.add_option("--codegen", opts.codegen, "The type of code generation to use.") ->transform(CLI::CheckedTransformer(codegen_types).description("{llvm-ir,cpp}")) - ->default_str(make_default("cpp")); + ->default_str(make_default(codegen_type_str(opts.codegen))); /* Native dependencies. */ cli.add_option("-I,--include-dir", From 746e7560b7de94c427b2677e153d8dd08dbaa4cb Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 20 Nov 2025 12:19:23 -0800 Subject: [PATCH 012/122] Fix more cppgen issues --- .../include/cpp/jank/analyze/expr/if.hpp | 1 + .../include/cpp/jank/codegen/processor.hpp | 4 + .../src/cpp/jank/analyze/cpp_util.cpp | 6 + .../src/cpp/jank/analyze/local_frame.cpp | 8 + .../src/cpp/jank/codegen/processor.cpp | 183 ++++++++++++++++-- compiler+runtime/src/cpp/jank/evaluate.cpp | 9 +- .../src/cpp/jank/runtime/obj/uuid.cpp | 2 +- .../test/jank/cpp/auto-box/pass-closure.jank | 4 +- 8 files changed, 192 insertions(+), 25 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/if.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/if.hpp index a97780514..a8636d3c8 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/if.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/if.hpp @@ -25,6 +25,7 @@ namespace jank::analyze::expr /* TODO: Rename to have _expr suffixes. */ expression_ref condition; + /* The then/else exprs are expected to have the same type. We handle this during analysis. */ expression_ref then; jtl::option else_; }; diff --git a/compiler+runtime/include/cpp/jank/codegen/processor.hpp b/compiler+runtime/include/cpp/jank/codegen/processor.hpp index f3f73d4eb..05cdb814f 100644 --- a/compiler+runtime/include/cpp/jank/codegen/processor.hpp +++ b/compiler+runtime/include/cpp/jank/codegen/processor.hpp @@ -142,6 +142,10 @@ namespace jank::codegen gen(analyze::expr::cpp_box_ref const, analyze::expr::function_arity const &); jtl::option gen(analyze::expr::cpp_unbox_ref const, analyze::expr::function_arity const &); + jtl::option + gen(analyze::expr::cpp_new_ref const, analyze::expr::function_arity const &); + jtl::option + gen(analyze::expr::cpp_delete_ref const, analyze::expr::function_arity const &); jtl::immutable_string declaration_str(); void build_header(); diff --git a/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp b/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp index fc08303c9..a16daf244 100644 --- a/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp @@ -294,6 +294,12 @@ namespace jank::analyze::cpp_util jtl::immutable_string get_qualified_type_name(jtl::ptr const type) { + if(type == untyped_object_ptr_type()) + { + return "jank::runtime::object_ref"; + } + /* TODO: Handle typed object refs, too. */ + if(auto const scope{ Cpp::GetScopeFromType(type) }; scope) { auto name{ get_qualified_name(scope) }; diff --git a/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp b/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp index d5dc397db..c3b5f4072 100644 --- a/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -103,6 +104,13 @@ namespace jank::analyze res.first->second.has_boxed_usage = true; /* To start with, we assume it's only boxed. */ res.first->second.has_unboxed_usage = false; + + /* Native values which are captured get auto-boxed, so we need to adjust the type + * of the binding. */ + if(!cpp_util::is_any_object(res.first->second.type)) + { + res.first->second.type = cpp_util::untyped_object_ptr_type(); + } } } diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index d7244e8a7..0f83ff3c2 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -34,13 +34,13 @@ * roughly this C++: * * ```c++ - * object_ref thing_result(thing->call()); - * object_ref if_result; + * object_ref thing_tmp(thing->call()); + * object_ref if_tmp; * if(foo) - * { if_result = bar; } + * { if_tmp = bar; } * else - * { if_result = spam; } - * println->call(thing_result, if_result); + * { if_tmp = spam; } + * println->call(thing_tmp, if_tmp); * ``` * * This is optimized by knowing what position every expression in, so trivial expressions used @@ -205,8 +205,8 @@ namespace jank::codegen else if constexpr(std::same_as) { util::format_to(buffer, - R"(jank::runtime::make_box({}))", - typed_o->to_code_string()); + R"(jank::runtime::make_box("{}"))", + util::escape(typed_o->to_string())); } else if constexpr(std::same_as) { @@ -220,8 +220,15 @@ namespace jank::codegen { util::format_to(buffer, R"(jank::runtime::make_box({}))", + /* We remove the # prefix here. */ typed_o->to_code_string().substr(1)); } + else if constexpr(std::same_as) + { + util::format_to(buffer, + R"(jank::runtime::make_box("{}"))", + typed_o->to_string()); + } else if constexpr(std::same_as) { util::format_to(buffer, @@ -1136,9 +1143,12 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::if_ref const expr, analyze::expr::function_arity const &fn_arity) { - /* TODO: Handle unboxed results! */ auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("if"))); - util::format_to(body_buffer, "object_ref {}{ };", ret_tmp); + auto const expr_type{ cpp_util::expression_type(expr->then) }; + util::format_to(body_buffer, + "{} {}{ };", + cpp_util::get_qualified_type_name(expr_type), + ret_tmp); auto const &condition_tmp(gen(expr->condition, fn_arity)); util::format_to(body_buffer, "if(jank::runtime::truthy({})) {", @@ -1330,12 +1340,12 @@ namespace jank::codegen util::format_to( body_buffer, - "auto const {}{ jank::runtime::convert<{}>::{}({}{}) };", + "auto const {}{ jank::runtime::convert<{}>::{}({}) };", ret_tmp, - cpp_util::get_qualified_type_name(expr->conversion_type), + cpp_util::get_qualified_type_name( + Cpp::GetTypeWithoutCv(Cpp::GetNonReferenceType(expr->conversion_type))), (expr->policy == conversion_policy::into_object ? "into_object" : "from_object"), - value_tmp.unwrap().str(true), - (expr->policy == conversion_policy::into_object ? "" : ".data")); + value_tmp.unwrap().str(true)); if(expr->position == expression_position::tail) { @@ -1406,8 +1416,59 @@ namespace jank::codegen } else { - jank_debug_assert(false); - return none; + auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("cpp_call"))); + + auto const source_tmp{ gen(expr->source_expr, arity).unwrap() }; + + native_vector arg_tmps; + arg_tmps.reserve(expr->arg_exprs.size()); + for(auto const &arg_expr : expr->arg_exprs) + { + arg_tmps.emplace_back(gen(arg_expr, arity).unwrap()); + } + + auto const is_void{ Cpp::IsVoid(expr->type) }; + + if(is_void) + { + util::format_to(body_buffer, "object_ref const {};", ret_tmp); + } + else + { + util::format_to(body_buffer, "auto const &{}{ ", ret_tmp); + } + + util::format_to(body_buffer, "{}(", source_tmp.str(true)); + + bool need_comma{}; + for(auto const &arg_tmp : arg_tmps) + { + if(need_comma) + { + util::format_to(body_buffer, ", "); + } + util::format_to(body_buffer, "{}", arg_tmp.str(true)); + need_comma = true; + } + + util::format_to(body_buffer, ")"); + + if(!is_void) + { + util::format_to(body_buffer, "};"); + } + else + { + util::format_to(body_buffer, ";"); + } + + if(expr->position == expression_position::tail) + { + util::format_to(body_buffer, "return {};", ret_tmp); + return none; + } + + return ret_tmp; } } @@ -1638,6 +1699,76 @@ namespace jank::codegen return ret_tmp; } + jtl::option + processor::gen(analyze::expr::cpp_new_ref const expr, analyze::expr::function_arity const &arity) + { + auto ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("cpp_new")) }; + auto finalizer_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("finalizer")) }; + auto value_tmp{ gen(expr->value_expr, arity) }; + + auto const type_name{ cpp_util::get_qualified_type_name(expr->type) }; + auto const needs_finalizer{ !Cpp::IsTriviallyDestructible(expr->type) }; + + if(needs_finalizer) + { + util::format_to(body_buffer, + "using T = {};\n" + "static auto const {}{ " + "[](void * const obj, void *){" + "reinterpret_cast(obj)->~T();" + "} };", + type_name, + finalizer_tmp); + } + + util::format_to(body_buffer, + "auto {}{ " + "new (GC{}) {}{ {} }" + " };", + ret_tmp, + (needs_finalizer ? ", " + finalizer_tmp : ""), + type_name, + value_tmp.unwrap().str(false)); + + if(expr->position == expression_position::tail) + { + util::format_to(body_buffer, "return {};", ret_tmp); + return none; + } + + return ret_tmp; + } + + jtl::option processor::gen(analyze::expr::cpp_delete_ref const expr, + analyze::expr::function_arity const &arity) + { + auto value_tmp{ gen(expr->value_expr, arity).unwrap() }; + auto const value_type{ Cpp::GetPointeeType(cpp_util::expression_type(expr->value_expr)) }; + auto const type_name{ cpp_util::get_qualified_type_name(value_type) }; + auto const needs_finalizer{ !Cpp::IsTriviallyDestructible(value_type) }; + + /* Calling GC_free won't trigger the finalizer. Not sure why, but it's explicitly + * documented in bdwgc. So, we'll invoke it manually if needed, prior to GC_free. */ + if(needs_finalizer) + { + util::format_to(body_buffer, + "using T = {};\n" + "{}->~T();", + type_name, + value_tmp.str(false)); + } + + util::format_to(body_buffer, "GC_free({});", value_tmp.str(false)); + + if(expr->position == expression_position::tail) + { + util::format_to(body_buffer, "return jank::runtime::jank_nil;"); + return none; + } + + return "jank::runtime::jank_nil"; + } + jtl::immutable_string processor::declaration_str() { if(!generated_declaration) @@ -1988,12 +2119,22 @@ namespace jank::codegen { auto const originating_local(root_fn->frame->find_local_or_capture(v.first)); handle const h{ originating_local.unwrap().binding }; - util::format_to(expression_buffer, - "{} {}", - (need_comma ? "," : ""), - h.str(true), - originating_local.unwrap().binding->name->to_code_string(), - originating_local.unwrap().binding->native_name); + auto const local_type{ originating_local.unwrap().binding->type }; + auto const needs_conversion{ !cpp_util::is_any_object(local_type) }; + + if(needs_conversion) + { + util::format_to(expression_buffer, + "{} jank::runtime::convert<{}>::{}({})", + (need_comma ? "," : ""), + cpp_util::get_qualified_type_name(local_type), + "into_object", + h.str(true)); + } + else + { + util::format_to(expression_buffer, "{} {}", (need_comma ? "," : ""), h.str(true)); + } } need_comma = true; } diff --git a/compiler+runtime/src/cpp/jank/evaluate.cpp b/compiler+runtime/src/cpp/jank/evaluate.cpp index 909749420..bf0abb321 100644 --- a/compiler+runtime/src/cpp/jank/evaluate.cpp +++ b/compiler+runtime/src/cpp/jank/evaluate.cpp @@ -605,7 +605,14 @@ namespace jank::evaluate else { codegen::processor cg_prc{ expr, module, codegen::compilation_target::eval }; - util::println("{}\n", util::format_cpp_source(cg_prc.declaration_str()).expect_ok()); + + /* TODO: Rename to something generic which makes sense for IR and C++ gen? */ + jtl::immutable_string_view const print_settings{ getenv("JANK_PRINT_IR") ?: "" }; + if(print_settings == "1") + { + util::println("{}\n", util::format_cpp_source(cg_prc.declaration_str()).expect_ok()); + } + __rt_ctx->jit_prc.eval_string(cg_prc.declaration_str()); auto const expr_str{ cg_prc.expression_str() + ".erase()" }; clang::Value v; diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/uuid.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/uuid.cpp index 38717e840..ef9634ebb 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/uuid.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/uuid.cpp @@ -17,7 +17,7 @@ namespace jank::runtime::obj static jtl::ref from_string(jtl::immutable_string const &s) { - auto const result = uuids::uuid::from_string(s.c_str()); + auto const result{ uuids::uuid::from_string(s.c_str()) }; if(result) { return jtl::make_ref(result.value()); diff --git a/compiler+runtime/test/jank/cpp/auto-box/pass-closure.jank b/compiler+runtime/test/jank/cpp/auto-box/pass-closure.jank index b0640ac19..a07fd8182 100644 --- a/compiler+runtime/test/jank/cpp/auto-box/pass-closure.jank +++ b/compiler+runtime/test/jank/cpp/auto-box/pass-closure.jank @@ -1,9 +1,9 @@ (let [i (cpp/int. 5) - ifn (fn* [] + ifn (fn* capture-i [] (assert (= 5 i))) _ (ifn) f (cpp/float. 5.0) - ffn (fn* [] + ffn (fn* capture-f [] (if (= 5.0 f) :success))] (ffn)) From 5025847ffad682ae0557d1cdd7552f78f5c05caa Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 20 Nov 2025 13:47:35 -0800 Subject: [PATCH 013/122] Fix some more cppgen tests --- .../src/cpp/jank/codegen/processor.cpp | 67 +++++++++++++------ 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 0f83ff3c2..d54874c8f 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -1493,34 +1493,61 @@ namespace jank::codegen return ret_tmp; } - util::format_to(body_buffer, "{} {}( ", cpp_util::get_qualified_type_name(expr->type), ret_tmp); + util::format_to(body_buffer, "{} {}{ ", cpp_util::get_qualified_type_name(expr->type), ret_tmp); - auto const is_primitive{ cpp_util::is_primitive(expr->type) }; - auto const arg_type{ cpp_util::expression_type(expr->arg_exprs[0]) }; - auto const needs_conversion{ !Cpp::IsConstructible(expr->type, arg_type) }; - if(is_primitive && needs_conversion) + if(!expr->arg_exprs.empty()) { - util::format_to(body_buffer, - "jank::runtime::convert<{}>::{}({}.get())", - cpp_util::get_qualified_type_name(expr->type), - "from_object", - arg_tmps[0].str(false)); - } - else - { - bool need_comma{}; - for(auto const &arg_tmp : arg_tmps) + auto const arg_type{ cpp_util::expression_type(expr->arg_exprs[0]) }; + bool needs_conversion{}; + jtl::immutable_string conversion_type; + if(cpp_util::is_any_object(expr->type) && !cpp_util::is_any_object(arg_type)) { - if(need_comma) + needs_conversion = true; + conversion_type = "into_object"; + } + else if(!cpp_util::is_any_object(expr->type) && cpp_util::is_any_object(arg_type)) + { + needs_conversion = true; + conversion_type = "from_object"; + } + + if(needs_conversion) + { + util::format_to(body_buffer, + "jank::runtime::convert<{}>::{}({}.get())", + cpp_util::get_qualified_type_name(expr->type), + conversion_type, + arg_tmps[0].str(false)); + } + else + { + auto const needs_static_cast{ expr->type != arg_type && expr->arg_exprs.size() == 1 }; + if(needs_static_cast) { - util::format_to(body_buffer, ", "); + util::format_to(body_buffer, + "static_cast<{}>(", + cpp_util::get_qualified_type_name(expr->type)); + } + + bool need_comma{}; + for(auto const &arg_tmp : arg_tmps) + { + if(need_comma) + { + util::format_to(body_buffer, ", "); + } + util::format_to(body_buffer, "{}", arg_tmp.str(false)); + need_comma = true; + } + + if(needs_static_cast) + { + util::format_to(body_buffer, ")"); } - util::format_to(body_buffer, "{}", arg_tmp.str(false)); - need_comma = true; } } - util::format_to(body_buffer, " );"); + util::format_to(body_buffer, " };"); if(expr->position == expression_position::tail) { From 88623e52dc3de80abbadeb95692dd3c14f94fcaf Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 20 Nov 2025 14:06:46 -0800 Subject: [PATCH 014/122] More cppgen fixes --- .../src/cpp/jank/codegen/processor.cpp | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index d54874c8f..12d38e148 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -1375,7 +1375,7 @@ namespace jank::codegen if(is_void) { - util::format_to(body_buffer, "object_ref const {};", ret_tmp); + util::format_to(body_buffer, "jank::runtime::object_ref const {};", ret_tmp); } else { @@ -1385,13 +1385,22 @@ namespace jank::codegen util::format_to(body_buffer, "{}(", Cpp::GetQualifiedCompleteName(source->scope)); bool need_comma{}; - for(auto const &arg_tmp : arg_tmps) + for(u8 arg_idx{}; arg_idx < expr->arg_exprs.size(); ++arg_idx) { + auto const arg_expr{ expr->arg_exprs[arg_idx] }; + auto const arg_type{ cpp_util::expression_type(arg_expr) }; + auto const param_type{ Cpp::GetFunctionArgType(source->scope, arg_idx) }; + auto const &arg_tmp{ arg_tmps[arg_idx] }; + if(need_comma) { util::format_to(body_buffer, ", "); } util::format_to(body_buffer, "{}", arg_tmp.str(true)); + if(Cpp::IsPointerType(param_type) && cpp_util::is_any_object(arg_type)) + { + util::format_to(body_buffer, ".erase()"); + } need_comma = true; } @@ -1431,7 +1440,7 @@ namespace jank::codegen if(is_void) { - util::format_to(body_buffer, "object_ref const {};", ret_tmp); + util::format_to(body_buffer, "jank::runtime::object_ref const {};", ret_tmp); } else { @@ -1867,20 +1876,21 @@ namespace jank::codegen } used_constants.emplace(v.second.native_name.to_hash()); + /* TODO: Typed lifted constants. */ util::format_to(header_buffer, "{} const {};", detail::gen_constant_type(v.second.data, true), runtime::munge(v.second.native_name)); - if(v.second.unboxed_native_name.is_some()) - { - util::format_to(header_buffer, - "static constexpr {} const {}{ ", - detail::gen_constant_type(v.second.data, false), - runtime::munge(v.second.unboxed_native_name.unwrap())); - detail::gen_constant(v.second.data, header_buffer, false); - util::format_to(header_buffer, "};"); - } + //if(v.second.unboxed_native_name.is_some()) + //{ + // util::format_to(header_buffer, + // "static constexpr {} const {}{ ", + // detail::gen_constant_type(v.second.data, false), + // runtime::munge(v.second.unboxed_native_name.unwrap())); + // detail::gen_constant(v.second.data, header_buffer, false); + // util::format_to(header_buffer, "};"); + //} } /* TODO: More useful types here. */ @@ -2026,7 +2036,9 @@ namespace jank::codegen if(!param_shadows_fn) { - util::format_to(body_buffer, "object_ref const {}{ this };", runtime::munge(root_fn->name)); + util::format_to(body_buffer, + "jank::runtime::object_ref const {}{ this };", + runtime::munge(root_fn->name)); } if(arity.fn_ctx->is_tail_recursive) From 05dda52db3600bd9d60ac5367545388631785d67 Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 20 Nov 2025 14:12:38 -0800 Subject: [PATCH 015/122] More cppgen fixes --- compiler+runtime/src/cpp/jank/codegen/processor.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 12d38e148..f592b8656 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -1697,11 +1697,16 @@ namespace jank::codegen { auto ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("cpp_box")) }; auto value_tmp{ gen(expr->value_expr, arity) }; + auto const value_expr_type{ cpp_util::expression_type(expr->value_expr) }; + auto const type_str{ Cpp::GetTypeAsString( + Cpp::GetCanonicalType(Cpp::GetNonReferenceType(value_expr_type))) }; - util::format_to(body_buffer, - "auto {}{ jank::runtime::make_box({}) };", - ret_tmp, - value_tmp.unwrap().str(false)); + util::format_to( + body_buffer, + "auto {}{ jank::runtime::make_box({}, \"{}\") };", + ret_tmp, + value_tmp.unwrap().str(false), + type_str); if(expr->position == expression_position::tail) { From a807c3dbad1441c9e8f2809c6fba4673afbb0190 Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 20 Nov 2025 16:49:04 -0800 Subject: [PATCH 016/122] More cppgen fixes --- .../include/cpp/jank/util/cli.hpp | 2 +- .../src/cpp/jank/codegen/processor.cpp | 37 ++++++++++++++----- .../src/cpp/jank/runtime/core/munge.cpp | 4 ++ 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/util/cli.hpp b/compiler+runtime/include/cpp/jank/util/cli.hpp index 0d63837e3..56b44ba88 100644 --- a/compiler+runtime/include/cpp/jank/util/cli.hpp +++ b/compiler+runtime/include/cpp/jank/util/cli.hpp @@ -42,7 +42,7 @@ namespace jank::util::cli bool profiler_enabled{}; bool perf_profiling_enabled{}; bool gc_incremental{}; - codegen_type codegen{ codegen_type::llvm_ir }; + codegen_type codegen{ codegen_type::cpp }; /* Native dependencies. */ native_vector include_dirs; diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index f592b8656..e302475d3 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -1335,6 +1335,11 @@ namespace jank::codegen if(Cpp::IsVoid(expr->conversion_type)) { + if(expr->position == expression_position::tail) + { + util::format_to(body_buffer, "return jank::runtime::jank_nil;"); + return none; + } return "jank::runtime::jank_nil"; } @@ -1379,7 +1384,7 @@ namespace jank::codegen } else { - util::format_to(body_buffer, "auto const &{}{ ", ret_tmp); + util::format_to(body_buffer, "auto &&{}{ ", ret_tmp); } util::format_to(body_buffer, "{}(", Cpp::GetQualifiedCompleteName(source->scope)); @@ -1397,7 +1402,7 @@ namespace jank::codegen util::format_to(body_buffer, ", "); } util::format_to(body_buffer, "{}", arg_tmp.str(true)); - if(Cpp::IsPointerType(param_type) && cpp_util::is_any_object(arg_type)) + if(param_type && Cpp::IsPointerType(param_type) && cpp_util::is_any_object(arg_type)) { util::format_to(body_buffer, ".erase()"); } @@ -1444,7 +1449,7 @@ namespace jank::codegen } else { - util::format_to(body_buffer, "auto const &{}{ ", ret_tmp); + util::format_to(body_buffer, "auto &&{}{ ", ret_tmp); } util::format_to(body_buffer, "{}(", source_tmp.str(true)); @@ -1667,16 +1672,30 @@ namespace jank::codegen if(expr->arg_exprs.size() == 1) { - util::format_to(body_buffer, - "auto {}( {}{} );", - ret_tmp, - cpp_util::operator_name(static_cast(expr->op)).unwrap(), - arg_tmps[0].str(false)); + auto const arg_type{ cpp_util::expression_type(expr->arg_exprs[0]) }; + if(Cpp::IsArrayType(Cpp::GetNonReferenceType(arg_type))) + { + util::format_to(body_buffer, + "auto &&{}( {} static_cast<{}>({}) );", + ret_tmp, + cpp_util::operator_name(static_cast(expr->op)).unwrap(), + cpp_util::get_qualified_type_name( + Cpp::GetPointerType(Cpp::GetArrayElementType(arg_type))), + arg_tmps[0].str(false)); + } + else + { + util::format_to(body_buffer, + "auto &&{}( {}{} );", + ret_tmp, + cpp_util::operator_name(static_cast(expr->op)).unwrap(), + arg_tmps[0].str(false)); + } } else { util::format_to(body_buffer, - "auto {}( {} {} {} );", + "auto &&{}( {} {} {} );", ret_tmp, arg_tmps[0].str(false), cpp_util::operator_name(static_cast(expr->op)).unwrap(), diff --git a/compiler+runtime/src/cpp/jank/runtime/core/munge.cpp b/compiler+runtime/src/cpp/jank/runtime/core/munge.cpp index 1c508e91e..449eaffa4 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/munge.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/munge.cpp @@ -28,6 +28,8 @@ namespace jank::runtime { '}', "_RBRACE_" }, { '[', "_LBRACK_" }, { ']', "_RBRACK_" }, + { '(', "_LPAREN_" }, + { ')', "_RPAREN_" }, { '/', "_SLASH_" }, { '\\', "_BSLASH_" }, { '?', "_QMARK_" } @@ -40,6 +42,8 @@ namespace jank::runtime { "_RBRACE_", '}' }, { "_LBRACK_", '[' }, { "_RBRACK_", ']' }, + { "_LPAREN_", '(' }, + { "_RPAREN_", ')' }, { "_BSLASH_", '\\' }, { "_SQUOTE_", '\'' }, { "_DQUOTE_", '"' }, From 39ed6d1a34f391dd5e084a15114bdb9a53fa68c2 Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 20 Nov 2025 16:58:15 -0800 Subject: [PATCH 017/122] More cppgen fixes --- .../src/cpp/jank/analyze/processor.cpp | 4 -- .../src/cpp/jank/codegen/processor.cpp | 63 +++++++------------ 2 files changed, 23 insertions(+), 44 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index 95900b8a8..6826c40df 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -3353,10 +3353,6 @@ namespace jank::analyze /* TODO: Error if it's static and non-primitive. */ type = Cpp::GetLValueReferenceType(type); } - if(Cpp::IsArrayType(Cpp::GetNonReferenceType(type))) - { - type = Cpp::GetPointerType(Cpp::GetArrayElementType(Cpp::GetNonReferenceType(type))); - } } else if(Cpp::IsEnumConstant(scope)) { diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index e302475d3..0c7d9ebe7 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -1002,6 +1002,7 @@ namespace jank::codegen pair.first->to_string()) }; } + auto const local_type{ cpp_util::expression_type(pair.second) }; auto const &val_tmp(gen(pair.second, fn_arity)); auto const &munged_name(runtime::munge(local.unwrap().binding->native_name)); @@ -1012,7 +1013,6 @@ namespace jank::codegen * be able to, just copy stack-allocated C++ objects around willy nilly. */ if(expr->is_loop) { - auto const local_type{ cpp_util::expression_type(pair.second) }; if(cpp_util::is_any_object(local_type)) { util::format_to(body_buffer, @@ -1027,17 +1027,24 @@ namespace jank::codegen } else { - util::format_to(body_buffer, "{ auto &&{}({}); ", munged_name, val_tmp.unwrap().str(false)); + /* Local array refs should be turned into pointers so we can work with them more easily. */ + if(Cpp::IsArrayType(Cpp::GetNonReferenceType(local_type))) + { + util::format_to(body_buffer, + "{ {} {}({}); ", + cpp_util::get_qualified_type_name(Cpp::GetPointerType( + Cpp::GetArrayElementType(Cpp::GetNonReferenceType(local_type)))), + munged_name, + val_tmp.unwrap().str(false)); + } + else + { + util::format_to(body_buffer, + "{ auto &&{}({}); ", + munged_name, + val_tmp.unwrap().str(false)); + } } - - //auto const binding(local.unwrap().binding); - //if(!binding->needs_box && binding->has_boxed_usage) - //{ - // util::format_to(body_buffer, - // "auto const {}({});", - // detail::boxed_local_name(munged_name), - // val_tmp.unwrap().str(true)); - //} } if(expr->is_loop) @@ -1672,25 +1679,11 @@ namespace jank::codegen if(expr->arg_exprs.size() == 1) { - auto const arg_type{ cpp_util::expression_type(expr->arg_exprs[0]) }; - if(Cpp::IsArrayType(Cpp::GetNonReferenceType(arg_type))) - { - util::format_to(body_buffer, - "auto &&{}( {} static_cast<{}>({}) );", - ret_tmp, - cpp_util::operator_name(static_cast(expr->op)).unwrap(), - cpp_util::get_qualified_type_name( - Cpp::GetPointerType(Cpp::GetArrayElementType(arg_type))), - arg_tmps[0].str(false)); - } - else - { - util::format_to(body_buffer, - "auto &&{}( {}{} );", - ret_tmp, - cpp_util::operator_name(static_cast(expr->op)).unwrap(), - arg_tmps[0].str(false)); - } + util::format_to(body_buffer, + "auto &&{}( {}{} );", + ret_tmp, + cpp_util::operator_name(static_cast(expr->op)).unwrap(), + arg_tmps[0].str(false)); } else { @@ -1905,16 +1898,6 @@ namespace jank::codegen "{} const {};", detail::gen_constant_type(v.second.data, true), runtime::munge(v.second.native_name)); - - //if(v.second.unboxed_native_name.is_some()) - //{ - // util::format_to(header_buffer, - // "static constexpr {} const {}{ ", - // detail::gen_constant_type(v.second.data, false), - // runtime::munge(v.second.unboxed_native_name.unwrap())); - // detail::gen_constant(v.second.data, header_buffer, false); - // util::format_to(header_buffer, "};"); - //} } /* TODO: More useful types here. */ From c571a7710c23752162614b1f4ecee444491eb0be Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 21 Nov 2025 11:18:43 -0800 Subject: [PATCH 018/122] More cppgen fixes --- compiler+runtime/include/cpp/jank/prelude.hpp | 2 ++ .../src/cpp/jank/codegen/processor.cpp | 22 +++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/prelude.hpp b/compiler+runtime/include/cpp/jank/prelude.hpp index 64789c2df..6fd3acb56 100644 --- a/compiler+runtime/include/cpp/jank/prelude.hpp +++ b/compiler+runtime/include/cpp/jank/prelude.hpp @@ -10,3 +10,5 @@ #include #include #include + +extern "C" void *jank_unbox(char const *type, void *o); diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 0c7d9ebe7..e7e4f60e5 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -1677,13 +1677,19 @@ namespace jank::codegen arg_tmps.emplace_back(gen(arg_expr, arity).unwrap()); } + auto const op_name{ cpp_util::operator_name(static_cast(expr->op)).unwrap() }; + if(expr->arg_exprs.size() == 1) + { + util::format_to(body_buffer, "auto &&{}( {}{} );", ret_tmp, op_name, arg_tmps[0].str(false)); + } + else if(op_name == "aget") { util::format_to(body_buffer, - "auto &&{}( {}{} );", + "auto &&{}( {}[{}] );", ret_tmp, - cpp_util::operator_name(static_cast(expr->op)).unwrap(), - arg_tmps[0].str(false)); + arg_tmps[0].str(false), + arg_tmps[1].str(false)); } else { @@ -1691,7 +1697,7 @@ namespace jank::codegen "auto &&{}( {} {} {} );", ret_tmp, arg_tmps[0].str(false), - cpp_util::operator_name(static_cast(expr->op)).unwrap(), + op_name, arg_tmps[1].str(false)); } @@ -1734,13 +1740,15 @@ namespace jank::codegen { auto ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("cpp_unbox")) }; auto value_tmp{ gen(expr->value_expr, arity) }; + auto const type_name{ cpp_util::get_qualified_type_name(expr->type) }; util::format_to(body_buffer, "auto {}{ " - "static_cast<{}>(jank::runtime::try_object({})-" - ">data.data) };", + "static_cast<{}>(jank_unbox(\"{}\", {}.data)" + ") };", ret_tmp, - Cpp::GetTypeAsString(expr->type), + type_name, + type_name, value_tmp.unwrap().str(false)); if(expr->position == expression_position::tail) From d4cc3aaa1d70a10f0978ea8d708d398cce917f22 Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 21 Nov 2025 11:31:49 -0800 Subject: [PATCH 019/122] Don't wrap cpp_raw during eval --- compiler+runtime/src/cpp/jank/evaluate.cpp | 3 ++- compiler+runtime/src/cpp/jank/jit/processor.cpp | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/evaluate.cpp b/compiler+runtime/src/cpp/jank/evaluate.cpp index bf0abb321..83837010f 100644 --- a/compiler+runtime/src/cpp/jank/evaluate.cpp +++ b/compiler+runtime/src/cpp/jank/evaluate.cpp @@ -723,7 +723,8 @@ namespace jank::evaluate object_ref eval(expr::cpp_raw_ref const expr) { - return dynamic_call(eval(wrap_expression(expr, "cpp_raw", {}))); + __rt_ctx->jit_prc.eval_string(expr->code); + return runtime::jank_nil; } object_ref eval(expr::cpp_type_ref const) diff --git a/compiler+runtime/src/cpp/jank/jit/processor.cpp b/compiler+runtime/src/cpp/jank/jit/processor.cpp index eebf61ffd..7030654ed 100644 --- a/compiler+runtime/src/cpp/jank/jit/processor.cpp +++ b/compiler+runtime/src/cpp/jank/jit/processor.cpp @@ -230,8 +230,11 @@ namespace jank::jit profile::timer const timer{ "jit eval_string" }; //util::println("// eval_string:\n{}\n", s); auto err(interpreter->ParseAndExecute({ s.data(), s.size() })); - /* TODO: Throw on errors. */ - llvm::logAllUnhandledErrors(std::move(err), llvm::errs(), "error: "); + if(err) + { + llvm::logAllUnhandledErrors(std::move(err), llvm::errs(), "error: "); + throw std::runtime_error{ "Failed to evaluate C++ code." }; + } register_jit_stack_frames(); } From 02032b958475e9fe05cc4b6f3c700fdc2c9bffd4 Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 21 Nov 2025 12:25:10 -0800 Subject: [PATCH 020/122] More cppgen fixes --- .../include/cpp/jank/codegen/processor.hpp | 1 + .../src/cpp/jank/codegen/processor.cpp | 105 +++++++++--------- .../pass-packing-exceeds-max-params.jank | 4 +- 3 files changed, 54 insertions(+), 56 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/codegen/processor.hpp b/compiler+runtime/include/cpp/jank/codegen/processor.hpp index 05cdb814f..a8832e187 100644 --- a/compiler+runtime/include/cpp/jank/codegen/processor.hpp +++ b/compiler+runtime/include/cpp/jank/codegen/processor.hpp @@ -101,6 +101,7 @@ namespace jank::codegen jtl::option gen(analyze::expr::call_ref const, analyze::expr::function_arity const &); jtl::option gen(analyze::expr::primitive_literal_ref const, analyze::expr::function_arity const &); + jtl::option gen(analyze::expr::list_ref const, analyze::expr::function_arity const &); jtl::option gen(analyze::expr::vector_ref const, analyze::expr::function_arity const &); jtl::option gen(analyze::expr::map_ref const, analyze::expr::function_arity const &); jtl::option gen(analyze::expr::set_ref const, analyze::expr::function_arity const &); diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index e7e4f60e5..e89b0a54e 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -589,22 +589,11 @@ namespace jank::codegen "auto const {}(jank::runtime::dynamic_call({}", ret_tmp, source_tmp); - for(size_t i{}; i < runtime::max_params && i < arg_tmps.size(); ++i) + for(size_t i{}; i < arg_tmps.size(); ++i) { util::format_to(body_buffer, ", {}", arg_tmps[i].str(true)); } - if(runtime::max_params < arg_tmps.size()) - { - util::format_to( - body_buffer, - ", jank::runtime::make_box(std::in_place"); - for(size_t i{ runtime::max_params }; i < arg_tmps.size(); ++i) - { - util::format_to(body_buffer, ", {}", arg_tmps[i].str(true)); - } - util::format_to(body_buffer, ")"); - } util::format_to(body_buffer, "));"); } @@ -654,6 +643,42 @@ namespace jank::codegen } } + jtl::option + processor::gen(analyze::expr::list_ref const expr, analyze::expr::function_arity const &fn_arity) + { + native_vector data_tmps; + data_tmps.reserve(expr->data_exprs.size()); + for(auto const &data_expr : expr->data_exprs) + { + data_tmps.emplace_back(gen(data_expr, fn_arity).unwrap()); + } + + auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("list"))); + util::format_to(body_buffer, + "auto const {}(jank::runtime::make_box(", + ret_tmp); + if(expr->meta.is_some()) + { + detail::gen_constant(expr->meta.unwrap(), body_buffer, true); + util::format_to(body_buffer, ", "); + } + util::format_to(body_buffer, "std::in_place "); + for(auto const &tmp : data_tmps) + { + util::format_to(body_buffer, ", "); + util::format_to(body_buffer, "{}", tmp.str(true)); + } + util::format_to(body_buffer, "));"); + + if(expr->position == analyze::expression_position::tail) + { + util::format_to(body_buffer, "return {};", ret_tmp); + return none; + } + + return ret_tmp; + } + jtl::option processor::gen(analyze::expr::vector_ref const expr, analyze::expr::function_arity const &fn_arity) { @@ -951,11 +976,10 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::let_ref const expr, analyze::expr::function_arity const &fn_arity) { - handle const ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("let")), - expr->needs_box }; + auto const &ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("let")) }; bool used_option{}; - if(expr->needs_box) + //if(expr->needs_box) { /* TODO: The type may not be default constructible so this may fail. We likely * want an array the same size as the desired type. When we have the last expression, @@ -972,26 +996,16 @@ namespace jank::codegen if(cpp_util::is_untyped_object(last_expr_type)) { type_name = "object_ref"; - util::format_to(body_buffer, "{} {}{ }; {", type_name, ret_tmp.str(expr->needs_box)); + util::format_to(body_buffer, "{} {}{ }; {", type_name, ret_tmp); } else { used_option = true; type_name = Cpp::GetTypeAsString(Cpp::GetNonReferenceType(last_expr_type)); /* TODO: Test for this with something non-default constructible. */ - util::format_to(body_buffer, - "jtl::option<{}> {}{ }; {", - type_name, - ret_tmp.str(expr->needs_box)); + util::format_to(body_buffer, "jtl::option<{}> {}{ }; {", type_name, ret_tmp); } } - else - { - util::format_to(body_buffer, - "auto const {}([&](){}{", - ret_tmp.str(expr->needs_box), - (expr->needs_box ? "-> object_ref" : "")); - } for(auto const &pair : expr->pairs) { @@ -1059,22 +1073,15 @@ namespace jank::codegen /* We ignore all values but the last. */ if(++it == expr->body->values.end() && val_tmp.is_some()) { - if(expr->needs_box) - { - /* The last expression tmp needs to be movable. */ - util::format_to(body_buffer, - "{} = std::move({});", - ret_tmp.str(true), - val_tmp.unwrap().str(expr->needs_box)); + /* The last expression tmp needs to be movable. */ + util::format_to(body_buffer, + "{} = std::move({});", + ret_tmp, + val_tmp.unwrap().str(expr->needs_box)); - if(expr->is_loop) - { - util::format_to(body_buffer, " break;"); - } - } - else + if(expr->is_loop) { - util::format_to(body_buffer, "return {};", val_tmp.unwrap().str(expr->needs_box)); + util::format_to(body_buffer, " break;"); } } } @@ -1089,25 +1096,15 @@ namespace jank::codegen util::format_to(body_buffer, "}"); } - if(expr->needs_box) - { - util::format_to(body_buffer, "}"); - } - else - { - util::format_to(body_buffer, "}());"); - } + util::format_to(body_buffer, "}"); if(expr->position == analyze::expression_position::tail) { - util::format_to(body_buffer, - "return {}{};", - ret_tmp.str(expr->needs_box), - (used_option ? ".unwrap()" : "")); + util::format_to(body_buffer, "return {}{};", ret_tmp, (used_option ? ".unwrap()" : "")); return none; } - return util::format("{}{}", ret_tmp.str(expr->needs_box), (used_option ? ".unwrap()" : "")); + return util::format("{}{}", ret_tmp, (used_option ? ".unwrap()" : "")); } jtl::option diff --git a/compiler+runtime/test/jank/form/fn/arity/variadic/pass-packing-exceeds-max-params.jank b/compiler+runtime/test/jank/form/fn/arity/variadic/pass-packing-exceeds-max-params.jank index 2986e57b1..eac3700fa 100644 --- a/compiler+runtime/test/jank/form/fn/arity/variadic/pass-packing-exceeds-max-params.jank +++ b/compiler+runtime/test/jank/form/fn/arity/variadic/pass-packing-exceeds-max-params.jank @@ -1,5 +1,5 @@ (def variadic - (fn* + (fn* variadic ([& args] args))) (assert (= (variadic 1 2 3 4 5 6 7 8 9) [1 2 3 4 5 6 7 8 9])) (assert (= (variadic 1 2 3 4 5 6 7 8 9 10) [1 2 3 4 5 6 7 8 9 10])) @@ -8,7 +8,7 @@ ; This will be code-generated, not evaluated. (def foo - (fn* [] + (fn* foo [] (assert (= (variadic 1 2 3 4 5 6 7 8 9 10 11) [1 2 3 4 5 6 7 8 9 10 11])) (assert (= (variadic 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15])))) (foo) From 03ab3445c26e4db8560661e892c5c79d427dda4b Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 21 Nov 2025 15:23:15 -0800 Subject: [PATCH 021/122] Implement cppgen for letfn --- .../src/cpp/jank/analyze/processor.cpp | 4 +- .../src/cpp/jank/codegen/processor.cpp | 155 +++++++++++++----- 2 files changed, 117 insertions(+), 42 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index 6826c40df..7b719cd29 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -2259,7 +2259,7 @@ namespace jank::analyze /* All bindings in a letfn appear simultaneously and may be mutually recursive. * This makes creating a letfn locals frame a bit more involved than let, where locals - * are introduced left-to-right. For example, each binding in (letfn [(a [] b) (b [] a)]) + * are introduced left-to-right. For example, each binding in (letfn [(a [] b) (b [] a)]) * requires the other to be in scope in order to be analyzed. * * We tackle this in two steps. First, we create empty local bindings for all names. @@ -2308,7 +2308,7 @@ namespace jank::analyze /* Populate the local frame we prepared for sym in the previous loop with its binding. */ auto it(ret->pairs.emplace_back(sym, fexpr)); - auto local(ret->frame->locals.find(sym)->second); + auto &local(ret->frame->locals.find(sym)->second); local.value_expr = some(it.second); local.needs_box = it.second->needs_box; } diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index e89b0a54e..f1c04f040 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -906,12 +906,6 @@ namespace jank::codegen { auto const &pair{ let->pairs[i] }; auto const local(expr->frame->find_local_or_capture(pair.first)); - if(local.is_none()) - { - throw std::runtime_error{ util::format("ICE: unable to find local: {}", - pair.first->to_string()) }; - } - auto const &local_name(runtime::munge(local.unwrap().binding->native_name)); auto const &val_name(arg_tmp_it->str(true)); @@ -979,43 +973,24 @@ namespace jank::codegen auto const &ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("let")) }; bool used_option{}; - //if(expr->needs_box) + auto const last_expr_type{ cpp_util::expression_type( + expr->body->values[expr->body->values.size() - 1]) }; + + auto const &type_name{ cpp_util::get_qualified_type_name( + Cpp::GetNonReferenceType(last_expr_type)) }; + if(cpp_util::is_any_object(last_expr_type)) { - /* TODO: The type may not be default constructible so this may fail. We likely - * want an array the same size as the desired type. When we have the last expression, - * we can then do a placement new with the move ctor. - * - * Also add a test for this. */ - auto const last_expr_type{ cpp_util::expression_type( - expr->body->values[expr->body->values.size() - 1]) }; - - jtl::immutable_string type_name; - /* In analysis, we treat untyped objects as object*, since that's easier for IR. - * However, for C++, we want to normalize that to object_ref to take full advantage - * of richer types. */ - if(cpp_util::is_untyped_object(last_expr_type)) - { - type_name = "object_ref"; - util::format_to(body_buffer, "{} {}{ }; {", type_name, ret_tmp); - } - else - { - used_option = true; - type_name = Cpp::GetTypeAsString(Cpp::GetNonReferenceType(last_expr_type)); - /* TODO: Test for this with something non-default constructible. */ - util::format_to(body_buffer, "jtl::option<{}> {}{ }; {", type_name, ret_tmp); - } + util::format_to(body_buffer, "{} {}{ }; {", type_name, ret_tmp); + } + else + { + used_option = true; + util::format_to(body_buffer, "jtl::option<{}> {}{ }; {", type_name, ret_tmp); } for(auto const &pair : expr->pairs) { auto const local(expr->frame->find_local_or_capture(pair.first)); - if(local.is_none()) - { - throw std::runtime_error{ util::format("ICE: unable to find local: {}", - pair.first->to_string()) }; - } - auto const local_type{ cpp_util::expression_type(pair.second) }; auto const &val_tmp(gen(pair.second, fn_arity)); auto const &munged_name(runtime::munge(local.unwrap().binding->native_name)); @@ -1108,9 +1083,108 @@ namespace jank::codegen } jtl::option - processor::gen(analyze::expr::letfn_ref const, analyze::expr::function_arity const &) + processor::gen(analyze::expr::letfn_ref const expr, analyze::expr::function_arity const &fn_arity) { - return none; + auto const &ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("let")) }; + bool used_option{}; + + auto const last_expr_type{ cpp_util::expression_type( + expr->body->values[expr->body->values.size() - 1]) }; + + auto const &type_name{ cpp_util::get_qualified_type_name( + Cpp::GetNonReferenceType(last_expr_type)) }; + if(cpp_util::is_any_object(last_expr_type)) + { + util::format_to(body_buffer, "{} {}{ }; {", type_name, ret_tmp); + } + else + { + used_option = true; + util::format_to(body_buffer, "jtl::option<{}> {}{ }; {", type_name, ret_tmp); + } + + /* We don't handle shadowed bindings very well, so we can run into problems where our + * codegen doesn't work. For letfn, we detect shadowed bindings and get around potential + * assignment issues by just using an object_ref. This can be removed once we + * properly give shadowed bindings individual local_binding entries or we have some other + * mechanism for tracking them. */ + bool has_shadowed_bindings{}; + native_set seen_names; + for(auto const &pair : expr->pairs) + { + auto const local(expr->frame->find_local_or_capture(pair.first)); + auto const &name{ local.unwrap().binding->native_name }; + if(seen_names.contains(name)) + { + has_shadowed_bindings = true; + break; + } + seen_names.emplace(name); + } + + for(auto const &pair : expr->pairs) + { + auto const local(expr->frame->find_local_or_capture(pair.first)); + auto const val_expr(llvm::cast(pair.second.data)); + auto const &munged_name(runtime::munge(local.unwrap().binding->native_name)); + auto const type_name{ ( + has_shadowed_bindings + ? "jank::runtime::object_ref" + : util::format("jank::runtime::oref<{}>", runtime::munge(val_expr->unique_name))) }; + util::format_to(body_buffer, "{ {} {};", type_name, munged_name); + } + + for(auto const &pair : expr->pairs) + { + auto const local(expr->frame->find_local_or_capture(pair.first)); + auto const &val_tmp(gen(pair.second, fn_arity)); + auto const &munged_name(runtime::munge(local.unwrap().binding->native_name)); + + util::format_to(body_buffer, "{} = {}; ", munged_name, val_tmp.unwrap().str(false)); + } + + for(auto const &pair : expr->pairs) + { + auto const local(expr->frame->find_local_or_capture(pair.first)); + + auto const &munged_name(runtime::munge(local.unwrap().binding->native_name)); + auto const val_expr(llvm::cast(pair.second.data)); + for(auto const &capture_pair : val_expr->captures()) + { + auto const &capture_name(runtime::munge(capture_pair.second->native_name)); + util::format_to(body_buffer, "{}->{} = {}; ", munged_name, capture_name, capture_name); + } + } + + for(auto it(expr->body->values.begin()); it != expr->body->values.end();) + { + auto const &val_tmp(gen(*it, fn_arity)); + + /* We ignore all values but the last. */ + if(++it == expr->body->values.end() && val_tmp.is_some()) + { + /* The last expression tmp needs to be movable. */ + util::format_to(body_buffer, + "{} = std::move({});", + ret_tmp, + val_tmp.unwrap().str(expr->needs_box)); + } + } + for(auto const &_ : expr->pairs) + { + static_cast(_); + util::format_to(body_buffer, "}"); + } + + util::format_to(body_buffer, "}"); + + if(expr->position == analyze::expression_position::tail) + { + util::format_to(body_buffer, "return {}{};", ret_tmp, (used_option ? ".unwrap()" : "")); + return none; + } + + return util::format("{}{}", ret_tmp, (used_option ? ".unwrap()" : "")); } jtl::option @@ -1914,8 +1988,9 @@ namespace jank::codegen } used_captures.emplace(v.first->to_hash()); + /* Captures aren't const since they could be late-assigned, in the case of a letfn. */ util::format_to(header_buffer, - "jank::runtime::object_ref const {};", + "jank::runtime::object_ref {};", runtime::munge(v.second.native_name)); } } From c5bc9efd1e090642375a5745846c76e867bf61cb Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 21 Nov 2025 18:30:10 -0800 Subject: [PATCH 022/122] Optimize core libs during phase 1 --- compiler+runtime/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index 2809c8f42..f2ade1f6f 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -888,7 +888,7 @@ add_custom_command( DEPENDS ${CMAKE_BINARY_DIR}/jank-phase-1 ${CMAKE_SOURCE_DIR}/src/jank/clojure/core.jank ${jank_incremental_pch_flag} OUTPUT ${jank_core_libraries_flag} BYPRODUCTS ${jank_clojure_core_o} - COMMAND ${CMAKE_BINARY_DIR}/jank-phase-1 compile-module -o ${jank_clojure_core_o} clojure.core + COMMAND ${CMAKE_BINARY_DIR}/jank-phase-1 compile-module -O3 -o ${jank_clojure_core_o} clojure.core COMMAND touch ${jank_core_libraries_flag} ) add_custom_target( From e026ce961076c160e517a11b1cc6cc7ce62b641a Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 21 Nov 2025 18:37:38 -0800 Subject: [PATCH 023/122] Add cppgen for case --- compiler+runtime/include/cpp/jank/prelude.hpp | 3 +- compiler+runtime/src/cpp/jank/c_api.cpp | 4 +- .../src/cpp/jank/codegen/processor.cpp | 67 ++++++++++++++++++- .../test/jank/form/case/pass-real.jank | 13 ++-- 4 files changed, 73 insertions(+), 14 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/prelude.hpp b/compiler+runtime/include/cpp/jank/prelude.hpp index 6fd3acb56..0049b7bd5 100644 --- a/compiler+runtime/include/cpp/jank/prelude.hpp +++ b/compiler+runtime/include/cpp/jank/prelude.hpp @@ -10,5 +10,4 @@ #include #include #include - -extern "C" void *jank_unbox(char const *type, void *o); +#include diff --git a/compiler+runtime/src/cpp/jank/c_api.cpp b/compiler+runtime/src/cpp/jank/c_api.cpp index 80e0e7d9b..faed7c122 100644 --- a/compiler+runtime/src/cpp/jank/c_api.cpp +++ b/compiler+runtime/src/cpp/jank/c_api.cpp @@ -940,8 +940,8 @@ extern "C" { if(o_obj->type == object_type::integer) { - /* We don't hash the integer if it's an int32 value. This is to be consistent with how keys are hashed in jank's - * case macro. */ + /* We don't hash the integer if it's within an i32 value. + * This is to be consistent with how keys are hashed in jank's case macro. */ integer = (integer >= std::numeric_limits::min() && integer <= std::numeric_limits::max()) ? integer diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index f1c04f040..8e7c2ceed 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -186,6 +186,25 @@ namespace jank::codegen "f64>({}))", typed_o->data); } + else if constexpr(std::same_as) + { + util::format_to(buffer, + "jank::runtime::make_box(\"{}\")", + typed_o->to_string()); + } + else if constexpr(std::same_as) + { + util::format_to(buffer, + "jank::runtime::make_box(\"{}\")", + typed_o->to_string()); + } + else if constexpr(std::same_as) + { + util::format_to(buffer, + "jank::runtime::obj::ratio::create({}, {})", + typed_o->data.numerator, + typed_o->data.denominator); + } else if constexpr(std::same_as) { if(typed_o->meta.is_some()) @@ -1085,7 +1104,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::letfn_ref const expr, analyze::expr::function_arity const &fn_arity) { - auto const &ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("let")) }; + auto const &ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("letfn")) }; bool used_option{}; auto const last_expr_type{ cpp_util::expression_type( @@ -1347,9 +1366,51 @@ namespace jank::codegen } jtl::option - processor::gen(analyze::expr::case_ref const, analyze::expr::function_arity const &) + processor::gen(analyze::expr::case_ref const expr, analyze::expr::function_arity const &fn_arity) { - return none; + auto const is_tail{ expr->position == analyze::expression_position::tail }; + auto const &ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("case")) }; + + util::format_to(body_buffer, "jank::runtime::object_ref {}{ };", ret_tmp); + + auto const &value_tmp{ gen(expr->value_expr, fn_arity) }; + + util::format_to(body_buffer, + "switch(jank_shift_mask_case_integer({}.erase(), {}, {})) {", + value_tmp.unwrap().str(true), + expr->shift, + expr->mask); + + jank_debug_assert(expr->keys.size() == expr->exprs.size()); + for(usize i{}; i < expr->keys.size(); ++i) + { + util::format_to(body_buffer, "case {}: {", expr->keys[i]); + + auto const &case_tmp{ gen(expr->exprs[i], fn_arity) }; + if(!is_tail) + { + util::format_to(body_buffer, "{} = {};", ret_tmp, case_tmp.unwrap().str(true)); + } + util::format_to(body_buffer, "break; }"); + } + + util::format_to(body_buffer, "default: {"); + + auto const &default_tmp{ gen(expr->default_expr, fn_arity) }; + if(!is_tail) + { + util::format_to(body_buffer, "{} = {};", ret_tmp, default_tmp.unwrap().str(true)); + } + + util::format_to(body_buffer, "} }"); + + if(is_tail) + { + util::format_to(body_buffer, "return {};", ret_tmp); + return none; + } + + return ret_tmp; } jtl::option processor::gen(expr::cpp_raw_ref const expr, expr::function_arity const &) diff --git a/compiler+runtime/test/jank/form/case/pass-real.jank b/compiler+runtime/test/jank/form/case/pass-real.jank index efb4ac9b3..4ebeabfb6 100644 --- a/compiler+runtime/test/jank/form/case/pass-real.jank +++ b/compiler+runtime/test/jank/form/case/pass-real.jank @@ -1,9 +1,8 @@ -(assert - (= - (case 3.14 3.14 :pi - 2.71 :e - 1.61 :phi - :default) - :pi)) +(assert (= (case 3.14 + 3.14 :pi + 2.71 :e + 1.61 :phi + :default) + :pi)) :success From 8796a4e73145f0568fe904ac6f57dd9a9ab14ad7 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 22 Nov 2025 12:22:05 -0800 Subject: [PATCH 024/122] Skip static member test for now It's blocked on this Clang bug: https://github.com/llvm/llvm-project/issues/146956 --- compiler+runtime/src/cpp/jank/codegen/processor.cpp | 2 +- .../test/jank/cpp/member/{pass-static.jank => skip-static.jank} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename compiler+runtime/test/jank/cpp/member/{pass-static.jank => skip-static.jank} (100%) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 8e7c2ceed..28c8ed371 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -1455,7 +1455,7 @@ namespace jank::codegen return util::format("{}", val); } - auto tmp{ Cpp::GetQualifiedCompleteName(expr->scope) }; + auto const tmp{ Cpp::GetQualifiedCompleteName(expr->scope) }; if(expr->position == expression_position::tail) { diff --git a/compiler+runtime/test/jank/cpp/member/pass-static.jank b/compiler+runtime/test/jank/cpp/member/skip-static.jank similarity index 100% rename from compiler+runtime/test/jank/cpp/member/pass-static.jank rename to compiler+runtime/test/jank/cpp/member/skip-static.jank From 9c3de6c977d4a24c83e597474f8b798771f9c2c6 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 22 Nov 2025 13:09:25 -0800 Subject: [PATCH 025/122] Detect unsupported static member access --- compiler+runtime/include/cpp/jank/error.hpp | 3 ++ .../include/cpp/jank/error/analyze.hpp | 3 ++ .../src/cpp/jank/analyze/processor.cpp | 18 ++++--- compiler+runtime/src/cpp/jank/error.cpp | 2 + .../src/cpp/jank/error/analyze.cpp | 47 +++++++++++-------- .../jank/cpp/global-value/pass-static.jank | 12 ++--- 6 files changed, 53 insertions(+), 32 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/error.hpp b/compiler+runtime/include/cpp/jank/error.hpp index 746dd0f40..accc37a99 100644 --- a/compiler+runtime/include/cpp/jank/error.hpp +++ b/compiler+runtime/include/cpp/jank/error.hpp @@ -103,6 +103,7 @@ namespace jank::error analyze_invalid_cpp_member_access, analyze_invalid_cpp_capture, analyze_mismatched_if_types, + analyze_known_issue, internal_analyze_failure, internal_codegen_failure, @@ -301,6 +302,8 @@ namespace jank::error return "analyze/invalid-cpp-capture"; case kind::analyze_mismatched_if_types: return "analyze/mismatched-if-types"; + case kind::analyze_known_issue: + return "analyze/known-issue"; case kind::internal_analyze_failure: return "internal/analysis-failure"; diff --git a/compiler+runtime/include/cpp/jank/error/analyze.hpp b/compiler+runtime/include/cpp/jank/error/analyze.hpp index 280d4312e..0c5dfda7f 100644 --- a/compiler+runtime/include/cpp/jank/error/analyze.hpp +++ b/compiler+runtime/include/cpp/jank/error/analyze.hpp @@ -150,6 +150,9 @@ namespace jank::error error_ref analyze_invalid_cpp_member_access(jtl::immutable_string const &message, read::source const &source, runtime::object_ref expansion); + error_ref analyze_known_issue(jtl::immutable_string const &message, + read::source const &source, + runtime::object_ref expansion); error_ref internal_analyze_failure(jtl::immutable_string const &message, runtime::object_ref expansion); error_ref internal_analyze_failure(jtl::immutable_string const &message, diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index 7b719cd29..5ead51ee5 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -3345,12 +3345,8 @@ namespace jank::analyze if(Cpp::IsVariable(scope)) { vk = expr::cpp_value::value_kind::variable; - /* TODO: A Clang bug prevents us from supporting references to static members. - * https://github.com/llvm/llvm-project/issues/146956 - */ - if(!Cpp::IsStaticDatamember(scope) && !Cpp::IsPointerType(type)) + if(!Cpp::IsPointerType(type)) { - /* TODO: Error if it's static and non-primitive. */ type = Cpp::GetLValueReferenceType(type); } } @@ -4355,8 +4351,18 @@ namespace jank::analyze ->add_usage(read::parse::reparse_nth(l, 0)); } + if(Cpp::IsStaticDatamember(member_scope)) + { + return error::analyze_known_issue( + "A blocking Clang bug prevents access to static members in some scenarios. See " + "https://github.com/llvm/llvm-project/issues/146956 for details.", + object_source(member), + latest_expansion(macro_expansions)) + ->add_usage(read::parse::reparse_nth(l, 0)); + } + val->val_kind = expr::cpp_value::value_kind::variable; - val->type = Cpp::GetTypeFromScope(member_scope); + val->type = Cpp::GetLValueReferenceType(Cpp::GetTypeFromScope(member_scope)); val->scope = member_scope; return val; } diff --git a/compiler+runtime/src/cpp/jank/error.cpp b/compiler+runtime/src/cpp/jank/error.cpp index 732e4d384..45c131497 100644 --- a/compiler+runtime/src/cpp/jank/error.cpp +++ b/compiler+runtime/src/cpp/jank/error.cpp @@ -184,6 +184,8 @@ namespace jank::error return "Invalid C++ delete."; case kind::analyze_invalid_cpp_member_access: return "Invalid C++ member access."; + case kind::analyze_known_issue: + return "Known issue."; case kind::internal_analyze_failure: return "Internal analysis failure."; diff --git a/compiler+runtime/src/cpp/jank/error/analyze.cpp b/compiler+runtime/src/cpp/jank/error/analyze.cpp index 53c0ae82c..f6e181327 100644 --- a/compiler+runtime/src/cpp/jank/error/analyze.cpp +++ b/compiler+runtime/src/cpp/jank/error/analyze.cpp @@ -153,7 +153,7 @@ namespace jank::error note &&extra, runtime::object_ref const expansion) { - return make_error(kind::analyze_invalid_try, message, source, std::move(extra), expansion); + return make_error(kind::analyze_invalid_try, message, source, jtl::move(extra), expansion); } error_ref analyze_unresolved_var(jtl::immutable_string const &message, @@ -229,28 +229,28 @@ namespace jank::error error_ref analyze_invalid_cpp_operator_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_operator_call, message, source, expansion); } error_ref analyze_invalid_cpp_constructor_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_constructor_call, message, source, expansion); } error_ref analyze_invalid_cpp_member_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_member_call, message, source, expansion); } error_ref analyze_invalid_cpp_capture(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_capture, message, @@ -261,109 +261,116 @@ namespace jank::error error_ref analyze_mismatched_if_types(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_mismatched_if_types, message, source, expansion); } error_ref analyze_invalid_cpp_function_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_function_call, message, source, expansion); } error_ref analyze_invalid_cpp_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_call, message, source, expansion); } error_ref analyze_invalid_cpp_conversion(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_conversion, message, source, expansion); } error_ref analyze_invalid_cpp_symbol(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_symbol, message, source, expansion); } error_ref analyze_unresolved_cpp_symbol(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_unresolved_cpp_symbol, message, source, expansion); } error_ref analyze_invalid_cpp_raw(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_raw, message, source, expansion); } error_ref analyze_invalid_cpp_type(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_type, message, source, expansion); } error_ref analyze_invalid_cpp_value(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_value, message, source, expansion); } error_ref analyze_invalid_cpp_cast(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_cast, message, source, expansion); } error_ref analyze_invalid_cpp_box(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_box, message, source, expansion); } error_ref analyze_invalid_cpp_unbox(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_unbox, message, source, expansion); } error_ref analyze_invalid_cpp_new(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_new, message, source, expansion); } error_ref analyze_invalid_cpp_delete(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_delete, message, source, expansion); } error_ref analyze_invalid_cpp_member_access(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_member_access, message, source, expansion); } + error_ref analyze_known_issue(jtl::immutable_string const &message, + read::source const &source, + runtime::object_ref const expansion) + { + return make_error(kind::analyze_known_issue, message, source, expansion); + } + error_ref internal_analyze_failure(jtl::immutable_string const &message, runtime::object_ref const expansion) { diff --git a/compiler+runtime/test/jank/cpp/global-value/pass-static.jank b/compiler+runtime/test/jank/cpp/global-value/pass-static.jank index ccbe5224a..54a3ab721 100644 --- a/compiler+runtime/test/jank/cpp/global-value/pass-static.jank +++ b/compiler+runtime/test/jank/cpp/global-value/pass-static.jank @@ -1,10 +1,10 @@ (cpp/raw "namespace jank::cpp::global_value::pass_static - { - struct foo - { - static int const boop{ 5 }; - }; - }") + { + struct foo + { + static int const boop{ 5 }; + }; + }") (if (= 5 cpp/jank.cpp.global_value.pass_static.foo.boop) :success :failure) From f97dc5a8228f07767ee277c8ad1e07806a32ef3e Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 22 Nov 2025 13:09:55 -0800 Subject: [PATCH 026/122] Add another static test --- .../pass-static-non-copyable.jank | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 compiler+runtime/test/jank/cpp/global-value/pass-static-non-copyable.jank diff --git a/compiler+runtime/test/jank/cpp/global-value/pass-static-non-copyable.jank b/compiler+runtime/test/jank/cpp/global-value/pass-static-non-copyable.jank new file mode 100644 index 000000000..f01aca9d6 --- /dev/null +++ b/compiler+runtime/test/jank/cpp/global-value/pass-static-non-copyable.jank @@ -0,0 +1,24 @@ +(cpp/raw "namespace jank::cpp::global_value::pass_static_non_copyable + { + struct foo + { + foo() = delete; + foo(foo const&) = delete; + foo(foo &&) = delete; + foo(int i) + : data{ i } + { } + + int data{}; + }; + + struct bar + { + static foo const boop; + }; + foo const bar::boop{ 5 }; + }") +(let* [foo cpp/jank.cpp.global_value.pass_static_non_copyable.bar.boop] + (if (= 5 (cpp/.-data foo)) + :success + :failure)) From bd95aabb8a6ff2c90b9b56e108a74f9203c48726 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 22 Nov 2025 13:28:45 -0800 Subject: [PATCH 027/122] Fix tidy issues --- compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp | 2 +- compiler+runtime/src/cpp/jank/codegen/processor.cpp | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp index e39af6c3b..654a4ef8a 100644 --- a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp @@ -3749,7 +3749,7 @@ namespace jank::codegen * as well, to detect cases where we're not restoring in the correct order. */ return { [stack_ptr, this]() { ssize found{ -1 }; - for(ssize i{}; i != static_cast(stack_saves.size()); ++i) + for(ssize i{}; std::cmp_not_equal(i, stack_saves.size()); ++i) { if(stack_saves[i].data == stack_ptr) { diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 28c8ed371..ea5b7b9d4 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -1455,7 +1455,7 @@ namespace jank::codegen return util::format("{}", val); } - auto const tmp{ Cpp::GetQualifiedCompleteName(expr->scope) }; + auto tmp{ Cpp::GetQualifiedCompleteName(expr->scope) }; if(expr->position == expression_position::tail) { @@ -1529,7 +1529,7 @@ namespace jank::codegen util::format_to(body_buffer, "{}(", Cpp::GetQualifiedCompleteName(source->scope)); bool need_comma{}; - for(u8 arg_idx{}; arg_idx < expr->arg_exprs.size(); ++arg_idx) + for(usize arg_idx{}; arg_idx < expr->arg_exprs.size(); ++arg_idx) { auto const arg_expr{ expr->arg_exprs[arg_idx] }; auto const arg_type{ cpp_util::expression_type(arg_expr) }; @@ -2271,7 +2271,6 @@ namespace jank::codegen if(!generated_expression) { - jtl::immutable_string close = ")"; util::format_to(expression_buffer, "jank::runtime::make_box<{}>(", runtime::module::nest_native_ns(module_ns, runtime::munge(struct_name.name))); @@ -2327,7 +2326,7 @@ namespace jank::codegen } } - util::format_to(expression_buffer, "{}", close); + util::format_to(expression_buffer, ")"); generated_expression = true; } From d4153d20fbfb8859a8bdaf752220b462aeb7350e Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 22 Nov 2025 23:02:37 -0800 Subject: [PATCH 028/122] Fix some string gc bits --- compiler+runtime/cmake/dependency/bdwgc.cmake | 10 ++++++++-- .../cpp/jank/runtime/convert/builtin.hpp | 10 ++++++++++ .../include/cpp/jtl/immutable_string.hpp | 20 ++++++++++--------- .../src/cpp/jank/jit/processor.cpp | 10 ++++++++-- .../src/cpp/jank/util/clang_format.cpp | 3 ++- 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/compiler+runtime/cmake/dependency/bdwgc.cmake b/compiler+runtime/cmake/dependency/bdwgc.cmake index 034bab9c6..0176e2692 100644 --- a/compiler+runtime/cmake/dependency/bdwgc.cmake +++ b/compiler+runtime/cmake/dependency/bdwgc.cmake @@ -2,8 +2,14 @@ set(CMAKE_C_FLAGS_OLD "${CMAKE_C_FLAGS}") set(CMAKE_CXX_FLAGS_OLD "${CMAKE_CXX_FLAGS}") set(BUILD_SHARED_LIBS_OLD ${BUILD_SHARED_LIBS}) set(CMAKE_CXX_CLANG_TIDY_OLD ${CMAKE_CXX_CLANG_TIDY}) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w -DREDIRECT_MALLOC=GC_malloc_uncollectable -DREDIR_MALLOC_AND_LINUX_THREADS") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w -DREDIRECT_MALLOC=GC_malloc_uncollectable -DREDIR_MALLOC_AND_LINUX_THREADS") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w") + + if(NOT APPLE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DREDIRECT_MALLOC=GC_malloc_uncollectable -DREDIR_MALLOC_AND_LINUX_THREADS") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DREDIRECT_MALLOC=GC_malloc_uncollectable -DREDIR_MALLOC_AND_LINUX_THREADS") + endif() + set(BUILD_SHARED_LIBS OFF) set(CMAKE_CXX_CLANG_TIDY "") set(enable_cplusplus ON CACHE BOOL "Enable C++") diff --git a/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp b/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp index eb8745bc8..148f0f7c3 100644 --- a/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp @@ -35,10 +35,20 @@ namespace jank::runtime return const_cast(t); } + static constexpr object *into_object(object_ref const t) + { + return t.erase(); + } + static constexpr object *from_object(T t) { return const_cast(t); } + + static constexpr object *from_object(object_ref const t) + { + return t.erase(); + } }; /* Any typed object can convert to/from itself easily. */ diff --git a/compiler+runtime/include/cpp/jtl/immutable_string.hpp b/compiler+runtime/include/cpp/jtl/immutable_string.hpp index afc94dc41..13034501f 100644 --- a/compiler+runtime/include/cpp/jtl/immutable_string.hpp +++ b/compiler+runtime/include/cpp/jtl/immutable_string.hpp @@ -54,12 +54,10 @@ namespace jtl struct immutable_string { using value_type = char; - using allocator_type = jank::native_allocator; - using allocator_traits = std::allocator_traits; - using size_type = allocator_traits::size_type; using traits_type = std::char_traits; using pointer_type = value_type *; using const_pointer_type = value_type const *; + using size_type = usize; using iterator = pointer_type; using const_iterator = const_pointer_type; using reverse_iterator = std::reverse_iterator; @@ -705,7 +703,7 @@ namespace jtl * 3. As a large_storage instance, containing a pointer, size, and capacity */ /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) */ - struct storage : allocator_type + struct storage { /* TODO: What if we store a max of 22 chars and dedicate a byte for flags with no masking? */ union { @@ -724,7 +722,7 @@ namespace jtl /* NOTE: No performance difference between if/switch here. */ if(get_category() == category::large_owned) { - allocator_traits::deallocate(store, store.large.data, store.large.size + 1); + GC_free(store.large.data); } } @@ -838,7 +836,8 @@ namespace jtl { jank_debug_assert(max_small_size < size); /* TODO: Apply gnu::malloc to this fn. */ - store.large.data = std::assume_aligned(store.allocate(size + 1)); + store.large.data = std::assume_aligned( + static_cast(GC_malloc_atomic(size + 1))); traits_type::copy(store.large.data, data, size); store.large.data[size] = 0; store.large.size = size; @@ -849,7 +848,8 @@ namespace jtl constexpr void init_large_fill(value_type const fill, u8 const size) noexcept { jank_debug_assert(max_small_size < size); - store.large.data = std::assume_aligned(store.allocate(size + 1)); + store.large.data = std::assume_aligned( + static_cast(GC_malloc_atomic(size + 1))); traits_type::assign(store.large.data, size, fill); store.large.data[size] = 0; store.large.size = size; @@ -864,7 +864,8 @@ namespace jtl { auto const size(lhs_size + rhs_size); jank_debug_assert(max_small_size < size); - store.large.data = std::assume_aligned(store.allocate(size + 1)); + store.large.data = std::assume_aligned( + static_cast(GC_malloc_atomic(size + 1))); traits_type::copy(store.large.data, lhs, lhs_size); traits_type::copy(store.large.data + lhs_size, rhs, rhs_size); store.large.data[size] = 0; @@ -878,7 +879,8 @@ namespace jtl { auto const size(std::distance(begin, end)); jank_debug_assert(max_small_size < size); - store.large.data = std::assume_aligned(store.allocate(size + 1)); + store.large.data = std::assume_aligned( + static_cast(GC_malloc_atomic(size + 1))); std::copy(begin, end, store.large.data); store.large.data[size] = 0; store.large.size = size; diff --git a/compiler+runtime/src/cpp/jank/jit/processor.cpp b/compiler+runtime/src/cpp/jank/jit/processor.cpp index 7030654ed..3001f093d 100644 --- a/compiler+runtime/src/cpp/jank/jit/processor.cpp +++ b/compiler+runtime/src/cpp/jank/jit/processor.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -152,6 +153,9 @@ namespace jank::jit args.emplace_back("-include-pch"); args.emplace_back(strdup(pch_path_str.c_str())); + args.emplace_back("-w"); + args.emplace_back("-Wno-c++11-narrowing"); + util::add_system_flags(args); /********* Every flag after this line is user-provided. *********/ @@ -228,8 +232,10 @@ namespace jank::jit void processor::eval_string(jtl::immutable_string const &s) const { profile::timer const timer{ "jit eval_string" }; - //util::println("// eval_string:\n{}\n", s); - auto err(interpreter->ParseAndExecute({ s.data(), s.size() })); + auto const &formatted{ s }; + //auto const &formatted{ util::format_cpp_source(s).expect_ok() }; + //util::println("// eval_string:\n{}\n", formatted); + auto err(interpreter->ParseAndExecute({ formatted.data(), formatted.size() })); if(err) { llvm::logAllUnhandledErrors(std::move(err), llvm::errs(), "error: "); diff --git a/compiler+runtime/src/cpp/jank/util/clang_format.cpp b/compiler+runtime/src/cpp/jank/util/clang_format.cpp index 820a2aaf9..87837b733 100644 --- a/compiler+runtime/src/cpp/jank/util/clang_format.cpp +++ b/compiler+runtime/src/cpp/jank/util/clang_format.cpp @@ -68,6 +68,7 @@ namespace jank::util { return err(llvm::toString(formatted_code.takeError())); } - return ok(jtl::immutable_string{ *formatted_code }); + jtl::immutable_string ret{ *formatted_code }; + return ok(ret); } } From 381a8bba4e3ca1551f9e14789606adba02ea84c8 Mon Sep 17 00:00:00 2001 From: jeaye Date: Mon, 24 Nov 2025 13:05:03 -0800 Subject: [PATCH 029/122] Bypass one layer of typedefs manually --- .../src/cpp/jank/analyze/cpp_util.cpp | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp b/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp index a16daf244..ff883c5a1 100644 --- a/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp @@ -300,6 +300,26 @@ namespace jank::analyze::cpp_util } /* TODO: Handle typed object refs, too. */ + /* TODO: We probably want a recursive approach to this, for types and scopes. */ + auto const qual_type{ clang::QualType::getFromOpaquePtr(type) }; + if(auto const *alias{ + llvm::dyn_cast_or_null(qual_type.getTypePtrOrNull()) }; + alias) + { + if(auto const *alias_decl{ alias->getDecl() }; alias_decl) + { + auto alias_name{ alias_decl->getQualifiedNameAsString() }; + if(!alias_name.empty()) + { + if(Cpp::IsPointerType(type)) + { + alias_name += "*"; + } + return alias_name; + } + } + } + if(auto const scope{ Cpp::GetScopeFromType(type) }; scope) { auto name{ get_qualified_name(scope) }; From 7f5eb1cc07be5417291253809dff0d12726e0eb0 Mon Sep 17 00:00:00 2001 From: jeaye Date: Mon, 24 Nov 2025 13:12:28 -0800 Subject: [PATCH 030/122] Ensure no implicit conversion for instantiation --- .../cpp/constructor/complex/fail-template-instantiation.jank | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler+runtime/test/jank/cpp/constructor/complex/fail-template-instantiation.jank b/compiler+runtime/test/jank/cpp/constructor/complex/fail-template-instantiation.jank index 59b73e64a..9f60209bc 100644 --- a/compiler+runtime/test/jank/cpp/constructor/complex/fail-template-instantiation.jank +++ b/compiler+runtime/test/jank/cpp/constructor/complex/fail-template-instantiation.jank @@ -10,6 +10,6 @@ std::string a{}; }; }") -(let* [arg (cpp/int 5) +(let* [arg (cpp/int* cpp/nullptr) _ (cpp/jank.cpp.constructor.complex.fail_template_instantiation.foo arg)] :success) From a5fb045c0722678ccee0c2fd645320c435eecf62 Mon Sep 17 00:00:00 2001 From: jeaye Date: Mon, 24 Nov 2025 13:53:12 -0800 Subject: [PATCH 031/122] Fix tidy issues --- .github/workflows/build.yml | 9 +++++---- compiler+runtime/src/cpp/jank/util/clang_format.cpp | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e87c092ac..06e4f89dd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -97,10 +97,11 @@ jobs: analyze: on ## Debug + sanitization - - name: Ubuntu - address sanitizer - os: ubuntu-24.04 - build_type: Debug - sanitize: address + # TODO: Fix this. GC issue: https://github.com/bdwgc/bdwgc/issues/772 + #- name: Ubuntu - address sanitizer + # os: ubuntu-24.04 + # build_type: Debug + # sanitize: address - name: Ubuntu - undefined behavior sanitizer os: ubuntu-24.04 diff --git a/compiler+runtime/src/cpp/jank/util/clang_format.cpp b/compiler+runtime/src/cpp/jank/util/clang_format.cpp index 87837b733..07176c5cc 100644 --- a/compiler+runtime/src/cpp/jank/util/clang_format.cpp +++ b/compiler+runtime/src/cpp/jank/util/clang_format.cpp @@ -68,7 +68,7 @@ namespace jank::util { return err(llvm::toString(formatted_code.takeError())); } - jtl::immutable_string ret{ *formatted_code }; + jtl::immutable_string const ret{ *formatted_code }; return ok(ret); } } From e32634c87e1cb37317fee8753b69ef5c5428c5e8 Mon Sep 17 00:00:00 2001 From: jeaye Date: Mon, 24 Nov 2025 14:27:25 -0800 Subject: [PATCH 032/122] Remove remaining bpptree references --- compiler+runtime/CMakeLists.txt | 1 - compiler+runtime/cmake/install.cmake | 5 ----- 2 files changed, 6 deletions(-) diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index f2ade1f6f..6654d5240 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -554,7 +554,6 @@ target_include_directories( PUBLIC "$" "$" - "$" "$" "$" "$" diff --git a/compiler+runtime/cmake/install.cmake b/compiler+runtime/cmake/install.cmake index 9c7f7553c..10b96a7ad 100644 --- a/compiler+runtime/cmake/install.cmake +++ b/compiler+runtime/cmake/install.cmake @@ -61,11 +61,6 @@ jank_glob_install_without_prefix( PATTERN "${CMAKE_SOURCE_DIR}/third-party/folly/folly/*.h" ) -jank_glob_install_without_prefix( - INPUT_PREFIX "${CMAKE_SOURCE_DIR}/third-party/bpptree/" - PATTERN "${CMAKE_SOURCE_DIR}/third-party/bpptree/include/*" -) - jank_glob_install_without_prefix( INPUT_PREFIX "${CMAKE_SOURCE_DIR}/third-party/immer/" OUTPUT_PREFIX "include/" From d8cfc8d1df767beb98619349d3af3cbb312036ae Mon Sep 17 00:00:00 2001 From: jeaye Date: Mon, 24 Nov 2025 18:43:01 -0800 Subject: [PATCH 033/122] Add some missing meta cppgen --- compiler+runtime/cmake/install.cmake | 6 ------ compiler+runtime/include/cpp/jank/prelude.hpp | 1 + .../src/cpp/jank/codegen/processor.cpp | 18 ++++++++++++++---- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/compiler+runtime/cmake/install.cmake b/compiler+runtime/cmake/install.cmake index 10b96a7ad..70121d454 100644 --- a/compiler+runtime/cmake/install.cmake +++ b/compiler+runtime/cmake/install.cmake @@ -77,12 +77,6 @@ jank_glob_install_without_prefix( PATTERN "${CMAKE_SOURCE_DIR}/third-party/ftxui/include/*" ) -jank_glob_install_without_prefix( - INPUT_PREFIX "${CMAKE_SOURCE_DIR}/third-party/libzippp/src/" - OUTPUT_PREFIX "include/" - PATTERN "${CMAKE_SOURCE_DIR}/third-party/libzippp/src/*" -) - jank_glob_install_without_prefix( INPUT_PREFIX "${CMAKE_SOURCE_DIR}/third-party/cpptrace/" PATTERN "${CMAKE_SOURCE_DIR}/third-party/cpptrace/include/*" diff --git a/compiler+runtime/include/cpp/jank/prelude.hpp b/compiler+runtime/include/cpp/jank/prelude.hpp index 0049b7bd5..2618f3e30 100644 --- a/compiler+runtime/include/cpp/jank/prelude.hpp +++ b/compiler+runtime/include/cpp/jank/prelude.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index ea5b7b9d4..13e2f87dd 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -361,7 +362,7 @@ namespace jank::codegen util::format_to( buffer, "jank::runtime::make_box(std::in_place"); - for(auto it : runtime::make_sequence_range(typed_o)) + for(auto const it : runtime::make_sequence_range(typed_o)) { util::format_to(buffer, ", "); gen_constant(it, buffer, true); @@ -1853,11 +1854,17 @@ namespace jank::codegen util::format_to( body_buffer, - "auto {}{ jank::runtime::make_box({}, \"{}\") };", + "auto {}{ jank::runtime::make_box({}, \"{}\") };\n", ret_tmp, value_tmp.unwrap().str(false), type_str); + auto const meta{ runtime::source_to_meta(expr->source) }; + util::format_to(body_buffer, + "jank::runtime::reset_meta({}, jank::runtime::__rt_ctx->read_string(\"{}\"));", + ret_tmp, + util::escape(runtime::to_code_string(meta))); + if(expr->position == expression_position::tail) { util::format_to(body_buffer, "return {};", ret_tmp); @@ -1873,15 +1880,18 @@ namespace jank::codegen auto ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("cpp_unbox")) }; auto value_tmp{ gen(expr->value_expr, arity) }; auto const type_name{ cpp_util::get_qualified_type_name(expr->type) }; + auto const meta{ runtime::source_to_meta(expr->source) }; util::format_to(body_buffer, "auto {}{ " - "static_cast<{}>(jank_unbox(\"{}\", {}.data)" + "static_cast<{}>(jank_unbox_with_source(\"{}\", {}.data, " + "jank::runtime::__rt_ctx->read_string(\"{}\").data)" ") };", ret_tmp, type_name, type_name, - value_tmp.unwrap().str(false)); + value_tmp.unwrap().str(false), + util::escape(runtime::to_code_string(meta))); if(expr->position == expression_position::tail) { From 1d72ec36ad45a7418e71c4fea73858e3eaf55179 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 25 Nov 2025 13:34:30 -0800 Subject: [PATCH 034/122] Intern ns in jank_load fn for cppgen --- compiler+runtime/include/cpp/jank/c_api.h | 2 ++ compiler+runtime/src/cpp/jank/c_api.cpp | 11 +++++++++++ compiler+runtime/src/cpp/jank/codegen/processor.cpp | 1 + 3 files changed, 14 insertions(+) diff --git a/compiler+runtime/include/cpp/jank/c_api.h b/compiler+runtime/include/cpp/jank/c_api.h index a66d5b9b5..ee4d6ceee 100644 --- a/compiler+runtime/include/cpp/jank/c_api.h +++ b/compiler+runtime/include/cpp/jank/c_api.h @@ -49,6 +49,8 @@ extern "C" jank_object_ref jank_read_string(jank_object_ref s); jank_object_ref jank_read_string_c(char const * const s); + jank_object_ref jank_ns_intern(jank_object_ref sym); + jank_object_ref jank_ns_intern_c(char const * const sym); void jank_ns_set_symbol_counter(char const * const ns, jank_u64 const count); jank_object_ref jank_var_intern(jank_object_ref ns, jank_object_ref name); diff --git a/compiler+runtime/src/cpp/jank/c_api.cpp b/compiler+runtime/src/cpp/jank/c_api.cpp index faed7c122..0be7e6aad 100644 --- a/compiler+runtime/src/cpp/jank/c_api.cpp +++ b/compiler+runtime/src/cpp/jank/c_api.cpp @@ -68,6 +68,17 @@ extern "C" return __rt_ctx->read_string(s).erase(); } + jank_object_ref jank_ns_intern(jank_object_ref const sym) + { + auto const sym_obj(try_object(reinterpret_cast(sym))); + return __rt_ctx->intern_ns(sym_obj).erase(); + } + + jank_object_ref jank_ns_intern_c(char const * const sym) + { + return __rt_ctx->intern_ns(sym).erase(); + } + void jank_ns_set_symbol_counter(char const * const ns, jank_u64 const count) { auto const ns_obj(__rt_ctx->intern_ns(ns)); diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 13e2f87dd..975eb4b3a 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -2267,6 +2267,7 @@ namespace jank::codegen util::format_to(footer_buffer, "extern \"C\" void* {}(){", runtime::module::module_to_load_function(module)); + util::format_to(footer_buffer, "jank_ns_intern_c(\"{}\");", module); util::format_to(footer_buffer, "return {}::{}{ }.call().erase();", runtime::module::module_to_native_ns(module), From 892800a7630ae0e2a46028b4543fefca79ac71ad Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 25 Nov 2025 13:42:56 -0800 Subject: [PATCH 035/122] Remove bpptree entirely --- .gitmodules | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index f4d195697..4bc396c22 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "compiler+runtime/third-party/folly"] path = compiler+runtime/third-party/folly url = https://github.com/jank-lang/folly.git -[submodule "compiler+runtime/third-party/bpptree"] - path = compiler+runtime/third-party/bpptree - url = https://github.com/jank-lang/BppTree.git [submodule "compiler+runtime/third-party/immer"] path = compiler+runtime/third-party/immer url = https://github.com/jank-lang/immer.git From a64bc41fd32f32b0c9439839e0bf4a1e28640813 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 25 Nov 2025 15:58:41 -0800 Subject: [PATCH 036/122] Fix aot cppgen for vars --- .../include/cpp/jank/analyze/local_frame.hpp | 3 +- .../include/cpp/jank/runtime/var.hpp | 1 + .../src/cpp/jank/analyze/local_frame.cpp | 23 ++++---------- .../src/cpp/jank/analyze/processor.cpp | 30 +++++++++++++------ .../src/cpp/jank/codegen/processor.cpp | 8 ++--- compiler+runtime/src/cpp/jank/runtime/var.cpp | 5 ++++ 6 files changed, 36 insertions(+), 34 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp b/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp index 9b389951d..a76a19852 100644 --- a/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp @@ -8,6 +8,7 @@ namespace jank::runtime { struct context; + using var_ref = oref; namespace obj { @@ -135,7 +136,7 @@ namespace jank::analyze static bool within_same_fn(jtl::ptr, jtl::ptr); - runtime::obj::symbol_ref lift_var(runtime::obj::symbol_ref const &); + void lift_var(runtime::var_ref const &); jtl::option> find_lifted_var(runtime::obj::symbol_ref const &) const; diff --git a/compiler+runtime/include/cpp/jank/runtime/var.hpp b/compiler+runtime/include/cpp/jank/runtime/var.hpp index 4a8c5b442..b111a57ac 100644 --- a/compiler+runtime/include/cpp/jank/runtime/var.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/var.hpp @@ -58,6 +58,7 @@ namespace jank::runtime var_ref set_dynamic(bool dyn); + obj::symbol_ref to_qualified_symbol() const; var_thread_binding_ref get_thread_binding() const; /* behavior::derefable */ diff --git a/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp b/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp index c3b5f4072..7d2456b5e 100644 --- a/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp @@ -190,34 +190,21 @@ namespace jank::analyze return &find_closest_fn_frame(*l) == &find_closest_fn_frame(*r); } - obj::symbol_ref local_frame::lift_var(obj::symbol_ref const &sym) + void local_frame::lift_var(var_ref const &var) { auto &closest_fn(find_closest_fn_frame(*this)); - auto const &found(closest_fn.lifted_vars.find(sym)); + auto const qualified_sym{ make_box(var->n->name->name, var->name->name) }; + auto const &found(closest_fn.lifted_vars.find(qualified_sym)); if(found != closest_fn.lifted_vars.end()) { - return found->first; - } - - obj::symbol_ref qualified_sym{}; - if(sym->ns.empty()) - { - qualified_sym - = make_box(expect_object(__rt_ctx->current_ns_var->deref())->name->name, - sym->name); - } - else - { - qualified_sym = make_box(*sym); + return; } /* We use unique native names, just so var names don't clash with the underlying C++ API. */ lifted_var lv{ __rt_ctx->unique_namespaced_string(munge(qualified_sym->name)), qualified_sym }; - closest_fn.lifted_vars.emplace(qualified_sym, std::move(lv)); - return qualified_sym; + closest_fn.lifted_vars.emplace(qualified_sym, jtl::move(lv)); } - /* TODO: These are not used in IR gen. Remove entirely? */ jtl::option> local_frame::find_lifted_var(obj::symbol_ref const &sym) const { diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index 5ead51ee5..82fa54925 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -1282,17 +1282,19 @@ namespace jank::analyze ->add_usage(read::parse::reparse_nth(l, 1)); } - auto qualified_sym(current_frame->lift_var(sym)); + auto qualified_sym(runtime::__rt_ctx->qualify_symbol(sym)); qualified_sym->meta = sym->meta; /* We always def in the current ns, so we want an owned var. */ - auto const var(__rt_ctx->intern_owned_var(qualified_sym)); - if(var.is_err()) + auto const var_res(__rt_ctx->intern_owned_var(qualified_sym)); + if(var_res.is_err()) { - return error::internal_analyze_failure(var.expect_err(), + return error::internal_analyze_failure(var_res.expect_err(), meta_source(sym), latest_expansion(macro_expansions)); } + current_frame->lift_var(var_res.expect_ok()); + jtl::option> value_expr; bool const has_value{ 3 <= length }; bool const has_docstring{ 4 <= length }; @@ -1316,7 +1318,7 @@ namespace jank::analyze } value_expr = some(value_result.expect_ok()); - vars.insert_or_assign(var.expect_ok(), value_expr.unwrap()); + vars.insert_or_assign(var_res.expect_ok(), value_expr.unwrap()); } if(has_docstring) @@ -1599,7 +1601,7 @@ namespace jank::analyze auto const macro_kw(__rt_ctx->intern_keyword("", "macro", true).expect_ok()); if(var->meta.is_none() || get(var->meta.unwrap(), macro_kw).is_nil()) { - current_frame->lift_var(qualified_sym); + current_frame->lift_var(var); } return jtl::make_ref(position, current_frame, true, qualified_sym, var); } @@ -2544,7 +2546,7 @@ namespace jank::analyze auto const arg_sym(runtime::expect_object(arg)); - auto const qualified_sym(current_frame->lift_var(arg_sym)); + auto const qualified_sym{ __rt_ctx->qualify_symbol(arg_sym) }; auto const found_var(__rt_ctx->find_var(qualified_sym)); if(found_var.is_nil()) { @@ -2553,6 +2555,7 @@ namespace jank::analyze meta_source(o->meta), latest_expansion(macro_expansions)); } + current_frame->lift_var(found_var); return jtl::make_ref(position, current_frame, true, qualified_sym, found_var); } @@ -2566,8 +2569,17 @@ namespace jank::analyze { auto const pop_macro_expansions{ push_macro_expansions(*this, o) }; - auto const qualified_sym( - current_frame->lift_var(make_box(o->n->name->name, o->name->name))); + auto const qualified_sym(__rt_ctx->qualify_symbol(o->to_qualified_symbol())); + + auto const found_var(__rt_ctx->find_var(qualified_sym)); + if(found_var.is_nil()) + { + return error::analyze_unresolved_var( + util::format("Unable to resolve var '{}'.", qualified_sym->to_string()), + meta_source(o->meta), + latest_expansion(macro_expansions)); + } + current_frame->lift_var(found_var); return jtl::make_ref(position, current_frame, true, qualified_sym, o); } diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 975eb4b3a..e591aebf4 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -555,7 +555,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::var_deref_ref const expr, analyze::expr::function_arity const &) { - auto const &var(expr->frame->find_lifted_var(expr->qualified_name).unwrap().get()); + auto const &var(expr->frame->find_lifted_var(expr->var->to_qualified_symbol()).unwrap().get()); switch(expr->position) { case analyze::expression_position::statement: @@ -2256,11 +2256,7 @@ namespace jank::codegen util::format_to(footer_buffer, "};"); /* Namespace. */ - //if(!runtime::module::is_nested_module(module)) - //if(target == compilation_target::module) - { - util::format_to(footer_buffer, "}"); - } + util::format_to(footer_buffer, "}"); if(target == compilation_target::module) { diff --git a/compiler+runtime/src/cpp/jank/runtime/var.cpp b/compiler+runtime/src/cpp/jank/runtime/var.cpp index 8894d37e8..788748899 100644 --- a/compiler+runtime/src/cpp/jank/runtime/var.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/var.cpp @@ -143,6 +143,11 @@ namespace jank::runtime return this; } + obj::symbol_ref var::to_qualified_symbol() const + { + return make_box(n->name->name, name->name); + } + var_thread_binding_ref var::get_thread_binding() const { if(!thread_bound.load()) From 90d5c0f7e8b5ffbcc744fd6b54f1c6a69a8cd883 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 25 Nov 2025 19:12:31 -0800 Subject: [PATCH 037/122] Fix var_ref cppgen --- .../include/cpp/jank/analyze/expr/var_ref.hpp | 6 ++++++ .../src/cpp/jank/analyze/processor.cpp | 17 ++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/var_ref.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/var_ref.hpp index 272b71803..6ddae3921 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/var_ref.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/var_ref.hpp @@ -26,6 +26,12 @@ namespace jank::analyze::expr runtime::object_ref to_runtime_data() const override; + /* Holds the fully qualified name for the originally resolved var. + * It will be useful to know that the var ref happened through a + * referred var, for static analysis and error reporting. + * + * For all the other purposes, `var` member should be used that points + * to the actual value of the var.. */ runtime::obj::symbol_ref qualified_name{}; runtime::var_ref var{}; }; diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index 82fa54925..b0c3f215f 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -2557,7 +2557,11 @@ namespace jank::analyze } current_frame->lift_var(found_var); - return jtl::make_ref(position, current_frame, true, qualified_sym, found_var); + return jtl::make_ref(position, + current_frame, + true, + found_var->to_qualified_symbol(), + found_var); } processor::expression_result @@ -2570,16 +2574,7 @@ namespace jank::analyze auto const pop_macro_expansions{ push_macro_expansions(*this, o) }; auto const qualified_sym(__rt_ctx->qualify_symbol(o->to_qualified_symbol())); - - auto const found_var(__rt_ctx->find_var(qualified_sym)); - if(found_var.is_nil()) - { - return error::analyze_unresolved_var( - util::format("Unable to resolve var '{}'.", qualified_sym->to_string()), - meta_source(o->meta), - latest_expansion(macro_expansions)); - } - current_frame->lift_var(found_var); + current_frame->lift_var(o); return jtl::make_ref(position, current_frame, true, qualified_sym, o); } From d233b773e3bc6cf5cc20d19a2f8e3a181a764e0d Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 25 Nov 2025 23:56:40 -0800 Subject: [PATCH 038/122] Clear up static const issue --- compiler+runtime/src/cpp/jank/analyze/processor.cpp | 10 ---------- .../cpp/member/{skip-static.jank => pass-static.jank} | 3 ++- .../test/jank/cpp/member/skip-static-const.jank | 11 +++++++++++ 3 files changed, 13 insertions(+), 11 deletions(-) rename compiler+runtime/test/jank/cpp/member/{skip-static.jank => pass-static.jank} (76%) create mode 100644 compiler+runtime/test/jank/cpp/member/skip-static-const.jank diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index b0c3f215f..ac1fdffd5 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -4358,16 +4358,6 @@ namespace jank::analyze ->add_usage(read::parse::reparse_nth(l, 0)); } - if(Cpp::IsStaticDatamember(member_scope)) - { - return error::analyze_known_issue( - "A blocking Clang bug prevents access to static members in some scenarios. See " - "https://github.com/llvm/llvm-project/issues/146956 for details.", - object_source(member), - latest_expansion(macro_expansions)) - ->add_usage(read::parse::reparse_nth(l, 0)); - } - val->val_kind = expr::cpp_value::value_kind::variable; val->type = Cpp::GetLValueReferenceType(Cpp::GetTypeFromScope(member_scope)); val->scope = member_scope; diff --git a/compiler+runtime/test/jank/cpp/member/skip-static.jank b/compiler+runtime/test/jank/cpp/member/pass-static.jank similarity index 76% rename from compiler+runtime/test/jank/cpp/member/skip-static.jank rename to compiler+runtime/test/jank/cpp/member/pass-static.jank index 56afb7ecd..582cb3460 100644 --- a/compiler+runtime/test/jank/cpp/member/skip-static.jank +++ b/compiler+runtime/test/jank/cpp/member/pass-static.jank @@ -2,8 +2,9 @@ { struct bar { - static const int a{ 5 }; + static int const a; }; + int const bar::a{ 5 }; }") (let* [b (cpp/jank.cpp.member.pass_static.bar.) a (cpp/.-a b)] diff --git a/compiler+runtime/test/jank/cpp/member/skip-static-const.jank b/compiler+runtime/test/jank/cpp/member/skip-static-const.jank new file mode 100644 index 000000000..757315a21 --- /dev/null +++ b/compiler+runtime/test/jank/cpp/member/skip-static-const.jank @@ -0,0 +1,11 @@ +(cpp/raw "namespace jank::cpp::member::pass_static_const + { + struct bar + { + static int const a{ 5 }; + }; + }") +(let* [b (cpp/jank.cpp.member.pass_static_const.bar.) + a (cpp/.-a b)] + (if (= 5 a) + :success)) From 7c7ae86e7ad3a062574ab55197e7257b0fe3b243 Mon Sep 17 00:00:00 2001 From: jeaye Date: Wed, 26 Nov 2025 12:34:47 -0800 Subject: [PATCH 039/122] Fix cppgen for throw --- compiler+runtime/src/cpp/jank/codegen/processor.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index e591aebf4..d84c0090e 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -1294,7 +1294,13 @@ namespace jank::codegen util::format_to(body_buffer, "throw static_cast({});", value_tmp.unwrap().str(true)); - return none; + + if(expr->position == analyze::expression_position::tail) + { + util::format_to(body_buffer, "return jank::runtime::jank_nil;"); + } + + return "jank::runtime::jank_nil"; } jtl::option From 87aaa10a4d181cb4beb9f53f8c3fd3be93f055ce Mon Sep 17 00:00:00 2001 From: jeaye Date: Wed, 26 Nov 2025 13:19:48 -0800 Subject: [PATCH 040/122] Fix inf/nan cppgen --- .../include/cpp/jank/error/report.hpp | 1 + .../src/cpp/jank/codegen/processor.cpp | 18 ++++++++++++++++-- compiler+runtime/src/cpp/jank/error/report.cpp | 11 +++++++++++ compiler+runtime/src/cpp/jank/runtime/ns.cpp | 15 +++++++-------- compiler+runtime/src/cpp/jank/util/cli.cpp | 7 +++++++ .../src/cpp/jtl/string_builder.cpp | 6 +++--- 6 files changed, 45 insertions(+), 13 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/error/report.hpp b/compiler+runtime/include/cpp/jank/error/report.hpp index 04b38c62a..46418aa46 100644 --- a/compiler+runtime/include/cpp/jank/error/report.hpp +++ b/compiler+runtime/include/cpp/jank/error/report.hpp @@ -5,4 +5,5 @@ namespace jank::error { void report(error_ref e); + void warn(jtl::immutable_string const &); } diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index d84c0090e..56fb27662 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -184,8 +184,22 @@ namespace jank::codegen { util::format_to(buffer, "jank::runtime::make_box(static_cast({}))", - typed_o->data); + "f64>("); + + if(std::isinf(typed_o->data)) + { + util::format_to(buffer, "INFINITY"); + } + else if(std::isnan(typed_o->data)) + { + util::format_to(buffer, "NAN"); + } + else + { + util::format_to(buffer, "{}", typed_o->data); + } + + util::format_to(buffer, "))"); } else if constexpr(std::same_as) { diff --git a/compiler+runtime/src/cpp/jank/error/report.cpp b/compiler+runtime/src/cpp/jank/error/report.cpp index a75d74538..5bbbc0069 100644 --- a/compiler+runtime/src/cpp/jank/error/report.cpp +++ b/compiler+runtime/src/cpp/jank/error/report.cpp @@ -5,6 +5,8 @@ #include #include +#include + #include #include #include @@ -592,4 +594,13 @@ namespace jank::error report(e->cause.as_ref()); } } + + void warn(jtl::immutable_string const &msg) + { + util::println(stderr, + "{}warning:{} {}", + jtl::terminal_style::yellow, + jtl::terminal_style::reset, + msg); + } } diff --git a/compiler+runtime/src/cpp/jank/runtime/ns.cpp b/compiler+runtime/src/cpp/jank/runtime/ns.cpp index fd971c22a..2306fe325 100644 --- a/compiler+runtime/src/cpp/jank/runtime/ns.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/ns.cpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace jank::runtime { @@ -85,14 +86,12 @@ namespace jank::runtime if(redefined) { auto const v{ expect_object(*found_var) }; - /* TODO: Util for warning. */ - util::println( - stderr, - "WARNING: '{}' already referred to {} in namespace '{}' but has been replaced by {}", - unqualified_sym->to_string(), - v->to_code_string(), - name->to_string(), - new_var->to_code_string()); + error::warn( + util::format("'{}' already referred to {} in namespace '{}' but has been replaced by {}", + unqualified_sym->to_string(), + v->to_code_string(), + name->to_string(), + new_var->to_code_string())); } *locked_vars = make_box((*locked_vars)->data.set(unqualified_sym, new_var)); diff --git a/compiler+runtime/src/cpp/jank/util/cli.cpp b/compiler+runtime/src/cpp/jank/util/cli.cpp index 8752374d4..ab4e6dfc0 100644 --- a/compiler+runtime/src/cpp/jank/util/cli.cpp +++ b/compiler+runtime/src/cpp/jank/util/cli.cpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace jank::util::cli { @@ -175,6 +176,12 @@ namespace jank::util::cli opts.command = command::check_health; } + if(opts.codegen == codegen_type::llvm_ir) + { + error::warn( + "LLVM IR code generation is currently unstable and incomplete. Use at your own risk."); + } + return ok(); } diff --git a/compiler+runtime/src/cpp/jtl/string_builder.cpp b/compiler+runtime/src/cpp/jtl/string_builder.cpp index 3c683c534..3cd52f8c1 100644 --- a/compiler+runtime/src/cpp/jtl/string_builder.cpp +++ b/compiler+runtime/src/cpp/jtl/string_builder.cpp @@ -122,18 +122,18 @@ namespace jtl string_builder &string_builder::operator()(float const d) & { - /* snprintf %f implicitly casts to double anyway. */ + /* snprintf %G implicitly casts to double anyway. */ return (*this)(static_cast(d)); } string_builder &string_builder::operator()(double const d) & { /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) */ - auto const required{ snprintf(nullptr, 0, "%f", d) }; + auto const required{ snprintf(nullptr, 0, "%G", d) }; maybe_realloc(*this, required); /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) */ - snprintf(buffer + pos, capacity - pos, "%f", d); + snprintf(buffer + pos, capacity - pos, "%G", d); pos += required; return *this; From 5bb730626da19469c6d47a15057fb2add6663094 Mon Sep 17 00:00:00 2001 From: jeaye Date: Wed, 26 Nov 2025 13:33:48 -0800 Subject: [PATCH 041/122] Lift macro derefs too This was needed to support some `is` usages within the clojure-test-suite. --- compiler+runtime/src/cpp/jank/analyze/processor.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index ac1fdffd5..2f4663a6e 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -1597,12 +1597,7 @@ namespace jank::analyze latest_expansion(macro_expansions)); } - /* Macros aren't lifted, since they're not used during runtime. */ - auto const macro_kw(__rt_ctx->intern_keyword("", "macro", true).expect_ok()); - if(var->meta.is_none() || get(var->meta.unwrap(), macro_kw).is_nil()) - { - current_frame->lift_var(var); - } + current_frame->lift_var(var); return jtl::make_ref(position, current_frame, true, qualified_sym, var); } From d416973dd5ca682f4df5260c9949f877bed91f47 Mon Sep 17 00:00:00 2001 From: jeaye Date: Wed, 26 Nov 2025 13:52:49 -0800 Subject: [PATCH 042/122] Test string_builder inf/nan --- .../src/cpp/jtl/string_builder.cpp | 6 +++--- .../test/cpp/jtl/string_builder.cpp | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/compiler+runtime/src/cpp/jtl/string_builder.cpp b/compiler+runtime/src/cpp/jtl/string_builder.cpp index 3cd52f8c1..3c683c534 100644 --- a/compiler+runtime/src/cpp/jtl/string_builder.cpp +++ b/compiler+runtime/src/cpp/jtl/string_builder.cpp @@ -122,18 +122,18 @@ namespace jtl string_builder &string_builder::operator()(float const d) & { - /* snprintf %G implicitly casts to double anyway. */ + /* snprintf %f implicitly casts to double anyway. */ return (*this)(static_cast(d)); } string_builder &string_builder::operator()(double const d) & { /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) */ - auto const required{ snprintf(nullptr, 0, "%G", d) }; + auto const required{ snprintf(nullptr, 0, "%f", d) }; maybe_realloc(*this, required); /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) */ - snprintf(buffer + pos, capacity - pos, "%G", d); + snprintf(buffer + pos, capacity - pos, "%f", d); pos += required; return *this; diff --git a/compiler+runtime/test/cpp/jtl/string_builder.cpp b/compiler+runtime/test/cpp/jtl/string_builder.cpp index 61f0d4b94..bcfcdde96 100644 --- a/compiler+runtime/test/cpp/jtl/string_builder.cpp +++ b/compiler+runtime/test/cpp/jtl/string_builder.cpp @@ -89,6 +89,24 @@ namespace jtl CHECK_EQ("3.140000", sb.view()); } + TEST_CASE("infinity") + { + string_builder sb; + sb(INFINITY); + CHECK_EQ(3, sb.pos); + CHECK_EQ(initial_capacity, sb.capacity); + CHECK_EQ("inf", sb.view()); + } + + TEST_CASE("nan") + { + string_builder sb; + sb(NAN); + CHECK_EQ(3, sb.pos); + CHECK_EQ(initial_capacity, sb.capacity); + CHECK_EQ("nan", sb.view()); + } + TEST_CASE("char32_t") { string_builder sb; From 3e0ef7a7d8923307a72429a4aa43f6fef9f8cedf Mon Sep 17 00:00:00 2001 From: jeaye Date: Wed, 26 Nov 2025 15:15:28 -0800 Subject: [PATCH 043/122] Improve profile output --- .../include/cpp/jank/jit/processor.hpp | 6 +++++ .../src/cpp/jank/codegen/llvm_processor.cpp | 2 +- .../src/cpp/jank/codegen/processor.cpp | 25 ++++++++++++++++++- compiler+runtime/src/cpp/jank/evaluate.cpp | 15 +++-------- .../src/cpp/jank/jit/processor.cpp | 12 ++++++--- .../src/cpp/jank/runtime/context.cpp | 2 ++ 6 files changed, 46 insertions(+), 16 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/jit/processor.hpp b/compiler+runtime/include/cpp/jank/jit/processor.hpp index ca870111a..b133f45f2 100644 --- a/compiler+runtime/include/cpp/jank/jit/processor.hpp +++ b/compiler+runtime/include/cpp/jank/jit/processor.hpp @@ -17,6 +17,11 @@ namespace llvm } } +namespace clang +{ + class Value; +} + namespace Cpp { class Interpreter; @@ -30,6 +35,7 @@ namespace jank::jit ~processor(); void eval_string(jtl::immutable_string const &s) const; + void eval_string(jtl::immutable_string const &s, clang::Value *) const; void load_object(jtl::immutable_string_view const &path) const; void load_dynamic_library(jtl::immutable_string const &path) const; void load_ir_module(llvm::orc::ThreadSafeModule &&m) const; diff --git a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp index 654a4ef8a..ac3a1df04 100644 --- a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp @@ -735,7 +735,7 @@ namespace jank::codegen jtl::string_result llvm_processor::impl::gen() { - profile::timer const timer{ "ir gen" }; + profile::timer const timer{ util::format("ir gen {}", root_fn->name) }; if(target != compilation_target::function) { create_global_ctor(); diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 56fb27662..b572e539b 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include /* The strategy for codegen to C++ is quite simple. Codegen always happens on a @@ -1436,7 +1437,7 @@ namespace jank::codegen jtl::option processor::gen(expr::cpp_raw_ref const expr, expr::function_arity const &) { - util::format_to(deps_buffer, "{}\n", expr->code); + util::format_to(deps_buffer, "\n{}\n", expr->code); if(expr->position == analyze::expression_position::tail) { @@ -1996,6 +1997,7 @@ namespace jank::codegen { if(!generated_declaration) { + profile::timer const timer{ util::format("cpp gen {}", root_fn->name) }; build_header(); build_body(); build_footer(); @@ -2283,7 +2285,28 @@ namespace jank::codegen util::format_to(footer_buffer, "extern \"C\" void* {}(){", runtime::module::module_to_load_function(module)); + + /* First thing we do when loading this module is to intern our ns. Everything else will + * build on that. */ util::format_to(footer_buffer, "jank_ns_intern_c(\"{}\");", module); + + /* This dance is performed to keep symbol names unique across all the modules. + * Considering LLVM JIT symbols to be global, we need to define them with + * unique names to avoid conflicts during JIT recompilation/reloading. + * + * The approach, right now, is for each namespace, we will keep a counter + * and will increase it every time we define a new symbol. When we JIT reload + * the same namespace again, we will define new symbols. + * + * This IR codegen for calling `jank_ns_set_symbol_counter`, is to set the counter + * on an initial load. + */ + auto const current_ns{ __rt_ctx->current_ns() }; + util::format_to(footer_buffer, + "jank_ns_set_symbol_counter(\"{}\", {});", + current_ns->name->get_name(), + current_ns->symbol_counter.load()); + util::format_to(footer_buffer, "return {}::{}{ }.call().erase();", runtime::module::module_to_native_ns(module), diff --git a/compiler+runtime/src/cpp/jank/evaluate.cpp b/compiler+runtime/src/cpp/jank/evaluate.cpp index 83837010f..aa2c1aab5 100644 --- a/compiler+runtime/src/cpp/jank/evaluate.cpp +++ b/compiler+runtime/src/cpp/jank/evaluate.cpp @@ -20,7 +20,6 @@ #include #include #include -#include namespace jank::evaluate { @@ -267,7 +266,8 @@ namespace jank::evaluate object_ref eval(expression_ref const ex) { - profile::timer const timer{ "eval ast node" }; + profile::timer const timer{ util::format("eval ast node {}", + analyze::expression_kind_str(ex->kind)) }; object_ref ret{}; visit_expr([&ret](auto const typed_ex) { ret = eval(typed_ex); }, ex); return ret; @@ -580,6 +580,7 @@ namespace jank::evaluate object_ref eval(expr::function_ref const expr) { + profile::timer const timer{ util::format("eval jit function {}", expr->name) }; auto const &module( module::nest_module(expect_object(__rt_ctx->current_ns_var->deref())->to_string(), munge(expr->unique_name))); @@ -616,15 +617,7 @@ namespace jank::evaluate __rt_ctx->jit_prc.eval_string(cg_prc.declaration_str()); auto const expr_str{ cg_prc.expression_str() + ".erase()" }; clang::Value v; - auto res( - __rt_ctx->jit_prc.interpreter->ParseAndExecute({ expr_str.data(), expr_str.size() }, &v)); - if(res) - { - /* TODO: Helper to turn an llvm::Error into a string. */ - jtl::immutable_string const msg{ "Unable to compile/eval C++ source." }; - llvm::logAllUnhandledErrors(jtl::move(res), llvm::errs(), "error: "); - throw error::internal_codegen_failure(msg); - } + __rt_ctx->jit_prc.eval_string({ expr_str.data(), expr_str.size() }, &v); return try_object(v.convertTo()); } } diff --git a/compiler+runtime/src/cpp/jank/jit/processor.cpp b/compiler+runtime/src/cpp/jank/jit/processor.cpp index 3001f093d..8dcc7512b 100644 --- a/compiler+runtime/src/cpp/jank/jit/processor.cpp +++ b/compiler+runtime/src/cpp/jank/jit/processor.cpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace jank::jit { @@ -230,16 +231,21 @@ namespace jank::jit } void processor::eval_string(jtl::immutable_string const &s) const + { + return eval_string(s, nullptr); + } + + void processor::eval_string(jtl::immutable_string const &s, clang::Value * const ret) const { profile::timer const timer{ "jit eval_string" }; auto const &formatted{ s }; //auto const &formatted{ util::format_cpp_source(s).expect_ok() }; //util::println("// eval_string:\n{}\n", formatted); - auto err(interpreter->ParseAndExecute({ formatted.data(), formatted.size() })); + auto err(interpreter->ParseAndExecute({ formatted.data(), formatted.size() }, ret)); if(err) { - llvm::logAllUnhandledErrors(std::move(err), llvm::errs(), "error: "); - throw std::runtime_error{ "Failed to evaluate C++ code." }; + llvm::logAllUnhandledErrors(jtl::move(err), llvm::errs(), "error: "); + throw error::internal_codegen_failure("Unable to compile C++ source."); } register_jit_stack_frames(); } diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 3af7ab700..347f0b145 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -181,6 +181,7 @@ namespace jank::runtime * targeted at AOT and doesn't have access to what's loaded in the JIT runtime. */ if(truthy(compile_files_var->deref())) { + profile::timer const timer{ "rt compile-module" }; auto const &module(runtime::to_string(current_module_var->deref())); auto const name{ module::module_to_load_function(module) }; @@ -203,6 +204,7 @@ namespace jank::runtime } else { + profile::timer const timer{ "rt compile-module parse + write" }; codegen::processor cg_prc{ fn, module, codegen::compilation_target::module }; //util::println("{}\n", util::format_cpp_source(cg_prc.declaration_str()).expect_ok()); auto const code{ cg_prc.declaration_str() }; From 5b47b3c8c09f3b4ea46e2ad1de1e969e59a3af6b Mon Sep 17 00:00:00 2001 From: jeaye Date: Wed, 26 Nov 2025 16:28:52 -0800 Subject: [PATCH 044/122] Start optimizing cppgen for size 1. Dedupe lifted constants/vars across arities 2. Remove lifting of nil/bools 3. Remove baked in `using namespace` usages Much, much more to go. --- .../include/cpp/jank/codegen/processor.hpp | 2 - .../src/cpp/jank/analyze/processor.cpp | 6 +- .../src/cpp/jank/codegen/processor.cpp | 150 +++++++----------- 3 files changed, 61 insertions(+), 97 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/codegen/processor.hpp b/compiler+runtime/include/cpp/jank/codegen/processor.hpp index a8832e187..4a2166a67 100644 --- a/compiler+runtime/include/cpp/jank/codegen/processor.hpp +++ b/compiler+runtime/include/cpp/jank/codegen/processor.hpp @@ -154,8 +154,6 @@ namespace jank::codegen void build_footer(); jtl::immutable_string expression_str(); - jtl::immutable_string module_init_str(jtl::immutable_string const &module); - void format_dynamic_call(jtl::immutable_string const &source_tmp, jtl::immutable_string const &ret_tmp, native_vector const &arg_exprs, diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index 2f4663a6e..b926056d8 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -2820,7 +2820,11 @@ namespace jank::analyze { auto const pop_macro_expansions{ push_macro_expansions(*this, o) }; - current_frame->lift_constant(o); + /* There's no need to lift these, since we'll just codgen the public constants for them. */ + if(o->type != object_type::nil && o->type != object_type::boolean) + { + current_frame->lift_constant(o); + } return jtl::make_ref(position, current_frame, needs_box, o); } diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index b572e539b..c9bb984d9 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -654,13 +655,26 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::primitive_literal_ref const expr, analyze::expr::function_arity const &) { - auto const &constant(expr->frame->find_lifted_constant(expr->data).unwrap().get()); - - handle ret{ runtime::munge(constant.native_name) }; - if(constant.unboxed_native_name.is_some()) + handle ret; + if(expr->data->type == runtime::object_type::nil) + { + ret = handle{ "jank::runtime::jank_nil" }; + } + else if(expr->data->type == runtime::object_type::boolean) { - ret = { runtime::munge(constant.native_name), - runtime::munge(constant.unboxed_native_name.unwrap()) }; + ret = handle{ runtime::truthy(expr->data) ? "jank::runtime::jank_true" + : "jank::runtime::jank_false" }; + } + else + { + auto const &constant(expr->frame->find_lifted_constant(expr->data).unwrap().get()); + + ret = runtime::munge(constant.native_name); + if(constant.unboxed_native_name.is_some()) + { + ret = { runtime::munge(constant.native_name), + runtime::munge(constant.unboxed_native_name.unwrap()) }; + } } switch(expr->position) @@ -1040,7 +1054,7 @@ namespace jank::codegen if(cpp_util::is_any_object(local_type)) { util::format_to(body_buffer, - "{ object_ref {}({}); ", + "{ jank::runtime::object_ref {}({}); ", munged_name, val_tmp.unwrap().str(true)); } @@ -1323,7 +1337,7 @@ namespace jank::codegen { auto const has_catch{ expr->catch_body.is_some() }; auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("try"))); - util::format_to(body_buffer, "object_ref {}{ };", ret_tmp); + util::format_to(body_buffer, "jank::runtime::object_ref {}{ };", ret_tmp); util::format_to(body_buffer, "{"); if(expr->finally_body.is_some()) @@ -2020,17 +2034,7 @@ namespace jank::codegen void processor::build_header() { - /* TODO: We don't want this for nested modules, but we do if they're in their own file. - * Do we need three module compilation targets? Top-level, nested, local? - * - * Local fns are within a struct already, so we can't enter the ns again. */ - //if(!runtime::module::is_nested_module(module)) - //if(target == compilation_target::module) - { - util::format_to(header_buffer, - "namespace {} {", - runtime::module::module_to_native_ns(module)); - } + util::format_to(header_buffer, "namespace {} {", runtime::module::module_to_native_ns(module)); util::format_to(header_buffer, R"( @@ -2041,16 +2045,17 @@ namespace jank::codegen { /* TODO: Constants and vars are not shared across arities. We'd need stable names. */ - native_set used_vars, used_constants, used_captures; + native_set used_vars, used_constants, used_captures; for(auto const &arity : root_fn->arities) { for(auto const &v : arity.frame->lifted_vars) { - if(used_vars.contains(v.second.native_name.to_hash())) + auto const hash{ v.first->to_hash() }; + if(used_vars.contains(hash)) { continue; } - used_vars.emplace(v.second.native_name.to_hash()); + used_vars.emplace(hash); util::format_to(header_buffer, "jank::runtime::var_ref const {};", @@ -2059,13 +2064,13 @@ namespace jank::codegen for(auto const &v : arity.frame->lifted_constants) { - if(used_constants.contains(v.second.native_name.to_hash())) + if(used_constants.contains(runtime::to_hash(v.first))) { continue; } - used_constants.emplace(v.second.native_name.to_hash()); + used_constants.emplace(runtime::to_hash(v.first)); - /* TODO: Typed lifted constants. */ + /* TODO: Typed lifted constants (in analysis). */ util::format_to(header_buffer, "{} const {};", detail::gen_constant_type(v.second.data, true), @@ -2075,11 +2080,12 @@ namespace jank::codegen /* TODO: More useful types here. */ for(auto const &v : arity.frame->captures) { - if(used_captures.contains(v.first->to_hash())) + auto const hash{ v.first->to_hash() }; + if(used_captures.contains(hash)) { continue; } - used_captures.emplace(v.first->to_hash()); + used_captures.emplace(hash); /* Captures aren't const since they could be late-assigned, in the case of a letfn. */ util::format_to(header_buffer, @@ -2090,7 +2096,7 @@ namespace jank::codegen } { - native_set used_captures; + native_set used_captures; util::format_to(header_buffer, "{}(", runtime::munge(struct_name.name)); bool need_comma{}; @@ -2098,11 +2104,12 @@ namespace jank::codegen { for(auto const &v : arity.frame->captures) { - if(used_captures.contains(v.first->to_hash())) + auto const hash{ v.first->to_hash() }; + if(used_captures.contains(hash)) { continue; } - used_captures.emplace(v.first->to_hash()); + used_captures.emplace(hash); /* TODO: More useful types here. */ util::format_to(header_buffer, @@ -2115,7 +2122,9 @@ namespace jank::codegen } { - native_set used_vars, used_constants, used_captures; + native_set used_captures; + native_map used_vars; + native_map used_constants; util::format_to(header_buffer, ") : jank::runtime::obj::jit_function{ "); /* TODO: All of the meta in clojure.core alone costs 2s to JIT compile at run-time. * How can this be faster? */ @@ -2124,13 +2133,16 @@ namespace jank::codegen for(auto const &arity : root_fn->arities) { - for(auto const &v : arity.frame->lifted_vars) + for(auto &v : arity.frame->lifted_vars) { - if(used_vars.contains(v.second.native_name.to_hash())) + auto const hash{ v.first->to_hash() }; + auto const existing{ used_vars.find(hash) }; + if(existing != used_vars.end()) { + v.second = existing->second; continue; } - used_vars.emplace(v.second.native_name.to_hash()); + used_vars.emplace(hash, v.second); util::format_to(header_buffer, R"(, {}{ jank::runtime::__rt_ctx->intern_var("{}", "{}").expect_ok() })", @@ -2139,13 +2151,16 @@ namespace jank::codegen v.second.var_name->name); } - for(auto const &v : arity.frame->lifted_constants) + for(auto &v : arity.frame->lifted_constants) { - if(used_constants.contains(v.second.native_name.to_hash())) + auto const hash{ runtime::to_hash(v.first) }; + auto const existing{ used_constants.find(hash) }; + if(existing != used_constants.end()) { + v.second = existing->second; continue; } - used_constants.emplace(v.second.native_name.to_hash()); + used_constants.emplace(hash, v.second); util::format_to(header_buffer, ", {}{", runtime::munge(v.second.native_name)); detail::gen_constant(v.second.data, header_buffer, true); @@ -2154,11 +2169,12 @@ namespace jank::codegen for(auto const &v : arity.frame->captures) { - if(used_captures.contains(v.first->to_hash())) + auto const hash{ v.first->to_hash() }; + if(used_captures.contains(hash)) { continue; } - used_captures.emplace(v.first->to_hash()); + used_captures.emplace(hash); auto const name{ runtime::munge(v.second.native_name) }; util::format_to(header_buffer, ", {}{ {} }", name, name); @@ -2205,12 +2221,7 @@ namespace jank::codegen param_shadows_fn |= param->name == root_fn->name; } - util::format_to(body_buffer, - R"( - ) final { - using namespace jank; - using namespace jank::runtime; - )"); + util::format_to(body_buffer, ") final {"); //util::format_to(body_buffer, "jank::profile::timer __timer{ \"{}\" };", root_fn->name); @@ -2382,53 +2393,4 @@ namespace jank::codegen } return { expression_buffer.data(), expression_buffer.size() }; } - - /* TODO: Not sure if we want any of this. The module dependency loading feels wrong, - * since it should be tied to calls to require instead. */ - jtl::immutable_string processor::module_init_str(jtl::immutable_string const &module) - { - jtl::string_builder module_buffer; - - util::format_to(module_buffer, "namespace {} {", runtime::module::module_to_native_ns(module)); - - util::format_to(module_buffer, - R"( - struct __ns__init - { - )"); - - util::format_to(module_buffer, "static void __init(){"); - //util::format_to(module_buffer, "jank::profile::timer __timer{ \"ns __init\" };"); - util::format_to(module_buffer, - "constexpr auto const deps(jank::util::make_array("); - bool needs_comma{}; - for(auto const &dep : __rt_ctx->module_dependencies[module]) - { - if(needs_comma) - { - util::format_to(module_buffer, ", "); - } - util::format_to(module_buffer, "\"/{}\"", dep); - needs_comma = true; - } - util::format_to(module_buffer, "));"); - - util::format_to(module_buffer, "for(auto const &dep : deps){"); - util::format_to(module_buffer, "jank::runtime::__rt_ctx->load_module(dep).expect_ok();"); - util::format_to(module_buffer, "}"); - - /* __init fn */ - util::format_to(module_buffer, "}"); - - /* Struct */ - util::format_to(module_buffer, "};"); - - /* Namespace */ - util::format_to(module_buffer, "}"); - - native_transient_string ret; - ret.reserve(module_buffer.size()); - ret += jtl::immutable_string_view{ module_buffer.data(), module_buffer.size() }; - return ret; - } } From ac27ef94729160afb9ccc962d65d9b0b1122dd03 Mon Sep 17 00:00:00 2001 From: jeaye Date: Wed, 26 Nov 2025 18:59:55 -0800 Subject: [PATCH 045/122] Move lifted constants and vars to codegen We want to dedupe them by arity, which gives us just as much work in codegen as tracking them normally would, if not more. This also gives each codegen processor its own flexibility about which things to lift and at which scope to do it. --- .../include/cpp/jank/analyze/local_frame.hpp | 33 --- .../include/cpp/jank/codegen/processor.hpp | 6 + .../include/cpp/jank/runtime/context.hpp | 23 ++- .../src/cpp/jank/analyze/local_frame.cpp | 89 +------- .../src/cpp/jank/analyze/processor.cpp | 29 +-- .../src/cpp/jank/codegen/llvm_processor.cpp | 88 ++++---- .../src/cpp/jank/codegen/processor.cpp | 194 +++++++++--------- compiler+runtime/src/cpp/jank/evaluate.cpp | 13 +- .../src/cpp/jank/runtime/context.cpp | 36 ++-- 9 files changed, 190 insertions(+), 321 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp b/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp index a76a19852..4c02ddcdb 100644 --- a/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp @@ -30,25 +30,6 @@ namespace jank::analyze using function_context_ref = jtl::ref; } - struct lifted_var - { - jtl::immutable_string native_name{}; - runtime::obj::symbol_ref var_name{}; - - runtime::object_ref to_runtime_data() const; - }; - - /* TODO: Track constant usages to figure out if boxing is needed at all, - * rather than just doing both. */ - struct lifted_constant - { - jtl::immutable_string native_name{}; - jtl::option unboxed_native_name{}; - runtime::object_ref data{}; - - runtime::object_ref to_runtime_data() const; - }; - struct local_binding { runtime::obj::symbol_ref name{}; @@ -136,14 +117,6 @@ namespace jank::analyze static bool within_same_fn(jtl::ptr, jtl::ptr); - void lift_var(runtime::var_ref const &); - jtl::option> - find_lifted_var(runtime::obj::symbol_ref const &) const; - - void lift_constant(runtime::object_ref); - jtl::option> - find_lifted_constant(runtime::object_ref) const; - static local_frame const &find_closest_fn_frame(local_frame const &frame); static local_frame &find_closest_fn_frame(local_frame &frame); @@ -153,12 +126,6 @@ namespace jank::analyze jtl::option> parent; native_unordered_map locals; native_unordered_map captures; - native_unordered_map lifted_vars; - native_unordered_map, - runtime::very_equal_to> - lifted_constants; /* This is only set if the frame type is fn. */ jtl::ptr fn_ctx; }; diff --git a/compiler+runtime/include/cpp/jank/codegen/processor.hpp b/compiler+runtime/include/cpp/jank/codegen/processor.hpp index 4a2166a67..51d40ee45 100644 --- a/compiler+runtime/include/cpp/jank/codegen/processor.hpp +++ b/compiler+runtime/include/cpp/jank/codegen/processor.hpp @@ -170,6 +170,12 @@ namespace jank::codegen jtl::string_builder footer_buffer; jtl::string_builder expression_buffer; jtl::immutable_string expression_fn_name; + native_unordered_map lifted_vars; + native_unordered_map, + runtime::very_equal_to> + lifted_constants; bool generated_declaration{}; bool generated_expression{}; }; diff --git a/compiler+runtime/include/cpp/jank/runtime/context.hpp b/compiler+runtime/include/cpp/jank/runtime/context.hpp index c1ac657ff..50adda9ea 100644 --- a/compiler+runtime/include/cpp/jank/runtime/context.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/context.hpp @@ -59,7 +59,8 @@ namespace jank::runtime obj::symbol_ref qualify_symbol(obj::symbol_ref const &) const; jtl::option find_local(obj::symbol_ref const &); - jtl::result intern_var(obj::symbol_ref const &); + jtl::result intern_var(obj::symbol_ref const &qualified_name); + jtl::result intern_var(jtl::immutable_string const &); jtl::result intern_var(jtl::immutable_string const &ns, jtl::immutable_string const &name); jtl::result intern_owned_var(obj::symbol_ref const &); @@ -79,11 +80,11 @@ namespace jank::runtime object_ref macroexpand(object_ref o); object_ref eval_file(jtl::immutable_string const &path); - object_ref eval_string(jtl::immutable_string_view const &code); - jtl::result eval_cpp_string(jtl::immutable_string_view const &code) const; - object_ref read_string(jtl::immutable_string_view const &code); + object_ref eval_string(jtl::immutable_string const &code); + jtl::result eval_cpp_string(jtl::immutable_string const &code) const; + object_ref read_string(jtl::immutable_string const &code); native_vector - analyze_string(jtl::immutable_string_view const &code, bool const eval = true); + analyze_string(jtl::immutable_string const &code, bool const eval = true); /* Finds the specified module on the module path and loads it. If * the module is already loaded, nothing is done. @@ -97,10 +98,10 @@ namespace jank::runtime * Module meow.cat refers to foo.bar$meow.cat */ jtl::result - load_module(jtl::immutable_string_view const &module, module::origin ori); + load_module(jtl::immutable_string const &module, module::origin ori); /* Does all the same work as load_module, but also writes compiled files to the file system. */ - jtl::result compile_module(jtl::immutable_string_view const &module); + jtl::result compile_module(jtl::immutable_string const &module); object_ref eval(object_ref const o); @@ -110,11 +111,11 @@ namespace jank::runtime /* Generates a unique name for use with anything from codgen structs, * lifted vars, to shadowed locals. Prefixes with current namespace. */ jtl::immutable_string unique_namespaced_string() const; - jtl::immutable_string unique_namespaced_string(jtl::immutable_string_view const &prefix) const; - jtl::immutable_string unique_munged_string() const; - jtl::immutable_string unique_munged_string(jtl::immutable_string_view const &prefix) const; + jtl::immutable_string unique_namespaced_string(jtl::immutable_string const &prefix) const; + jtl::immutable_string unique_string() const; + jtl::immutable_string unique_string(jtl::immutable_string const &prefix) const; obj::symbol unique_symbol() const; - obj::symbol unique_symbol(jtl::immutable_string_view const &prefix) const; + obj::symbol unique_symbol(jtl::immutable_string const &prefix) const; folly::Synchronized> namespaces; folly::Synchronized> keywords; diff --git a/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp b/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp index 7d2456b5e..523014dbf 100644 --- a/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp @@ -14,16 +14,6 @@ namespace jank::analyze { using namespace jank::runtime; - object_ref lifted_var::to_runtime_data() const - { - return obj::persistent_array_map::create_unique(make_box("var_name"), var_name); - } - - object_ref lifted_constant::to_runtime_data() const - { - return obj::persistent_array_map::create_unique(make_box("data"), data); - } - object_ref local_binding::to_runtime_data() const { return obj::persistent_array_map::create_unique( @@ -190,78 +180,15 @@ namespace jank::analyze return &find_closest_fn_frame(*l) == &find_closest_fn_frame(*r); } - void local_frame::lift_var(var_ref const &var) - { - auto &closest_fn(find_closest_fn_frame(*this)); - auto const qualified_sym{ make_box(var->n->name->name, var->name->name) }; - auto const &found(closest_fn.lifted_vars.find(qualified_sym)); - if(found != closest_fn.lifted_vars.end()) - { - return; - } - - /* We use unique native names, just so var names don't clash with the underlying C++ API. */ - lifted_var lv{ __rt_ctx->unique_namespaced_string(munge(qualified_sym->name)), qualified_sym }; - closest_fn.lifted_vars.emplace(qualified_sym, jtl::move(lv)); - } - - jtl::option> - local_frame::find_lifted_var(obj::symbol_ref const &sym) const - { - auto const &closest_fn(find_closest_fn_frame(*this)); - auto const &found(closest_fn.lifted_vars.find(sym)); - if(found != closest_fn.lifted_vars.end()) - { - return some(std::ref(found->second)); - } - return none; - } - - void local_frame::lift_constant(object_ref const constant) - { - auto &closest_fn(find_closest_fn_frame(*this)); - auto const &found(closest_fn.lifted_constants.find(constant)); - if(found != closest_fn.lifted_constants.end()) - { - return; - } - - auto const name(__rt_ctx->unique_symbol("const")); - auto const unboxed_name{ visit_number_like( - [&](auto const) -> jtl::option { return name.name + "__unboxed"; }, - []() -> jtl::option { return none; }, - constant) }; - - lifted_constant l{ name.name, unboxed_name, constant }; - closest_fn.lifted_constants.emplace(constant, std::move(l)); - } - - jtl::option> - local_frame::find_lifted_constant(object_ref const o) const - { - auto const &closest_fn(find_closest_fn_frame(*this)); - auto const &found(closest_fn.lifted_constants.find(o)); - if(found != closest_fn.lifted_constants.end()) - { - return some(std::ref(found->second)); - } - return none; - } - object_ref local_frame::to_runtime_data() const { - return obj::persistent_array_map::create_unique( - make_box("type"), - make_box(frame_type_str(type)), - make_box("parent"), - jank::detail::to_runtime_data(parent), - make_box("locals"), - jank::detail::to_runtime_data(locals), - make_box("captures"), - jank::detail::to_runtime_data(captures), - make_box("lifted_vars"), - jank::detail::to_runtime_data(lifted_vars), - make_box("lifted_constants"), - jank::detail::to_runtime_data(lifted_constants)); + return obj::persistent_array_map::create_unique(make_box("type"), + make_box(frame_type_str(type)), + make_box("parent"), + jank::detail::to_runtime_data(parent), + make_box("locals"), + jank::detail::to_runtime_data(locals), + make_box("captures"), + jank::detail::to_runtime_data(captures)); } } diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index b926056d8..6c73b33b0 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -942,7 +943,9 @@ namespace jank::analyze latest_expansion(macro_expansions)); } if(is_ctor - && Cpp::IsAggregateConstructible(val->type, arg_types, __rt_ctx->unique_munged_string())) + && Cpp::IsAggregateConstructible(val->type, + arg_types, + runtime::munge(__rt_ctx->unique_namespaced_string()))) { //util::println("using aggregate initializaation"); return jtl::make_ref(position, @@ -1293,8 +1296,6 @@ namespace jank::analyze latest_expansion(macro_expansions)); } - current_frame->lift_var(var_res.expect_ok()); - jtl::option> value_expr; bool const has_value{ 3 <= length }; bool const has_docstring{ 4 <= length }; @@ -1337,13 +1338,6 @@ namespace jank::analyze qualified_sym = qualified_sym->with_meta(meta_with_doc); } - /* Lift this so it can be used during codegen. */ - /* TODO: I don't think lifting meta is actually needed anymore. Verify. */ - if(qualified_sym->meta.is_some()) - { - current_frame->lift_constant(qualified_sym->meta.unwrap()); - } - return jtl::make_ref(position, current_frame, true, qualified_sym, value_expr); } @@ -1597,7 +1591,6 @@ namespace jank::analyze latest_expansion(macro_expansions)); } - current_frame->lift_var(var); return jtl::make_ref(position, current_frame, true, qualified_sym, var); } @@ -2550,7 +2543,6 @@ namespace jank::analyze meta_source(o->meta), latest_expansion(macro_expansions)); } - current_frame->lift_var(found_var); return jtl::make_ref(position, current_frame, @@ -2569,7 +2561,6 @@ namespace jank::analyze auto const pop_macro_expansions{ push_macro_expansions(*this, o) }; auto const qualified_sym(__rt_ctx->qualify_symbol(o->to_qualified_symbol())); - current_frame->lift_var(o); return jtl::make_ref(position, current_frame, true, qualified_sym, o); } @@ -2819,12 +2810,6 @@ namespace jank::analyze bool const needs_box) { auto const pop_macro_expansions{ push_macro_expansions(*this, o) }; - - /* There's no need to lift these, since we'll just codgen the public constants for them. */ - if(o->type != object_type::nil && o->type != object_type::boolean) - { - current_frame->lift_constant(o); - } return jtl::make_ref(position, current_frame, needs_box, o); } @@ -2869,9 +2854,6 @@ namespace jank::analyze jtl::make_ref(position, current_frame, true, std::move(exprs), o->meta)); auto const o(evaluate::eval(pre_eval_expr)); - /* TODO: Order lifted constants. Use sub constants during codegen. */ - current_frame->lift_constant(o); - return jtl::make_ref(position, current_frame, true, o); } @@ -2980,9 +2962,6 @@ namespace jank::analyze typed_o->meta)); auto const constant(evaluate::eval(pre_eval_expr)); - /* TODO: Order lifted constants. Use sub constants during codegen. */ - current_frame->lift_constant(constant); - return jtl::make_ref(position, current_frame, true, constant); } diff --git a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp index ac3a1df04..27d49c296 100644 --- a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp @@ -210,6 +210,16 @@ namespace jank::codegen usize alignment{}; }; + static jtl::immutable_string unique_munged_string() + { + return runtime::munge(__rt_ctx->unique_namespaced_string()); + } + + static jtl::immutable_string unique_munged_string(jtl::immutable_string const &prefix) + { + return runtime::munge(__rt_ctx->unique_namespaced_string(prefix)); + } + static llvm::Type *llvm_builtin_type(reusable_context const &ctx, jtl::ref const llvm_ctx, jtl::ptr const type) @@ -409,7 +419,7 @@ namespace jank::codegen || Cpp::IsPointerType(param_type) /*|| Cpp::IsArrayType(param_type)*/) }; - auto const fn_callable{ Cpp::MakeAotCallable(match, __rt_ctx->unique_munged_string()) }; + auto const fn_callable{ Cpp::MakeAotCallable(match, unique_munged_string()) }; link_module(ctx, reinterpret_cast(fn_callable.getModule())); llvm::Value *arg_alloc{ arg }; @@ -515,7 +525,7 @@ namespace jank::codegen reusable_context::reusable_context(jtl::immutable_string const &module_name, std::unique_ptr llvm_ctx) : module_name{ module_name } - , ctor_name{ __rt_ctx->unique_munged_string("jank_global_init") } + , ctor_name{ unique_munged_string("jank_global_init") } //, llvm_ctx{ std::make_unique() } //, llvm_ctx{ reinterpret_cast *>( // reinterpret_cast( @@ -527,8 +537,7 @@ namespace jank::codegen , mam{ std::make_unique() } , pic{ std::make_unique() } { - auto m{ std::make_unique(__rt_ctx->unique_munged_string(module_name).c_str(), - *llvm_ctx) }; + auto m{ std::make_unique(unique_munged_string(module_name).c_str(), *llvm_ctx) }; module = llvm::orc::ThreadSafeModule{ std::move(m), std::move(llvm_ctx) }; auto const raw_ctx{ extract_context(module) }; @@ -1853,7 +1862,7 @@ namespace jank::codegen /* We also need to surface this RTTI upward, to the module level, so it * can end up in the generated object file. */ auto const callable{ - Cpp::MakeRTTICallable(catch_type, exception_rtti, __rt_ctx->unique_munged_string()) + Cpp::MakeRTTICallable(catch_type, exception_rtti, unique_munged_string()) }; global_rtti.emplace(exception_rtti, callable); } @@ -2213,14 +2222,14 @@ namespace jank::codegen return alloc; } - auto const callable{ Cpp::IsFunctionPointerType(expr->type) - /* We pass the type and the scope in here so that unresolved template + auto const callable{ + Cpp::IsFunctionPointerType(expr->type) + /* We pass the type and the scope in here so that unresolved template * scopes can be turned into the correct specialization which matches * the type we have. */ - ? Cpp::MakeFunctionValueAotCallable(expr->scope, - expr->type, - __rt_ctx->unique_munged_string()) - : Cpp::MakeAotCallable(expr->scope, __rt_ctx->unique_munged_string()) }; + ? Cpp::MakeFunctionValueAotCallable(expr->scope, expr->type, unique_munged_string()) + : Cpp::MakeAotCallable(expr->scope, unique_munged_string()) + }; jank_debug_assert(callable); link_module(*ctx, reinterpret_cast(callable.getModule())); @@ -2471,30 +2480,28 @@ namespace jank::codegen if(expr->source_expr->kind == expression_kind::cpp_value) { auto const source{ llvm::cast(expr->source_expr.data) }; - return gen_aot_call( - Cpp::MakeAotCallable(source->scope, arg_types, __rt_ctx->unique_munged_string()), - source->scope, - expr->type, - Cpp::GetName(source->scope), - expr->arg_exprs, - expr->position, - expr->kind, - arity); + return gen_aot_call(Cpp::MakeAotCallable(source->scope, arg_types, unique_munged_string()), + source->scope, + expr->type, + Cpp::GetName(source->scope), + expr->arg_exprs, + expr->position, + expr->kind, + arity); } else { auto const source_type{ cpp_util::expression_type(expr->source_expr) }; auto arg_exprs{ expr->arg_exprs }; arg_exprs.insert(arg_exprs.begin(), expr->source_expr); - return gen_aot_call( - Cpp::MakeApplyCallable(source_type, arg_types, __rt_ctx->unique_munged_string()), - nullptr, - expr->type, - "call", - jtl::move(arg_exprs), - expr->position, - expr->kind, - arity); + return gen_aot_call(Cpp::MakeApplyCallable(source_type, arg_types, unique_munged_string()), + nullptr, + expr->type, + "call", + jtl::move(arg_exprs), + expr->position, + expr->kind, + arity); } } @@ -2512,7 +2519,7 @@ namespace jank::codegen * We can save ourselves the time of JIT compiling more C++ and make the IR easier * to optimize. */ ctor_fn_callable - = Cpp::MakeBuiltinConstructorAotCallable(expr->type, __rt_ctx->unique_munged_string()); + = Cpp::MakeBuiltinConstructorAotCallable(expr->type, unique_munged_string()); } else { @@ -2523,7 +2530,7 @@ namespace jank::codegen ctor_fn_callable = Cpp::MakeBuiltinConstructorAotCallable(expr->type, needs_conversion ? expr->type : arg_type, - __rt_ctx->unique_munged_string()); + unique_munged_string()); } } else if(expr->is_aggregate) @@ -2533,15 +2540,14 @@ namespace jank::codegen { arg_types.emplace_back(cpp_util::expression_type(arg_expr)); } - ctor_fn_callable - = Cpp::MakeAggregateInitializationAotCallable(expr->type, - arg_types, - __rt_ctx->unique_munged_string()); + ctor_fn_callable = Cpp::MakeAggregateInitializationAotCallable(expr->type, + arg_types, + unique_munged_string()); } else { jank_debug_assert(expr->fn); - ctor_fn_callable = Cpp::MakeAotCallable(expr->fn, __rt_ctx->unique_munged_string()); + ctor_fn_callable = Cpp::MakeAotCallable(expr->fn, unique_munged_string()); } jank_debug_assert(ctor_fn_callable); @@ -2565,7 +2571,7 @@ namespace jank::codegen llvm::Value * llvm_processor::impl::gen(expr::cpp_member_call_ref const expr, expr::function_arity const &arity) { - return gen_aot_call(Cpp::MakeAotCallable(expr->fn, __rt_ctx->unique_munged_string()), + return gen_aot_call(Cpp::MakeAotCallable(expr->fn, unique_munged_string()), expr->fn, cpp_util::expression_type(expr), Cpp::GetName(expr->fn), @@ -2578,7 +2584,7 @@ namespace jank::codegen llvm::Value *llvm_processor::impl::gen(expr::cpp_member_access_ref const expr, expr::function_arity const &arity) { - return gen_aot_call(Cpp::MakeAotCallable(expr->scope, __rt_ctx->unique_munged_string()), + return gen_aot_call(Cpp::MakeAotCallable(expr->scope, unique_munged_string()), nullptr, expr->type, Cpp::GetName(expr->scope), @@ -2654,7 +2660,7 @@ namespace jank::codegen return gen_aot_call(Cpp::MakeBuiltinOperatorAotCallable(static_cast(expr->op), expr->type, arg_types, - __rt_ctx->unique_munged_string()), + unique_munged_string()), nullptr, expr->type, name.getAsString(), @@ -2755,7 +2761,7 @@ namespace jank::codegen if(!Cpp::IsTriviallyDestructible(expr->type)) { auto const dtor{ Cpp::GetDestructor(Cpp::GetScopeFromType(expr->type)) }; - auto const dtor_callable{ Cpp::MakeAotCallable(dtor, __rt_ctx->unique_munged_string()) }; + auto const dtor_callable{ Cpp::MakeAotCallable(dtor, unique_munged_string()) }; link_module(*ctx, reinterpret_cast(dtor_callable.getModule())); auto const reg_fn_type(llvm::FunctionType::get(ctx->builder->getVoidTy(), @@ -2803,7 +2809,7 @@ namespace jank::codegen if(!Cpp::IsTriviallyDestructible(value_type)) { auto const dtor{ Cpp::GetDestructor(Cpp::GetScopeFromType(value_type)) }; - auto const dtor_callable{ Cpp::MakeAotCallable(dtor, __rt_ctx->unique_munged_string()) }; + auto const dtor_callable{ Cpp::MakeAotCallable(dtor, unique_munged_string()) }; link_module(*ctx, reinterpret_cast(dtor_callable.getModule())); auto const dtor_fn_type( diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index c9bb984d9..09ddef423 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -484,17 +484,53 @@ namespace jank::codegen return ret; } + static jtl::immutable_string + lift_var(native_unordered_map &lifted_vars, + jtl::immutable_string const &qualified_name) + { + auto const existing{ lifted_vars.find(qualified_name) }; + if(existing != lifted_vars.end()) + { + return existing->second; + } + + static jtl::immutable_string const dot{ "\\." }; + auto const us{ __rt_ctx->unique_string(qualified_name) }; + auto const native_name{ runtime::munge_and_replace(us, dot, "_") }; + //util::println("lifting var '{}' with '{}' as '{}'", qualified_name, us, native_name); + lifted_vars.emplace(qualified_name, native_name); + return native_name; + } + + static jtl::immutable_string + lift_constant(native_unordered_map, + runtime::very_equal_to> &lifted_constants, + object_ref const &o) + { + auto const existing{ lifted_constants.find(o) }; + if(existing != lifted_constants.end()) + { + return existing->second; + } + + auto const &native_name{ runtime::munge(__rt_ctx->unique_namespaced_string("const")) }; + //util::println("lifting constant {} as {}", runtime::to_code_string(o), native_name); + lifted_constants.emplace(o, native_name); + return native_name; + } + jtl::option processor::gen(analyze::expr::def_ref const expr, analyze::expr::function_arity const &fn_arity) { - auto const &var(expr->frame->find_lifted_var(expr->name).unwrap().get()); - auto const &munged_name(runtime::munge(var.native_name)); - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string(munged_name))); + auto const &var(lift_var(lifted_vars, expr->name->to_string())); + auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string(var))); - jtl::option> meta; + jtl::option meta; if(expr->name->meta.is_some()) { - meta = expr->frame->find_lifted_constant(expr->name->meta.unwrap()).unwrap(); + meta = lift_constant(lifted_constants, expr->name->meta.unwrap()); } /* Forward declarations just intern the var and evaluate to it. */ @@ -503,16 +539,12 @@ namespace jank::codegen if(meta.is_some()) { auto const dynamic{ truthy( - get(meta.unwrap().get().data, __rt_ctx->intern_keyword("dynamic").expect_ok())) }; - return util::format("{}->with_meta({})->set_dynamic({})", - runtime::munge(var.native_name), - runtime::munge(meta.unwrap().get().native_name), - dynamic); + get(expr->name->meta.unwrap(), __rt_ctx->intern_keyword("dynamic").expect_ok())) }; + return util::format("{}->with_meta({})->set_dynamic({})", var, meta.unwrap(), dynamic); } else { - return util::format("{}->with_meta(jank::runtime::jank_nil)", - runtime::munge(var.native_name)); + return util::format("{}->with_meta(jank::runtime::jank_nil)", var); } } @@ -524,17 +556,17 @@ namespace jank::codegen if(meta.is_some()) { auto const dynamic{ truthy( - get(meta.unwrap().get().data, __rt_ctx->intern_keyword("dynamic").expect_ok())) }; + get(expr->name->meta.unwrap(), __rt_ctx->intern_keyword("dynamic").expect_ok())) }; return util::format("{}->bind_root({})->with_meta({})->set_dynamic({})", - runtime::munge(var.native_name), + var, val.str(true), - runtime::munge(meta.unwrap().get().native_name), + meta.unwrap(), dynamic); } else { return util::format("{}->bind_root({})->with_meta(jank::runtime::jank_nil)", - runtime::munge(var.native_name), + var, val.str(true)); } } @@ -548,19 +580,19 @@ namespace jank::codegen if(meta.is_some()) { auto const dynamic{ truthy( - get(meta.unwrap().get().data, __rt_ctx->intern_keyword("dynamic").expect_ok())) }; + get(expr->name->meta.unwrap(), __rt_ctx->intern_keyword("dynamic").expect_ok())) }; util::format_to(body_buffer, "{}->bind_root({})->with_meta({})->set_dynamic({});", - runtime::munge(var.native_name), + var, val.str(true), - runtime::munge(meta.unwrap().get().native_name), + meta.unwrap(), dynamic); } else { util::format_to(body_buffer, "{}->bind_root({})->with_meta(jank::runtime::jank_nil);", - runtime::munge(var.native_name), + var, val.str(true)); } return none; @@ -571,17 +603,17 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::var_deref_ref const expr, analyze::expr::function_arity const &) { - auto const &var(expr->frame->find_lifted_var(expr->var->to_qualified_symbol()).unwrap().get()); + auto const &var(lift_var(lifted_vars, expr->var->to_qualified_symbol()->to_string())); switch(expr->position) { case analyze::expression_position::statement: case analyze::expression_position::value: { - return util::format("{}->deref()", runtime::munge(var.native_name)); + return util::format("{}->deref()", var); } case analyze::expression_position::tail: { - util::format_to(body_buffer, "return {}->deref();", runtime::munge(var.native_name)); + util::format_to(body_buffer, "return {}->deref();", var); return none; } } @@ -590,17 +622,17 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::var_ref_ref const expr, analyze::expr::function_arity const &) { - auto const &var(expr->frame->find_lifted_var(expr->qualified_name).unwrap().get()); + auto const &var(lift_var(lifted_vars, expr->qualified_name->to_string())); switch(expr->position) { case analyze::expression_position::statement: case analyze::expression_position::value: { - return runtime::munge(var.native_name); + return var; } case analyze::expression_position::tail: { - util::format_to(body_buffer, "return {};", runtime::munge(var.native_name)); + util::format_to(body_buffer, "return {};", var); return none; } } @@ -667,14 +699,7 @@ namespace jank::codegen } else { - auto const &constant(expr->frame->find_lifted_constant(expr->data).unwrap().get()); - - ret = runtime::munge(constant.native_name); - if(constant.unboxed_native_name.is_some()) - { - ret = { runtime::munge(constant.native_name), - runtime::munge(constant.unboxed_native_name.unwrap()) }; - } + ret = lift_constant(lifted_constants, expr->data); } switch(expr->position) @@ -2012,8 +2037,8 @@ namespace jank::codegen if(!generated_declaration) { profile::timer const timer{ util::format("cpp gen {}", root_fn->name) }; - build_header(); build_body(); + build_header(); build_footer(); generated_declaration = true; } @@ -2044,39 +2069,9 @@ namespace jank::codegen runtime::munge(struct_name.name)); { - /* TODO: Constants and vars are not shared across arities. We'd need stable names. */ - native_set used_vars, used_constants, used_captures; + native_set used_captures; for(auto const &arity : root_fn->arities) { - for(auto const &v : arity.frame->lifted_vars) - { - auto const hash{ v.first->to_hash() }; - if(used_vars.contains(hash)) - { - continue; - } - used_vars.emplace(hash); - - util::format_to(header_buffer, - "jank::runtime::var_ref const {};", - runtime::munge(v.second.native_name)); - } - - for(auto const &v : arity.frame->lifted_constants) - { - if(used_constants.contains(runtime::to_hash(v.first))) - { - continue; - } - used_constants.emplace(runtime::to_hash(v.first)); - - /* TODO: Typed lifted constants (in analysis). */ - util::format_to(header_buffer, - "{} const {};", - detail::gen_constant_type(v.second.data, true), - runtime::munge(v.second.native_name)); - } - /* TODO: More useful types here. */ for(auto const &v : arity.frame->captures) { @@ -2093,6 +2088,21 @@ namespace jank::codegen runtime::munge(v.second.native_name)); } } + + for(auto const &v : lifted_vars) + { + util::format_to(header_buffer, "jank::runtime::var_ref const {};", v.second); + } + + + for(auto const &v : lifted_constants) + { + /* TODO: Typed lifted constants (in analysis). */ + util::format_to(header_buffer, + "{} const {};", + detail::gen_constant_type(v.first, true), + v.second); + } } { @@ -2123,8 +2133,6 @@ namespace jank::codegen { native_set used_captures; - native_map used_vars; - native_map used_constants; util::format_to(header_buffer, ") : jank::runtime::obj::jit_function{ "); /* TODO: All of the meta in clojure.core alone costs 2s to JIT compile at run-time. * How can this be faster? */ @@ -2133,40 +2141,6 @@ namespace jank::codegen for(auto const &arity : root_fn->arities) { - for(auto &v : arity.frame->lifted_vars) - { - auto const hash{ v.first->to_hash() }; - auto const existing{ used_vars.find(hash) }; - if(existing != used_vars.end()) - { - v.second = existing->second; - continue; - } - used_vars.emplace(hash, v.second); - - util::format_to(header_buffer, - R"(, {}{ jank::runtime::__rt_ctx->intern_var("{}", "{}").expect_ok() })", - runtime::munge(v.second.native_name), - v.second.var_name->ns, - v.second.var_name->name); - } - - for(auto &v : arity.frame->lifted_constants) - { - auto const hash{ runtime::to_hash(v.first) }; - auto const existing{ used_constants.find(hash) }; - if(existing != used_constants.end()) - { - v.second = existing->second; - continue; - } - used_constants.emplace(hash, v.second); - - util::format_to(header_buffer, ", {}{", runtime::munge(v.second.native_name)); - detail::gen_constant(v.second.data, header_buffer, true); - util::format_to(header_buffer, "}"); - } - for(auto const &v : arity.frame->captures) { auto const hash{ v.first->to_hash() }; @@ -2180,6 +2154,22 @@ namespace jank::codegen util::format_to(header_buffer, ", {}{ {} }", name, name); } } + + for(auto const &v : lifted_vars) + { + util::format_to(header_buffer, + R"(, {}{ jank::runtime::__rt_ctx->intern_var("{}").expect_ok() })", + v.second, + v.first); + } + + + for(auto const &v : lifted_constants) + { + util::format_to(header_buffer, ", {}{", v.second); + detail::gen_constant(v.first, header_buffer, true); + util::format_to(header_buffer, "}"); + } } util::format_to(header_buffer, "{ }"); diff --git a/compiler+runtime/src/cpp/jank/evaluate.cpp b/compiler+runtime/src/cpp/jank/evaluate.cpp index aa2c1aab5..ae4632738 100644 --- a/compiler+runtime/src/cpp/jank/evaluate.cpp +++ b/compiler+runtime/src/cpp/jank/evaluate.cpp @@ -129,12 +129,7 @@ namespace jank::evaluate } /* Some expressions don't make sense to eval outright and aren't fns that can be JIT compiled. - * For those, we wrap them in a fn expression and then JIT compile and call them. - * - * There's an oddity here, since that expr wouldn't've been analyzed within a fn frame, so - * its lifted vars/constants, for example, aren't in a fn frame. Instead, they're put in the - * root frame. So, when wrapping this expr, we give the fn the root frame, but change its - * type to a fn frame. */ + * For those, we wrap them in a fn expression and then JIT compile and call them. */ template static expr::function_ref wrap_expression(jtl::ref const orig_expr, jtl::immutable_string const &name, @@ -147,8 +142,6 @@ namespace jank::evaluate ret->unique_name = __rt_ctx->unique_namespaced_string(ret->name); ret->meta = obj::persistent_hash_map::empty(); - auto const &closest_fn_frame(local_frame::find_closest_fn_frame(*expr->frame)); - auto const frame{ jtl::make_ref(local_frame::frame_type::fn, expr->frame->parent) }; auto const fn_ctx{ jtl::make_ref() }; @@ -158,16 +151,12 @@ namespace jank::evaluate fn_ctx }; expr->frame->parent = arity.frame; ret->frame = arity.frame->parent.unwrap_or(arity.frame); - ret->frame->lift_constant(ret->meta); fn_ctx->name = ret->name; fn_ctx->unique_name = ret->unique_name; fn_ctx->fn = ret; arity.frame->fn_ctx = fn_ctx; arity.fn_ctx = fn_ctx; - arity.frame->lifted_vars = closest_fn_frame.lifted_vars; - arity.frame->lifted_constants = closest_fn_frame.lifted_constants; - arity.fn_ctx->param_count = arity.params.size(); for(auto const sym : arity.params) { diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 347f0b145..e2e12f8aa 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -154,7 +154,7 @@ namespace jank::runtime return eval_string(file.expect_ok().view()); } - object_ref context::eval_string(jtl::immutable_string_view const &code) + object_ref context::eval_string(jtl::immutable_string const &code) { profile::timer const timer{ "rt eval_string" }; read::lex::processor l_prc{ code }; @@ -225,8 +225,7 @@ namespace jank::runtime return ret; } - jtl::result - context::eval_cpp_string(jtl::immutable_string_view const &code) const + jtl::result context::eval_cpp_string(jtl::immutable_string const &code) const { profile::timer const timer{ "rt eval_cpp_string" }; @@ -256,7 +255,7 @@ namespace jank::runtime return ok(); } - object_ref context::read_string(jtl::immutable_string_view const &code) + object_ref context::read_string(jtl::immutable_string const &code) { profile::timer const timer{ "rt read_string" }; @@ -278,7 +277,7 @@ namespace jank::runtime } native_vector - context::analyze_string(jtl::immutable_string_view const &code, bool const eval) + context::analyze_string(jtl::immutable_string const &code, bool const eval) { profile::timer const timer{ "rt analyze_string" }; read::lex::processor l_prc{ code }; @@ -308,7 +307,7 @@ namespace jank::runtime } jtl::result - context::load_module(jtl::immutable_string_view const &module, module::origin const ori) + context::load_module(jtl::immutable_string const &module, module::origin const ori) { auto const ns(current_ns()); @@ -345,7 +344,7 @@ namespace jank::runtime } } - jtl::result context::compile_module(jtl::immutable_string_view const &module) + jtl::result context::compile_module(jtl::immutable_string const &module) { module_dependencies.clear(); @@ -418,26 +417,25 @@ namespace jank::runtime return unique_namespaced_string("G_"); } - jtl::immutable_string - context::unique_namespaced_string(jtl::immutable_string_view const &prefix) const + jtl::immutable_string context::unique_namespaced_string(jtl::immutable_string const &prefix) const { static jtl::immutable_string const dot{ "\\." }; auto const ns{ current_ns() }; return util::format("{}-{}-{}", runtime::munge_and_replace(ns->name->get_name(), dot, "_"), - prefix.data(), + prefix.c_str(), ++ns->symbol_counter); } - jtl::immutable_string context::unique_munged_string() const + jtl::immutable_string context::unique_string() const { - return munge(unique_namespaced_string()); + return unique_string("G_"); } - jtl::immutable_string - context::unique_munged_string(jtl::immutable_string_view const &prefix) const + jtl::immutable_string context::unique_string(jtl::immutable_string const &prefix) const { - return munge(unique_namespaced_string(prefix)); + auto const ns{ current_ns() }; + return util::format("{}-{}", prefix.c_str(), ++ns->symbol_counter); } obj::symbol context::unique_symbol() const @@ -445,7 +443,7 @@ namespace jank::runtime return unique_symbol("G-"); } - obj::symbol context::unique_symbol(jtl::immutable_string_view const &prefix) const + obj::symbol context::unique_symbol(jtl::immutable_string const &prefix) const { return { "", unique_namespaced_string(prefix) }; } @@ -514,6 +512,12 @@ namespace jank::runtime return expect_object(current_ns_var->deref()); } + jtl::result + context::intern_var(jtl::immutable_string const &qualified_name) + { + return intern_var(make_box(qualified_name)); + } + jtl::result context::intern_var(jtl::immutable_string const &ns, jtl::immutable_string const &name) { From 65d38b6328ab74cd3c9eb62d10ddf89cd4b3f712 Mon Sep 17 00:00:00 2001 From: jeaye Date: Wed, 26 Nov 2025 19:54:15 -0800 Subject: [PATCH 046/122] Use explicit empty containers in cppgen --- .../src/cpp/jank/codegen/processor.cpp | 193 ++++++++++++------ 1 file changed, 132 insertions(+), 61 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 09ddef423..4de1a0230 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -273,103 +273,174 @@ namespace jank::codegen } else if constexpr(std::same_as) { - util::format_to(buffer, - "jank::runtime::make_box("); - if(typed_o->meta.is_some()) + if(typed_o->data.empty()) { - /* TODO: If meta is empty, use empty() fn. We'll need a gen helper for this. */ - util::format_to(buffer, - "jank::runtime::__rt_ctx->read_string(\"{}\"), ", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + util::format_to(buffer, "jank::runtime::obj::persistent_vector::empty()"); + if(typed_o->meta.is_some()) + { + /* TODO: If meta is empty, use empty() fn. We'll need a gen helper for this. */ + util::format_to(buffer, + "->with_meta(jank::runtime::__rt_ctx->read_string(\"{}\"))", + util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + } } - util::format_to(buffer, "std::in_place "); - for(auto const &form : typed_o->data) + else { - util::format_to(buffer, ", "); - gen_constant(form, buffer, true); + util::format_to(buffer, + "jank::runtime::make_box("); + if(typed_o->meta.is_some()) + { + /* TODO: If meta is empty, use empty() fn. We'll need a gen helper for this. */ + util::format_to(buffer, + "jank::runtime::__rt_ctx->read_string(\"{}\"), ", + util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + } + util::format_to(buffer, "std::in_place "); + for(auto const &form : typed_o->data) + { + util::format_to(buffer, ", "); + gen_constant(form, buffer, true); + } + util::format_to(buffer, ")"); } - util::format_to(buffer, ")"); } else if constexpr(std::same_as) { - util::format_to(buffer, - "jank::runtime::make_box("); - if(typed_o->meta.is_some()) + if(typed_o->data.empty()) { - util::format_to(buffer, - "jank::runtime::__rt_ctx->read_string(\"{}\"), ", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + util::format_to(buffer, "jank::runtime::obj::persistent_list::empty()"); + if(typed_o->meta.is_some()) + { + /* TODO: If meta is empty, use empty() fn. We'll need a gen helper for this. */ + util::format_to(buffer, + "->with_meta(jank::runtime::__rt_ctx->read_string(\"{}\"))", + util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + } } - util::format_to(buffer, "std::in_place "); - for(auto const &form : typed_o->data) + else { - util::format_to(buffer, ", "); - gen_constant(form, buffer, true); + util::format_to(buffer, + "jank::runtime::make_box("); + if(typed_o->meta.is_some()) + { + util::format_to(buffer, + "jank::runtime::__rt_ctx->read_string(\"{}\"), ", + util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + } + util::format_to(buffer, "std::in_place "); + for(auto const &form : typed_o->data) + { + util::format_to(buffer, ", "); + gen_constant(form, buffer, true); + } + util::format_to(buffer, ")"); } - util::format_to(buffer, ")"); } else if constexpr(std::same_as) { - util::format_to(buffer, - "jank::runtime::make_box("); - if(typed_o->meta.is_some()) + if(typed_o->data.empty()) { - util::format_to(buffer, - "jank::runtime::__rt_ctx->read_string(\"{}\"), ", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + util::format_to(buffer, "jank::runtime::obj::persistent_hash_set::empty()"); + if(typed_o->meta.is_some()) + { + /* TODO: If meta is empty, use empty() fn. We'll need a gen helper for this. */ + util::format_to(buffer, + "->with_meta(jank::runtime::__rt_ctx->read_string(\"{}\"))", + util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + } } - util::format_to(buffer, "std::in_place "); - for(auto const &form : typed_o->data) + else { - util::format_to(buffer, ", "); - gen_constant(form, buffer, true); + util::format_to(buffer, + "jank::runtime::make_box("); + if(typed_o->meta.is_some()) + { + util::format_to(buffer, + "jank::runtime::__rt_ctx->read_string(\"{}\"), ", + util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + } + util::format_to(buffer, "std::in_place "); + for(auto const &form : typed_o->data) + { + util::format_to(buffer, ", "); + gen_constant(form, buffer, true); + } + util::format_to(buffer, ")"); } - util::format_to(buffer, ")"); } else if constexpr(std::same_as) { - bool need_comma{}; - if(typed_o->meta.is_some()) + if(typed_o->data.empty()) { - util::format_to(buffer, - "jank::runtime::obj::persistent_array_map::create_unique_with_meta("); - util::format_to(buffer, - "jank::runtime::__rt_ctx->read_string(\"{}\")", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); - need_comma = true; + util::format_to(buffer, "jank::runtime::obj::persistent_array_map::empty()"); + if(typed_o->meta.is_some()) + { + /* TODO: If meta is empty, use empty() fn. We'll need a gen helper for this. */ + util::format_to(buffer, + "->with_meta(jank::runtime::__rt_ctx->read_string(\"{}\"))", + util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + } } else { - util::format_to(buffer, "jank::runtime::obj::persistent_array_map::create_unique("); - } - for(auto const &form : typed_o->data) - { - if(need_comma) + bool need_comma{}; + if(typed_o->meta.is_some()) + { + util::format_to( + buffer, + "jank::runtime::obj::persistent_array_map::create_unique_with_meta("); + util::format_to(buffer, + "jank::runtime::__rt_ctx->read_string(\"{}\")", + util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + need_comma = true; + } + else + { + util::format_to(buffer, "jank::runtime::obj::persistent_array_map::create_unique("); + } + for(auto const &form : typed_o->data) { + if(need_comma) + { + util::format_to(buffer, ", "); + } + need_comma = true; + gen_constant(form.first, buffer, true); util::format_to(buffer, ", "); + gen_constant(form.second, buffer, true); } - need_comma = true; - gen_constant(form.first, buffer, true); - util::format_to(buffer, ", "); - gen_constant(form.second, buffer, true); + util::format_to(buffer, ")"); } - util::format_to(buffer, ")"); } else if constexpr(std::same_as) { - auto const has_meta{ typed_o->meta.is_some() }; - if(has_meta) + if(typed_o->data.empty()) { - util::format_to(buffer, "jank::runtime::reset_meta("); + util::format_to(buffer, "jank::runtime::obj::persistent_hash_map::empty()"); + if(typed_o->meta.is_some()) + { + /* TODO: If meta is empty, use empty() fn. We'll need a gen helper for this. */ + util::format_to(buffer, + "->with_meta(jank::runtime::__rt_ctx->read_string(\"{}\"))", + util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + } } - util::format_to(buffer, - "jank::runtime::__rt_ctx->read_string(\"{}\")", - util::escape(typed_o->to_code_string())); - if(has_meta) + else { + auto const has_meta{ typed_o->meta.is_some() }; + if(has_meta) + { + util::format_to(buffer, "jank::runtime::with_meta("); + } util::format_to(buffer, - ", jank::runtime::__rt_ctx->read_string(\"{}\"))", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + "jank::runtime::__rt_ctx->read_string(\"{}\")", + util::escape(typed_o->to_code_string())); + if(has_meta) + { + util::format_to(buffer, + ", jank::runtime::__rt_ctx->read_string(\"{}\"))", + util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + } } } /* Cons, etc. */ From 636a38a39db5ae4caf0edeefdb6bb545c430dcbf Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 27 Nov 2025 15:37:00 -0800 Subject: [PATCH 047/122] Add empty string cppgen --- compiler+runtime/src/cpp/jank/codegen/processor.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 4de1a0230..a90f719d3 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -267,9 +267,16 @@ namespace jank::codegen } else if constexpr(std::same_as) { - util::format_to(buffer, - "jank::runtime::make_box({})", - typed_o->to_code_string()); + if(typed_o->data.empty()) + { + util::format_to(buffer, "jank::runtime::obj::persistent_string::empty()"); + } + else + { + util::format_to(buffer, + "jank::runtime::make_box({})", + typed_o->to_code_string()); + } } else if constexpr(std::same_as) { From b28b6c2b59d071f037b27b8f72d1c81dc46733fc Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 28 Nov 2025 17:52:45 -0800 Subject: [PATCH 048/122] More cppgen fixes --- .../include/cpp/jank/codegen/processor.hpp | 9 +++- compiler+runtime/include/cpp/jank/error.hpp | 10 ++++ .../include/cpp/jank/error/runtime.hpp | 1 + .../include/cpp/jank/runtime/context.hpp | 1 + compiler+runtime/include/cpp/jtl/result.hpp | 51 ++++++++++++++++--- .../src/cpp/jank/codegen/processor.cpp | 42 +++++++++------ compiler+runtime/src/cpp/jank/error.cpp | 12 +++++ .../src/cpp/jank/error/runtime.cpp | 7 +++ .../src/cpp/jank/runtime/context.cpp | 12 ++++- .../src/cpp/jank/runtime/module/loader.cpp | 15 +++++- 10 files changed, 135 insertions(+), 25 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/codegen/processor.hpp b/compiler+runtime/include/cpp/jank/codegen/processor.hpp index 51d40ee45..559f46ed4 100644 --- a/compiler+runtime/include/cpp/jank/codegen/processor.hpp +++ b/compiler+runtime/include/cpp/jank/codegen/processor.hpp @@ -170,7 +170,14 @@ namespace jank::codegen jtl::string_builder footer_buffer; jtl::string_builder expression_buffer; jtl::immutable_string expression_fn_name; - native_unordered_map lifted_vars; + + struct lifted_var + { + jtl::immutable_string native_name; + bool owned{}; + }; + + native_unordered_map lifted_vars; native_unordered_map, diff --git a/compiler+runtime/include/cpp/jank/error.hpp b/compiler+runtime/include/cpp/jank/error.hpp index accc37a99..7526cea62 100644 --- a/compiler+runtime/include/cpp/jank/error.hpp +++ b/compiler+runtime/include/cpp/jank/error.hpp @@ -381,6 +381,8 @@ namespace jank::error * is because cpptrace doesn't use our GC allocator. */ struct base : gc_cleanup { + static constexpr bool is_error{ true }; + base() = delete; base(base const &) = delete; base(base &&) noexcept = default; @@ -460,4 +462,12 @@ namespace jank { return jtl::make_ref(jtl::forward(args)...); } + + namespace error + { + error_ref internal_failure(jtl::immutable_string const &message); + /* This can be used by jtl helpers which can't reach into jank but which fail. */ + [[noreturn]] + void throw_internal_failure(jtl::immutable_string const &message); + } } diff --git a/compiler+runtime/include/cpp/jank/error/runtime.hpp b/compiler+runtime/include/cpp/jank/error/runtime.hpp index 1deab795f..706a2e5e0 100644 --- a/compiler+runtime/include/cpp/jank/error/runtime.hpp +++ b/compiler+runtime/include/cpp/jank/error/runtime.hpp @@ -9,6 +9,7 @@ namespace jank::error error_ref runtime_unable_to_open_file(jtl::immutable_string const &message); error_ref runtime_invalid_cpp_eval(); error_ref runtime_unable_to_load_module(jtl::immutable_string const &message); + error_ref runtime_unable_to_load_module(error_ref cause); error_ref internal_runtime_failure(jtl::immutable_string const &message); error_ref runtime_invalid_unbox(jtl::immutable_string const &message, read::source const &unbox_source); diff --git a/compiler+runtime/include/cpp/jank/runtime/context.hpp b/compiler+runtime/include/cpp/jank/runtime/context.hpp index 50adda9ea..80efc9405 100644 --- a/compiler+runtime/include/cpp/jank/runtime/context.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/context.hpp @@ -64,6 +64,7 @@ namespace jank::runtime jtl::result intern_var(jtl::immutable_string const &ns, jtl::immutable_string const &name); jtl::result intern_owned_var(obj::symbol_ref const &); + jtl::result intern_owned_var(jtl::immutable_string const &); jtl::result intern_owned_var(jtl::immutable_string const &ns, jtl::immutable_string const &name); var_ref find_var(obj::symbol_ref const &); diff --git a/compiler+runtime/include/cpp/jtl/result.hpp b/compiler+runtime/include/cpp/jtl/result.hpp index 6162aa035..946ff95d5 100644 --- a/compiler+runtime/include/cpp/jtl/result.hpp +++ b/compiler+runtime/include/cpp/jtl/result.hpp @@ -6,6 +6,12 @@ #include #include +namespace jank::error +{ + [[noreturn]] + void throw_internal_failure(jtl::immutable_string const &message); +} + namespace jtl { namespace detail @@ -30,6 +36,37 @@ namespace jtl struct result { }; + + template + [[noreturn]] + constexpr void panic(Result const &r) + { + using E = typename Result::error_type; + + /* A result can hold any type of error type, but when we expect a value + * and it's not there, we only want to throw a jank::error_ref. This + * not only makes catching easier, it also fits into our error reporting. + * + * So we need to do some work here to see if we have an error_ref, something + * we can use to build an error_ref (like a string), or just something else. */ + + /* This is a roundabout way of looking for error_ref. */ + if constexpr(requires(E t) { E::value_type::is_error; }) + { + throw r.expect_err(); + } + else if constexpr(jtl::is_same) + { + jank::error::throw_internal_failure(r.expect_err()); + } + else + { + immutable_string s{ "Unexpected result<" }; + s = s + type_name().data(); + s = s + ">"; + jank::error::throw_internal_failure(s); + } + } } constexpr detail::result ok() noexcept @@ -54,6 +91,9 @@ namespace jtl { static_assert(!std::same_as, "Result and error type must be different."); + using value_type = R; + using error_type = E; + constexpr result(detail::result &&r) noexcept : data{ R{ std::move(r.data) } } { @@ -112,9 +152,7 @@ namespace jtl return; } - /* TODO: Update all of these throws to throw a consistent type, regardless of the - * error type. This simplifies our catching logic. */ - throw expect_err(); + detail::panic(*this); } constexpr R const &expect_ok() const @@ -183,9 +221,8 @@ namespace jtl constexpr R unwrap_move() { if(!is_ok()) - /* TODO: Panic function. */ { - throw expect_err(); + detail::panic(*this); } return std::move(std::get(data)); } @@ -245,6 +282,8 @@ namespace jtl template struct [[nodiscard]] result { + using error_type = E; + constexpr result(detail::result &&) noexcept : data{ void_t{} } { @@ -288,7 +327,7 @@ namespace jtl return; } - throw expect_err(); + detail::panic(*this); } constexpr void expect_ok() const diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index a90f719d3..3de59e04c 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -23,8 +23,8 @@ * jank fn has a nested fn, it becomes a nested struct, since this whole * generation works recursively. * - * Analysis lifts constants and vars, so those just become members which are - * initialized in the ctor. + * During codegen, we lift constants and vars, so those just become members which + * are initialized in the ctor. * * The most interesting part is the translation of expressions into statements, * so that something like `(println (if foo bar spam))` can become sane C++. @@ -563,20 +563,21 @@ namespace jank::codegen } static jtl::immutable_string - lift_var(native_unordered_map &lifted_vars, - jtl::immutable_string const &qualified_name) + lift_var(native_unordered_map &lifted_vars, + jtl::immutable_string const &qualified_name, + bool const owned) { auto const existing{ lifted_vars.find(qualified_name) }; if(existing != lifted_vars.end()) { - return existing->second; + return existing->second.native_name; } static jtl::immutable_string const dot{ "\\." }; auto const us{ __rt_ctx->unique_string(qualified_name) }; auto const native_name{ runtime::munge_and_replace(us, dot, "_") }; //util::println("lifting var '{}' with '{}' as '{}'", qualified_name, us, native_name); - lifted_vars.emplace(qualified_name, native_name); + lifted_vars.emplace(qualified_name, processor::lifted_var{ native_name, owned }); return native_name; } @@ -602,7 +603,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::def_ref const expr, analyze::expr::function_arity const &fn_arity) { - auto const &var(lift_var(lifted_vars, expr->name->to_string())); + auto const &var(lift_var(lifted_vars, expr->name->to_string(), true)); auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string(var))); jtl::option meta; @@ -681,7 +682,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::var_deref_ref const expr, analyze::expr::function_arity const &) { - auto const &var(lift_var(lifted_vars, expr->var->to_qualified_symbol()->to_string())); + auto const &var(lift_var(lifted_vars, expr->var->to_qualified_symbol()->to_string(), false)); switch(expr->position) { case analyze::expression_position::statement: @@ -700,7 +701,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::var_ref_ref const expr, analyze::expr::function_arity const &) { - auto const &var(lift_var(lifted_vars, expr->qualified_name->to_string())); + auto const &var(lift_var(lifted_vars, expr->qualified_name->to_string(), false)); switch(expr->position) { case analyze::expression_position::statement: @@ -2169,7 +2170,7 @@ namespace jank::codegen for(auto const &v : lifted_vars) { - util::format_to(header_buffer, "jank::runtime::var_ref const {};", v.second); + util::format_to(header_buffer, "jank::runtime::var_ref const {};", v.second.native_name); } @@ -2235,10 +2236,20 @@ namespace jank::codegen for(auto const &v : lifted_vars) { - util::format_to(header_buffer, - R"(, {}{ jank::runtime::__rt_ctx->intern_var("{}").expect_ok() })", - v.second, - v.first); + if(v.second.owned) + { + util::format_to(header_buffer, + R"(, {}{ jank::runtime::__rt_ctx->intern_owned_var("{}").expect_ok() })", + v.second.native_name, + v.first); + } + else + { + util::format_to(header_buffer, + R"(, {}{ jank::runtime::__rt_ctx->intern_var("{}").expect_ok() })", + v.second.native_name, + v.first); + } } @@ -2362,7 +2373,7 @@ namespace jank::codegen if(target == compilation_target::module) { util::format_to(footer_buffer, - "extern \"C\" void* {}(){", + "void* {}(){", runtime::module::module_to_load_function(module)); /* First thing we do when loading this module is to intern our ns. Everything else will @@ -2390,6 +2401,7 @@ namespace jank::codegen "return {}::{}{ }.call().erase();", runtime::module::module_to_native_ns(module), runtime::munge(struct_name.name)); + util::format_to(footer_buffer, "}"); } } diff --git a/compiler+runtime/src/cpp/jank/error.cpp b/compiler+runtime/src/cpp/jank/error.cpp index 45c131497..cae8deb79 100644 --- a/compiler+runtime/src/cpp/jank/error.cpp +++ b/compiler+runtime/src/cpp/jank/error.cpp @@ -471,4 +471,16 @@ namespace jank::error { return os << "error(" << kind_str(e.kind) << " - " << e.source << ", \"" << e.message << "\")"; } + + error_ref internal_failure(jtl::immutable_string const &message) + { + auto const e{ make_error(kind::internal_failure, message, read::source::unknown) }; + e->trace = std::make_unique(cpptrace::generate_trace()); + return e; + } + + void throw_internal_failure(jtl::immutable_string const &message) + { + throw internal_failure(message); + } } diff --git a/compiler+runtime/src/cpp/jank/error/runtime.cpp b/compiler+runtime/src/cpp/jank/error/runtime.cpp index f84a5327f..bac4d49ab 100644 --- a/compiler+runtime/src/cpp/jank/error/runtime.cpp +++ b/compiler+runtime/src/cpp/jank/error/runtime.cpp @@ -29,6 +29,13 @@ namespace jank::error return make_error(kind::runtime_unable_to_load_module, message, read::source::unknown); } + error_ref runtime_unable_to_load_module(error_ref const cause) + { + auto const e{ make_error(kind::runtime_unable_to_load_module, read::source::unknown) }; + e->cause = cause; + return e; + } + error_ref internal_runtime_failure(jtl::immutable_string const &message) { return make_error(kind::internal_runtime_failure, message, read::source::unknown); diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index e2e12f8aa..c7595fb3f 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -338,10 +338,14 @@ namespace jank::runtime { return error::runtime_unable_to_load_module(e.what()); } - catch(object_ref const &e) + catch(object_ref const e) { return error::runtime_unable_to_load_module(runtime::to_code_string(e)); } + catch(error_ref const e) + { + return error::runtime_unable_to_load_module(e); + } } jtl::result context::compile_module(jtl::immutable_string const &module) @@ -551,6 +555,12 @@ namespace jank::runtime return intern_owned_var(make_box(ns, name)); } + jtl::result + context::intern_owned_var(jtl::immutable_string const &qualified_name) + { + return intern_owned_var(make_box(qualified_name)); + } + jtl::result context::intern_owned_var(obj::symbol_ref const &qualified_sym) { diff --git a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp index 2687ff978..178c6fe4f 100644 --- a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp @@ -992,8 +992,19 @@ namespace jank::runtime::module __rt_ctx->jit_prc.load_object(entry.path); } - auto const load{ __rt_ctx->jit_prc.find_symbol(load_function_name).expect_ok() }; - reinterpret_cast(load)(); + /* For C++ codegen, we don't use extern "C" for the load fn, since it's UB + * to throw exceptions across C boundaries. Instead, we just declare the function + * and then try to call it. */ + auto const load_fn_res{ __rt_ctx->jit_prc.find_symbol(load_function_name) }; + if(load_fn_res.is_ok()) + { + reinterpret_cast(load_fn_res.expect_ok())(); + } + else + { + __rt_ctx->jit_prc.eval_string( + util::format("void* {}(); {}();", load_function_name, load_function_name)); + } return ok(); } From 5a162b2aabc6f1e744b647b2b92105e23644f9d8 Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 28 Nov 2025 18:11:57 -0800 Subject: [PATCH 049/122] Fix var interning order for cppgen --- .../src/cpp/jank/codegen/processor.cpp | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 3de59e04c..f275dd0a6 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -603,8 +603,17 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::def_ref const expr, analyze::expr::function_arity const &fn_arity) { - auto const &var(lift_var(lifted_vars, expr->name->to_string(), true)); - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string(var))); + /* def uses a var, but we don't lift it. Even if it's lifted by another usage, + * it'll be re-interned here as an owned var. This needs to happen at the point + * of the def, rather than prior (i.e. due to lifting), since there could be + * some other var-related effects such as refer which need to happen before + * def. */ + auto var_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("var"))); + util::format_to( + body_buffer, + R"(auto const {}(jank::runtime::__rt_ctx->intern_owned_var("{}").expect_ok());)", + var_tmp, + expr->name->to_string()); jtl::option meta; if(expr->name->meta.is_some()) @@ -619,11 +628,11 @@ namespace jank::codegen { auto const dynamic{ truthy( get(expr->name->meta.unwrap(), __rt_ctx->intern_keyword("dynamic").expect_ok())) }; - return util::format("{}->with_meta({})->set_dynamic({})", var, meta.unwrap(), dynamic); + return util::format("{}->with_meta({})->set_dynamic({})", var_tmp, meta.unwrap(), dynamic); } else { - return util::format("{}->with_meta(jank::runtime::jank_nil)", var); + return util::format("{}->with_meta(jank::runtime::jank_nil)", var_tmp); } } @@ -637,7 +646,7 @@ namespace jank::codegen auto const dynamic{ truthy( get(expr->name->meta.unwrap(), __rt_ctx->intern_keyword("dynamic").expect_ok())) }; return util::format("{}->bind_root({})->with_meta({})->set_dynamic({})", - var, + var_tmp, val.str(true), meta.unwrap(), dynamic); @@ -645,7 +654,7 @@ namespace jank::codegen else { return util::format("{}->bind_root({})->with_meta(jank::runtime::jank_nil)", - var, + var_tmp, val.str(true)); } } @@ -662,7 +671,7 @@ namespace jank::codegen get(expr->name->meta.unwrap(), __rt_ctx->intern_keyword("dynamic").expect_ok())) }; util::format_to(body_buffer, "{}->bind_root({})->with_meta({})->set_dynamic({});", - var, + var_tmp, val.str(true), meta.unwrap(), dynamic); @@ -671,7 +680,7 @@ namespace jank::codegen { util::format_to(body_buffer, "{}->bind_root({})->with_meta(jank::runtime::jank_nil);", - var, + var_tmp, val.str(true)); } return none; From 5f9a6e31d1cce2e7142dc11e523f06e681c146f2 Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 28 Nov 2025 18:27:36 -0800 Subject: [PATCH 050/122] Remove some dead code --- .../src/cpp/jank/codegen/processor.cpp | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index f275dd0a6..0d7207e8d 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -471,11 +471,6 @@ namespace jank::codegen }, o); } - - static jtl::immutable_string boxed_local_name(jtl::immutable_string const &local_name) - { - return local_name; // + "__boxed"; - } } handle::handle(jtl::immutable_string const &name, bool const boxed) @@ -518,7 +513,7 @@ namespace jank::codegen else if(binding->has_boxed_usage) { unboxed_name = runtime::munge(binding->native_name); - boxed_name = detail::boxed_local_name(unboxed_name); + boxed_name = unboxed_name; } else { @@ -996,17 +991,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::local_reference_ref const expr, analyze::expr::function_arity const &) { - auto const munged_name(runtime::munge(expr->binding->native_name)); - - handle ret; - if(expr->binding->needs_box) - { - ret = munged_name; - } - else - { - ret = handle{ detail::boxed_local_name(munged_name), munged_name }; - } + auto const ret(runtime::munge(expr->binding->native_name)); switch(expr->position) { @@ -1017,7 +1002,7 @@ namespace jank::codegen } case analyze::expression_position::tail: { - util::format_to(body_buffer, "return {};", ret.str(expr->needs_box)); + util::format_to(body_buffer, "return {};", ret); return none; } } From a1ead4f49820fd05c98443f778c5260b1833ae08 Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 28 Nov 2025 18:38:46 -0800 Subject: [PATCH 051/122] Clean up some cppgen --- .../src/cpp/jank/codegen/processor.cpp | 212 +++++++----------- 1 file changed, 76 insertions(+), 136 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 0d7207e8d..c0f6e59a8 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -75,73 +74,45 @@ namespace jank::codegen switch(o->type) { case jank::runtime::object_type::nil: - { - return "jank::runtime::obj::nil_ref"; - } + return "jank::runtime::obj::nil_ref"; case jank::runtime::object_type::boolean: - { - return "jank::runtime::obj::boolean_ref"; - } + return "jank::runtime::obj::boolean_ref"; case jank::runtime::object_type::integer: + if(boxed) { - if(boxed) - { - return "jank::runtime::obj::integer_ref"; - } - return "jank::i64"; + return "jank::runtime::obj::integer_ref"; } + return "jank::i64"; case jank::runtime::object_type::character: + if(boxed) { - if(boxed) - { - return "jank::runtime::obj::character_ref"; - } - return "jank::runtime::obj::character"; + return "jank::runtime::obj::character_ref"; } + return "jank::runtime::obj::character"; case jank::runtime::object_type::real: + if(boxed) { - if(boxed) - { - return "jank::runtime::obj::real_ref"; - } - return "jank::f64"; + return "jank::runtime::obj::real_ref"; } + return "jank::f64"; case jank::runtime::object_type::symbol: - { - return "jank::runtime::obj::symbol_ref"; - } + return "jank::runtime::obj::symbol_ref"; case jank::runtime::object_type::keyword: - { - return "jank::runtime::obj::keyword_ref"; - } + return "jank::runtime::obj::keyword_ref"; case jank::runtime::object_type::persistent_string: - { - return "jank::runtime::obj::persistent_string_ref"; - } + return "jank::runtime::obj::persistent_string_ref"; case jank::runtime::object_type::persistent_list: - { - return "jank::runtime::obj::persistent_list_ref"; - } + return "jank::runtime::obj::persistent_list_ref"; case jank::runtime::object_type::persistent_vector: - { - return "jank::runtime::obj::persistent_vector_ref"; - } + return "jank::runtime::obj::persistent_vector_ref"; case jank::runtime::object_type::persistent_hash_set: - { - return "jank::runtime::obj::persistent_hash_set_ref"; - } + return "jank::runtime::obj::persistent_hash_set_ref"; case jank::runtime::object_type::persistent_array_map: - { - return "jank::runtime::obj::persistent_array_map_ref"; - } + return "jank::runtime::obj::persistent_array_map_ref"; case jank::runtime::object_type::var: - { - return "jank::runtime::var_ref"; - } + return "jank::runtime::var_ref"; default: - { - return "jank::runtime::object_ref"; - } + return "jank::runtime::object_ref"; } #pragma clang diagnostic pop } @@ -635,51 +606,45 @@ namespace jank::codegen switch(expr->position) { case analyze::expression_position::value: + if(meta.is_some()) { - if(meta.is_some()) - { - auto const dynamic{ truthy( - get(expr->name->meta.unwrap(), __rt_ctx->intern_keyword("dynamic").expect_ok())) }; - return util::format("{}->bind_root({})->with_meta({})->set_dynamic({})", - var_tmp, - val.str(true), - meta.unwrap(), - dynamic); - } - else - { - return util::format("{}->bind_root({})->with_meta(jank::runtime::jank_nil)", - var_tmp, - val.str(true)); - } + auto const dynamic{ truthy( + get(expr->name->meta.unwrap(), __rt_ctx->intern_keyword("dynamic").expect_ok())) }; + return util::format("{}->bind_root({})->with_meta({})->set_dynamic({})", + var_tmp, + val.str(true), + meta.unwrap(), + dynamic); } - case analyze::expression_position::tail: + else { - util::format_to(body_buffer, "return "); + return util::format("{}->bind_root({})->with_meta(jank::runtime::jank_nil)", + var_tmp, + val.str(true)); } + case analyze::expression_position::tail: + util::format_to(body_buffer, "return "); [[fallthrough]]; case analyze::expression_position::statement: + if(meta.is_some()) { - if(meta.is_some()) - { - auto const dynamic{ truthy( - get(expr->name->meta.unwrap(), __rt_ctx->intern_keyword("dynamic").expect_ok())) }; - util::format_to(body_buffer, - "{}->bind_root({})->with_meta({})->set_dynamic({});", - var_tmp, - val.str(true), - meta.unwrap(), - dynamic); - } - else - { - util::format_to(body_buffer, - "{}->bind_root({})->with_meta(jank::runtime::jank_nil);", - var_tmp, - val.str(true)); - } - return none; + auto const dynamic{ truthy( + get(expr->name->meta.unwrap(), __rt_ctx->intern_keyword("dynamic").expect_ok())) }; + util::format_to(body_buffer, + "{}->bind_root({})->with_meta({})->set_dynamic({});", + var_tmp, + val.str(true), + meta.unwrap(), + dynamic); } + else + { + util::format_to(body_buffer, + "{}->bind_root({})->with_meta(jank::runtime::jank_nil);", + var_tmp, + val.str(true)); + } + return none; } } @@ -691,14 +656,10 @@ namespace jank::codegen { case analyze::expression_position::statement: case analyze::expression_position::value: - { - return util::format("{}->deref()", var); - } + return util::format("{}->deref()", var); case analyze::expression_position::tail: - { - util::format_to(body_buffer, "return {}->deref();", var); - return none; - } + util::format_to(body_buffer, "return {}->deref();", var); + return none; } } @@ -710,14 +671,10 @@ namespace jank::codegen { case analyze::expression_position::statement: case analyze::expression_position::value: - { - return var; - } + return var; case analyze::expression_position::tail: - { - util::format_to(body_buffer, "return {};", var); - return none; - } + util::format_to(body_buffer, "return {};", var); + return none; } } @@ -789,14 +746,10 @@ namespace jank::codegen { case analyze::expression_position::statement: case analyze::expression_position::value: - { - return ret; - } + return ret; case analyze::expression_position::tail: - { - util::format_to(body_buffer, "return {};", ret.str(expr->needs_box)); - return none; - } + util::format_to(body_buffer, "return {};", ret.str(expr->needs_box)); + return none; } } @@ -997,14 +950,10 @@ namespace jank::codegen { case analyze::expression_position::statement: case analyze::expression_position::value: - { - return ret; - } + return ret; case analyze::expression_position::tail: - { - util::format_to(body_buffer, "return {};", ret); - return none; - } + util::format_to(body_buffer, "return {};", ret); + return none; } } @@ -1023,15 +972,10 @@ namespace jank::codegen { case analyze::expression_position::statement: case analyze::expression_position::value: - /* TODO: Return a handle. */ - { - return prc.expression_str(); - } + return prc.expression_str(); case analyze::expression_position::tail: - { - util::format_to(body_buffer, "return {};", prc.expression_str()); - return none; - } + util::format_to(body_buffer, "return {};", prc.expression_str()); + return none; } } @@ -1347,21 +1291,17 @@ namespace jank::codegen { case analyze::expression_position::statement: case analyze::expression_position::value: + return last; + case analyze::expression_position::tail: + if(last.is_none()) { - return last; + util::format_to(body_buffer, "return jank::runtime::jank_nil;"); } - case analyze::expression_position::tail: + else { - if(last.is_none()) - { - util::format_to(body_buffer, "return jank::runtime::jank_nil;"); - } - else - { - util::format_to(body_buffer, "return {};", last.unwrap().str(expr->needs_box)); - } - return none; + util::format_to(body_buffer, "return {};", last.unwrap().str(expr->needs_box)); } + return none; } } @@ -2110,6 +2050,9 @@ namespace jank::codegen if(!generated_declaration) { profile::timer const timer{ util::format("cpp gen {}", root_fn->name) }; + + /* We generate the body first so that we know what we need for the header. This is + * necessary since we end up lifting vars and constants while building the body. */ build_body(); build_header(); build_footer(); @@ -2124,9 +2067,6 @@ namespace jank::codegen ret += jtl::immutable_string_view{ body_buffer.data(), body_buffer.size() }; ret += jtl::immutable_string_view{ footer_buffer.data(), footer_buffer.size() }; - //ret = util::format_cpp_source(ret).expect_ok(); - - //util::println("codegen declaration {}", ret); return ret; } From f2ad20e239e29a17fdf4916bb1c6bfec322e7f8e Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 28 Nov 2025 18:44:18 -0800 Subject: [PATCH 052/122] Remove some dead cppgen code --- .../src/cpp/jank/codegen/processor.cpp | 53 +++---------------- 1 file changed, 8 insertions(+), 45 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index c0f6e59a8..762a406f3 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -66,7 +66,6 @@ namespace jank::codegen * the actual param names as mutable locals outside of the while loop. */ constexpr jtl::immutable_string_view const recur_suffix{ "__recur" }; - /* TODO: Consider making this a on the typed object: the C++ name. */ static jtl::immutable_string gen_constant_type(runtime::object_ref const o, bool const boxed) { #pragma clang diagnostic push @@ -444,18 +443,10 @@ namespace jank::codegen } } - handle::handle(jtl::immutable_string const &name, bool const boxed) + handle::handle(jtl::immutable_string const &name, bool const) { - if(boxed) - { - boxed_name = name; - unboxed_name = boxed_name; - } - else - { - unboxed_name = name; - boxed_name = util::format("jank::runtime::make_box({})", unboxed_name); - } + boxed_name = name; + unboxed_name = boxed_name; } handle::handle(jtl::immutable_string const &boxed_name) @@ -470,43 +461,19 @@ namespace jank::codegen { if(this->boxed_name.empty()) { - this->boxed_name = util::format("jank::runtime::make_box({})", unboxed_name); + this->boxed_name = unboxed_name; } } handle::handle(analyze::local_binding_ptr const binding) { - if(binding->needs_box) - { - boxed_name = runtime::munge(binding->native_name); - unboxed_name = boxed_name; - } - else if(binding->has_boxed_usage) - { - unboxed_name = runtime::munge(binding->native_name); - boxed_name = unboxed_name; - } - else - { - unboxed_name = runtime::munge(binding->native_name); - } + boxed_name = runtime::munge(binding->native_name); + unboxed_name = boxed_name; } - jtl::immutable_string handle::str([[maybe_unused]] bool const needs_box) const + jtl::immutable_string handle::str(bool const) const { return boxed_name; - //if(needs_box) - //{ - // if(boxed_name.empty()) - // { - // throw std::runtime_error{ util::format("Missing boxed name for handle {}", unboxed_name) }; - // } - // return boxed_name; - //} - //else - //{ - // return unboxed_name; - //} } processor::processor(analyze::expr::function_ref const expr, @@ -542,7 +509,6 @@ namespace jank::codegen static jtl::immutable_string const dot{ "\\." }; auto const us{ __rt_ctx->unique_string(qualified_name) }; auto const native_name{ runtime::munge_and_replace(us, dot, "_") }; - //util::println("lifting var '{}' with '{}' as '{}'", qualified_name, us, native_name); lifted_vars.emplace(qualified_name, processor::lifted_var{ native_name, owned }); return native_name; } @@ -561,7 +527,6 @@ namespace jank::codegen } auto const &native_name{ runtime::munge(__rt_ctx->unique_namespaced_string("const")) }; - //util::println("lifting constant {} as {}", runtime::to_code_string(o), native_name); lifted_constants.emplace(o, native_name); return native_name; } @@ -624,6 +589,7 @@ namespace jank::codegen } case analyze::expression_position::tail: util::format_to(body_buffer, "return "); + [[fallthrough]]; case analyze::expression_position::statement: if(meta.is_some()) @@ -683,13 +649,10 @@ namespace jank::codegen native_vector const &arg_exprs, analyze::expr::function_arity const &fn_arity) { - //util::println("format_dynamic_call source {}", source_tmp); native_vector arg_tmps; arg_tmps.reserve(arg_exprs.size()); for(auto const &arg_expr : arg_exprs) { - //util::println("\tformat_dynamic_call arg {}", - // runtime::to_code_string(arg_expr->to_runtime_data())); arg_tmps.emplace_back(gen(arg_expr, fn_arity).unwrap()); } From 1374093ce979186c2d5b3153ff772663256e0dc7 Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 28 Nov 2025 18:52:32 -0800 Subject: [PATCH 053/122] Don't use namespaced strings for cppgen --- .../src/cpp/jank/codegen/processor.cpp | 48 +++++++++---------- .../src/cpp/jank/jit/processor.cpp | 2 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 762a406f3..986ee5b72 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -526,7 +526,7 @@ namespace jank::codegen return existing->second; } - auto const &native_name{ runtime::munge(__rt_ctx->unique_namespaced_string("const")) }; + auto const &native_name{ runtime::munge(__rt_ctx->unique_string("const")) }; lifted_constants.emplace(o, native_name); return native_name; } @@ -539,7 +539,7 @@ namespace jank::codegen * of the def, rather than prior (i.e. due to lifting), since there could be * some other var-related effects such as refer which need to happen before * def. */ - auto var_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("var"))); + auto var_tmp(runtime::munge(__rt_ctx->unique_string("var"))); util::format_to( body_buffer, R"(auto const {}(jank::runtime::__rt_ctx->intern_owned_var("{}").expect_ok());)", @@ -671,7 +671,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::call_ref const expr, analyze::expr::function_arity const &fn_arity) { - handle ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("call")) }; + handle ret_tmp{ runtime::munge(__rt_ctx->unique_string("call")) }; auto const &source_tmp(gen(expr->source_expr, fn_arity)); format_dynamic_call(source_tmp.unwrap().str(true), ret_tmp.str(true), @@ -726,7 +726,7 @@ namespace jank::codegen data_tmps.emplace_back(gen(data_expr, fn_arity).unwrap()); } - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("list"))); + auto ret_tmp(runtime::munge(__rt_ctx->unique_string("list"))); util::format_to(body_buffer, "auto const {}(jank::runtime::make_box(", ret_tmp); @@ -762,7 +762,7 @@ namespace jank::codegen data_tmps.emplace_back(gen(data_expr, fn_arity).unwrap()); } - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("vec"))); + auto ret_tmp(runtime::munge(__rt_ctx->unique_string("vec"))); util::format_to(body_buffer, "auto const {}(jank::runtime::make_box(", ret_tmp); @@ -799,7 +799,7 @@ namespace jank::codegen gen(data_expr.second, fn_arity).unwrap()); } - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("map"))); + auto ret_tmp(runtime::munge(__rt_ctx->unique_string("map"))); /* Jump right to a hash map, if we have enough values. */ if(expr->data_exprs.size() <= runtime::obj::persistent_array_map::max_size) @@ -877,7 +877,7 @@ namespace jank::codegen data_tmps.emplace_back(gen(data_expr, fn_arity).unwrap()); } - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("set"))); + auto ret_tmp(runtime::munge(__rt_ctx->unique_string("set"))); util::format_to( body_buffer, "auto const {}(jank::runtime::make_box(", @@ -1003,7 +1003,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::named_recursion_ref const expr, analyze::expr::function_arity const &fn_arity) { - handle ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("named_recursion")) }; + handle ret_tmp{ runtime::munge(__rt_ctx->unique_string("named_recursion")) }; auto const &source_tmp( gen(jtl::ref{ &expr->recursion_ref }, fn_arity)); @@ -1024,7 +1024,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::let_ref const expr, analyze::expr::function_arity const &fn_arity) { - auto const &ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("let")) }; + auto const &ret_tmp{ runtime::munge(__rt_ctx->unique_string("let")) }; bool used_option{}; auto const last_expr_type{ cpp_util::expression_type( @@ -1139,7 +1139,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::letfn_ref const expr, analyze::expr::function_arity const &fn_arity) { - auto const &ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("letfn")) }; + auto const &ret_tmp{ runtime::munge(__rt_ctx->unique_string("letfn")) }; bool used_option{}; auto const last_expr_type{ cpp_util::expression_type( @@ -1271,7 +1271,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::if_ref const expr, analyze::expr::function_arity const &fn_arity) { - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("if"))); + auto ret_tmp(runtime::munge(__rt_ctx->unique_string("if"))); auto const expr_type{ cpp_util::expression_type(expr->then) }; util::format_to(body_buffer, "{} {}{ };", @@ -1337,7 +1337,7 @@ namespace jank::codegen processor::gen(analyze::expr::try_ref const expr, analyze::expr::function_arity const &fn_arity) { auto const has_catch{ expr->catch_body.is_some() }; - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("try"))); + auto ret_tmp(runtime::munge(__rt_ctx->unique_string("try"))); util::format_to(body_buffer, "jank::runtime::object_ref {}{ };", ret_tmp); util::format_to(body_buffer, "{"); @@ -1406,7 +1406,7 @@ namespace jank::codegen processor::gen(analyze::expr::case_ref const expr, analyze::expr::function_arity const &fn_arity) { auto const is_tail{ expr->position == analyze::expression_position::tail }; - auto const &ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("case")) }; + auto const &ret_tmp{ runtime::munge(__rt_ctx->unique_string("case")) }; util::format_to(body_buffer, "jank::runtime::object_ref {}{ };", ret_tmp); @@ -1506,7 +1506,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::cpp_cast_ref const expr, analyze::expr::function_arity const &arity) { - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("cpp_cast"))); + auto ret_tmp(runtime::munge(__rt_ctx->unique_string("cpp_cast"))); auto const value_tmp{ gen(expr->value_expr, arity) }; if(Cpp::IsVoid(expr->conversion_type)) @@ -1543,7 +1543,7 @@ namespace jank::codegen if(expr->source_expr->kind == expression_kind::cpp_value) { auto const source{ static_cast(expr->source_expr.data) }; - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("cpp_call"))); + auto ret_tmp(runtime::munge(__rt_ctx->unique_string("cpp_call"))); native_vector arg_tmps; arg_tmps.reserve(expr->arg_exprs.size()); @@ -1606,7 +1606,7 @@ namespace jank::codegen } else { - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("cpp_call"))); + auto ret_tmp(runtime::munge(__rt_ctx->unique_string("cpp_call"))); auto const source_tmp{ gen(expr->source_expr, arity).unwrap() }; @@ -1665,7 +1665,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::cpp_constructor_call_ref const expr, analyze::expr::function_arity const &arity) { - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("cpp_ctor"))); + auto ret_tmp(runtime::munge(__rt_ctx->unique_string("cpp_ctor"))); native_vector arg_tmps; arg_tmps.reserve(expr->arg_exprs.size()); @@ -1751,7 +1751,7 @@ namespace jank::codegen analyze::expr::function_arity const &arity) { auto const fn_name{ Cpp::GetName(expr->fn) }; - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string(fn_name))); + auto ret_tmp(runtime::munge(__rt_ctx->unique_string(fn_name))); native_vector arg_tmps; arg_tmps.reserve(expr->arg_exprs.size()); @@ -1815,7 +1815,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::cpp_member_access_ref const expr, analyze::expr::function_arity const &arity) { - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string(expr->name))); + auto ret_tmp(runtime::munge(__rt_ctx->unique_string(expr->name))); auto obj_tmp(gen(expr->obj_expr, arity)); util::format_to(body_buffer, @@ -1837,7 +1837,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::cpp_builtin_operator_call_ref const expr, analyze::expr::function_arity const &arity) { - auto ret_tmp(runtime::munge(__rt_ctx->unique_namespaced_string("cpp_operator"))); + auto ret_tmp(runtime::munge(__rt_ctx->unique_string("cpp_operator"))); native_vector arg_tmps; arg_tmps.reserve(expr->arg_exprs.size()); @@ -1882,7 +1882,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::cpp_box_ref const expr, analyze::expr::function_arity const &arity) { - auto ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("cpp_box")) }; + auto ret_tmp{ runtime::munge(__rt_ctx->unique_string("cpp_box")) }; auto value_tmp{ gen(expr->value_expr, arity) }; auto const value_expr_type{ cpp_util::expression_type(expr->value_expr) }; auto const type_str{ Cpp::GetTypeAsString( @@ -1913,7 +1913,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::cpp_unbox_ref const expr, analyze::expr::function_arity const &arity) { - auto ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("cpp_unbox")) }; + auto ret_tmp{ runtime::munge(__rt_ctx->unique_string("cpp_unbox")) }; auto value_tmp{ gen(expr->value_expr, arity) }; auto const type_name{ cpp_util::get_qualified_type_name(expr->type) }; auto const meta{ runtime::source_to_meta(expr->source) }; @@ -1941,8 +1941,8 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::cpp_new_ref const expr, analyze::expr::function_arity const &arity) { - auto ret_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("cpp_new")) }; - auto finalizer_tmp{ runtime::munge(__rt_ctx->unique_namespaced_string("finalizer")) }; + auto ret_tmp{ runtime::munge(__rt_ctx->unique_string("cpp_new")) }; + auto finalizer_tmp{ runtime::munge(__rt_ctx->unique_string("finalizer")) }; auto value_tmp{ gen(expr->value_expr, arity) }; auto const type_name{ cpp_util::get_qualified_type_name(expr->type) }; diff --git a/compiler+runtime/src/cpp/jank/jit/processor.cpp b/compiler+runtime/src/cpp/jank/jit/processor.cpp index 8dcc7512b..82443ad8e 100644 --- a/compiler+runtime/src/cpp/jank/jit/processor.cpp +++ b/compiler+runtime/src/cpp/jank/jit/processor.cpp @@ -232,7 +232,7 @@ namespace jank::jit void processor::eval_string(jtl::immutable_string const &s) const { - return eval_string(s, nullptr); + eval_string(s, nullptr); } void processor::eval_string(jtl::immutable_string const &s, clang::Value * const ret) const From 4bfdaca2ec5226ab8b73a2ec09be4c91182d61dc Mon Sep 17 00:00:00 2001 From: jeaye Date: Sun, 30 Nov 2025 18:55:06 -0800 Subject: [PATCH 054/122] Start changing module gen --- .../include/cpp/jtl/string_builder.hpp | 1 + .../src/cpp/jank/codegen/processor.cpp | 35 +++++++++++++++---- .../src/cpp/jtl/string_builder.cpp | 5 +++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/compiler+runtime/include/cpp/jtl/string_builder.hpp b/compiler+runtime/include/cpp/jtl/string_builder.hpp index d76874209..22767fd78 100644 --- a/compiler+runtime/include/cpp/jtl/string_builder.hpp +++ b/compiler+runtime/include/cpp/jtl/string_builder.hpp @@ -81,6 +81,7 @@ namespace jtl void reserve(usize capacity); value_type *data() const; usize size() const; + bool empty() const; jtl::immutable_string release(); std::string str() const; diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 986ee5b72..afaae7f37 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -923,11 +923,21 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::function_ref const expr, analyze::expr::function_arity const &) { - auto const compiling(truthy(__rt_ctx->compile_files_var->deref())); + auto const fn_target((target == compilation_target::eval) ? compilation_target::eval + : compilation_target::function); /* Since each codegen proc handles one callable struct, we create a new one for this fn. */ - processor prc{ expr, - module, - compiling ? compilation_target::function : compilation_target::eval }; + processor prc{ expr, module, fn_target }; + + /* TODO: Share a context instead. */ + prc.lifted_vars = lifted_vars; + prc.lifted_constants = lifted_constants; + + prc.build_body(); + + lifted_vars = jtl::move(prc.lifted_vars); + lifted_constants = jtl::move(prc.lifted_constants); + prc.lifted_vars.clear(); + prc.lifted_constants.clear(); util::format_to(deps_buffer, "{}", prc.declaration_str()); @@ -2035,7 +2045,12 @@ namespace jank::codegen void processor::build_header() { - util::format_to(header_buffer, "namespace {} {", runtime::module::module_to_native_ns(module)); + if(target != compilation_target::function) + { + util::format_to(header_buffer, + "namespace {} {", + runtime::module::module_to_native_ns(module)); + } util::format_to(header_buffer, R"( @@ -2163,6 +2178,11 @@ namespace jank::codegen void processor::build_body() { + if(!body_buffer.empty()) + { + return; + } + analyze::expr::function_arity const *variadic_arity{}; analyze::expr::function_arity const *highest_fixed_arity{}; for(auto const &arity : root_fn->arities) @@ -2265,7 +2285,10 @@ namespace jank::codegen util::format_to(footer_buffer, "};"); /* Namespace. */ - util::format_to(footer_buffer, "}"); + if(target != compilation_target::function) + { + util::format_to(footer_buffer, "}"); + } if(target == compilation_target::module) { diff --git a/compiler+runtime/src/cpp/jtl/string_builder.cpp b/compiler+runtime/src/cpp/jtl/string_builder.cpp index 3c683c534..dd9000f09 100644 --- a/compiler+runtime/src/cpp/jtl/string_builder.cpp +++ b/compiler+runtime/src/cpp/jtl/string_builder.cpp @@ -392,6 +392,11 @@ namespace jtl return pos; } + bool string_builder::empty() const + { + return pos == 0; + } + jtl::immutable_string string_builder::release() { jank_debug_assert(pos < capacity); From ceef6a88d8a9524165b84aea70378be4cdfac3ee Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 2 Dec 2025 21:11:46 -0800 Subject: [PATCH 055/122] Finish module-level cppgen optimizations --- .../include/cpp/jank/codegen/processor.hpp | 2 + .../src/cpp/jank/codegen/processor.cpp | 145 +++++++++++++----- 2 files changed, 110 insertions(+), 37 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/codegen/processor.hpp b/compiler+runtime/include/cpp/jank/codegen/processor.hpp index 559f46ed4..c24b3407b 100644 --- a/compiler+runtime/include/cpp/jank/codegen/processor.hpp +++ b/compiler+runtime/include/cpp/jank/codegen/processor.hpp @@ -164,6 +164,8 @@ namespace jank::codegen compilation_target target{}; runtime::obj::symbol struct_name; + jtl::string_builder module_header_buffer; + jtl::string_builder module_footer_buffer; jtl::string_builder deps_buffer; jtl::string_builder header_buffer; jtl::string_builder body_buffer; diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index afaae7f37..7bc71332a 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -48,10 +48,11 @@ * This is optimized by knowing what position every expression in, so trivial expressions used * as arguments, for example, don't need to be first stored in temporaries. * - * Lastly, this is complicated by tracking boxing requirements so that not everything is an - * `object_ref`. Judicious use of `auto` and semantic analysis alows us to track when unboxing - * is supported, although we very rarely know for certain if something is unboxed. We usually - * only know if it _could_ be. + * Code generation has a target, which is either for eval or for a module. + * When the target is for eval, each generated function is standalone. This + * is the normal operation. However, when doing AOT compilation, our target + * will be a module and we'll do some code size optimizations to group all + * of the functions within a module into one namespace, dedupe constants, etc. */ namespace jank::codegen @@ -928,16 +929,19 @@ namespace jank::codegen /* Since each codegen proc handles one callable struct, we create a new one for this fn. */ processor prc{ expr, module, fn_target }; - /* TODO: Share a context instead. */ - prc.lifted_vars = lifted_vars; - prc.lifted_constants = lifted_constants; + if(fn_target == compilation_target::function) + { + /* TODO: Share a context instead. */ + prc.lifted_vars = lifted_vars; + prc.lifted_constants = lifted_constants; - prc.build_body(); + prc.build_body(); - lifted_vars = jtl::move(prc.lifted_vars); - lifted_constants = jtl::move(prc.lifted_constants); - prc.lifted_vars.clear(); - prc.lifted_constants.clear(); + lifted_vars = jtl::move(prc.lifted_vars); + lifted_constants = jtl::move(prc.lifted_constants); + prc.lifted_vars.clear(); + prc.lifted_constants.clear(); + } util::format_to(deps_buffer, "{}", prc.declaration_str()); @@ -2024,18 +2028,42 @@ namespace jank::codegen { profile::timer const timer{ util::format("cpp gen {}", root_fn->name) }; + /* Module targeting works in a special way, with the goal of + * cutting down the generated code size. Instead of each function + * having its own lifted vars/constants, we have one namespace for + * the module with the lifted globals there, at namespace level. + * Then every function within that module can share the same globals. + * This also makes creating functions cheaper. However, it requires + * some special tracking. */ + if(target == compilation_target::module) + { + util::format_to(module_header_buffer, + "namespace {} {", + runtime::module::module_to_native_ns(module)); + } + + /* We generate the body first so that we know what we need for the header. This is * necessary since we end up lifting vars and constants while building the body. */ build_body(); build_header(); build_footer(); + + if(target == compilation_target::module) + { + /* Namespace. */ + util::format_to(module_footer_buffer, "}"); + } + generated_declaration = true; } native_transient_string ret; - ret.reserve(deps_buffer.size() + header_buffer.size() + body_buffer.size() - + footer_buffer.size()); + ret.reserve(module_header_buffer.size() + module_footer_buffer.size() + deps_buffer.size() + + header_buffer.size() + body_buffer.size() + footer_buffer.size()); + ret += jtl::immutable_string_view{ module_header_buffer.data(), module_header_buffer.size() }; ret += jtl::immutable_string_view{ deps_buffer.data(), deps_buffer.size() }; + ret += jtl::immutable_string_view{ module_footer_buffer.data(), module_footer_buffer.size() }; ret += jtl::immutable_string_view{ header_buffer.data(), header_buffer.size() }; ret += jtl::immutable_string_view{ body_buffer.data(), body_buffer.size() }; ret += jtl::immutable_string_view{ footer_buffer.data(), footer_buffer.size() }; @@ -2080,18 +2108,26 @@ namespace jank::codegen } } + auto &lifted_buffer{ (target == compilation_target::module) ? module_header_buffer + : header_buffer }; + auto const lifted_const{ (target == compilation_target::module) ? "" : "const" }; + for(auto const &v : lifted_vars) { - util::format_to(header_buffer, "jank::runtime::var_ref const {};", v.second.native_name); + util::format_to(lifted_buffer, + "jank::runtime::var_ref {} {};", + lifted_const, + v.second.native_name); } for(auto const &v : lifted_constants) { /* TODO: Typed lifted constants (in analysis). */ - util::format_to(header_buffer, - "{} const {};", + util::format_to(lifted_buffer, + "{} {} {};", detail::gen_constant_type(v.first, true), + lifted_const, v.second); } } @@ -2146,30 +2182,34 @@ namespace jank::codegen } } - for(auto const &v : lifted_vars) + if(target == compilation_target::eval) { - if(v.second.owned) + for(auto const &v : lifted_vars) { - util::format_to(header_buffer, - R"(, {}{ jank::runtime::__rt_ctx->intern_owned_var("{}").expect_ok() })", - v.second.native_name, - v.first); - } - else - { - util::format_to(header_buffer, - R"(, {}{ jank::runtime::__rt_ctx->intern_var("{}").expect_ok() })", - v.second.native_name, - v.first); + if(v.second.owned) + { + util::format_to( + header_buffer, + R"(, {}{ jank::runtime::__rt_ctx->intern_owned_var("{}").expect_ok() })", + v.second.native_name, + v.first); + } + else + { + util::format_to(header_buffer, + R"(, {}{ jank::runtime::__rt_ctx->intern_var("{}").expect_ok() })", + v.second.native_name, + v.first); + } } - } - for(auto const &v : lifted_constants) - { - util::format_to(header_buffer, ", {}{", v.second); - detail::gen_constant(v.first, header_buffer, true); - util::format_to(header_buffer, "}"); + for(auto const &v : lifted_constants) + { + util::format_to(header_buffer, ", {}{", v.second); + detail::gen_constant(v.first, header_buffer, true); + util::format_to(header_buffer, "}"); + } } } @@ -2296,6 +2336,8 @@ namespace jank::codegen "void* {}(){", runtime::module::module_to_load_function(module)); + auto const ns{ runtime::module::module_to_native_ns(module) }; + /* First thing we do when loading this module is to intern our ns. Everything else will * build on that. */ util::format_to(footer_buffer, "jank_ns_intern_c(\"{}\");", module); @@ -2317,9 +2359,38 @@ namespace jank::codegen current_ns->name->get_name(), current_ns->symbol_counter.load()); + for(auto const &v : lifted_vars) + { + if(v.second.owned) + { + util::format_to( + footer_buffer, + R"({}::{} = jank::runtime::__rt_ctx->intern_owned_var("{}").expect_ok();)", + ns, + v.second.native_name, + v.first); + } + else + { + util::format_to(footer_buffer, + R"({}::{} = jank::runtime::__rt_ctx->intern_var("{}").expect_ok();)", + ns, + v.second.native_name, + v.first); + } + } + + + for(auto const &v : lifted_constants) + { + util::format_to(footer_buffer, "{}::{} = ", ns, v.second); + detail::gen_constant(v.first, footer_buffer, true); + util::format_to(footer_buffer, ";"); + } + util::format_to(footer_buffer, "return {}::{}{ }.call().erase();", - runtime::module::module_to_native_ns(module), + ns, runtime::munge(struct_name.name)); util::format_to(footer_buffer, "}"); From 9df0a956c99beaf2bc89bba5e9351e6c2d113a3e Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 2 Dec 2025 21:25:11 -0800 Subject: [PATCH 056/122] Further optimize cppgen --- .../include/cpp/jank/analyze/expr/function.hpp | 6 +++++- compiler+runtime/src/cpp/jank/analyze/processor.cpp | 6 ++++-- compiler+runtime/src/cpp/jank/codegen/processor.cpp | 12 ++++++------ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp index 9dbe3087b..b6db7de04 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp @@ -27,7 +27,11 @@ namespace jank::analyze::expr jtl::immutable_string unique_name; usize param_count{}; bool is_variadic{}; - bool is_tail_recursive{}; + /* Is recur used within this function? */ + bool is_recur_recursive{}; + /* Is there any named recrusion within this function (tail or otherwise)? + * This counts any named recursion reference, not just calls. */ + bool is_named_recursive{}; /* TODO: is_pure */ }; diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index 6c73b33b0..f8d5fecaf 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -1574,6 +1574,8 @@ namespace jank::analyze auto &unwrapped_named_recursion(found_named_recursion.unwrap()); local_frame::register_captures(current_frame, unwrapped_named_recursion); + unwrapped_named_recursion.fn_frame->fn_ctx->is_named_recursive = true; + return jtl::make_ref( position, current_frame, @@ -1724,7 +1726,7 @@ namespace jank::analyze /* If it turns out this function uses recur, we need to ensure that its tail expression * is boxed. This is because unboxed values may use IIFE for initialization, which will * not work with the generated while/continue we use for recursion. */ - if(fn_ctx->is_tail_recursive) + if(fn_ctx->is_recur_recursive) { step::force_boxed(body_do); } @@ -2026,7 +2028,7 @@ namespace jank::analyze } else { - fn_ctx.unwrap()->is_tail_recursive = true; + fn_ctx.unwrap()->is_recur_recursive = true; } return jtl::make_ref(position, diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 7bc71332a..626765ca3 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -2238,7 +2238,7 @@ namespace jank::codegen } jtl::immutable_string recur_suffix; - if(arity.fn_ctx->is_tail_recursive) + if(arity.fn_ctx->is_recur_recursive) { recur_suffix = detail::recur_suffix; } @@ -2261,14 +2261,14 @@ namespace jank::codegen //util::format_to(body_buffer, "jank::profile::timer __timer{ \"{}\" };", root_fn->name); - if(!param_shadows_fn) + if(!param_shadows_fn && arity.fn_ctx->is_named_recursive) { util::format_to(body_buffer, "jank::runtime::object_ref const {}{ this };", runtime::munge(root_fn->name)); } - if(arity.fn_ctx->is_tail_recursive) + if(arity.fn_ctx->is_recur_recursive) { util::format_to(body_buffer, "{"); @@ -2295,7 +2295,7 @@ namespace jank::codegen util::format_to(body_buffer, "return jank::runtime::jank_nil;"); } - if(arity.fn_ctx->is_tail_recursive) + if(arity.fn_ctx->is_recur_recursive) { util::format_to(body_buffer, "} }"); } @@ -2311,8 +2311,8 @@ namespace jank::codegen util::format_to(body_buffer, R"( - jank::runtime::behavior::callable::arity_flag_t get_arity_flags() const final - { return jank::runtime::behavior::callable::build_arity_flags({}, true, {}); } + callable::arity_flag_t get_arity_flags() const final + { return callable::build_arity_flags({}, true, {}); } )", variadic_arity->fn_ctx->param_count - 1, variadic_ambiguous); From 2064e91bc660922ee477b28001bfb623b6f3d265 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 2 Dec 2025 22:19:15 -0800 Subject: [PATCH 057/122] Properly gen all meta --- .../src/cpp/jank/codegen/processor.cpp | 141 +++++++++--------- 1 file changed, 70 insertions(+), 71 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 626765ca3..027f91b23 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -55,6 +55,13 @@ * of the functions within a module into one namespace, dedupe constants, etc. */ +/* TODO: Size optimizations: + * - Remove extra object->object conversions + * - Add inlining back + * - Remove object requirement for if condition + * - Remove extra if_n = jank_nil on empty branches + */ + namespace jank::codegen { using namespace jank::analyze; @@ -67,6 +74,24 @@ namespace jank::codegen * the actual param names as mutable locals outside of the while loop. */ constexpr jtl::immutable_string_view const recur_suffix{ "__recur" }; + static jtl::immutable_string + lift_constant(native_unordered_map, + runtime::very_equal_to> &lifted_constants, + object_ref const &o) + { + auto const existing{ lifted_constants.find(o) }; + if(existing != lifted_constants.end()) + { + return existing->second; + } + + auto const &native_name{ runtime::munge(__rt_ctx->unique_string("const")) }; + lifted_constants.emplace(o, native_name); + return native_name; + } + static jtl::immutable_string gen_constant_type(runtime::object_ref const o, bool const boxed) { #pragma clang diagnostic push @@ -117,6 +142,11 @@ namespace jank::codegen #pragma clang diagnostic pop } + static bool should_gen_meta(jtl::option const &meta) + { + return meta.is_some() && !runtime::is_empty(meta.unwrap()); + } + static void gen_constant(runtime::object_ref const o, jtl::string_builder &buffer, bool const boxed) { @@ -254,24 +284,21 @@ namespace jank::codegen if(typed_o->data.empty()) { util::format_to(buffer, "jank::runtime::obj::persistent_vector::empty()"); - if(typed_o->meta.is_some()) + if(should_gen_meta(typed_o->meta)) { - /* TODO: If meta is empty, use empty() fn. We'll need a gen helper for this. */ - util::format_to(buffer, - "->with_meta(jank::runtime::__rt_ctx->read_string(\"{}\"))", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + util::format_to(buffer, "->with_meta("); + gen_constant(typed_o->meta.unwrap(), buffer, true); + util::format_to(buffer, ")"); } } else { util::format_to(buffer, "jank::runtime::make_box("); - if(typed_o->meta.is_some()) + if(should_gen_meta(typed_o->meta)) { - /* TODO: If meta is empty, use empty() fn. We'll need a gen helper for this. */ - util::format_to(buffer, - "jank::runtime::__rt_ctx->read_string(\"{}\"), ", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + gen_constant(typed_o->meta.unwrap(), buffer, true); + util::format_to(buffer, ","); } util::format_to(buffer, "std::in_place "); for(auto const &form : typed_o->data) @@ -287,23 +314,21 @@ namespace jank::codegen if(typed_o->data.empty()) { util::format_to(buffer, "jank::runtime::obj::persistent_list::empty()"); - if(typed_o->meta.is_some()) + if(should_gen_meta(typed_o->meta)) { - /* TODO: If meta is empty, use empty() fn. We'll need a gen helper for this. */ - util::format_to(buffer, - "->with_meta(jank::runtime::__rt_ctx->read_string(\"{}\"))", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + util::format_to(buffer, "->with_meta("); + gen_constant(typed_o->meta.unwrap(), buffer, true); + util::format_to(buffer, ")"); } } else { util::format_to(buffer, "jank::runtime::make_box("); - if(typed_o->meta.is_some()) + if(should_gen_meta(typed_o->meta)) { - util::format_to(buffer, - "jank::runtime::__rt_ctx->read_string(\"{}\"), ", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + gen_constant(typed_o->meta.unwrap(), buffer, true); + util::format_to(buffer, ","); } util::format_to(buffer, "std::in_place "); for(auto const &form : typed_o->data) @@ -319,23 +344,21 @@ namespace jank::codegen if(typed_o->data.empty()) { util::format_to(buffer, "jank::runtime::obj::persistent_hash_set::empty()"); - if(typed_o->meta.is_some()) + if(should_gen_meta(typed_o->meta)) { - /* TODO: If meta is empty, use empty() fn. We'll need a gen helper for this. */ - util::format_to(buffer, - "->with_meta(jank::runtime::__rt_ctx->read_string(\"{}\"))", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + util::format_to(buffer, "->with_meta("); + gen_constant(typed_o->meta.unwrap(), buffer, true); + util::format_to(buffer, ")"); } } else { util::format_to(buffer, "jank::runtime::make_box("); - if(typed_o->meta.is_some()) + if(should_gen_meta(typed_o->meta)) { - util::format_to(buffer, - "jank::runtime::__rt_ctx->read_string(\"{}\"), ", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + gen_constant(typed_o->meta.unwrap(), buffer, true); + util::format_to(buffer, ","); } util::format_to(buffer, "std::in_place "); for(auto const &form : typed_o->data) @@ -351,25 +374,22 @@ namespace jank::codegen if(typed_o->data.empty()) { util::format_to(buffer, "jank::runtime::obj::persistent_array_map::empty()"); - if(typed_o->meta.is_some()) + if(should_gen_meta(typed_o->meta)) { - /* TODO: If meta is empty, use empty() fn. We'll need a gen helper for this. */ - util::format_to(buffer, - "->with_meta(jank::runtime::__rt_ctx->read_string(\"{}\"))", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + util::format_to(buffer, "->with_meta("); + gen_constant(typed_o->meta.unwrap(), buffer, true); + util::format_to(buffer, ")"); } } else { bool need_comma{}; - if(typed_o->meta.is_some()) + if(should_gen_meta(typed_o->meta)) { util::format_to( buffer, "jank::runtime::obj::persistent_array_map::create_unique_with_meta("); - util::format_to(buffer, - "jank::runtime::__rt_ctx->read_string(\"{}\")", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + gen_constant(typed_o->meta.unwrap(), buffer, true); need_comma = true; } else @@ -395,17 +415,16 @@ namespace jank::codegen if(typed_o->data.empty()) { util::format_to(buffer, "jank::runtime::obj::persistent_hash_map::empty()"); - if(typed_o->meta.is_some()) + if(should_gen_meta(typed_o->meta)) { - /* TODO: If meta is empty, use empty() fn. We'll need a gen helper for this. */ - util::format_to(buffer, - "->with_meta(jank::runtime::__rt_ctx->read_string(\"{}\"))", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + util::format_to(buffer, "->with_meta("); + gen_constant(typed_o->meta.unwrap(), buffer, true); + util::format_to(buffer, ")"); } } else { - auto const has_meta{ typed_o->meta.is_some() }; + auto const has_meta{ should_gen_meta(typed_o->meta) }; if(has_meta) { util::format_to(buffer, "jank::runtime::with_meta("); @@ -415,9 +434,8 @@ namespace jank::codegen util::escape(typed_o->to_code_string())); if(has_meta) { - util::format_to(buffer, - ", jank::runtime::__rt_ctx->read_string(\"{}\"))", - util::escape(runtime::to_code_string(typed_o->meta.unwrap()))); + util::format_to(buffer, ","); + gen_constant(typed_o->meta.unwrap(), buffer, true); } } } @@ -514,24 +532,6 @@ namespace jank::codegen return native_name; } - static jtl::immutable_string - lift_constant(native_unordered_map, - runtime::very_equal_to> &lifted_constants, - object_ref const &o) - { - auto const existing{ lifted_constants.find(o) }; - if(existing != lifted_constants.end()) - { - return existing->second; - } - - auto const &native_name{ runtime::munge(__rt_ctx->unique_string("const")) }; - lifted_constants.emplace(o, native_name); - return native_name; - } - jtl::option processor::gen(analyze::expr::def_ref const expr, analyze::expr::function_arity const &fn_arity) { @@ -550,7 +550,7 @@ namespace jank::codegen jtl::option meta; if(expr->name->meta.is_some()) { - meta = lift_constant(lifted_constants, expr->name->meta.unwrap()); + meta = detail::lift_constant(lifted_constants, expr->name->meta.unwrap()); } /* Forward declarations just intern the var and evaluate to it. */ @@ -703,7 +703,7 @@ namespace jank::codegen } else { - ret = lift_constant(lifted_constants, expr->data); + ret = detail::lift_constant(lifted_constants, expr->data); } switch(expr->position) @@ -1930,18 +1930,17 @@ namespace jank::codegen auto ret_tmp{ runtime::munge(__rt_ctx->unique_string("cpp_unbox")) }; auto value_tmp{ gen(expr->value_expr, arity) }; auto const type_name{ cpp_util::get_qualified_type_name(expr->type) }; - auto const meta{ runtime::source_to_meta(expr->source) }; + auto const meta{ detail::lift_constant(lifted_constants, + runtime::source_to_meta(expr->source)) }; util::format_to(body_buffer, "auto {}{ " - "static_cast<{}>(jank_unbox_with_source(\"{}\", {}.data, " - "jank::runtime::__rt_ctx->read_string(\"{}\").data)" - ") };", + "static_cast<{}>(jank_unbox_with_source(\"{}\", {}.data, {}.data)) };", ret_tmp, type_name, type_name, value_tmp.unwrap().str(false), - util::escape(runtime::to_code_string(meta))); + meta); if(expr->position == expression_position::tail) { From 15fc082db6736c4dd6389cd4c530aca2baaa1e8b Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 2 Dec 2025 22:32:49 -0800 Subject: [PATCH 058/122] Optimize cppgen size more --- .../include/cpp/jank/codegen/processor.hpp | 1 + compiler+runtime/src/cpp/jank/codegen/processor.cpp | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/codegen/processor.hpp b/compiler+runtime/include/cpp/jank/codegen/processor.hpp index c24b3407b..d7dd037a6 100644 --- a/compiler+runtime/include/cpp/jank/codegen/processor.hpp +++ b/compiler+runtime/include/cpp/jank/codegen/processor.hpp @@ -164,6 +164,7 @@ namespace jank::codegen compilation_target target{}; runtime::obj::symbol struct_name; + jtl::string_builder cpp_raw_buffer; jtl::string_builder module_header_buffer; jtl::string_builder module_footer_buffer; jtl::string_builder deps_buffer; diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 027f91b23..8b9ad28a7 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -57,6 +57,7 @@ /* TODO: Size optimizations: * - Remove extra object->object conversions + * - Typed object to object * - Add inlining back * - Remove object requirement for if condition * - Remove extra if_n = jank_nil on empty branches @@ -500,8 +501,8 @@ namespace jank::codegen compilation_target const target) : root_fn{ expr } , module{ module } - , target{ target } - , struct_name{ root_fn->unique_name } + , target{ target } /* The normal unique name is fully namespaced, which we don't need. */ + , struct_name{ runtime::__rt_ctx->unique_string(root_fn->name) } { assert(root_fn->frame.data); } @@ -1466,7 +1467,7 @@ namespace jank::codegen jtl::option processor::gen(expr::cpp_raw_ref const expr, expr::function_arity const &) { - util::format_to(deps_buffer, "\n{}\n", expr->code); + util::format_to(cpp_raw_buffer, "\n{}\n", expr->code); if(expr->position == analyze::expression_position::tail) { @@ -2058,8 +2059,10 @@ namespace jank::codegen } native_transient_string ret; - ret.reserve(module_header_buffer.size() + module_footer_buffer.size() + deps_buffer.size() - + header_buffer.size() + body_buffer.size() + footer_buffer.size()); + ret.reserve(cpp_raw_buffer.size() + module_header_buffer.size() + module_footer_buffer.size() + + deps_buffer.size() + header_buffer.size() + body_buffer.size() + + footer_buffer.size()); + ret += jtl::immutable_string_view{ cpp_raw_buffer.data(), cpp_raw_buffer.size() }; ret += jtl::immutable_string_view{ module_header_buffer.data(), module_header_buffer.size() }; ret += jtl::immutable_string_view{ deps_buffer.data(), deps_buffer.size() }; ret += jtl::immutable_string_view{ module_footer_buffer.data(), module_footer_buffer.size() }; From a8bc2857b6b79e0ce8f1b698a31806c949d2b78d Mon Sep 17 00:00:00 2001 From: jeaye Date: Wed, 3 Dec 2025 18:55:28 -0800 Subject: [PATCH 059/122] Try adding hard-coded inlining back --- .../include/cpp/jank/codegen/processor.hpp | 10 + .../src/cpp/jank/codegen/processor.cpp | 372 +++++++++++++++++- 2 files changed, 376 insertions(+), 6 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/codegen/processor.hpp b/compiler+runtime/include/cpp/jank/codegen/processor.hpp index d7dd037a6..b941a07e8 100644 --- a/compiler+runtime/include/cpp/jank/codegen/processor.hpp +++ b/compiler+runtime/include/cpp/jank/codegen/processor.hpp @@ -154,10 +154,20 @@ namespace jank::codegen void build_footer(); jtl::immutable_string expression_str(); + void format_elided_var(jtl::immutable_string const &start, + jtl::immutable_string const &end, + jtl::immutable_string const &ret_tmp, + native_vector const &arg_exprs, + analyze::expr::function_arity const &fn_arity, + bool ret_box_needed); void format_dynamic_call(jtl::immutable_string const &source_tmp, jtl::immutable_string const &ret_tmp, native_vector const &arg_exprs, analyze::expr::function_arity const &fn_arity); + void format_direct_call(jtl::immutable_string const &source_tmp, + jtl::immutable_string const &ret_tmp, + native_vector const &arg_exprs, + analyze::expr::function_arity const &fn_arity); analyze::expr::function_ref root_fn; jtl::immutable_string module; diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 8b9ad28a7..42c124543 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -58,7 +58,6 @@ /* TODO: Size optimizations: * - Remove extra object->object conversions * - Typed object to object - * - Add inlining back * - Remove object requirement for if condition * - Remove extra if_n = jank_nil on empty branches */ @@ -670,15 +669,376 @@ namespace jank::codegen util::format_to(body_buffer, "));"); } + void processor::format_elided_var(jtl::immutable_string const &start, + jtl::immutable_string const &end, + jtl::immutable_string const &ret_tmp, + native_vector const &arg_exprs, + analyze::expr::function_arity const &fn_arity, + bool ret_box_needed) + { + /* TODO: Assert arg count when we know it. */ + native_vector arg_tmps; + arg_tmps.reserve(arg_exprs.size()); + for(auto const &arg_expr : arg_exprs) + { + arg_tmps.emplace_back(gen(arg_expr, fn_arity).unwrap()); + } + + jtl::immutable_string ret_box; + if(ret_box_needed) + { + ret_box = "jank::runtime::make_box("; + } + util::format_to(body_buffer, "auto const {}({}{}", ret_tmp, ret_box, start); + bool need_comma{}; + for(size_t i{}; i < runtime::max_params && i < arg_tmps.size(); ++i) + { + if(need_comma) + { + util::format_to(body_buffer, ", "); + } + util::format_to(body_buffer, "{}", arg_tmps[i].str(false)); + need_comma = true; + } + util::format_to(body_buffer, "{}{});", end, (ret_box_needed ? ")" : "")); + } + + void processor::format_direct_call(jtl::immutable_string const &source_tmp, + jtl::immutable_string const &ret_tmp, + native_vector const &arg_exprs, + analyze::expr::function_arity const &fn_arity) + { + native_vector arg_tmps; + arg_tmps.reserve(arg_exprs.size()); + for(auto const &arg_expr : arg_exprs) + { + arg_tmps.emplace_back(gen(arg_expr, fn_arity).unwrap()); + } + + util::format_to(body_buffer, "auto const {}({}->call(", ret_tmp, source_tmp); + + bool need_comma{}; + for(size_t i{}; i < runtime::max_params && i < arg_tmps.size(); ++i) + { + if(need_comma) + { + util::format_to(body_buffer, ", "); + } + util::format_to(body_buffer, "{}", arg_tmps[i].str(true)); + need_comma = true; + } + util::format_to(body_buffer, "));"); + } + jtl::option processor::gen(analyze::expr::call_ref const expr, analyze::expr::function_arity const &fn_arity) { handle ret_tmp{ runtime::munge(__rt_ctx->unique_string("call")) }; - auto const &source_tmp(gen(expr->source_expr, fn_arity)); - format_dynamic_call(source_tmp.unwrap().str(true), - ret_tmp.str(true), - expr->arg_exprs, - fn_arity); + + /* Clojure's codegen actually skips vars for certain calls to clojure.core + * fns; this is not the same as direct linking, which uses `invokeStatic` + * instead. Rather, this makes calls to `get` become `RT.get`, calls to `+` become + * `Numbers.add`, and so on. We do the same thing here. */ + bool elided{}; + /* TODO: Use the actual var meta to do this, not a hard-coded set of if checks. */ + if(auto const ref{ dynamic_cast(expr->source_expr.data) }; ref) + { + auto const &sym{ ref->var->name->name }; + if(ref->var->n->name->name != "clojure.core") + { + } + else if(sym == "get") + { + format_elided_var("jank::runtime::get(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + false); + elided = true; + } + else if(expr->arg_exprs.empty()) + { + if(sym == "rand") + { + format_elided_var("jank::runtime::rand(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + } + else if(expr->arg_exprs.size() == 1) + { + if(sym == "abs") + { + format_elided_var("jank::runtime::abs(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + else if(sym == "sqrt") + { + format_elided_var("jank::runtime::sqrt(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + else if(sym == "int") + { + format_elided_var("jank::runtime::to_int(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + else if(sym == "seq") + { + format_elided_var("jank::runtime::seq(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + false); + elided = true; + } + else if(sym == "fresh_seq") + { + format_elided_var("jank::runtime::fresh_seq(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + false); + elided = true; + } + else if(sym == "first") + { + format_elided_var("jank::runtime::first(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + false); + elided = true; + } + else if(sym == "next") + { + format_elided_var("jank::runtime::next(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + false); + elided = true; + } + else if(sym == "next_in_place") + { + format_elided_var("jank::runtime::next_in_place(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + false); + elided = true; + } + else if(sym == "nil?") + { + format_elided_var("jank::runtime::is_nil(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + else if(sym == "some?") + { + format_elided_var("jank::runtime::is_some(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + } + else if(expr->arg_exprs.size() == 2) + { + if(sym == "+") + { + format_elided_var("jank::runtime::add(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + else if(sym == "-") + { + format_elided_var("jank::runtime::sub(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + else if(sym == "*") + { + format_elided_var("jank::runtime::mul(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + else if(sym == "/") + { + format_elided_var("jank::runtime::div(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + else if(sym == "<") + { + format_elided_var("jank::runtime::lt(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + else if(sym == "<=") + { + format_elided_var("jank::runtime::lte(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + else if(sym == ">") + { + format_elided_var("jank::runtime::lt(", + ")", + ret_tmp.str(false), + { expr->arg_exprs.rbegin(), expr->arg_exprs.rend() }, + fn_arity, + true); + elided = true; + } + else if(sym == ">=") + { + format_elided_var("jank::runtime::lte(", + ")", + ret_tmp.str(false), + { expr->arg_exprs.rbegin(), expr->arg_exprs.rend() }, + fn_arity, + true); + elided = true; + } + else if(sym == "min") + { + format_elided_var("jank::runtime::min(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + else if(sym == "max") + { + format_elided_var("jank::runtime::max(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + else if(sym == "pow") + { + format_elided_var("jank::runtime::pow(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + true); + elided = true; + } + else if(sym == "conj") + { + format_elided_var("jank::runtime::conj(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + false); + elided = true; + } + } + else if(expr->arg_exprs.size() == 3) + { + if(sym == "assoc") + { + format_elided_var("jank::runtime::assoc(", + ")", + ret_tmp.str(false), + expr->arg_exprs, + fn_arity, + false); + elided = true; + } + } + } + else if(auto const * const fn = dynamic_cast(expr->source_expr.data)) + { + bool variadic{}; + for(auto const &arity : fn->arities) + { + if(arity.fn_ctx->is_variadic) + { + variadic = true; + } + } + if(!variadic) + { + auto const &source_tmp(gen(expr->source_expr, fn_arity)); + format_direct_call(source_tmp.unwrap().str(false), + ret_tmp.str(true), + expr->arg_exprs, + fn_arity); + elided = true; + } + } + + if(!elided) + { + auto const &source_tmp(gen(expr->source_expr, fn_arity)); + format_dynamic_call(source_tmp.unwrap().str(true), + ret_tmp.str(true), + expr->arg_exprs, + fn_arity); + } if(expr->position == analyze::expression_position::tail) { From 3b804a434033f1691bd4c01ae0bce27c3711413d Mon Sep 17 00:00:00 2001 From: jeaye Date: Wed, 3 Dec 2025 22:29:51 -0800 Subject: [PATCH 060/122] Prevent extra conversion from typed to untyped --- .../src/cpp/jank/codegen/processor.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 42c124543..948c5a92c 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -1884,6 +1884,9 @@ namespace jank::codegen auto ret_tmp(runtime::munge(__rt_ctx->unique_string("cpp_cast"))); auto const value_tmp{ gen(expr->value_expr, arity) }; + /* There's no need to do a conversion for void, since we always just + * want nil. There's no need for generating a tmp for it either, since + * we have a global nil constant. */ if(Cpp::IsVoid(expr->conversion_type)) { if(expr->position == expression_position::tail) @@ -1894,6 +1897,18 @@ namespace jank::codegen return "jank::runtime::jank_nil"; } + /* We can rely on the C++ type system to handle conversion from typed objects + * to untype objects. */ + if(cpp_util::is_untyped_object(expr->type) && cpp_util::is_any_object(expr->conversion_type)) + { + if(expr->position == expression_position::tail) + { + util::format_to(body_buffer, "return {};", value_tmp.unwrap().str(true)); + return none; + } + return value_tmp.unwrap().str(true); + } + util::format_to( body_buffer, "auto const {}{ jank::runtime::convert<{}>::{}({}) };", From fc6e2c19f38790426ac116c0d86ca106f1db1ed9 Mon Sep 17 00:00:00 2001 From: jeaye Date: Wed, 3 Dec 2025 22:57:01 -0800 Subject: [PATCH 061/122] Clean up thread id --- compiler+runtime/src/cpp/jank/codegen/processor.cpp | 2 -- compiler+runtime/src/cpp/jank/runtime/context.cpp | 5 ++--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 948c5a92c..fd69bccd3 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -56,8 +56,6 @@ */ /* TODO: Size optimizations: - * - Remove extra object->object conversions - * - Typed object to object * - Remove object requirement for if condition * - Remove extra if_n = jank_nil on empty branches */ diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index c7595fb3f..90daf49e5 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -745,14 +745,13 @@ namespace jank::runtime context::push_thread_bindings(obj::persistent_hash_map_ref const bindings) { thread_binding_frame frame{ obj::persistent_hash_map::empty() }; - auto &tbfs(thread_binding_frames[std::this_thread::get_id()]); + auto const &thread_id(std::this_thread::get_id()); + auto &tbfs(thread_binding_frames[thread_id]); if(!tbfs.empty()) { frame.bindings = tbfs.front().bindings; } - auto const thread_id(std::this_thread::get_id()); - for(auto it(bindings->fresh_seq()); it.is_some(); it = it->next_in_place()) { auto const entry(it->first()); From 213ca1a99df8be179f885795580a65502d87e7ca Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 4 Dec 2025 18:15:22 -0800 Subject: [PATCH 062/122] Move immutable_string to system heap --- .../include/cpp/jtl/immutable_string.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler+runtime/include/cpp/jtl/immutable_string.hpp b/compiler+runtime/include/cpp/jtl/immutable_string.hpp index 13034501f..15bc247b9 100644 --- a/compiler+runtime/include/cpp/jtl/immutable_string.hpp +++ b/compiler+runtime/include/cpp/jtl/immutable_string.hpp @@ -722,7 +722,7 @@ namespace jtl /* NOTE: No performance difference between if/switch here. */ if(get_category() == category::large_owned) { - GC_free(store.large.data); + free(store.large.data); } } @@ -836,8 +836,8 @@ namespace jtl { jank_debug_assert(max_small_size < size); /* TODO: Apply gnu::malloc to this fn. */ - store.large.data = std::assume_aligned( - static_cast(GC_malloc_atomic(size + 1))); + store.large.data + = std::assume_aligned(static_cast(malloc(size + 1))); traits_type::copy(store.large.data, data, size); store.large.data[size] = 0; store.large.size = size; @@ -848,8 +848,8 @@ namespace jtl constexpr void init_large_fill(value_type const fill, u8 const size) noexcept { jank_debug_assert(max_small_size < size); - store.large.data = std::assume_aligned( - static_cast(GC_malloc_atomic(size + 1))); + store.large.data + = std::assume_aligned(static_cast(malloc(size + 1))); traits_type::assign(store.large.data, size, fill); store.large.data[size] = 0; store.large.size = size; @@ -864,8 +864,8 @@ namespace jtl { auto const size(lhs_size + rhs_size); jank_debug_assert(max_small_size < size); - store.large.data = std::assume_aligned( - static_cast(GC_malloc_atomic(size + 1))); + store.large.data + = std::assume_aligned(static_cast(malloc(size + 1))); traits_type::copy(store.large.data, lhs, lhs_size); traits_type::copy(store.large.data + lhs_size, rhs, rhs_size); store.large.data[size] = 0; @@ -879,8 +879,8 @@ namespace jtl { auto const size(std::distance(begin, end)); jank_debug_assert(max_small_size < size); - store.large.data = std::assume_aligned( - static_cast(GC_malloc_atomic(size + 1))); + store.large.data + = std::assume_aligned(static_cast(malloc(size + 1))); std::copy(begin, end, store.large.data); store.large.data[size] = 0; store.large.size = size; From 3e70522a94836a93ee0fa34f19868891ff10d7d7 Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 4 Dec 2025 18:16:15 -0800 Subject: [PATCH 063/122] Move string_builder to system heap --- compiler+runtime/src/cpp/jtl/string_builder.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler+runtime/src/cpp/jtl/string_builder.cpp b/compiler+runtime/src/cpp/jtl/string_builder.cpp index dd9000f09..c433efd28 100644 --- a/compiler+runtime/src/cpp/jtl/string_builder.cpp +++ b/compiler+runtime/src/cpp/jtl/string_builder.cpp @@ -15,9 +15,9 @@ namespace jtl static void realloc(string_builder &sb, usize const required) { auto const new_capacity{ std::bit_ceil(required) }; - auto const new_data{ reinterpret_cast(GC_malloc_atomic(new_capacity)) }; + auto const new_data{ reinterpret_cast(malloc(new_capacity)) }; string_builder::traits_type::copy(new_data, sb.buffer, sb.pos); - GC_free(sb.buffer); + free(sb.buffer); sb.buffer = new_data; sb.capacity = new_capacity; } @@ -99,7 +99,7 @@ namespace jtl string_builder::~string_builder() { - GC_free(buffer); + free(buffer); } string_builder &string_builder::operator()(bool const d) & From b457dbcbc551c81ccec3928b304b9363132daa55 Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 4 Dec 2025 18:20:21 -0800 Subject: [PATCH 064/122] Switch native allocator and immer policy to system --- compiler+runtime/include/cpp/jank/type.hpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/type.hpp b/compiler+runtime/include/cpp/jank/type.hpp index 0fb35c802..87821211c 100644 --- a/compiler+runtime/include/cpp/jank/type.hpp +++ b/compiler+runtime/include/cpp/jank/type.hpp @@ -22,12 +22,8 @@ namespace jank { template - using native_allocator = gc_allocator; - using memory_policy = immer::memory_policy, - immer::no_refcount_policy, - immer::default_lock_policy, - immer::gc_transience_policy, - false>; + using native_allocator = std::allocator; + using memory_policy = immer::default_memory_policy; using native_persistent_string_view = std::string_view; using native_big_integer From 75c982da20a31ed38a80e3aa7ed160b27d4c90fc Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 5 Dec 2025 09:15:39 -0800 Subject: [PATCH 065/122] Switch to reference counting --- .gitmodules | 3 - compiler+runtime/CMakeLists.txt | 14 +- compiler+runtime/cmake/dependency/bdwgc.cmake | 41 -- compiler+runtime/cmake/summary.cmake | 1 - .../cpp/jank/analyze/expr/function.hpp | 11 +- .../cpp/jank/analyze/expr/local_reference.hpp | 6 +- .../include/cpp/jank/analyze/expression.hpp | 2 +- .../include/cpp/jank/analyze/local_frame.hpp | 2 +- .../include/cpp/jank/codegen/processor.hpp | 2 +- compiler+runtime/include/cpp/jank/error.hpp | 2 +- .../include/cpp/jank/read/source.hpp | 4 +- .../include/cpp/jank/runtime/context.hpp | 4 +- .../cpp/jank/runtime/convert/builtin.hpp | 16 +- .../cpp/jank/runtime/core/to_string.hpp | 2 +- .../include/cpp/jank/runtime/ns.hpp | 2 +- .../cpp/jank/runtime/obj/array_chunk.hpp | 2 +- .../include/cpp/jank/runtime/obj/atom.hpp | 6 +- .../cpp/jank/runtime/obj/big_decimal.hpp | 2 +- .../cpp/jank/runtime/obj/big_integer.hpp | 2 +- .../cpp/jank/runtime/obj/character.hpp | 2 +- .../cpp/jank/runtime/obj/chunk_buffer.hpp | 2 +- .../cpp/jank/runtime/obj/chunked_cons.hpp | 2 +- .../include/cpp/jank/runtime/obj/cons.hpp | 2 +- .../include/cpp/jank/runtime/obj/delay.hpp | 2 +- .../obj/detail/base_persistent_map.hpp | 2 +- .../detail/base_persistent_map_sequence.hpp | 2 +- .../include/cpp/jank/runtime/obj/inst.hpp | 2 +- .../include/cpp/jank/runtime/obj/iterator.hpp | 2 +- .../cpp/jank/runtime/obj/jit_closure.hpp | 4 +- .../cpp/jank/runtime/obj/jit_function.hpp | 4 +- .../include/cpp/jank/runtime/obj/keyword.hpp | 9 +- .../cpp/jank/runtime/obj/lazy_sequence.hpp | 2 +- .../cpp/jank/runtime/obj/multi_function.hpp | 4 +- .../runtime/obj/native_array_sequence.hpp | 2 +- .../runtime/obj/native_function_wrapper.hpp | 4 +- .../runtime/obj/native_pointer_wrapper.hpp | 2 +- .../runtime/obj/native_vector_sequence.hpp | 2 +- .../include/cpp/jank/runtime/obj/nil.hpp | 5 +- .../include/cpp/jank/runtime/obj/number.hpp | 6 +- .../cpp/jank/runtime/obj/opaque_box.hpp | 2 +- .../jank/runtime/obj/persistent_hash_set.hpp | 2 +- .../obj/persistent_hash_set_sequence.hpp | 3 +- .../cpp/jank/runtime/obj/persistent_list.hpp | 2 +- .../runtime/obj/persistent_sorted_set.hpp | 2 +- .../obj/persistent_sorted_set_sequence.hpp | 3 +- .../jank/runtime/obj/persistent_string.hpp | 2 +- .../obj/persistent_string_sequence.hpp | 2 +- .../jank/runtime/obj/persistent_vector.hpp | 2 +- .../obj/persistent_vector_sequence.hpp | 2 +- .../include/cpp/jank/runtime/obj/range.hpp | 2 +- .../include/cpp/jank/runtime/obj/ratio.hpp | 2 +- .../cpp/jank/runtime/obj/re_matcher.hpp | 2 +- .../cpp/jank/runtime/obj/re_pattern.hpp | 2 +- .../include/cpp/jank/runtime/obj/reduced.hpp | 2 +- .../include/cpp/jank/runtime/obj/repeat.hpp | 2 +- .../include/cpp/jank/runtime/obj/symbol.hpp | 2 +- .../cpp/jank/runtime/obj/tagged_literal.hpp | 2 +- .../jank/runtime/obj/transient_array_map.hpp | 2 +- .../jank/runtime/obj/transient_hash_map.hpp | 2 +- .../jank/runtime/obj/transient_hash_set.hpp | 2 +- .../jank/runtime/obj/transient_sorted_map.hpp | 2 +- .../jank/runtime/obj/transient_sorted_set.hpp | 2 +- .../cpp/jank/runtime/obj/transient_vector.hpp | 2 +- .../include/cpp/jank/runtime/obj/uuid.hpp | 2 +- .../include/cpp/jank/runtime/obj/volatile.hpp | 2 +- .../include/cpp/jank/runtime/object.hpp | 7 + .../include/cpp/jank/runtime/oref.hpp | 196 ++++++-- .../include/cpp/jank/runtime/rtti.hpp | 4 +- .../cpp/jank/runtime/sequence_range.hpp | 16 + .../include/cpp/jank/runtime/var.hpp | 23 +- .../include/cpp/jank/runtime/visit.hpp | 4 +- .../include/cpp/jank/runtime/weak_oref.hpp | 448 ++++++++++++++++++ compiler+runtime/include/cpp/jank/type.hpp | 5 - compiler+runtime/include/cpp/jtl/ref.hpp | 20 +- .../src/cpp/clojure/core_native.cpp | 1 - .../src/cpp/jank/analyze/expr/function.cpp | 2 +- .../src/cpp/jank/analyze/processor.cpp | 2 +- compiler+runtime/src/cpp/jank/c_api.cpp | 6 +- .../src/cpp/jank/codegen/llvm_processor.cpp | 6 + .../src/cpp/jank/codegen/processor.cpp | 36 +- compiler+runtime/src/cpp/jank/error.cpp | 6 +- .../src/cpp/jank/error/analyze.cpp | 4 +- compiler+runtime/src/cpp/jank/error/aot.cpp | 6 +- .../src/cpp/jank/error/codegen.cpp | 2 +- compiler+runtime/src/cpp/jank/error/parse.cpp | 2 +- .../src/cpp/jank/error/report.cpp | 2 +- .../src/cpp/jank/error/runtime.cpp | 14 +- .../src/cpp/jank/error/system.cpp | 4 +- compiler+runtime/src/cpp/jank/evaluate.cpp | 2 +- compiler+runtime/src/cpp/jank/read/parse.cpp | 2 +- .../src/cpp/jank/read/reparse.cpp | 8 +- compiler+runtime/src/cpp/jank/read/source.cpp | 17 +- .../src/cpp/jank/runtime/context.cpp | 11 +- .../src/cpp/jank/runtime/core.cpp | 2 +- .../src/cpp/jank/runtime/core/meta.cpp | 6 +- .../src/cpp/jank/runtime/core/to_string.cpp | 2 +- .../jank/runtime/detail/native_array_map.cpp | 123 ++--- .../src/cpp/jank/runtime/obj/atom.cpp | 2 +- .../src/cpp/jank/runtime/obj/nil.cpp | 9 +- .../src/cpp/jank/runtime/obj/number.cpp | 2 + .../jank/runtime/obj/persistent_hash_set.cpp | 4 +- .../runtime/obj/persistent_sorted_set.cpp | 4 +- .../src/cpp/jank/runtime/object.cpp | 21 + compiler+runtime/src/cpp/jank/runtime/var.cpp | 9 +- compiler+runtime/src/cpp/main.cpp | 6 +- compiler+runtime/third-party/bdwgc | 1 - 106 files changed, 904 insertions(+), 383 deletions(-) delete mode 100644 compiler+runtime/cmake/dependency/bdwgc.cmake create mode 100644 compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp delete mode 160000 compiler+runtime/third-party/bdwgc diff --git a/.gitmodules b/.gitmodules index 4bc396c22..f723a3232 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,9 +25,6 @@ [submodule "compiler+runtime/third-party/boost-multiprecision"] path = compiler+runtime/third-party/boost-multiprecision url = https://github.com/jank-lang/boost-multiprecision.git -[submodule "compiler+runtime/third-party/bdwgc"] - path = compiler+runtime/third-party/bdwgc - url = https://github.com/jank-lang/bdwgc.git [submodule "compiler+runtime/third-party/stduuid"] path = compiler+runtime/third-party/stduuid url = https://github.com/jank-lang/stduuid.git diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index 6654d5240..b7abaff36 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -28,13 +28,6 @@ project( LANGUAGES C CXX ) -# BDWGC redefines BUILD_SHARED_LIBS as an option. The old policy behavior here -# is to reset the value to the new default defined, which is ON. However, we -# want it to keep the value we've already specified, to force BDWGC to build -# as a static lib, so we choose the new behavior. -set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) -cmake_policy(SET CMP0077 NEW) - # All options are available here. option(jank_local_clang "Whether or not to use a local Clang/LLVM source build" OFF) option(jank_install_local_clang "Whether or not to install the local Clang/LLVM alongside jank" ON) @@ -42,7 +35,6 @@ option(jank_coverage "Enable code coverage measurement" OFF) option(jank_analyze "Enable static analysis" OFF) option(jank_test "Enable jank's test suite" OFF) option(jank_unity_build "Optimize translation unit compilation for the number of cores" OFF) -option(jank_debug_gc "Enable GC debug assertions" OFF) set(jank_sanitize "none" CACHE STRING "The type of Clang sanitization to use (or none)") set(jank_resource_dir "../lib/jank/${CMAKE_PROJECT_VERSION}" @@ -100,7 +92,7 @@ set( set( jank_common_compiler_flags -std=gnu++20 - -DIMMER_HAS_LIBGC=1 -DIMMER_TAGGED_NODE=0 -DHAVE_CXX14=1 + -DIMMER_TAGGED_NODE=0 -DHAVE_CXX14=1 -DCPPINTEROP_USE_REPL -DFOLLY_HAVE_JEMALLOC=0 -DFOLLY_HAVE_TCMALLOC=0 -DFOLLY_ASSUME_NO_JEMALLOC=1 -DFOLLY_ASSUME_NO_TCMALLOC=1 #-DLIBASSERT_STATIC_DEFINE=1 @@ -330,7 +322,6 @@ set(jank_lib_standalone_deps Boost::multiprecision nanobench_lib jankzip_lib - bdwgc::gc bdwgc::gctba folly_lib clangCppInterOp ) @@ -366,7 +357,6 @@ add_custom_target( set(BUILD_SHARED_LIBS OFF) include(FetchContent) -include(cmake/dependency/bdwgc.cmake) include(cmake/dependency/ftxui.cmake) include(cmake/dependency/cpptrace.cmake) include(cmake/dependency/cppinterop.cmake) @@ -554,7 +544,6 @@ target_include_directories( PUBLIC "$" "$" - "$" "$" "$" "$" @@ -575,7 +564,6 @@ target_link_libraries( ftxui::screen ftxui::dom Boost::multiprecision nanobench_lib - bdwgc::gc bdwgc::gctba ) if(APPLE) diff --git a/compiler+runtime/cmake/dependency/bdwgc.cmake b/compiler+runtime/cmake/dependency/bdwgc.cmake deleted file mode 100644 index 0176e2692..000000000 --- a/compiler+runtime/cmake/dependency/bdwgc.cmake +++ /dev/null @@ -1,41 +0,0 @@ -set(CMAKE_C_FLAGS_OLD "${CMAKE_C_FLAGS}") -set(CMAKE_CXX_FLAGS_OLD "${CMAKE_CXX_FLAGS}") -set(BUILD_SHARED_LIBS_OLD ${BUILD_SHARED_LIBS}) -set(CMAKE_CXX_CLANG_TIDY_OLD ${CMAKE_CXX_CLANG_TIDY}) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w") - - if(NOT APPLE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DREDIRECT_MALLOC=GC_malloc_uncollectable -DREDIR_MALLOC_AND_LINUX_THREADS") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DREDIRECT_MALLOC=GC_malloc_uncollectable -DREDIR_MALLOC_AND_LINUX_THREADS") - endif() - - set(BUILD_SHARED_LIBS OFF) - set(CMAKE_CXX_CLANG_TIDY "") - set(enable_cplusplus ON CACHE BOOL "Enable C++") - set(build_cord OFF CACHE BOOL "Build cord") - set(enable_docs OFF CACHE BOOL "Enable docs") - set(enable_threads ON CACHE BOOL "Enable multi-threading support") - set(enable_large_config ON CACHE BOOL "Optimize for large heap or root set") - set(enable_throw_bad_alloc_library ON CACHE BOOL "Enable C++ gctba library build") - set(enable_gc_debug OFF CACHE BOOL "Support for pointer back-tracing") - - if(jank_debug_gc) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGC_ASSERTIONS") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGC_ASSERTIONS") - set(enable_gc_debug ON CACHE BOOL "Support for pointer back-tracing") - endif() - - add_subdirectory(third-party/bdwgc EXCLUDE_FROM_ALL) - - unset(enable_cplusplus) - unset(build_cord) - unset(enable_docs) - unset(enable_threads) - unset(enable_large_config) - unset(enable_throw_bad_alloc_library) - unset(enable_gc_debug) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_OLD}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_OLD}") -set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_OLD}) -set(CMAKE_CXX_CLANG_TIDY ${CMAKE_CXX_CLANG_TIDY_OLD}) diff --git a/compiler+runtime/cmake/summary.cmake b/compiler+runtime/cmake/summary.cmake index 8477b6e01..d5000b845 100644 --- a/compiler+runtime/cmake/summary.cmake +++ b/compiler+runtime/cmake/summary.cmake @@ -11,7 +11,6 @@ jank_message("│ jank analyze : ${jank_analyze}") jank_message("│ jank sanitize : ${jank_sanitize}") jank_message("│ jank unity build : ${jank_unity_build}") jank_message("│ jank resource dir : ${jank_resource_dir}") -jank_message("│ jank debug gc : ${jank_debug_gc}") jank_message("│ clang version : ${LLVM_PACKAGE_VERSION}") jank_message("│ clang prefix : ${CLANG_INSTALL_PREFIX}") jank_message("│ clang resource dir : ${clang_resource_dir}") diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp index b6db7de04..8a0cdbd80 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp @@ -1,14 +1,9 @@ #pragma once +#include +#include #include -namespace jank::runtime::obj -{ - using symbol_ref = oref; - using persistent_hash_map_ref = oref; - using persistent_hash_map_ref = oref; -} - namespace jank::analyze { using local_binding_ptr = jtl::ptr; @@ -18,7 +13,7 @@ namespace jank::analyze::expr { using function_ref = jtl::ref; - struct function_context : gc + struct function_context { static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/local_reference.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/local_reference.hpp index 1fe5ee797..492c2b80d 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/local_reference.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/local_reference.hpp @@ -1,12 +1,8 @@ #pragma once +#include #include -namespace jank::runtime::obj -{ - using symbol_ref = oref; -} - namespace jank::analyze { using local_binding_ptr = jtl::ptr; diff --git a/compiler+runtime/include/cpp/jank/analyze/expression.hpp b/compiler+runtime/include/cpp/jank/analyze/expression.hpp index 8934ee3de..2c313e4bb 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expression.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expression.hpp @@ -150,7 +150,7 @@ namespace jank::analyze } /* Common base class for every expression. */ - struct expression : gc + struct expression { static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp b/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp index 4c02ddcdb..0540017b9 100644 --- a/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp @@ -48,7 +48,7 @@ namespace jank::analyze using local_binding_ptr = jtl::ptr; - struct local_frame : gc + struct local_frame { enum class frame_type : u8 { diff --git a/compiler+runtime/include/cpp/jank/codegen/processor.hpp b/compiler+runtime/include/cpp/jank/codegen/processor.hpp index b941a07e8..972160695 100644 --- a/compiler+runtime/include/cpp/jank/codegen/processor.hpp +++ b/compiler+runtime/include/cpp/jank/codegen/processor.hpp @@ -173,7 +173,7 @@ namespace jank::codegen jtl::immutable_string module; compilation_target target{}; - runtime::obj::symbol struct_name; + jtl::immutable_string struct_name; jtl::string_builder cpp_raw_buffer; jtl::string_builder module_header_buffer; jtl::string_builder module_footer_buffer; diff --git a/compiler+runtime/include/cpp/jank/error.hpp b/compiler+runtime/include/cpp/jank/error.hpp index 7526cea62..aad6be87d 100644 --- a/compiler+runtime/include/cpp/jank/error.hpp +++ b/compiler+runtime/include/cpp/jank/error.hpp @@ -379,7 +379,7 @@ namespace jank::error /* We need gc_cleanup to run the dtor for the unique_ptr. This * is because cpptrace doesn't use our GC allocator. */ - struct base : gc_cleanup + struct base { static constexpr bool is_error{ true }; diff --git a/compiler+runtime/include/cpp/jank/read/source.hpp b/compiler+runtime/include/cpp/jank/read/source.hpp index e51cb4879..a0f7337a0 100644 --- a/compiler+runtime/include/cpp/jank/read/source.hpp +++ b/compiler+runtime/include/cpp/jank/read/source.hpp @@ -9,7 +9,7 @@ namespace jank::read struct source_position { - static source_position const unknown; + static source_position unknown(); bool operator==(source_position const &rhs) const; bool operator!=(source_position const &rhs) const; @@ -23,7 +23,7 @@ namespace jank::read struct source { - static source const unknown; + static source unknown(); source() = delete; source(source const &) = default; diff --git a/compiler+runtime/include/cpp/jank/runtime/context.hpp b/compiler+runtime/include/cpp/jank/runtime/context.hpp index 80efc9405..95d1c8578 100644 --- a/compiler+runtime/include/cpp/jank/runtime/context.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/context.hpp @@ -115,8 +115,8 @@ namespace jank::runtime jtl::immutable_string unique_namespaced_string(jtl::immutable_string const &prefix) const; jtl::immutable_string unique_string() const; jtl::immutable_string unique_string(jtl::immutable_string const &prefix) const; - obj::symbol unique_symbol() const; - obj::symbol unique_symbol(jtl::immutable_string const &prefix) const; + obj::symbol_ref unique_symbol() const; + obj::symbol_ref unique_symbol(jtl::immutable_string const &prefix) const; folly::Synchronized> namespaces; folly::Synchronized> keywords; diff --git a/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp b/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp index 148f0f7c3..edeff2b2b 100644 --- a/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp @@ -26,6 +26,20 @@ namespace jank::runtime } }; + template <> + struct convert + { + static constexpr weak_object_ref into_object(weak_object_ref const t) + { + return t; + } + + static constexpr weak_object_ref from_object(weak_object_ref const t) + { + return t; + } + }; + template requires(jtl::is_any_same) struct convert @@ -306,7 +320,7 @@ namespace jank::runtime static constexpr V from_object(obj::persistent_vector_ref const o) { V ret; - for(auto const e : o->data) + for(auto const &e : o->data) { ret.push_back(e); } diff --git a/compiler+runtime/include/cpp/jank/runtime/core/to_string.hpp b/compiler+runtime/include/cpp/jank/runtime/core/to_string.hpp index 3a2fca274..1e1860d0e 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/to_string.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/to_string.hpp @@ -8,7 +8,7 @@ namespace jank::runtime object_ref first(object_ref s); object_ref next(object_ref s); - jtl::immutable_string to_string(object_ref const o); + jtl::immutable_string to_string(weak_object_ref const o); void to_string(char ch, jtl::string_builder &buff); void to_string(object_ref o, jtl::string_builder &buff); diff --git a/compiler+runtime/include/cpp/jank/runtime/ns.hpp b/compiler+runtime/include/cpp/jank/runtime/ns.hpp index 30630f9fb..a3fce0e48 100644 --- a/compiler+runtime/include/cpp/jank/runtime/ns.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/ns.hpp @@ -15,7 +15,7 @@ namespace jank::runtime using ns_ref = oref; - struct ns : gc + struct ns { static constexpr object_type obj_type{ object_type::ns }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/array_chunk.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/array_chunk.hpp index c51f9a2f5..7e32d9d1d 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/array_chunk.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/array_chunk.hpp @@ -6,7 +6,7 @@ namespace jank::runtime::obj { using array_chunk_ref = oref; - struct array_chunk : gc + struct array_chunk { static constexpr object_type obj_type{ object_type::array_chunk }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp index 622ee06e1..479708a68 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp @@ -3,14 +3,14 @@ #include #include +#include +#include namespace jank::runtime::obj { using atom_ref = oref; - using persistent_vector_ref = oref; - using persistent_hash_map_ref = oref; - struct atom : gc + struct atom { static constexpr object_type obj_type{ object_type::atom }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/big_decimal.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/big_decimal.hpp index 5a8c0b2cb..03fddd534 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/big_decimal.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/big_decimal.hpp @@ -32,7 +32,7 @@ namespace jank::runtime::obj struct ratio; - struct big_decimal : gc + struct big_decimal { static constexpr object_type obj_type{ object_type::big_decimal }; static constexpr bool pointer_free{ true }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/big_integer.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/big_integer.hpp index dfd88120c..a6bf1097d 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/big_integer.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/big_integer.hpp @@ -30,7 +30,7 @@ namespace jank::runtime::obj { using big_integer_ref = oref; - struct big_integer : gc + struct big_integer { static constexpr object_type obj_type{ object_type::big_integer }; static constexpr bool pointer_free{ true }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/character.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/character.hpp index 9bb3245f7..cf88e79c9 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/character.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/character.hpp @@ -6,7 +6,7 @@ namespace jank::runtime::obj { using character_ref = oref; - struct character : gc + struct character { static constexpr object_type obj_type{ object_type::character }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/chunk_buffer.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/chunk_buffer.hpp index e1cb56d42..f75a23213 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/chunk_buffer.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/chunk_buffer.hpp @@ -7,7 +7,7 @@ namespace jank::runtime::obj using array_chunk_ref = oref; using chunk_buffer_ref = oref; - struct chunk_buffer : gc + struct chunk_buffer { static constexpr object_type obj_type{ object_type::chunk_buffer }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/chunked_cons.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/chunked_cons.hpp index d4cc84e27..18c715ff7 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/chunked_cons.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/chunked_cons.hpp @@ -9,7 +9,7 @@ namespace jank::runtime::obj using cons_ref = oref; using chunked_cons_ref = oref; - struct chunked_cons : gc + struct chunked_cons { static constexpr object_type obj_type{ object_type::chunked_cons }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/cons.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/cons.hpp index ce1728b0c..cc71746f2 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/cons.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/cons.hpp @@ -8,7 +8,7 @@ namespace jank::runtime::obj { using cons_ref = oref; - struct cons : gc + struct cons { static constexpr object_type obj_type{ object_type::cons }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/delay.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/delay.hpp index 1686d4604..5895a636e 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/delay.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/delay.hpp @@ -6,7 +6,7 @@ namespace jank::runtime::obj { using delay_ref = oref; - struct delay : gc + struct delay { static constexpr object_type obj_type{ object_type::delay }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map.hpp index 7b5400d8c..5b34aef6c 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map.hpp @@ -22,7 +22,7 @@ namespace jank::runtime::obj::detail /* Array maps and hash maps share a lot of common code, so we have a common base. * No virtual fns are used, so this structure won't survive release optimizations. */ template - struct base_persistent_map : gc + struct base_persistent_map { static constexpr bool pointer_free{ false }; static constexpr bool is_map_like{ true }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.hpp index 00a75c3f4..477110412 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.hpp @@ -17,7 +17,7 @@ namespace jank::runtime namespace jank::runtime::obj::detail { template - struct base_persistent_map_sequence : gc + struct base_persistent_map_sequence { static constexpr bool pointer_free{ false }; static constexpr bool is_sequential{ true }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/inst.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/inst.hpp index 1ede41f1a..66f1ac589 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/inst.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/inst.hpp @@ -9,7 +9,7 @@ namespace jank::runtime::obj using inst_ref = oref; using inst_time_point = std::chrono::time_point; - struct inst : gc + struct inst { static constexpr object_type obj_type{ object_type::inst }; static constexpr bool pointer_free{ true }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/iterator.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/iterator.hpp index 2ed4522d3..7f6aff14e 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/iterator.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/iterator.hpp @@ -9,7 +9,7 @@ namespace jank::runtime::obj using iterator_ref = oref; /* TODO: Rename to iterator_sequence. */ - struct iterator : gc + struct iterator { static constexpr object_type obj_type{ object_type::iterator }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp index a4187acb1..4305b027e 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp @@ -7,9 +7,7 @@ namespace jank::runtime::obj { using jit_closure_ref = oref; - struct jit_closure - : gc - , behavior::callable + struct jit_closure : behavior::callable { static constexpr object_type obj_type{ object_type::jit_closure }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp index b36d62b6a..312f031e6 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp @@ -7,9 +7,7 @@ namespace jank::runtime::obj { using jit_function_ref = oref; - struct jit_function - : gc - , behavior::callable + struct jit_function : behavior::callable { static constexpr object_type obj_type{ object_type::jit_function }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp index 73b260716..06c62feb4 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp @@ -1,16 +1,13 @@ #pragma once #include +#include #include namespace jank::runtime::obj { - using persistent_array_map_ref = oref; - using symbol_ref = oref; - using keyword_ref = oref; - /* The correct way to create a keyword for normal use is through interning via the RT context. */ - struct keyword : gc + struct keyword { static constexpr object_type obj_type{ object_type::keyword }; static constexpr bool pointer_free{ false }; @@ -51,6 +48,8 @@ namespace jank::runtime::obj object base{ obj_type }; symbol_ref sym; }; + + using keyword_ref = oref; } /* TODO: Move to .cpp */ diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/lazy_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/lazy_sequence.hpp index 919651d9b..779ae78df 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/lazy_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/lazy_sequence.hpp @@ -11,7 +11,7 @@ namespace jank::runtime::obj using lazy_sequence_ref = oref; /* TODO: IPending analog, to implement `realized?`. */ - struct lazy_sequence : gc + struct lazy_sequence { static constexpr object_type obj_type{ object_type::lazy_sequence }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp index 13f00fa4c..a3424a0f2 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp @@ -11,9 +11,7 @@ namespace jank::runtime::obj using persistent_hash_map_ref = oref; using multi_function_ref = oref; - struct multi_function - : gc - , behavior::callable + struct multi_function : behavior::callable { static constexpr object_type obj_type{ object_type::multi_function }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/native_array_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/native_array_sequence.hpp index 65b4df1f6..bb623391d 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/native_array_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/native_array_sequence.hpp @@ -7,7 +7,7 @@ namespace jank::runtime::obj using native_array_sequence_ref = oref; using cons_ref = oref; - struct native_array_sequence : gc + struct native_array_sequence { static constexpr object_type obj_type{ object_type::native_array_sequence }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp index 0b3be7035..691729484 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp @@ -64,9 +64,7 @@ namespace jank::runtime { using native_function_wrapper_ref = oref; - struct native_function_wrapper - : gc - , behavior::callable + struct native_function_wrapper : behavior::callable { static constexpr object_type obj_type{ object_type::native_function_wrapper }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/native_pointer_wrapper.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/native_pointer_wrapper.hpp index 353adde85..d2ab6d1c7 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/native_pointer_wrapper.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/native_pointer_wrapper.hpp @@ -6,7 +6,7 @@ namespace jank::runtime::obj { using native_pointer_wrapper_ref = oref; - struct native_pointer_wrapper : gc + struct native_pointer_wrapper { static constexpr object_type obj_type{ object_type::native_pointer_wrapper }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/native_vector_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/native_vector_sequence.hpp index a586e2e02..5455463e3 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/native_vector_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/native_vector_sequence.hpp @@ -9,7 +9,7 @@ namespace jank::runtime::obj using cons_ref = oref; using native_vector_sequence_ref = oref; - struct native_vector_sequence : gc + struct native_vector_sequence { static constexpr object_type obj_type{ object_type::native_vector_sequence }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp index 6aa29abe5..3ea07f3ea 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp @@ -7,8 +7,9 @@ namespace jank::runtime::obj using persistent_array_map_ref = oref; using cons_ref = oref; using nil_ref = oref; + using weak_nil_ref = weak_oref; - struct nil : gc + struct nil { static constexpr object_type obj_type{ object_type::nil }; static constexpr bool pointer_free{ true }; @@ -59,7 +60,7 @@ namespace jank::runtime bool operator!=(object *, obj::nil_ref); /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ - extern obj::nil_ref jank_nil; + extern obj::weak_nil_ref jank_nil; namespace detail { diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/number.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/number.hpp index 1dbeacbe0..5bd22be4e 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/number.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/number.hpp @@ -6,7 +6,7 @@ namespace jank::runtime::obj { using boolean_ref = oref; - struct boolean : gc + struct boolean { static constexpr object_type obj_type{ object_type::boolean }; static constexpr bool pointer_free{ true }; @@ -39,7 +39,7 @@ namespace jank::runtime::obj using integer_ref = oref; - struct integer : gc + struct integer { static constexpr object_type obj_type{ object_type::integer }; static constexpr bool pointer_free{ true }; @@ -73,7 +73,7 @@ namespace jank::runtime::obj using real_ref = oref; - struct real : gc + struct real { static constexpr object_type obj_type{ object_type::real }; static constexpr bool pointer_free{ true }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/opaque_box.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/opaque_box.hpp index 3de3c3970..9b846a2a3 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/opaque_box.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/opaque_box.hpp @@ -8,7 +8,7 @@ namespace jank::runtime::obj { using opaque_box_ref = oref; - struct opaque_box : gc + struct opaque_box { static constexpr object_type obj_type{ object_type::opaque_box }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp index 6dc4fee59..327e1c66a 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp @@ -9,7 +9,7 @@ namespace jank::runtime::obj using persistent_hash_set_ref = oref; using persistent_hash_set_sequence_ref = oref; - struct persistent_hash_set : gc + struct persistent_hash_set { static constexpr object_type obj_type{ object_type::persistent_hash_set }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set_sequence.hpp index 08c427dab..9d6de52bb 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set_sequence.hpp @@ -11,8 +11,7 @@ namespace jank::runtime::obj using persistent_hash_set_sequence_ref = oref; struct persistent_hash_set_sequence - : gc - , obj::detail::iterator_sequence { static constexpr object_type obj_type{ object_type::persistent_hash_set_sequence }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_list.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_list.hpp index 1f20768cc..854314fbb 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_list.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_list.hpp @@ -8,7 +8,7 @@ namespace jank::runtime::obj using nil_ref = oref; using persistent_list_ref = oref; - struct persistent_list : gc + struct persistent_list { using value_type = runtime::detail::native_persistent_list; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp index 28efff3ce..ae3e2d7e9 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp @@ -9,7 +9,7 @@ namespace jank::runtime::obj using persistent_sorted_set_ref = oref; using persistent_sorted_set_sequence_ref = oref; - struct persistent_sorted_set : gc + struct persistent_sorted_set { static constexpr object_type obj_type{ object_type::persistent_sorted_set }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set_sequence.hpp index 05c655004..fde5a19c0 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set_sequence.hpp @@ -11,8 +11,7 @@ namespace jank::runtime::obj using persistent_sorted_set_sequence_ref = oref; struct persistent_sorted_set_sequence - : gc - , obj::detail::iterator_sequence { static constexpr object_type obj_type{ object_type::persistent_sorted_set_sequence }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string.hpp index ff51d1704..86533ccc9 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string.hpp @@ -9,7 +9,7 @@ namespace jank::runtime::obj using persistent_string_ref = oref; using persistent_string_sequence_ref = oref; - struct persistent_string : gc + struct persistent_string { static constexpr object_type obj_type{ object_type::persistent_string }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string_sequence.hpp index 7d2e353a3..d96219307 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string_sequence.hpp @@ -8,7 +8,7 @@ namespace jank::runtime::obj using persistent_string_ref = oref; using persistent_string_sequence_ref = oref; - struct persistent_string_sequence : gc + struct persistent_string_sequence { static constexpr object_type obj_type{ object_type::persistent_string_sequence }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp index f763bdc0a..1b8d65f67 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp @@ -9,7 +9,7 @@ namespace jank::runtime::obj using persistent_vector_ref = oref; using persistent_vector_sequence_ref = oref; - struct persistent_vector : gc + struct persistent_vector { static constexpr object_type obj_type{ object_type::persistent_vector }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector_sequence.hpp index 0cc124287..6e529e8d5 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector_sequence.hpp @@ -8,7 +8,7 @@ namespace jank::runtime::obj using persistent_vector_ref = oref; using persistent_vector_sequence_ref = oref; - struct persistent_vector_sequence : gc + struct persistent_vector_sequence { static constexpr object_type obj_type{ object_type::persistent_vector_sequence }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp index bbfe5a2be..245ffe046 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp @@ -13,7 +13,7 @@ namespace jank::runtime::obj /* A range from X to Y, exclusive, incrementing by S. This is for non-integer values. * For integer values, use integer_range. This is not countable in constant time, due * to floating point shenanigans. */ - struct range : gc + struct range { static constexpr object_type obj_type{ object_type::range }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp index 6ecffb5de..efe9d3214 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp @@ -24,7 +24,7 @@ namespace jank::runtime::obj using real_ref = oref; using ratio_ref = oref; - struct ratio : gc + struct ratio { static constexpr object_type obj_type{ object_type::ratio }; static constexpr bool pointer_free{ true }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/re_matcher.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/re_matcher.hpp index f01792d55..65860f48c 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/re_matcher.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/re_matcher.hpp @@ -10,7 +10,7 @@ namespace jank::runtime::obj { using re_matcher_ref = oref; - struct re_matcher : gc_cleanup + struct re_matcher { static constexpr object_type obj_type{ object_type::re_matcher }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/re_pattern.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/re_pattern.hpp index f3024aa20..55d745cc5 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/re_pattern.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/re_pattern.hpp @@ -9,7 +9,7 @@ namespace jank::runtime::obj { using re_pattern_ref = oref; - struct re_pattern : gc_cleanup + struct re_pattern { static constexpr object_type obj_type{ object_type::re_pattern }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/reduced.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/reduced.hpp index 1a1306001..e134b8eb9 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/reduced.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/reduced.hpp @@ -6,7 +6,7 @@ namespace jank::runtime::obj { using reduced_ref = oref; - struct reduced : gc + struct reduced { static constexpr object_type obj_type{ object_type::reduced }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/repeat.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/repeat.hpp index 050b5a072..b9cd17153 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/repeat.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/repeat.hpp @@ -9,7 +9,7 @@ namespace jank::runtime::obj using cons_ref = oref; using repeat_ref = oref; - struct repeat : gc + struct repeat { static constexpr object_type obj_type{ object_type::repeat }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/symbol.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/symbol.hpp index 10df7eb5d..e1d70698e 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/symbol.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/symbol.hpp @@ -9,7 +9,7 @@ namespace jank::runtime::obj using persistent_array_map_ref = oref; using symbol_ref = oref; - struct symbol : gc + struct symbol { static constexpr object_type obj_type{ object_type::symbol }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/tagged_literal.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/tagged_literal.hpp index 39a241f0a..0ebdbacd2 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/tagged_literal.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/tagged_literal.hpp @@ -6,7 +6,7 @@ namespace jank::runtime::obj { using tagged_literal_ref = oref; - struct tagged_literal : gc + struct tagged_literal { static constexpr object_type obj_type{ object_type::tagged_literal }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp index 9eb6e32b3..f69f05373 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp @@ -8,7 +8,7 @@ namespace jank::runtime::obj using transient_array_map_ref = oref; /* TODO: Benchmark how fast is the transient array map vs the transient hash map for small maps? */ - struct transient_array_map : gc + struct transient_array_map { static constexpr object_type obj_type{ object_type::transient_array_map }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp index 19ef8fd54..a67b9ce48 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp @@ -12,7 +12,7 @@ namespace jank::runtime::obj { using transient_hash_map_ref = oref; - struct transient_hash_map : gc + struct transient_hash_map { static constexpr object_type obj_type{ object_type::transient_hash_map }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp index 4cae8df4a..20ee8fe8d 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp @@ -7,7 +7,7 @@ namespace jank::runtime::obj { using transient_hash_set_ref = oref; - struct transient_hash_set : gc + struct transient_hash_set { static constexpr object_type obj_type{ object_type::transient_hash_set }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp index 5b77e1145..546eb4c8d 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp @@ -7,7 +7,7 @@ namespace jank::runtime::obj { using transient_sorted_map_ref = oref; - struct transient_sorted_map : gc + struct transient_sorted_map { static constexpr object_type obj_type{ object_type::transient_sorted_map }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp index 1f05fab0b..80723695e 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp @@ -7,7 +7,7 @@ namespace jank::runtime::obj { using transient_sorted_set_ref = oref; - struct transient_sorted_set : gc + struct transient_sorted_set { static constexpr object_type obj_type{ object_type::transient_sorted_set }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp index cfb586f73..a6663e9a3 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp @@ -7,7 +7,7 @@ namespace jank::runtime::obj { using transient_vector_ref = oref; - struct transient_vector : gc + struct transient_vector { static constexpr object_type obj_type{ object_type::transient_vector }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/uuid.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/uuid.hpp index f5f04b1e6..914e7cf46 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/uuid.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/uuid.hpp @@ -11,7 +11,7 @@ namespace jank::runtime::obj { using uuid_ref = oref; - struct uuid : gc + struct uuid { static constexpr object_type obj_type{ object_type::uuid }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/volatile.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/volatile.hpp index f80517541..f181cbb9a 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/volatile.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/volatile.hpp @@ -6,7 +6,7 @@ namespace jank::runtime::obj { using volatile_ref = oref; - struct volatile_ : gc + struct volatile_ { static constexpr object_type obj_type{ object_type::volatile_ }; static constexpr bool pointer_free{ false }; diff --git a/compiler+runtime/include/cpp/jank/runtime/object.hpp b/compiler+runtime/include/cpp/jank/runtime/object.hpp index 6ace6c701..dc94589e7 100644 --- a/compiler+runtime/include/cpp/jank/runtime/object.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/object.hpp @@ -243,7 +243,12 @@ namespace jank::runtime struct object { + void retain(); + void release(); + object_type type{}; + /* TODO: Atomic. */ + i16 ref_count{}; }; namespace obj @@ -291,10 +296,12 @@ namespace jank::runtime::behavior } #include +#include namespace jank::runtime { using object_ref = oref; + using weak_object_ref = weak_oref; /* This isn't a great name, but it represents more than just value equality, since it * also includes type equality. Otherwise, [] equals '(). This is important when deduping diff --git a/compiler+runtime/include/cpp/jank/runtime/oref.hpp b/compiler+runtime/include/cpp/jank/runtime/oref.hpp index 9b09341c5..0d7cae2a8 100644 --- a/compiler+runtime/include/cpp/jank/runtime/oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/oref.hpp @@ -43,10 +43,26 @@ namespace jank::runtime constexpr oref() : data{ std::bit_cast(detail::jank_nil_ptr) } { + jank_debug_assert(data); } - constexpr oref(oref const &) = default; - constexpr oref(oref &&) noexcept = default; + constexpr oref(oref const &rhs) + : data{ rhs.data } + { + if(!data) + { + __builtin_debugtrap(); + } + jank_assert_throw(data); + retain(); + } + + constexpr oref(oref &&rhs) noexcept + : data{ jtl::move(rhs.data) } + { + jank_assert_throw(data); + retain(); + } constexpr oref(nullptr_t) noexcept = delete; @@ -54,12 +70,14 @@ namespace jank::runtime : data{ data } { jank_assert_throw(data); + retain(); } constexpr oref(value_type const * const data) : data{ const_cast(data) } { jank_assert_throw(data); + retain(); } template @@ -68,6 +86,7 @@ namespace jank::runtime : data{ &typed_data->base } { jank_assert_throw(this->data); + retain(); } template @@ -76,13 +95,36 @@ namespace jank::runtime : data{ const_cast(&typed_data->base) } { jank_assert_throw(this->data); + retain(); } template requires behavior::object_like - constexpr oref(oref const typed_data) noexcept + constexpr oref(oref const &typed_data) noexcept : data{ typed_data.erase() } { + retain(); + } + + constexpr ~oref() + { + release(); + } + + constexpr void retain() + { + if(is_some()) + { + data->retain(); + } + } + + constexpr void release() + { + if(is_some()) + { + data->release(); + } } constexpr value_type *operator->() const @@ -97,14 +139,39 @@ namespace jank::runtime return *data; } - constexpr oref &operator=(oref const &rhs) noexcept = default; - constexpr oref &operator=(oref &&rhs) noexcept = default; + constexpr oref &operator=(oref const &rhs) noexcept + { + if(this == &rhs) + { + return *this; + } + + release(); + data = rhs.data; + retain(); + return *this; + } + + constexpr oref &operator=(oref &&rhs) noexcept + { + if(this == &rhs) + { + return *this; + } + + release(); + data = rhs.data; + retain(); + return *this; + } template requires behavior::object_like constexpr oref &operator=(oref const &rhs) noexcept { + release(); data = &rhs->base; + retain(); return *this; } @@ -173,32 +240,68 @@ namespace jank::runtime { } + constexpr oref(oref const &rhs) noexcept + : data{ rhs.data } + { + retain(); + } + + constexpr oref(oref &&rhs) noexcept + : data{ rhs.data } + { + retain(); + } + constexpr oref(nullptr_t) = delete; constexpr oref(jtl::remove_const_t * const data) : data{ data } { jank_assert_throw(this->data); + retain(); } constexpr oref(T const * const data) : data{ const_cast(data) } { jank_assert_throw(this->data); + retain(); } template requires jtl::is_convertible - constexpr oref(oref const data) noexcept + constexpr oref(oref const &data) noexcept : data{ data.data } { } template requires(C::obj_type == object_type::nil) - constexpr oref(oref const data) noexcept + constexpr oref(oref const &data) noexcept : data{ data.data } { + retain(); + } + + constexpr ~oref() + { + release(); + } + + constexpr void retain() + { + if(is_some()) + { + (*this)->base.retain(); + } + } + + constexpr void release() + { + if(is_some()) + { + (*this)->base.release(); + } } constexpr T *operator->() const @@ -240,17 +343,47 @@ namespace jank::runtime return data != rhs.data; } + constexpr oref &operator=(oref const &rhs) noexcept + { + if(this == &rhs) + { + return *this; + } + + release(); + data = rhs.data; + retain(); + return *this; + } + + constexpr oref &operator=(oref &&rhs) noexcept + { + if(this == &rhs) + { + return *this; + } + + release(); + data = rhs.data; + retain(); + return *this; + } + constexpr oref &operator=(std::remove_cv_t> * const rhs) { + release(); data = rhs; jank_assert_throw(data); + retain(); return *this; } constexpr oref &operator=(std::remove_cv_t> const * const rhs) { + release(); data = const_cast(rhs); jank_assert_throw(data); + retain(); return *this; } @@ -258,7 +391,9 @@ namespace jank::runtime requires(C::obj_type == object_type::nil) constexpr oref &operator=(oref const &) noexcept { + release(); data = std::bit_cast(detail::jank_nil_ptr); + retain(); return *this; } @@ -319,14 +454,14 @@ namespace jank::runtime template requires jtl::is_convertible - constexpr oref(oref const data) noexcept + constexpr oref(oref const &data) noexcept : data{ data.data } { } template requires(C::obj_type == object_type::nil) - constexpr oref(oref const data) noexcept + constexpr oref(oref const &data) noexcept : data{ data.data } { } @@ -411,26 +546,9 @@ namespace jank::runtime jtl::ref make_box(Args &&...args) { static_assert(sizeof(jtl::ref) == sizeof(T *)); - T *ret{}; - if constexpr(requires { T::pointer_free; }) - { - if constexpr(T::pointer_free) - { - ret = new(PointerFreeGC) T{ std::forward(args)... }; - } - else - { - ret = new(GC) T{ std::forward(args)... }; - } - } - else - { - ret = new(GC) T{ std::forward(args)... }; - } - + T *ret{ new T{ std::forward(args)... } }; if(!ret) { - /* TODO: Panic. */ throw std::runtime_error{ "unable to allocate box" }; } return ret; @@ -448,30 +566,14 @@ namespace jank::runtime oref make_box(Args &&...args) { static_assert(sizeof(oref) == sizeof(T *)); - oref ret; - if constexpr(requires { T::pointer_free; }) - { - if constexpr(T::pointer_free) - { - ret = new(PointerFreeGC) T{ std::forward(args)... }; - } - else - { - ret = new(GC) T{ std::forward(args)... }; - } - } - else - { - ret = new(GC) T{ std::forward(args)... }; - } - + oref ret{ new T{ std::forward(args)... } }; return ret; } template constexpr jtl::ref make_array_box() { - auto const ret(new(GC) T[N]{}); + auto const ret(new T[N]{}); if(!ret) { throw std::runtime_error{ "unable to allocate array box" }; @@ -482,7 +584,7 @@ namespace jank::runtime template constexpr jtl::ref make_array_box(usize const length) { - auto const ret(new(GC) T[length]{}); + auto const ret(new T[length]{}); if(!ret) { throw std::runtime_error{ "Unable to allocate array box" }; @@ -494,7 +596,7 @@ namespace jank::runtime jtl::ref make_array_box(Args &&...args) { /* TODO: pointer_free? */ - auto const ret(new(GC) T[sizeof...(Args)]{ std::forward(args)... }); + auto const ret(new T[sizeof...(Args)]{ std::forward(args)... }); if(!ret) { throw std::runtime_error{ "Unable to allocate array box" }; diff --git a/compiler+runtime/include/cpp/jank/runtime/rtti.hpp b/compiler+runtime/include/cpp/jank/runtime/rtti.hpp index 0576f3217..2c355f730 100644 --- a/compiler+runtime/include/cpp/jank/runtime/rtti.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/rtti.hpp @@ -16,7 +16,7 @@ namespace jank::runtime template requires behavior::object_like [[gnu::always_inline, gnu::flatten, gnu::hot]] - constexpr oref dyn_cast(object_ref const o) + constexpr oref dyn_cast(object_ref const &o) { if(o->type != T::obj_type) { @@ -49,7 +49,7 @@ namespace jank::runtime template requires behavior::object_like [[gnu::always_inline, gnu::flatten, gnu::hot]] - constexpr oref expect_object(object_ref const o) + constexpr oref expect_object(object_ref const &o) { if constexpr(T::obj_type != object_type::nil) { diff --git a/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp b/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp index c3bb71434..19e2425d0 100644 --- a/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp @@ -176,4 +176,20 @@ namespace jank::runtime return sequence_range{ s.is_some() ? s->seq() : s }; } } + + template + requires behavior::seqable + auto make_sequence_range(weak_oref const s) + { + using S = typename decltype(s->seq())::value_type; + + if constexpr(behavior::sequenceable_in_place) + { + return sequence_range{ s.is_some() ? s->fresh_seq() : weak_oref{} }; + } + else + { + return sequence_range{ s.is_some() ? s->seq() : s }; + } + } } diff --git a/compiler+runtime/include/cpp/jank/runtime/var.hpp b/compiler+runtime/include/cpp/jank/runtime/var.hpp index b111a57ac..c3669c756 100644 --- a/compiler+runtime/include/cpp/jank/runtime/var.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/var.hpp @@ -5,30 +5,27 @@ #include #include + #include #include +#include namespace jank::runtime { - using ns_ref = oref; + using weak_ns_ref = weak_oref; using var_ref = oref; using var_thread_binding_ref = oref; using var_unbound_root_ref = oref; - namespace obj - { - using persistent_hash_map_ref = oref; - } - - struct var : gc + struct var { static constexpr object_type obj_type{ object_type::var }; static constexpr bool pointer_free{ false }; var() = delete; - var(ns_ref const &n, obj::symbol_ref const &name); - var(ns_ref const &n, obj::symbol_ref const &name, object_ref root); - var(ns_ref const &n, + var(weak_ns_ref const &n, obj::symbol_ref const &name); + var(weak_ns_ref const &n, obj::symbol_ref const &name, object_ref root); + var(weak_ns_ref const &n, obj::symbol_ref const &name, object_ref const root, bool dynamic, @@ -69,7 +66,7 @@ namespace jank::runtime var_ref clone() const; object base{ obj_type }; - ns_ref n; + weak_ns_ref n; /* Unqualified. */ obj::symbol_ref name{}; jtl::option meta; @@ -83,7 +80,7 @@ namespace jank::runtime std::atomic_bool thread_bound{ false }; }; - struct var_thread_binding : gc + struct var_thread_binding { static constexpr object_type obj_type{ object_type::var_thread_binding }; static constexpr bool pointer_free{ false }; @@ -107,7 +104,7 @@ namespace jank::runtime obj::persistent_hash_map_ref bindings{}; }; - struct var_unbound_root : gc + struct var_unbound_root { static constexpr object_type obj_type{ object_type::var_unbound_root }; static constexpr bool pointer_free{ true }; diff --git a/compiler+runtime/include/cpp/jank/runtime/visit.hpp b/compiler+runtime/include/cpp/jank/runtime/visit.hpp index ef1f095d4..0f7f60297 100644 --- a/compiler+runtime/include/cpp/jank/runtime/visit.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/visit.hpp @@ -68,7 +68,7 @@ namespace jank::runtime template requires behavior::object_like [[gnu::hot]] - constexpr auto visit_object(F const &fn, oref const not_erased, Args &&...args) + constexpr auto visit_object(F const &fn, weak_oref const not_erased, Args &&...args) { return fn(const_cast(¬_erased->base), std::forward(args)...); } @@ -79,7 +79,7 @@ namespace jank::runtime template requires visitable [[gnu::hot]] - auto visit_object(F const &fn, object_ref const erased, Args &&...args) + auto visit_object(F const &fn, weak_object_ref const erased, Args &&...args) { switch(erased->type) { diff --git a/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp b/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp new file mode 100644 index 000000000..6630297d8 --- /dev/null +++ b/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp @@ -0,0 +1,448 @@ +#pragma once + +#include + +namespace jank::runtime +{ + template + struct weak_oref; + + /* This variation of ref is for type-erased objects. + * + * It cannot be null, but it can be nil. */ + template + requires(jtl::is_same, object>) + struct weak_oref + { + using value_type = object; + + constexpr weak_oref() + : data{ std::bit_cast(detail::jank_nil_ptr) } + { + } + + constexpr weak_oref(weak_oref const &rhs) = default; + constexpr weak_oref(weak_oref &&) noexcept = default; + + constexpr weak_oref(oref const &rhs) + : data{ rhs.data } + { + } + + constexpr weak_oref(nullptr_t) noexcept = delete; + + constexpr weak_oref(value_type * const data) + : data{ data } + { + jank_assert_throw(data); + } + + constexpr weak_oref(value_type const * const data) + : data{ const_cast(data) } + { + jank_assert_throw(data); + } + + template + requires behavior::object_like + constexpr weak_oref(T * const typed_data) + : data{ &typed_data->base } + { + jank_assert_throw(this->data); + } + + template + requires behavior::object_like + constexpr weak_oref(T const * const typed_data) + : data{ const_cast(&typed_data->base) } + { + jank_assert_throw(this->data); + } + + template + requires behavior::object_like + constexpr weak_oref(weak_oref const typed_data) noexcept + : data{ typed_data.erase() } + { + } + + template + requires behavior::object_like + constexpr weak_oref(oref const typed_data) noexcept + : data{ typed_data.erase() } + { + } + + constexpr value_type *operator->() const + { + jank_assert_throw(data); + return data; + } + + constexpr value_type &operator*() const + { + jank_assert_throw(data); + return *data; + } + + constexpr weak_oref &operator=(weak_oref const &rhs) noexcept = default; + constexpr weak_oref &operator=(weak_oref &&rhs) noexcept = default; + + template + requires behavior::object_like + constexpr weak_oref &operator=(weak_oref const &rhs) noexcept + { + data = &rhs->base; + return *this; + } + + constexpr bool operator==(weak_oref const &rhs) const noexcept + { + return data == rhs.data; + } + + template + requires behavior::object_like + constexpr bool operator==(weak_oref const &rhs) const noexcept + { + return data == rhs.erase(); + } + + constexpr bool operator!=(weak_oref const &rhs) const noexcept + { + return data != rhs.data; + } + + template + requires behavior::object_like + constexpr bool operator!=(weak_oref const &rhs) const noexcept + { + return data != rhs.erase(); + } + + constexpr weak_oref &operator=(jtl::nullptr_t) noexcept = delete; + constexpr bool operator==(jtl::nullptr_t) noexcept = delete; + constexpr bool operator!=(jtl::nullptr_t) noexcept = delete; + + constexpr operator oref() const noexcept + { + return { data }; + } + + constexpr value_type *get() const noexcept + { + return data; + } + + constexpr value_type *erase() const noexcept + { + return data; + } + + constexpr bool is_some() const noexcept + { + return data->type != object_type::nil; + } + + constexpr bool is_nil() const noexcept + { + return data->type == object_type::nil; + } + + value_type *data{}; + }; + + /* This specialization of weak_oref is for fully-typed objects like nil, + * persistent_list, persistent_array_map, etc. + * + * It cannot be null, but it can be nil. */ + template + struct weak_oref + { + using value_type = T; + + constexpr weak_oref() + : data{ std::bit_cast(detail::jank_nil_ptr) } + { + } + + constexpr weak_oref(nullptr_t) = delete; + + constexpr weak_oref(jtl::remove_const_t * const data) + : data{ data } + { + jank_assert_throw(this->data); + } + + constexpr weak_oref(T const * const data) + : data{ const_cast(data) } + { + jank_assert_throw(this->data); + } + + template + requires jtl::is_convertible + constexpr weak_oref(weak_oref const data) noexcept + : data{ data.data } + { + } + + template + requires jtl::is_convertible + constexpr weak_oref(oref const data) noexcept + : data{ data.data } + { + } + + template + requires(C::obj_type == object_type::nil) + constexpr weak_oref(weak_oref const data) noexcept + : data{ data.data } + { + } + + template + requires(C::obj_type == object_type::nil) + constexpr weak_oref(oref const data) noexcept + : data{ data.data } + { + } + + constexpr T *operator->() const + { + /* TODO: Add type name. */ + //jank_assert_fmt_throw(*this, "Null reference on weak_oref<{}>", jtl::type_name()); + jank_assert_throw(is_some()); + return reinterpret_cast(data); + } + + constexpr T &operator*() const + { + //jank_assert_fmt_throw(*this, "Null reference on weak_oref<{}>", jtl::type_name()); + jank_assert_throw(is_some()); + return *reinterpret_cast(data); + } + + constexpr bool operator==(weak_oref const &rhs) const + { + return erase() == rhs.erase(); + } + + constexpr bool operator!=(weak_oref const &rhs) const + { + return erase() != rhs.erase(); + } + + template + requires behavior::object_like + constexpr bool operator==(weak_oref const &rhs) const + { + return data == rhs.data; + } + + template + requires behavior::object_like + constexpr bool operator!=(weak_oref const &rhs) const + { + return data != rhs.data; + } + + constexpr weak_oref &operator=(std::remove_cv_t> * const rhs) + { + data = rhs; + jank_assert_throw(data); + return *this; + } + + constexpr weak_oref &operator=(std::remove_cv_t> const * const rhs) + { + data = const_cast(rhs); + jank_assert_throw(data); + return *this; + } + + template + requires(C::obj_type == object_type::nil) + constexpr weak_oref &operator=(weak_oref const &) noexcept + { + data = std::bit_cast(detail::jank_nil_ptr); + return *this; + } + + constexpr weak_oref &operator=(jtl::nullptr_t) noexcept = delete; + constexpr bool operator==(jtl::nullptr_t) noexcept = delete; + constexpr bool operator!=(jtl::nullptr_t) noexcept = delete; + + constexpr operator oref() const noexcept + { + if(is_nil()) + { + return {}; + } + return reinterpret_cast(data); + } + + constexpr operator oref() const noexcept + { + return erase(); + } + + constexpr object *get() const noexcept + { + return erase(); + } + + constexpr object *erase() const noexcept + { + if(is_nil()) + { + return std::bit_cast(detail::jank_nil_ptr); + } + return &reinterpret_cast(data)->base; + } + + constexpr bool is_some() const noexcept + { + return data != std::bit_cast(detail::jank_nil_ptr); + } + + constexpr bool is_nil() const noexcept + { + return data == std::bit_cast(detail::jank_nil_ptr); + } + + void *data{}; + }; + + template <> + struct weak_oref + { + using value_type = obj::nil; + + constexpr weak_oref() + : data{ std::bit_cast(detail::jank_nil_ptr) } + { + } + + constexpr weak_oref(nullptr_t) = delete; + + constexpr weak_oref(value_type * const data) + : data{ data } + { + jank_assert_throw(this->data); + } + + constexpr weak_oref(value_type const * const data) + : data{ const_cast(data) } + { + jank_assert_throw(this->data); + } + + template + requires jtl::is_convertible + constexpr weak_oref(weak_oref const data) noexcept + : data{ data.data } + { + } + + template + requires jtl::is_convertible + constexpr weak_oref(oref const data) noexcept + : data{ data.data } + { + } + + template + requires(C::obj_type == object_type::nil) + constexpr weak_oref(weak_oref const data) noexcept + : data{ data.data } + { + } + + template + requires(C::obj_type == object_type::nil) + constexpr weak_oref(oref const data) noexcept + : data{ data.data } + { + } + + constexpr value_type *operator->() const + { + return data; + } + + constexpr value_type &operator*() const + { + return *data; + } + + constexpr bool operator==(weak_oref const &rhs) const + { + return rhs.is_nil(); + } + + constexpr bool operator!=(weak_oref const &rhs) const + { + return rhs.is_some(); + } + + template + requires behavior::object_like + constexpr bool operator==(weak_oref const &rhs) const + { + return rhs.is_nil(); + } + + template + requires behavior::object_like + constexpr bool operator!=(weak_oref const &rhs) const + { + return rhs.is_some(); + } + + constexpr weak_oref &operator=(jtl::nullptr_t) noexcept = delete; + constexpr bool operator==(jtl::nullptr_t) noexcept = delete; + constexpr bool operator!=(jtl::nullptr_t) noexcept = delete; + + template + requires behavior::object_like + constexpr operator oref() const noexcept + { + return {}; + } + + constexpr operator oref() const noexcept + { + return {}; + } + + constexpr object *get() const noexcept + { + return erase(); + } + + constexpr object *erase() const noexcept + { + return std::bit_cast(data); + } + + constexpr bool is_some() const noexcept + { + return false; + } + + constexpr bool is_nil() const noexcept + { + return true; + } + + value_type *data{}; + }; + + template + constexpr weak_oref make_box(weak_oref const &o) + { + static_assert(sizeof(weak_oref) == sizeof(T *)); + return o; + } +} diff --git a/compiler+runtime/include/cpp/jank/type.hpp b/compiler+runtime/include/cpp/jank/type.hpp index 87821211c..31be4f94e 100644 --- a/compiler+runtime/include/cpp/jank/type.hpp +++ b/compiler+runtime/include/cpp/jank/type.hpp @@ -7,11 +7,6 @@ #include #include -#include -#include - -#include -#include #include #include #include diff --git a/compiler+runtime/include/cpp/jtl/ref.hpp b/compiler+runtime/include/cpp/jtl/ref.hpp index 818ba3e41..c4996a12a 100644 --- a/compiler+runtime/include/cpp/jtl/ref.hpp +++ b/compiler+runtime/include/cpp/jtl/ref.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include #include #include @@ -101,23 +99,7 @@ namespace jtl ref make_ref(Args &&...args) { static_assert(sizeof(ref) == sizeof(T *)); - T *ret{}; - if constexpr(requires { T::pointer_free; }) - { - if constexpr(T::pointer_free) - { - ret = new(PointerFreeGC) T{ jtl::forward(args)... }; - } - else - { - ret = new(GC) T{ jtl::forward(args)... }; - } - } - else - { - ret = new(GC) T{ jtl::forward(args)... }; - } - + T *ret{ new T{ jtl::forward(args)... } }; jank_debug_assert(ret); return ret; } diff --git a/compiler+runtime/src/cpp/clojure/core_native.cpp b/compiler+runtime/src/cpp/clojure/core_native.cpp index 3c6d8e698..28db6e3ec 100644 --- a/compiler+runtime/src/cpp/clojure/core_native.cpp +++ b/compiler+runtime/src/cpp/clojure/core_native.cpp @@ -355,7 +355,6 @@ extern "C" jank_object_ref jank_load_clojure_core_native() intern_fn("pr-str", static_cast(&to_code_string)); intern_fn("string?", &is_string); intern_fn("char?", &is_char); - intern_fn("to-string", static_cast(&to_string)); intern_fn("str", static_cast(&str)); intern_fn("symbol?", &is_symbol); intern_fn("true?", &is_true); diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/function.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/function.cpp index dc88c8ca5..388adbc89 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/function.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/function.cpp @@ -29,7 +29,7 @@ namespace jank::analyze::expr object_ref function_arity::to_runtime_data() const { object_ref param_maps(make_box()); - for(auto const e : params) + for(auto const &e : params) { param_maps = conj(param_maps, e); } diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index f8d5fecaf..84d6b2d39 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -98,7 +98,7 @@ namespace jank::analyze /* Try to find an expansion which specifically has the `jank/macro-expansion` key * set in the meta. This is the root of our most recent expansion. */ - for(auto const latest : std::ranges::reverse_view(expansions)) + for(auto const &latest : std::ranges::reverse_view(expansions)) { auto const latest_meta{ meta(latest) }; auto const expansion( diff --git a/compiler+runtime/src/cpp/jank/c_api.cpp b/compiler+runtime/src/cpp/jank/c_api.cpp index 0be7e6aad..f1e106097 100644 --- a/compiler+runtime/src/cpp/jank/c_api.cpp +++ b/compiler+runtime/src/cpp/jank/c_api.cpp @@ -1034,8 +1034,8 @@ extern "C" /* The GC needs to enabled even before arg parsing, since our native types, * like strings, use the GC for allocations. It can still be configured later. */ - GC_set_all_interior_pointers(1); - GC_init(); + //GC_set_all_interior_pointers(1); + //GC_init(); llvm::llvm_shutdown_obj const Y{}; @@ -1049,7 +1049,7 @@ extern "C" } if(init_default_ctx) { - runtime::__rt_ctx = new(GC) runtime::context{}; + runtime::__rt_ctx = new runtime::context{}; } return fn(argc, argv); diff --git a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp index 27d49c296..2b9593e06 100644 --- a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp @@ -135,6 +135,7 @@ namespace jank::codegen void create_global_ctor() const; llvm::GlobalVariable *create_global_var(jtl::immutable_string const &name) const; + llvm::Value *gen_global(runtime::obj::weak_nil_ref) const; llvm::Value *gen_global(runtime::obj::nil_ref) const; llvm::Value *gen_global(runtime::obj::boolean_ref b) const; llvm::Value *gen_global(runtime::obj::integer_ref i) const; @@ -2953,6 +2954,11 @@ namespace jank::codegen return ctx->c_string_globals[s] = ctx->builder->CreateGlobalString(s.c_str()); } + llvm::Value *llvm_processor::impl::gen_global(obj::weak_nil_ref const nil) const + { + return gen_global(obj::nil_ref{ nil }); + } + llvm::Value *llvm_processor::impl::gen_global(obj::nil_ref const nil) const { auto const found(ctx->literal_globals.find(nil)); diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index fd69bccd3..da6e66ed0 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -499,7 +499,7 @@ namespace jank::codegen : root_fn{ expr } , module{ module } , target{ target } /* The normal unique name is fully namespaced, which we don't need. */ - , struct_name{ runtime::__rt_ctx->unique_string(root_fn->name) } + , struct_name{ runtime::munge(runtime::__rt_ctx->unique_string(root_fn->name)) } { assert(root_fn->frame.data); } @@ -2349,10 +2349,9 @@ namespace jank::codegen util::format_to(body_buffer, "auto {}{ " - "new (GC{}) {}{ {} }" + "new {}{ {} }" " };", ret_tmp, - (needs_finalizer ? ", " + finalizer_tmp : ""), type_name, value_tmp.unwrap().str(false)); @@ -2371,20 +2370,20 @@ namespace jank::codegen auto value_tmp{ gen(expr->value_expr, arity).unwrap() }; auto const value_type{ Cpp::GetPointeeType(cpp_util::expression_type(expr->value_expr)) }; auto const type_name{ cpp_util::get_qualified_type_name(value_type) }; - auto const needs_finalizer{ !Cpp::IsTriviallyDestructible(value_type) }; + //auto const needs_finalizer{ !Cpp::IsTriviallyDestructible(value_type) }; /* Calling GC_free won't trigger the finalizer. Not sure why, but it's explicitly * documented in bdwgc. So, we'll invoke it manually if needed, prior to GC_free. */ - if(needs_finalizer) - { - util::format_to(body_buffer, - "using T = {};\n" - "{}->~T();", - type_name, - value_tmp.str(false)); - } + //if(needs_finalizer) + //{ + // util::format_to(body_buffer, + // "using T = {};\n" + // "{}->~T();", + // type_name, + // value_tmp.str(false)); + //} - util::format_to(body_buffer, "GC_free({});", value_tmp.str(false)); + util::format_to(body_buffer, "delete {};", value_tmp.str(false)); if(expr->position == expression_position::tail) { @@ -2460,7 +2459,7 @@ namespace jank::codegen struct {} : jank::runtime::obj::jit_function { )", - runtime::munge(struct_name.name)); + struct_name); { native_set used_captures; @@ -2509,7 +2508,7 @@ namespace jank::codegen { native_set used_captures; - util::format_to(header_buffer, "{}(", runtime::munge(struct_name.name)); + util::format_to(header_buffer, "{}(", struct_name); bool need_comma{}; for(auto const &arity : root_fn->arities) @@ -2763,10 +2762,7 @@ namespace jank::codegen util::format_to(footer_buffer, ";"); } - util::format_to(footer_buffer, - "return {}::{}{ }.call().erase();", - ns, - runtime::munge(struct_name.name)); + util::format_to(footer_buffer, "return {}::{}{ }.call().erase();", ns, struct_name); util::format_to(footer_buffer, "}"); } @@ -2780,7 +2776,7 @@ namespace jank::codegen { util::format_to(expression_buffer, "jank::runtime::make_box<{}>(", - runtime::module::nest_native_ns(module_ns, runtime::munge(struct_name.name))); + runtime::module::nest_native_ns(module_ns, struct_name)); native_set used_captures; bool need_comma{}; diff --git a/compiler+runtime/src/cpp/jank/error.cpp b/compiler+runtime/src/cpp/jank/error.cpp index cae8deb79..ab54ddba8 100644 --- a/compiler+runtime/src/cpp/jank/error.cpp +++ b/compiler+runtime/src/cpp/jank/error.cpp @@ -451,11 +451,11 @@ namespace jank::error * begin with. In that case, we update the existing note rather than adding a new one. */ jtl::ref base::add_usage(read::source const &usage_source) { - if(usage_source == read::source::unknown || usage_source.overlaps(source)) + if(usage_source == read::source::unknown() || usage_source.overlaps(source)) { return this; } - else if(source == read::source::unknown) + else if(source == read::source::unknown()) { source = usage_source; notes[0].source = usage_source; @@ -474,7 +474,7 @@ namespace jank::error error_ref internal_failure(jtl::immutable_string const &message) { - auto const e{ make_error(kind::internal_failure, message, read::source::unknown) }; + auto const e{ make_error(kind::internal_failure, message, read::source::unknown()) }; e->trace = std::make_unique(cpptrace::generate_trace()); return e; } diff --git a/compiler+runtime/src/cpp/jank/error/analyze.cpp b/compiler+runtime/src/cpp/jank/error/analyze.cpp index f6e181327..2d04d1d02 100644 --- a/compiler+runtime/src/cpp/jank/error/analyze.cpp +++ b/compiler+runtime/src/cpp/jank/error/analyze.cpp @@ -224,7 +224,7 @@ namespace jank::error error_ref analyze_invalid_conversion(jtl::immutable_string const &message) { - return make_error(kind::analyze_invalid_conversion, message, read::source::unknown); + return make_error(kind::analyze_invalid_conversion, message, read::source::unknown()); } error_ref analyze_invalid_cpp_operator_call(jtl::immutable_string const &message, @@ -374,7 +374,7 @@ namespace jank::error error_ref internal_analyze_failure(jtl::immutable_string const &message, runtime::object_ref const expansion) { - return make_error(kind::internal_analyze_failure, message, read::source::unknown, expansion); + return make_error(kind::internal_analyze_failure, message, read::source::unknown(), expansion); } error_ref internal_analyze_failure(jtl::immutable_string const &message, diff --git a/compiler+runtime/src/cpp/jank/error/aot.cpp b/compiler+runtime/src/cpp/jank/error/aot.cpp index d06a468d5..754faf169 100644 --- a/compiler+runtime/src/cpp/jank/error/aot.cpp +++ b/compiler+runtime/src/cpp/jank/error/aot.cpp @@ -6,16 +6,16 @@ namespace jank::error { error_ref aot_unresolved_main(jtl::immutable_string const &message) { - return make_error(kind::aot_unresolved_main, message, read::source::unknown); + return make_error(kind::aot_unresolved_main, message, read::source::unknown()); } error_ref aot_compilation_failure() { - return make_error(kind::aot_compilation_failure, read::source::unknown); + return make_error(kind::aot_compilation_failure, read::source::unknown()); } error_ref internal_aot_failure(jtl::immutable_string const &message) { - return make_error(kind::internal_aot_failure, message, read::source::unknown); + return make_error(kind::internal_aot_failure, message, read::source::unknown()); } } diff --git a/compiler+runtime/src/cpp/jank/error/codegen.cpp b/compiler+runtime/src/cpp/jank/error/codegen.cpp index 19d89eacc..2cb851c63 100644 --- a/compiler+runtime/src/cpp/jank/error/codegen.cpp +++ b/compiler+runtime/src/cpp/jank/error/codegen.cpp @@ -4,6 +4,6 @@ namespace jank::error { error_ref internal_codegen_failure(jtl::immutable_string const &message) { - return make_error(kind::internal_codegen_failure, message, read::source::unknown); + return make_error(kind::internal_codegen_failure, message, read::source::unknown()); } } diff --git a/compiler+runtime/src/cpp/jank/error/parse.cpp b/compiler+runtime/src/cpp/jank/error/parse.cpp index 9caa39708..f022b822f 100644 --- a/compiler+runtime/src/cpp/jank/error/parse.cpp +++ b/compiler+runtime/src/cpp/jank/error/parse.cpp @@ -269,6 +269,6 @@ namespace jank::error error_ref internal_parse_failure(jtl::immutable_string const &message) { - return make_error(kind::internal_parse_failure, message, read::source::unknown); + return make_error(kind::internal_parse_failure, message, read::source::unknown()); } } diff --git a/compiler+runtime/src/cpp/jank/error/report.cpp b/compiler+runtime/src/cpp/jank/error/report.cpp index 5bbbc0069..b34b8707b 100644 --- a/compiler+runtime/src/cpp/jank/error/report.cpp +++ b/compiler+runtime/src/cpp/jank/error/report.cpp @@ -356,7 +356,7 @@ namespace jank::error void plan::add(read::source const &body_source, note const &n) { - if(n.source == read::source::unknown) + if(n.source == read::source::unknown()) { return; } diff --git a/compiler+runtime/src/cpp/jank/error/runtime.cpp b/compiler+runtime/src/cpp/jank/error/runtime.cpp index bac4d49ab..4898dbdff 100644 --- a/compiler+runtime/src/cpp/jank/error/runtime.cpp +++ b/compiler+runtime/src/cpp/jank/error/runtime.cpp @@ -6,39 +6,39 @@ namespace jank::error { error_ref runtime_module_not_found(jtl::immutable_string const &message) { - return make_error(kind::runtime_module_not_found, message, read::source::unknown); + return make_error(kind::runtime_module_not_found, message, read::source::unknown()); } error_ref runtime_module_binary_without_source(jtl::immutable_string const &message) { - return make_error(kind::runtime_module_binary_without_source, message, read::source::unknown); + return make_error(kind::runtime_module_binary_without_source, message, read::source::unknown()); } error_ref runtime_unable_to_open_file(jtl::immutable_string const &message) { - return make_error(kind::runtime_unable_to_open_file, message, read::source::unknown); + return make_error(kind::runtime_unable_to_open_file, message, read::source::unknown()); } error_ref runtime_invalid_cpp_eval() { - return make_error(kind::runtime_invalid_cpp_eval, read::source::unknown); + return make_error(kind::runtime_invalid_cpp_eval, read::source::unknown()); } error_ref runtime_unable_to_load_module(jtl::immutable_string const &message) { - return make_error(kind::runtime_unable_to_load_module, message, read::source::unknown); + return make_error(kind::runtime_unable_to_load_module, message, read::source::unknown()); } error_ref runtime_unable_to_load_module(error_ref const cause) { - auto const e{ make_error(kind::runtime_unable_to_load_module, read::source::unknown) }; + auto const e{ make_error(kind::runtime_unable_to_load_module, read::source::unknown()) }; e->cause = cause; return e; } error_ref internal_runtime_failure(jtl::immutable_string const &message) { - return make_error(kind::internal_runtime_failure, message, read::source::unknown); + return make_error(kind::internal_runtime_failure, message, read::source::unknown()); } error_ref diff --git a/compiler+runtime/src/cpp/jank/error/system.cpp b/compiler+runtime/src/cpp/jank/error/system.cpp index 5564690bd..780d4621a 100644 --- a/compiler+runtime/src/cpp/jank/error/system.cpp +++ b/compiler+runtime/src/cpp/jank/error/system.cpp @@ -5,11 +5,11 @@ namespace jank::error { error_ref system_clang_executable_not_found() { - return make_error(kind::system_clang_executable_not_found, read::source::unknown); + return make_error(kind::system_clang_executable_not_found, read::source::unknown()); } error_ref system_failure(jtl::immutable_string const &message) { - return make_error(kind::system_failure, message, read::source::unknown); + return make_error(kind::system_failure, message, read::source::unknown()); } } diff --git a/compiler+runtime/src/cpp/jank/evaluate.cpp b/compiler+runtime/src/cpp/jank/evaluate.cpp index ae4632738..fc276ced7 100644 --- a/compiler+runtime/src/cpp/jank/evaluate.cpp +++ b/compiler+runtime/src/cpp/jank/evaluate.cpp @@ -158,7 +158,7 @@ namespace jank::evaluate arity.fn_ctx = fn_ctx; arity.fn_ctx->param_count = arity.params.size(); - for(auto const sym : arity.params) + for(auto const &sym : arity.params) { arity.frame->locals.emplace(sym, local_binding{ sym, sym->name, none, arity.frame }); } diff --git a/compiler+runtime/src/cpp/jank/read/parse.cpp b/compiler+runtime/src/cpp/jank/read/parse.cpp index d3ca61ede..93e8e6c92 100644 --- a/compiler+runtime/src/cpp/jank/read/parse.cpp +++ b/compiler+runtime/src/cpp/jank/read/parse.cpp @@ -1269,7 +1269,7 @@ namespace jank::read::parse auto gensym(get(env, sym)); if(gensym->type == object_type::nil) { - gensym = make_box(__rt_ctx->unique_symbol(sym->name)); + gensym = __rt_ctx->unique_symbol(sym->name); __rt_ctx->gensym_env_var->set(assoc(env, sym, gensym)).expect_ok(); } sym = expect_object(gensym); diff --git a/compiler+runtime/src/cpp/jank/read/reparse.cpp b/compiler+runtime/src/cpp/jank/read/reparse.cpp index 6f0c0eb68..2aef559e8 100644 --- a/compiler+runtime/src/cpp/jank/read/reparse.cpp +++ b/compiler+runtime/src/cpp/jank/read/reparse.cpp @@ -65,7 +65,7 @@ namespace jank::read::parse source reparse_nth(obj::persistent_list_ref const o, usize const n) { auto source(object_source(o)); - if(source == source::unknown) + if(source == source::unknown()) { return source; } @@ -76,7 +76,7 @@ namespace jank::read::parse }; if(res.is_err()) { - return source::unknown; + return source::unknown(); } return res.expect_ok(); } @@ -84,7 +84,7 @@ namespace jank::read::parse source reparse_nth(runtime::obj::persistent_vector_ref const o, usize const n) { auto source(object_source(o)); - if(source == source::unknown) + if(source == source::unknown()) { return source; } @@ -95,7 +95,7 @@ namespace jank::read::parse }; if(res.is_err()) { - return source::unknown; + return source::unknown(); } return res.expect_ok(); } diff --git a/compiler+runtime/src/cpp/jank/read/source.cpp b/compiler+runtime/src/cpp/jank/read/source.cpp index a6ad207fe..b4457208a 100644 --- a/compiler+runtime/src/cpp/jank/read/source.cpp +++ b/compiler+runtime/src/cpp/jank/read/source.cpp @@ -4,11 +4,18 @@ namespace jank::read { - source_position const source_position::unknown{ 0, 0, 0 }; - source const source::unknown{ no_source_path, - no_source_path, - source_position::unknown, - source_position::unknown }; + source_position source_position::unknown() + { + return { 0, 0, 0 }; + } + + source source::unknown() + { + return { no_source_path, + no_source_path, + source_position::unknown(), + source_position::unknown() }; + } source::source(source_position const &start) : source{ start, start } diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 90daf49e5..f8afe5c52 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -442,14 +442,14 @@ namespace jank::runtime return util::format("{}-{}", prefix.c_str(), ++ns->symbol_counter); } - obj::symbol context::unique_symbol() const + obj::symbol_ref context::unique_symbol() const { return unique_symbol("G-"); } - obj::symbol context::unique_symbol(jtl::immutable_string const &prefix) const + obj::symbol_ref context::unique_symbol(jtl::immutable_string const &prefix) const { - return { "", unique_namespaced_string(prefix) }; + return make_box("", unique_namespaced_string(prefix)); } ns_ref context::intern_ns(jtl::immutable_string const &name) @@ -539,7 +539,8 @@ namespace jank::runtime } auto locked_namespaces(namespaces.wlock()); - obj::symbol const ns_sym{ qualified_sym->ns }; + obj::symbol ns_sym{ qualified_sym->ns }; + ns_sym.base.retain(); auto const found_ns(locked_namespaces->find(&ns_sym)); if(found_ns == locked_namespaces->end()) { @@ -677,7 +678,7 @@ namespace jank::runtime /* If we've actually expanded `o` into something else, it's helpful to update the meta * on the expanded data to tie it back to the original form. */ auto const source{ object_source(o) }; - if(source != read::source::unknown) + if(source != read::source::unknown()) { auto meta{ runtime::meta(expanded) }; auto const macro_kw{ __rt_ctx->intern_keyword("jank/macro-expansion").expect_ok() }; diff --git a/compiler+runtime/src/cpp/jank/runtime/core.cpp b/compiler+runtime/src/cpp/jank/runtime/core.cpp index c6f04cca8..87eadc610 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core.cpp @@ -380,7 +380,7 @@ namespace jank::runtime object_ref gensym(object_ref const o) { - return make_box(__rt_ctx->unique_symbol(to_string(o))); + return __rt_ctx->unique_symbol(to_string(o)); } object_ref atom(object_ref const o) diff --git a/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp b/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp index 755edd2d1..162ec0995 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp @@ -109,13 +109,13 @@ namespace jank::runtime auto const source(get(meta, __rt_ctx->intern_keyword("jank/source").expect_ok())); if(source == jank_nil) { - return read::source::unknown; + return read::source::unknown(); } auto const file(get(source, __rt_ctx->intern_keyword("file").expect_ok())); if(file == jank_nil) { - return read::source::unknown; + return read::source::unknown(); } auto const module(get(source, __rt_ctx->intern_keyword("module").expect_ok())); @@ -152,7 +152,7 @@ namespace jank::runtime auto const meta(runtime::meta(o)); if(meta == jank_nil) { - return read::source::unknown; + return read::source::unknown(); } return meta_source(meta); } diff --git a/compiler+runtime/src/cpp/jank/runtime/core/to_string.cpp b/compiler+runtime/src/cpp/jank/runtime/core/to_string.cpp index a240d2bc3..ab32d9245 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/to_string.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/to_string.cpp @@ -3,7 +3,7 @@ namespace jank::runtime { - jtl::immutable_string to_string(object_ref const o) + jtl::immutable_string to_string(weak_object_ref const o) { return visit_object([](auto const typed_o) { return typed_o->to_string(); }, o); } diff --git a/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp b/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp index d1ab5e2fe..fbe7794cf 100644 --- a/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp @@ -22,91 +22,91 @@ namespace jank::runtime::detail { case 0: { - auto const ret(new(GC) object_ref[2]{ key, value }); + auto const ret(new object_ref[2]{ key, value }); return ret; } case 2: { - auto const ret(new(GC) object_ref[4]{ prev[0], prev[1], key, value }); + auto const ret(new object_ref[4]{ prev[0], prev[1], key, value }); return ret; } case 4: { - auto const ret(new(GC) object_ref[6]{ prev[0], prev[1], prev[2], prev[3], key, value }); + auto const ret(new object_ref[6]{ prev[0], prev[1], prev[2], prev[3], key, value }); return ret; } case 6: { - auto const ret(new( - GC) object_ref[8]{ prev[0], prev[1], prev[2], prev[3], prev[4], prev[5], key, value }); + auto const ret( + new object_ref[8]{ prev[0], prev[1], prev[2], prev[3], prev[4], prev[5], key, value }); return ret; } case 8: { - auto const ret(new(GC) object_ref[10]{ prev[0], - prev[1], - prev[2], - prev[3], - prev[4], - prev[5], - prev[6], - prev[7], - key, - value }); + auto const ret(new object_ref[10]{ prev[0], + prev[1], + prev[2], + prev[3], + prev[4], + prev[5], + prev[6], + prev[7], + key, + value }); return ret; } case 10: { - auto const ret(new(GC) object_ref[12]{ prev[0], - prev[1], - prev[2], - prev[3], - prev[4], - prev[5], - prev[6], - prev[7], - prev[8], - prev[9], - key, - value }); + auto const ret(new object_ref[12]{ prev[0], + prev[1], + prev[2], + prev[3], + prev[4], + prev[5], + prev[6], + prev[7], + prev[8], + prev[9], + key, + value }); return ret; } case 12: { - auto const ret(new(GC) object_ref[14]{ prev[0], - prev[1], - prev[2], - prev[3], - prev[4], - prev[5], - prev[6], - prev[7], - prev[8], - prev[9], - prev[10], - prev[11], - key, - value }); + auto const ret(new object_ref[14]{ prev[0], + prev[1], + prev[2], + prev[3], + prev[4], + prev[5], + prev[6], + prev[7], + prev[8], + prev[9], + prev[10], + prev[11], + key, + value }); return ret; } case 14: { - auto const ret(new(GC) object_ref[16]{ prev[0], - prev[1], - prev[2], - prev[3], - prev[4], - prev[5], - prev[6], - prev[7], - prev[8], - prev[9], - prev[10], - prev[11], - prev[12], - prev[13], - key, - value }); + auto const ret(new object_ref[16]{ prev[0], + prev[1], + prev[2], + prev[3], + prev[4], + prev[5], + prev[6], + prev[7], + prev[8], + prev[9], + prev[10], + prev[11], + prev[12], + prev[13], + key, + value }); return ret; } default: @@ -297,7 +297,7 @@ namespace jank::runtime::detail return; } - auto const new_data{ new(GC) object_ref[new_capacity]{} }; + auto const new_data{ new object_ref[new_capacity]{} }; for(u8 i{}; i < length; i += 2) { @@ -327,8 +327,11 @@ namespace jank::runtime::detail native_array_map native_array_map::clone() const { native_array_map ret{ *this }; - ret.data = new(GC) object_ref[length]; - memcpy(ret.data, data, length * sizeof(object_ref)); + ret.data = new object_ref[length]; + for(usize i{}; i < length; ++i) + { + ret.data[i] = data[i]; + } return ret; } } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp index 9f38e0322..c3fe810cd 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp @@ -48,7 +48,7 @@ namespace jank::runtime::obj static void notify_watches(atom_ref const a, object_ref const old_val, object_ref const new_val) { auto const locked_watches(a->watches.rlock()); - for(auto const entry : (*locked_watches)->data) + for(auto const &entry : (*locked_watches)->data) { auto const fn(entry.second); if(fn.is_some()) diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp index 76fb5940e..d678b0bc8 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp @@ -108,18 +108,19 @@ namespace jank::runtime return lhs->type != object_type::nil; } - static obj::nil_ref nil_const() + static obj::weak_nil_ref nil_const() { static obj::nil n; + n.base.retain(); return &n; } - /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ - obj::nil_ref jank_nil{ nil_const() }; - namespace detail { /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ obj::nil *jank_nil_ptr{ nil_const().data }; } + + /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ + obj::weak_nil_ref jank_nil{ nil_const() }; } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp index 10bf11c54..6913750d8 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp @@ -212,12 +212,14 @@ namespace jank::runtime static obj::boolean_ref true_const() { static obj::boolean r{ true }; + r.base.retain(); return &r; } static obj::boolean_ref false_const() { static obj::boolean r{ false }; + r.base.retain(); return &r; } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp index 1890c9651..f9ce7b519 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp @@ -49,13 +49,13 @@ namespace jank::runtime::obj } return visit_set_like( - [&](auto const typed_o) -> bool { + [&](auto const &typed_o) -> bool { if(typed_o->count() != count()) { return false; } - for(auto const entry : data) + for(auto const &entry : data) { if(!typed_o->contains(entry)) { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp index 283d1bef3..69b36ce3d 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp @@ -56,13 +56,13 @@ namespace jank::runtime::obj } return visit_set_like( - [&](auto const typed_o) -> bool { + [&](auto const &typed_o) -> bool { if(typed_o->count() != count()) { return false; } - for(auto const entry : data) + for(auto const &entry : data) { if(!typed_o->contains(entry)) { diff --git a/compiler+runtime/src/cpp/jank/runtime/object.cpp b/compiler+runtime/src/cpp/jank/runtime/object.cpp index 89878309e..ffe8a870f 100644 --- a/compiler+runtime/src/cpp/jank/runtime/object.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/object.cpp @@ -2,9 +2,30 @@ #include #include #include +#include namespace jank::runtime { + void object::retain() + { + ++ref_count; + } + + void object::release() + { + --ref_count; + if(ref_count == 0) + { + visit_object( + [](auto const &typed_this) { + using T = typename jtl::decay_t::value_type; + + delete static_cast(typed_this.data); + }, + this); + } + } + bool very_equal_to::operator()(object_ref const lhs, object_ref const rhs) const noexcept { if(lhs->type != rhs->type) diff --git a/compiler+runtime/src/cpp/jank/runtime/var.cpp b/compiler+runtime/src/cpp/jank/runtime/var.cpp index 788748899..5cf87dc38 100644 --- a/compiler+runtime/src/cpp/jank/runtime/var.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/var.cpp @@ -13,21 +13,21 @@ namespace jank::runtime { - var::var(ns_ref const &n, obj::symbol_ref const &name) + var::var(weak_ns_ref const &n, obj::symbol_ref const &name) : n{ n } , name{ name } , root{ make_box(this) } { } - var::var(ns_ref const &n, obj::symbol_ref const &name, object_ref const root) + var::var(weak_ns_ref const &n, obj::symbol_ref const &name, object_ref const root) : n{ n } , name{ name } , root{ root } { } - var::var(ns_ref const &n, + var::var(weak_ns_ref const &n, obj::symbol_ref const &name, object_ref const root, bool const dynamic, @@ -55,7 +55,8 @@ namespace jank::runtime return n == v.n && name == v.name; } - static void to_string_impl(ns_ref const n, obj::symbol_ref const &name, jtl::string_builder &buff) + static void + to_string_impl(weak_ns_ref const n, obj::symbol_ref const &name, jtl::string_builder &buff) { buff("#'")(n->name->name)('/')(name->name); } diff --git a/compiler+runtime/src/cpp/main.cpp b/compiler+runtime/src/cpp/main.cpp index 4c1e2dced..e1add713c 100644 --- a/compiler+runtime/src/cpp/main.cpp +++ b/compiler+runtime/src/cpp/main.cpp @@ -46,7 +46,7 @@ namespace jank { profile::timer const timer{ "load clojure.core" }; - __rt_ctx->load_module("/clojure.core", module::origin::latest).expect_ok(); + //__rt_ctx->load_module("/clojure.core", module::origin::latest).expect_ok(); } { @@ -288,7 +288,7 @@ int main(int const argc, char const **argv) if(jank::util::cli::opts.gc_incremental) { - GC_enable_incremental(); + //GC_enable_incremental(); } profile::configure(); @@ -299,7 +299,7 @@ int main(int const argc, char const **argv) return jank::environment::check_health() ? 0 : 1; } - __rt_ctx = new(GC) runtime::context{}; + __rt_ctx = new runtime::context{}; jank_load_clojure_core_native(); jank_load_jank_compiler_native(); diff --git a/compiler+runtime/third-party/bdwgc b/compiler+runtime/third-party/bdwgc deleted file mode 160000 index 19a7f495c..000000000 --- a/compiler+runtime/third-party/bdwgc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 19a7f495cd7c48cdf6f56c593c6dd57187afa079 From fd8e465a8a6a821041339850b062247b78b7bb4d Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 5 Dec 2025 18:00:03 -0800 Subject: [PATCH 066/122] Fix more arc issues --- .../jank/runtime/detail/native_array_map.hpp | 2 +- .../jank/runtime/obj/persistent_hash_map.hpp | 1 + .../include/cpp/jank/runtime/object.hpp | 2 +- .../include/cpp/jank/runtime/oref.hpp | 47 +- .../cpp/jank/runtime/sequence_range.hpp | 10 +- .../include/cpp/jank/runtime/weak_oref.hpp | 7 - compiler+runtime/include/cpp/jtl/ref.hpp | 1 + .../src/cpp/jank/codegen/processor.cpp | 14 - .../jank/runtime/detail/native_array_map.cpp | 12 +- .../src/cpp/jank/runtime/object.cpp | 8 +- compiler+runtime/src/jank/clojure/core.jank | 13626 ++++++++-------- compiler+runtime/test/cpp/main.cpp | 3 - 12 files changed, 6882 insertions(+), 6851 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp b/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp index daf2a73d9..f6577be43 100644 --- a/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp @@ -34,7 +34,7 @@ namespace jank::runtime::detail { } - ~native_array_map() = default; + ~native_array_map(); void insert_unique(object_ref const key, object_ref const val); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp index b511a8ecd..53678455a 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp @@ -10,6 +10,7 @@ namespace jank::runtime::obj using persistent_array_map_ref = oref; using transient_hash_map_ref = oref; using persistent_hash_map_ref = oref; + using weak_persistent_hash_map_ref = weak_oref; struct persistent_hash_map : obj::detail::base_persistent_maprelease(); + reset(); } } + constexpr void reset() + { + data = std::bit_cast(detail::jank_nil_ptr); + } + constexpr value_type *operator->() const { jank_assert_throw(data); @@ -169,6 +171,11 @@ namespace jank::runtime requires behavior::object_like constexpr oref &operator=(oref const &rhs) noexcept { + if(data == &rhs->base) + { + return *this; + } + release(); data = &rhs->base; retain(); @@ -273,6 +280,7 @@ namespace jank::runtime constexpr oref(oref const &data) noexcept : data{ data.data } { + retain(); } template @@ -280,7 +288,6 @@ namespace jank::runtime constexpr oref(oref const &data) noexcept : data{ data.data } { - retain(); } constexpr ~oref() @@ -301,9 +308,15 @@ namespace jank::runtime if(is_some()) { (*this)->base.release(); + reset(); } } + constexpr void reset() + { + data = std::bit_cast(detail::jank_nil_ptr); + } + constexpr T *operator->() const { /* TODO: Add type name. */ @@ -371,6 +384,11 @@ namespace jank::runtime constexpr oref &operator=(std::remove_cv_t> * const rhs) { + if(data == rhs) + { + return *this; + } + release(); data = rhs; jank_assert_throw(data); @@ -380,6 +398,11 @@ namespace jank::runtime constexpr oref &operator=(std::remove_cv_t> const * const rhs) { + if(data == rhs) + { + return *this; + } + release(); data = const_cast(rhs); jank_assert_throw(data); @@ -391,6 +414,11 @@ namespace jank::runtime requires(C::obj_type == object_type::nil) constexpr oref &operator=(oref const &) noexcept { + if(is_nil()) + { + return *this; + } + release(); data = std::bit_cast(detail::jank_nil_ptr); retain(); @@ -466,6 +494,10 @@ namespace jank::runtime { } + constexpr void reset() + { + } + constexpr value_type *operator->() const { return data; @@ -546,6 +578,7 @@ namespace jank::runtime jtl::ref make_box(Args &&...args) { static_assert(sizeof(jtl::ref) == sizeof(T *)); + /* TODO: Figure out cleanup for this. */ T *ret{ new T{ std::forward(args)... } }; if(!ret) { @@ -573,6 +606,7 @@ namespace jank::runtime template constexpr jtl::ref make_array_box() { + /* TODO: Figure out cleanup for this. */ auto const ret(new T[N]{}); if(!ret) { @@ -584,6 +618,7 @@ namespace jank::runtime template constexpr jtl::ref make_array_box(usize const length) { + /* TODO: Figure out cleanup for this. */ auto const ret(new T[length]{}); if(!ret) { @@ -595,7 +630,7 @@ namespace jank::runtime template jtl::ref make_array_box(Args &&...args) { - /* TODO: pointer_free? */ + /* TODO: Figure out cleanup for this. */ auto const ret(new T[sizeof...(Args)]{ std::forward(args)... }); if(!ret) { diff --git a/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp b/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp index 19e2425d0..416b01f99 100644 --- a/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp @@ -183,13 +183,17 @@ namespace jank::runtime { using S = typename decltype(s->seq())::value_type; - if constexpr(behavior::sequenceable_in_place) + if constexpr(jtl::is_same) + { + return s; + } + else if constexpr(behavior::sequenceable_in_place) { - return sequence_range{ s.is_some() ? s->fresh_seq() : weak_oref{} }; + return sequence_range{ s.is_some() ? weak_oref{ s->fresh_seq() } : weak_oref{} }; } else { - return sequence_range{ s.is_some() ? s->seq() : s }; + return sequence_range{ s.is_some() ? weak_oref{ s->seq() } : s }; } } } diff --git a/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp b/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp index 6630297d8..8399638d9 100644 --- a/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp @@ -338,13 +338,6 @@ namespace jank::runtime jank_assert_throw(this->data); } - template - requires jtl::is_convertible - constexpr weak_oref(weak_oref const data) noexcept - : data{ data.data } - { - } - template requires jtl::is_convertible constexpr weak_oref(oref const data) noexcept diff --git a/compiler+runtime/include/cpp/jtl/ref.hpp b/compiler+runtime/include/cpp/jtl/ref.hpp index c4996a12a..bffbeeb3c 100644 --- a/compiler+runtime/include/cpp/jtl/ref.hpp +++ b/compiler+runtime/include/cpp/jtl/ref.hpp @@ -99,6 +99,7 @@ namespace jtl ref make_ref(Args &&...args) { static_assert(sizeof(ref) == sizeof(T *)); + /* TODO: Figure out cleanup for this. */ T *ret{ new T{ jtl::forward(args)... } }; jank_debug_assert(ret); return ret; diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index da6e66ed0..9142cb8ec 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -2331,21 +2331,7 @@ namespace jank::codegen auto ret_tmp{ runtime::munge(__rt_ctx->unique_string("cpp_new")) }; auto finalizer_tmp{ runtime::munge(__rt_ctx->unique_string("finalizer")) }; auto value_tmp{ gen(expr->value_expr, arity) }; - auto const type_name{ cpp_util::get_qualified_type_name(expr->type) }; - auto const needs_finalizer{ !Cpp::IsTriviallyDestructible(expr->type) }; - - if(needs_finalizer) - { - util::format_to(body_buffer, - "using T = {};\n" - "static auto const {}{ " - "[](void * const obj, void *){" - "reinterpret_cast(obj)->~T();" - "} };", - type_name, - finalizer_tmp); - } util::format_to(body_buffer, "auto {}{ " diff --git a/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp b/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp index fbe7794cf..2a7c43820 100644 --- a/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp @@ -8,8 +8,8 @@ namespace jank::runtime::detail static object_ref *make_next_array(object_ref * const prev, u8 const cap, u8 const length, - object_ref const key, - object_ref const value) + object_ref const &key, + object_ref const &value) { if((length + 2) <= cap) { @@ -117,6 +117,12 @@ namespace jank::runtime::detail } } + native_array_map::~native_array_map() + { + /* TODO: data could still be referenced by iterators. shared ptr? */ + //delete[] data; + } + void native_array_map::insert_unique(object_ref const key, object_ref const val) { data = make_next_array(data, cap, length, key, val); @@ -305,6 +311,8 @@ namespace jank::runtime::detail new_data[i + 1] = data[i + 1]; } + //delete[] data; + data = new_data; cap = new_capacity; } diff --git a/compiler+runtime/src/cpp/jank/runtime/object.cpp b/compiler+runtime/src/cpp/jank/runtime/object.cpp index ffe8a870f..32a7bb795 100644 --- a/compiler+runtime/src/cpp/jank/runtime/object.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/object.cpp @@ -9,18 +9,24 @@ namespace jank::runtime void object::retain() { ++ref_count; + jank_debug_assert(ref_count > 0); + util::println("retain {} type {} count {}", this, object_type_str(type), ref_count); } void object::release() { + jank_debug_assert(ref_count > 0); --ref_count; + util::println("release {} type {} count {}", this, object_type_str(type), ref_count); if(ref_count == 0) { visit_object( - [](auto const &typed_this) { + [](auto typed_this) { using T = typename jtl::decay_t::value_type; delete static_cast(typed_this.data); + + typed_this.reset(); }, this); } diff --git a/compiler+runtime/src/jank/clojure/core.jank b/compiler+runtime/src/jank/clojure/core.jank index c614b5efd..700ae8b40 100644 --- a/compiler+runtime/src/jank/clojure/core.jank +++ b/compiler+runtime/src/jank/clojure/core.jank @@ -720,6816 +720,6816 @@ "Ignores body, yields nil" [& body]) -;; Transients. -(defn- transientable? - "Returns a whether the collection can be made transient." - [coll] - (cpp/jank.runtime.is_transientable coll)) - -(defn transient - "Returns a new, transient version of the collection, in constant time." - [coll] - (cpp/jank.runtime.transient coll)) - -(defn persistent! - "Returns a new, persistent version of the transient collection, in - constant time. The transient collection cannot be used after this - call, any such use will throw an exception." - [coll] - (cpp/jank.runtime.persistent coll)) - -(defn conj! - "Adds x to the transient collection, and return coll. The 'addition' - may happen at different 'places' depending on the concrete type." - ([] - (transient [])) - ([coll] - coll) - ([coll x] - (cpp/jank.runtime.conj_in_place coll x))) - -(defn assoc! - "When applied to a transient map, adds mapping of key(s) to - val(s). When applied to a transient vector, sets the val at index. - Note - index must be <= (count vector). Returns coll." - ([coll k v] - (cpp/jank.runtime.assoc_in_place coll k v)) - ([coll k v & kvs] - (let [ret (assoc! coll k v)] - (if kvs - (recur ret (first kvs) (second kvs) (nnext kvs)) - ret)))) - -(defn dissoc! - "Returns a transient map that doesn't contain a mapping for key(s)." - ([coll k] - (cpp/jank.runtime.dissoc_in_place coll k)) - ([coll k & ks] - (let [ret (dissoc! coll k)] - (if ks - (recur ret (first ks) (next ks)) - ret)))) - -(defn pop! - "Removes the last item from a transient vector. If - the collection is empty, throws an exception. Returns coll" - [coll] - (cpp/jank.runtime.pop_in_place coll)) - -(defn disj! - "disj[oin]. Returns a transient set of the same (hashed/sorted) type, that - does not contain key(s)." - ([set] set) - ([set elem] - (cpp/jank.runtime.dissoc_in_place set elem)) - ([set elem & elems] - (let [ret (disj! set elem)] - (if elems - (recur ret (first elems) (next elems)) - ret)))) - -;; Functions. -(defn- spread - [arglist] - (cond - (nil? arglist) nil - (nil? (next arglist)) (seq (first arglist)) - :else (cons (first arglist) (spread (next arglist))))) - -(defn list* - "Creates a new seq containing the items prepended to the rest, the - last of which will be treated as a sequence." - ([args] - (seq args)) - ([a args] - (cons a args)) - ([a b args] - (cons a (cons b args))) - ([a b c args] - (cons a (cons b (cons c args)))) - ([a b c d & more] - (cons a (cons b (cons c (cons d (spread more))))))) - -(defn apply - "Applies fn f to the argument list formed by prepending intervening arguments to args." - ([f args] - (cpp/jank.runtime.apply_to f args)) - ([f x args] - (cpp/jank.runtime.apply_to f (list* x args))) - ([f x y args] - (cpp/jank.runtime.apply_to f (list* x y args))) - ([f x y z args] - (cpp/jank.runtime.apply_to f (list* x y z args))) - ([f a b c d & args] - (cpp/jank.runtime.apply_to f (cons a (cons b (cons c (cons d (spread args)))))))) - -(defn constantly - "Returns a function that takes any number of arguments and returns x." - [x] - (fn [& args] - x)) - -(defn identity - "Returns its argument." - [x] - x) - -(defn complement - "Takes a fn f and returns a fn that takes the same arguments as f, - has the same effects, if any, and returns the opposite truth value." - [f] - (fn - ([] (not (f))) - ([x] (not (f x))) - ([x y] (not (f x y))) - ([x y & zs] (not (apply f x y zs))))) - -; Utils. -(defn deref - "Also reader macro: @ref/@agent/@var/@atom/@delay/@future/@promise. Within a transaction, - returns the in-transaction-value of ref, else returns the - most-recently-committed value of ref. When applied to a var, agent - or atom, returns its current state. When applied to a delay, forces - it if not already forced. When applied to a future, will block if - computation not complete. When applied to a promise, will block - until a value is delivered. The variant taking a timeout can be - used for blocking references (futures and promises), and will return - timeout-val if the timeout (in milliseconds) is reached before a - value is available. See also - realized?." - ([ref] - (cpp/jank.runtime.deref ref)) - ; TODO: Blocking. - ([ref timeout-ms timeout-val] - ;(if (instance? clojure.lang.IBlockingDeref ref) - ; (.deref ^clojure.lang.IBlockingDeref ref timeout-ms timeout-val) - ; (deref-future ref timeout-ms timeout-val)) - )) - -(defn reduced - "Wraps x in a way such that a reduce will terminate with the value x" - [x] - (cpp/jank.runtime.reduced x)) - -(defn reduced? - "Returns true if x is the result of a call to reduced" - [x] - (cpp/jank.runtime.is_reduced x)) - -(defn ensure-reduced - "If x is already reduced?, returns it, else returns (reduced x)" - [x] - (if (reduced? x) - x - (reduced x))) - -(defn unreduced - "If x is reduced?, returns (deref x), else returns x" - [x] - (if (reduced? x) - (deref x) - x)) - -(defn reduce - "f should be a function of 2 arguments. If val is not supplied, - returns the result of applying f to the first 2 items in coll, then - applying f to that result and the 3rd item, etc. If coll contains no - items, f must accept no arguments as well, and reduce returns the - result of calling f with no arguments. If coll has only 1 item, it - is returned and f is not called. If val is supplied, returns the - result of applying f to val and the first item in coll, then - applying f to that result and the 2nd item, etc. If coll contains no - items, returns val and f is not called." - ([f coll] - (let [s (seq coll)] - (if s - (reduce f (first s) (next s)) - (f)))) - ([f init coll] - ; TODO: Chunking support. - (cpp/jank.runtime.reduce f init coll))) - -(defn completing - "Takes a reducing function f of 2 args and returns a fn suitable for - transduce by adding an arity-1 signature that calls cf (default - - identity) on the result argument." - ([f] (completing f identity)) - ([f cf] - (fn - ([] (f)) - ([x] (cf x)) - ([x y] (f x y))))) - -(defn transduce - "reduce with a transformation of rf (xf). If init is not - supplied, (rf) will be called to produce it. f should be a reducing - step function that accepts both 1 and 2 arguments, if it accepts - only 2 you can add the arity-1 with 'completing'. Returns the result - of applying (the transformed) xf to init and the first item in coll, - then applying xf to that result and the 2nd item, etc. If coll - contains no items, returns init and rf is not called. Note that - certain transforms may inject or skip items." - ([xform rf coll] - (transduce xform rf (rf) coll)) - ([xform rf init coll] - (let [f (xform rf) - ret (reduce f init coll)] - (f ret)))) - -;; TODO: private -(defn preserving-reduced - [rf] - #(let [ret (rf %1 %2)] - (if (reduced? ret) - (reduced ret) - ret))) - -(defn cat - "A transducer which concatenates the contents of each input, which must be a - collection, into the reduction." - [rf] - (let [rrf (preserving-reduced rf)] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] - (reduce rrf result input))))) - -(defn run! - "Runs the supplied procedure (via reduce), for purposes of side - effects, on successive items in the collection. Returns nil" - [proc coll] - (reduce #(proc %2) nil coll) - nil) - -(defn comp - "Takes a set of functions and returns a fn that is the composition - of those fns. The returned fn takes a variable number of args, - applies the rightmost of fns to the args, the next - fn (right-to-left) to the result, etc." - ([] identity) - ([f] f) - ([f g] - (let [a 1] (fn - ([] (f (g))) - ([x] (f (g x))) - ([x y] (f (g x y))) - ([x y z] (f (g x y z))) - ([x y z & args] (f (apply g x y z args)))))) - ([f g & fs] - (reduce comp (list* f g fs)))) - -(defn peek - "For a list or queue, same as first, for a vector, same as, but much - more efficient than, last. If the collection is empty, returns nil." - [coll] - (cpp/jank.runtime.peek coll)) - -(defn pop - "For a list or queue, returns a new list/queue without the first - item, for a vector, returns a new vector without the last item. If - the collection is empty, throws an exception. Note - not the same - as next/butlast." - [coll] - (cpp/jank.runtime.pop coll)) - -(defn vary-meta - "Returns an object of the same type and value as obj, with - (apply f (meta obj) args) as its metadata." - [o f & args] - (with-meta o (apply f (meta o) args))) - -(defn alter-meta! - "Atomically sets the metadata for a namespace/var/ref/agent/atom to be: - - (apply f its-current-meta args) - - f must be free of side-effects" - [o f & args] - ; TODO: Atomics. - (reset-meta! o (apply f (meta o) args))) - -;; Atoms. -(defn atom - "Creates and returns an Atom with an initial value of x and zero or - more options (in any order): - - :meta metadata-map - - :validator validate-fn - - If metadata-map is supplied, it will become the metadata on the - atom. validate-fn must be nil or a side-effect-free fn of one - argument, which will be passed the intended new state on any state - change. If the new state is unacceptable, the validate-fn should - return false or throw an exception." - ([x] - (cpp/jank.runtime.atom x)) - ; TODO: Validators. - #_([x & options] - (setup-reference (atom x) options))) - -(defn swap! - "Atomically swaps the value of atom to be: - (apply f current-value-of-atom args). Note that f may be called - multiple times, and thus should be free of side effects. Returns - the value that was swapped in." - ([atom f] - (cpp/jank.runtime.swap_atom atom f)) - ([atom f x] - (cpp/jank.runtime.swap_atom atom f x)) - ([atom f x y] - (cpp/jank.runtime.swap_atom atom f x y)) - ([atom f x y & args] - (cpp/jank.runtime.swap_atom atom f x y args))) - -(defn swap-vals! - "Atomically swaps the value of atom to be: - (apply f current-value-of-atom args). Note that f may be called - multiple times, and thus should be free of side effects. - Returns [old new], the value of the atom before and after the swap." - ([atom f] - (cpp/jank.runtime.swap_vals atom f)) - ([atom f x] - (cpp/jank.runtime.swap_vals atom f x)) - ([atom f x y] - (cpp/jank.runtime.swap_vals atom f x y)) - ([atom f x y & args] - (cpp/jank.runtime.swap_vals atom f x y args))) - -(defn compare-and-set! - "Atomically sets the value of atom to newval if and only if the - current value of the atom is identical to oldval. Returns true if - set happened, else false" - [atom oldval newval] - (cpp/jank.runtime.compare_and_set atom oldval newval)) - -(defn reset! - "Sets the value of atom to newval without regard for the - current value. Returns newval." - [atom newval] - (cpp/jank.runtime.reset atom newval)) - -(defn reset-vals! - "Sets the value of atom to newval. Returns [old new], the value of the - atom before and after the reset." - [atom newval] - (cpp/jank.runtime.reset_vals atom newval)) - -;; Volatiles. -(defn volatile! - "Creates and returns a volatile with an initial value of val." - [val] - (cpp/jank.runtime.volatile_ val)) - -(defn vreset! - "Sets the value of volatile to newval without regard for the - current value. Returns newval." - [vol newval] - (cpp/jank.runtime.vreset vol newval)) - -; TODO: In Clojure, this is a macro (for perf reasons). -(defn vswap! - "Non-atomically swaps the value of the volatile as if: - (apply f current-value-of-vol args). Returns the value that - was swapped in." - ([vol f] - (cpp/jank.runtime.vswap vol f)) - ([vol f & args] - (cpp/jank.runtime.vswap vol f args))) - -(defn volatile? - "Returns true if x is a volatile." - [x] - (cpp/jank.runtime.is_volatile x)) - -(defn- delay* [f] (cpp/clojure.core_native.delay f)) - -(defmacro delay - "Takes a body of expressions and yields a Delay object that will - invoke the body only the first time it is forced (with force or deref/@), and - will cache the result and return it on all subsequent force - calls. See also - realized?" - [& body] - (list `delay* (cons `fn (cons '[] body)))) - -(defn force - "If x is a Delay, returns the (possibly cached) value of its expression, else returns x" - [x] - (cpp/jank.runtime.force x)) - -;; Primitives. -;;; Arithmetic. -(defn - ^{:arities {2 {:supports-unboxed-input? true - :unboxed-output? true}}} - + - ([] - 0) - ([x] - x) - ([l r] - (cpp/jank.runtime.add l r)) - ([l r & args] - (let [res (cpp/jank.runtime.add l r)] - (if (empty? args) - res - (recur res (first args) (next args)))))) - -(defn - ^{:arities {2 {:supports-unboxed-input? true - :unboxed-output? true}}} - - - ([x] - (- 0 x)) - ([l r] - (cpp/jank.runtime.sub l r)) - ([l r & args] - (let [res (cpp/jank.runtime.sub l r)] - (if (empty? args) - res - (recur res (first args) (next args)))))) - -(defn - ^{:arities {2 {:supports-unboxed-input? true - :unboxed-output? true}}} - * - ([] - 1) - ([x] - x) - ([l r] - (cpp/jank.runtime.mul l r)) - ([l r & args] - (let [res (cpp/jank.runtime.mul l r)] - (if (empty? args) - res - (recur res (first args) (next args)))))) - -(defn - ^{:arities {2 {:supports-unboxed-input? true - :unboxed-output? true}}} - / - ([x] - (/ 1 x)) - ([l r] - (cpp/jank.runtime.div l r)) - ([l r & args] - (let [res (cpp/jank.runtime.div l r)] - (if (empty? args) - res - (recur res (first args) (next args)))))) - -;; Bit operations. -; TODO: Unboxing and inlining for these. -(defn bit-not - "Bitwise complement" - [x] - (cpp/jank.runtime.bit_not x)) - -(defn bit-and - "Bitwise and" - ([x y] - (cpp/jank.runtime.bit_and x y)) - ([x y & more] - (reduce bit-and (bit-and x y) more))) - -(defn bit-or - "Bitwise or" - ([x y] - (cpp/jank.runtime.bit_or x y)) - ([x y & more] - (reduce bit-or (bit-or x y) more))) - -(defn bit-xor - "Bitwise exclusive or" - ([x y] - (cpp/jank.runtime.bit_xor x y)) - ([x y & more] - (reduce bit-xor (bit-xor x y) more))) - -(defn bit-and-not - "Bitwise and with complement" - ([x y] - (cpp/jank.runtime.bit_and_not x y)) - ([x y & more] - (reduce bit-and-not (bit-and-not x y) more))) - -(defn bit-clear - "Clear bit at index n" - [x n] - (cpp/jank.runtime.bit_clear x n)) - -(defn bit-set - "Set bit at index n" - [x n] - (cpp/jank.runtime.bit_set x n)) - -(defn bit-flip - "Flip bit at index n" - [x n] - (cpp/jank.runtime.bit_flip x n)) - -(defn bit-test - "Test bit at index n" - [x n] - (cpp/jank.runtime.bit_test x n)) - -(defn bit-shift-left - "Bitwise shift left" - [x n] - (cpp/jank.runtime.bit_shift_left x n)) - -(defn bit-shift-right - "Bitwise shift right" - [x n] - (cpp/jank.runtime.bit_shift_right x n)) - -(defn unsigned-bit-shift-right - "Bitwise shift right, without sign-extension." - [x n] - (cpp/jank.runtime.bit_unsigned_shift_right x n)) - -(defn not= - ([x] - false) - ([x y] - (not (= x y))) - ([x y & more] - (not (apply = x y more)))) - -(defn - ^{:arities {2 {:supports-unboxed-input? true - :unboxed-output? true}}} - < - ([x] - true) - ([l r] - (cpp/jank.runtime.lt l r)) - ([l r & args] - (if (cpp/jank.runtime.lt l r) - (if (next args) - (recur r (first args) (next args)) - (cpp/jank.runtime.lt r (first args))) - false))) - -(defn - ^{:arities {2 {:supports-unboxed-input? true - :unboxed-output? true}}} - <= - ([x] - true) - ([l r] - (cpp/jank.runtime.lte l r)) - ([l r & args] - (if (cpp/jank.runtime.lte l r) - (if (next args) - (recur r (first args) (next args)) - (cpp/jank.runtime.lte r (first args))) - false))) - -(defn - ^{:arities {2 {:supports-unboxed-input? true - :unboxed-output? true}}} - > - ([x] - true) - ([l r] - (cpp/jank.runtime.lt r l)) - ([l r & args] - (if (cpp/jank.runtime.lt r l) - (if (next args) - (recur r (first args) (next args)) - (cpp/jank.runtime.lt (first args) r)) - false))) - -(defn - ^{:arities {2 {:supports-unboxed-input? true - :unboxed-output? true}}} - >= - ([x] - true) - ([l r] - (cpp/jank.runtime.lte r l)) - ([l r & args] - (if (cpp/jank.runtime.lte r l) - (if (next args) - (recur r (first args) (next args)) - (cpp/jank.runtime.lte (first args) r)) - false))) - -(defn - ^{:arities {2 {:supports-unboxed-input? true - :unboxed-output? true}}} - min - ([x] - x) - ([l r] - (cpp/jank.runtime.min l r)) - ([l r & args] - (let [res (cpp/jank.runtime.min l r)] - (if (empty? args) - res - (recur res (first args) (next args)))))) - -(defn - ^{:arities {2 {:supports-unboxed-input? true - :unboxed-output? true}}} - max - ([x] - x) - ([l r] - (cpp/jank.runtime.max l r)) - ([l r & args] - (let [res (cpp/jank.runtime.max l r)] - (if (empty? args) - res - (recur res (first args) (next args)))))) - -(defn inc - "Returns a number one greater than num. Does not auto-promote - longs, will throw on overflow. See also: inc'" - [x] - (cpp/jank.runtime.inc x)) -(defn dec - "Returns a number one less than num. Does not auto-promote - longs, will throw on overflow. See also: dec" - [x] - (cpp/jank.runtime.dec x)) - -(defn pos? - "Returns true if num is greater than zero, else false" - [num] - (cpp/jank.runtime.is_pos num)) -(defn neg? - "Returns true if num is less than zero, else false" - [num] - (cpp/jank.runtime.is_neg num)) -(defn zero? - "Returns true if num is zero, else false" - [num] - (cpp/jank.runtime.is_zero num)) - -(defn rem - "Returns the remainder of dividing numerator by denominator." - [num div] - (cpp/jank.runtime.rem num div)) -(defn quot - "quot[ient] of dividing numerator by denominator." - [num div] - (cpp/jank.runtime.quot num div)) - -(defn mod - "Modulus of num and div. Truncates toward negative infinity." - [num div] - (let [m (rem num div)] - (if (or (zero? m) (= (pos? num) (pos? div))) - m - (+ m div)))) - -;; Numbers. -(defn integer? - "Returns true if n is an integer" - [n] - (cpp/jank.runtime.is_integer n)) -(defn float? - "Returns true if n is a floating point number" - [n] - (cpp/jank.runtime.is_real n)) -(defn boolean? - "Returns true if x is a boolean" - [x] - (cpp/jank.runtime.is_boolean x)) -(defn number? - "Returns true if x is a number" - [x] - (cpp/jank.runtime.is_number x)) - -(defn even? - "Returns true if n is even, throws an exception if n is not an integer" - [n] - (cpp/jank.runtime.is_even n)) -(defn odd? - "Returns true if n is odd, throws an exception if n is not an integer" - [n] - (cpp/jank.runtime.is_odd n)) - -;; Random. -(defn rand - "Returns a random floating point number between 0 (inclusive) and - n (default 1) (exclusive)." - ([] - (cpp/jank.runtime.rand)) - ([n] - (* (rand) n))) - -;; Strings. -(defn subs - "Returns the substring of s beginning at start inclusive, and ending - at end (defaults to length of string), exclusive." - ([s start] - (cpp/jank.runtime.subs s start)) - ([s start end] - (cpp/jank.runtime.subs s start end))) - -;; Sequences (again). -(defn sequential? - "Returns true if coll implements sequential" - [coll] - (cpp/jank.runtime.is_sequential coll)) - -(defn reverse - "Returns a seq of the items in coll in reverse order. Not lazy." - [coll] - (reduce conj '() coll)) - -(defn every? - "Returns true if (pred x) is logical true for every x in coll, else false." - [pred coll] - (cond - (nil? (seq coll)) true - (pred (first coll)) (recur pred (next coll)) - :else false)) - -(defn vector - "Creates a new vector containing the args." - ([] - []) - ([a] - [a]) - ([a b] - [a b]) - ([a b c] - [a b c]) - ([a b c d] - [a b c d]) - ([a b c d e] - [a b c d e]) - ([a b c d e f] - [a b c d e f]) - ([a b c d e f & args] - ; TODO: LazilyPersistentVector - (vec (concat* [a b c d e f] args)))) - -(defn- lazy-seq* [o] (cpp/clojure.core_native.lazy_seq o)) - -(defmacro lazy-seq - "Takes a body of expressions that returns an ISeq or nil, and yields - a Seqable object that will invoke the body only the first time seq - is called, and will cache the result and return it on all subsequent - seq calls. See also - realized?" - [& body] - (list `lazy-seq* (list* `fn `lazy-seq# [] body))) - -(defn chunk-buffer - [capacity] - (cpp/jank.runtime.chunk_buffer capacity)) - -(defn chunk-append - [b x] - (cpp/jank.runtime.chunk_append b x)) - -(defn chunk - [b] - (cpp/jank.runtime.chunk b)) - -(defn chunk-first - [s] - (cpp/jank.runtime.chunk_first s)) - -(defn chunk-next - [s] - (cpp/jank.runtime.chunk_next s)) - -(defn chunk-rest - [s] - (cpp/jank.runtime.chunk_rest s)) - -(defn chunk-cons [chunk rest] - (if (empty? chunk) - rest - (cpp/jank.runtime.chunk_cons chunk rest))) - -(defn chunked-seq? - [s] - (cpp/jank.runtime.is_chunked_seq s)) - -; TODO: Support more bindings -; TODO: Support `for` functionality -(defmacro doseq - "Repeatedly executes body (presumably for side-effects) with - bindings and filtering as provided by `for`. Does not retain - the head of the sequence. Returns nil." - [bindings & body] - (let [arg (first bindings) - s (second bindings)] - (list 'clojure.core/reduce (concat* (list 'clojure.core/fn ['_ arg]) - body - [nil]) - nil - s))) - -(defn concat - "Returns a lazy seq representing the concatenation of the elements in the supplied colls." - ([] (lazy-seq nil)) - ([x] (lazy-seq x)) - ([x y] - (lazy-seq - (let [s (seq x)] - (if s - (if (chunked-seq? s) - (chunk-cons (chunk-first s) (concat (chunk-rest s) y)) - (cons (first s) (concat (rest s) y))) - y)))) - ([x y & zs] - (let [cat* (fn cat* [xys zs] - (lazy-seq - (let [xys (seq xys)] - (if xys - (if (chunked-seq? xys) - (chunk-cons (chunk-first xys) - (cat* (chunk-rest xys) zs)) - (cons (first xys) (cat* (rest xys) zs))) - (when zs - (cat* (first zs) (next zs)))))))] - (cat* (concat x y) zs)))) - -(defn juxt - "Takes a set of functions and returns a fn that is the juxtaposition - of those fns. The returned fn takes a variable number of args, and - returns a vector containing the result of applying each fn to the - args (left-to-right). - ((juxt a b c) x) => [(a x) (b x) (c x)]" - ([f] - (fn - ([] [(f)]) - ([x] [(f x)]) - ([x y] [(f x y)]) - ([x y z] [(f x y z)]) - ([x y z & args] [(apply f x y z args)]))) - ([f g] - (fn - ([] [(f) (g)]) - ([x] [(f x) (g x)]) - ([x y] [(f x y) (g x y)]) - ([x y z] [(f x y z) (g x y z)]) - ([x y z & args] [(apply f x y z args) (apply g x y z args)]))) - ([f g h] - (fn - ([] [(f) (g) (h)]) - ([x] [(f x) (g x) (h x)]) - ([x y] [(f x y) (g x y) (h x y)]) - ([x y z] [(f x y z) (g x y z) (h x y z)]) - ([x y z & args] [(apply f x y z args) (apply g x y z args) (apply h x y z args)]))) - ([f g h & fs] - (let [fs (list* f g h fs)] - (fn - ([] (reduce #(conj %1 (%2)) [] fs)) - ([x] (reduce #(conj %1 (%2 x)) [] fs)) - ([x y] (reduce #(conj %1 (%2 x y)) [] fs)) - ([x y z] (reduce #(conj %1 (%2 x y z)) [] fs)) - ([x y z & args] (reduce #(conj %1 (apply %2 x y z args)) [] fs)))))) - -(defn partial - "Takes a function f and fewer than the normal arguments to f, and - returns a fn that takes a variable number of additional args. When - called, the returned function calls f with args + additional args." - ([f] f) - ([f arg1] - (fn - ([] (f arg1)) - ([x] (f arg1 x)) - ([x y] (f arg1 x y)) - ([x y z] (f arg1 x y z)) - ([x y z & args] (apply f arg1 x y z args)))) - ([f arg1 arg2] - (fn - ([] (f arg1 arg2)) - ([x] (f arg1 arg2 x)) - ([x y] (f arg1 arg2 x y)) - ([x y z] (f arg1 arg2 x y z)) - ([x y z & args] (apply f arg1 arg2 x y z args)))) - ([f arg1 arg2 arg3] - (fn - ([] (f arg1 arg2 arg3)) - ([x] (f arg1 arg2 arg3 x)) - ([x y] (f arg1 arg2 arg3 x y)) - ([x y z] (f arg1 arg2 arg3 x y z)) - ([x y z & args] (apply f arg1 arg2 arg3 x y z args)))) - ([f arg1 arg2 arg3 & more] - (fn [& args] (apply f arg1 arg2 arg3 (concat more args))))) - -(defn fnil - "Takes a function f, and returns a function that calls f, replacing - a nil first argument to f with the supplied value x. Higher arity - versions can replace arguments in the second and third - positions (y, z). Note that the function f can take any number of - arguments, not just the one(s) being nil-patched." - ([f x] - (fn - ([a] (f (if (nil? a) x a))) - ([a b] (f (if (nil? a) x a) b)) - ([a b c] (f (if (nil? a) x a) b c)) - ([a b c & ds] (apply f (if (nil? a) x a) b c ds)))) - ([f x y] - (fn - ([a b] (f (if (nil? a) x a) (if (nil? b) y b))) - ([a b c] (f (if (nil? a) x a) (if (nil? b) y b) c)) - ([a b c & ds] (apply f (if (nil? a) x a) (if (nil? b) y b) c ds)))) - ([f x y z] - (fn - ([a b] (f (if (nil? a) x a) (if (nil? b) y b))) - ([a b c] (f (if (nil? a) x a) (if (nil? b) y b) (if (nil? c) z c))) - ([a b c & ds] (apply f (if (nil? a) x a) (if (nil? b) y b) (if (nil? c) z c) ds))))) - -(defn some - "Returns the first logical true value of (pred x) for any x in coll, - else nil. One common idiom is to use a set as pred, for example - this will return :fred if :fred is in the sequence, otherwise nil: - (some #{:fred} coll)" - [pred coll] - (let [s (seq coll)] - (when s - (or (pred (first s)) (recur pred (next s)))))) - - -(defn every-pred - "Takes a set of predicates and returns a function f that returns true if all of its - composing predicates return a logical true value against all of its arguments, else it returns - false. Note that f is short-circuiting in that it will stop execution on the first - argument that triggers a logical false result against the original predicates." - ([p] - (fn ep1 - ([] true) - ([x] (boolean (p x))) - ([x y] (boolean (and (p x) (p y)))) - ([x y z] (boolean (and (p x) (p y) (p z)))) - ([x y z & args] (boolean (and (ep1 x y z) - (every? p args)))))) - ([p1 p2] - (fn ep2 - ([] true) - ([x] (boolean (and (p1 x) (p2 x)))) - ([x y] (boolean (and (p1 x) (p1 y) (p2 x) (p2 y)))) - ([x y z] (boolean (and (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z)))) - ([x y z & args] (boolean (and (ep2 x y z) - (every? #(and (p1 %) (p2 %)) args)))))) - ([p1 p2 p3] - (fn ep3 - ([] true) - ([x] (boolean (and (p1 x) (p2 x) (p3 x)))) - ([x y] (boolean (and (p1 x) (p1 y) (p2 x) (p2 y) (p3 x) (p3 y)))) - ([x y z] (boolean (and (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z) (p3 x) (p3 y) (p3 z)))) - ([x y z & args] (boolean (and (ep3 x y z) - (every? #(and (p1 %) (p2 %) (p3 %)) args)))))) - ([p1 p2 p3 & ps] - (let [ps (list* p1 p2 p3 ps)] - (fn epn - ([] true) - ([x] (every? #(% x) ps)) - ([x y] (every? #(and (% x) (% y)) ps)) - ([x y z] (every? #(and (% x) (% y) (% z)) ps)) - ([x y z & args] (boolean (and (epn x y z) - (every? #(every? % args) ps)))))))) - -(defn some-fn - "Takes a set of predicates and returns a function f that returns the first logical true value - returned by one of its composing predicates against any of its arguments, else it returns - logical false. Note that f is short-circuiting in that it will stop execution on the first - argument that triggers a logical true result against the original predicates." - ([p] - (fn sp1 - ([] nil) - ([x] (p x)) - ([x y] (or (p x) (p y))) - ([x y z] (or (p x) (p y) (p z))) - ([x y z & args] (or (sp1 x y z) - (some p args))))) - ([p1 p2] - (fn sp2 - ([] nil) - ([x] (or (p1 x) (p2 x))) - ([x y] (or (p1 x) (p1 y) (p2 x) (p2 y))) - ([x y z] (or (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z))) - ([x y z & args] (or (sp2 x y z) - (some #(or (p1 %) (p2 %)) args))))) - ([p1 p2 p3] - (fn sp3 - ([] nil) - ([x] (or (p1 x) (p2 x) (p3 x))) - ([x y] (or (p1 x) (p1 y) (p2 x) (p2 y) (p3 x) (p3 y))) - ([x y z] (or (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z) (p3 x) (p3 y) (p3 z))) - ([x y z & args] (or (sp3 x y z) - (some #(or (p1 %) (p2 %) (p3 %)) args))))) - ([p1 p2 p3 & ps] - (let [ps (list* p1 p2 p3 ps)] - (fn spn - ([] nil) - ([x] (some #(% x) ps)) - ([x y] (some #(or (% x) (% y)) ps)) - ([x y z] (some #(or (% x) (% y) (% z)) ps)) - ([x y z & args] (or (spn x y z) - (some #(some % args) ps))))))) - - -(defn not-any? [pred coll] - (not (some pred coll))) - -(defmacro -> - "Threads the expr through the forms. Inserts x as the - second item in the first form, making a list of it if it is not a - list already. If there are more forms, inserts the first form as the - second item in second form, etc." - [x & forms] - (loop* [x x - forms forms] - (if forms - (let [form (first forms) - threaded (if (seq? form) - (with-meta `(~(first form) ~x ~@(next form)) (meta form)) - (list form x))] - (recur threaded (next forms))) - x))) - -(defmacro ->> - "Threads the expr through the forms. Inserts x as the - last item in the first form, making a list of it if it is not a - list already. If there are more forms, inserts the first form as the - last item in second form, etc." - [x & forms] - (loop* [x x - forms forms] - (if forms - (let [form (first forms) - threaded (if (seq? form) - (with-meta `(~(first form) ~@(next form) ~x) (meta form)) - (list form x))] - (recur threaded (next forms))) - x))) - -;; Maps. -(defn key - "Returns the key of the map entry." - [e] - (first e)) - -(defn val - "Returns the value in the map entry." - [e] - (second e)) - -(defn keys - "Returns a sequence of the map's keys, in the same order as (seq map)." - [m] - ; TODO: Use a proper key seq instead. - (reduce (fn [acc kv] - (conj acc (first kv))) - [] - m)) - -(defn vals - "Returns a sequence of the map's values, in the same order as (seq map)." - [m] - ; TODO: Use a proper val seq instead. - (reduce (fn [acc kv] - (conj acc (second kv))) - [] - m)) - -(defn get - "Returns the value mapped to key, not-found or nil if key not present - in associative collection, set, string, array, or ILookup instance." - ([map key] - (cpp/jank.runtime.get map key)) - ([map key not-found] - (cpp/jank.runtime.get map key not-found))) -(defn get-in - "Returns the value in a nested associative structure, - where ks is a sequence of keys. Returns nil if the key - is not present, or the not-found value if supplied." - ([m ks] - (cpp/jank.runtime.get_in m ks)) - ([m ks not-found] - (cpp/jank.runtime.get_in m ks not-found))) - -(defn dissoc - "dissoc[iate]. Returns a new map of the same (hashed/sorted) type, - that does not contain a mapping for key(s)." - ([m] - m) - ([m k] - (cpp/jank.runtime.dissoc m k)) - ([m k & ks] - (let* [ret (dissoc m k)] - (if ks - (recur ret (first ks) (next ks)) - ret)))) - -(defn contains? - "Returns true if key is present in the given collection, otherwise - returns false. Note that for numerically indexed collections like - vectors and Java arrays, this tests if the numeric key is within the - range of indexes. 'contains?' operates constant or logarithmic time; - it will not perform a linear search for a value. See also 'some'." - [coll key] - (cpp/jank.runtime.contains coll key)) - -(defn find - "Returns the map entry for key, or nil if key not present." - [map key] - (cpp/jank.runtime.find map key)) - -(defn select-keys - "Returns a map containing only those entries in map whose key is in keys" - [m ks] - (reduce (fn [acc k] - (let [e (find m k)] - (if e - (conj acc e) - acc))) - {} - ks)) - -(defn zipmap - "Returns a map with the keys mapped to the corresponding vals." - [keys vals] - (loop* [map (transient (hash-map)) - ks (seq keys) - vs (seq vals)] - (if (and ks vs) - (recur (assoc! map (first ks) (first vs)) - (next ks) - (next vs)) - (persistent! map)))) - -;; Sets. -(defn hash-set - "Returns a new hash set with supplied keys. Any equal keys are - handled as if by repeated uses of conj." - ([] (cpp/jank.runtime.obj.persistent_hash_set.empty)) - ([& keys] - (cpp/jank.runtime.obj.persistent_hash_set.create_from_seq keys))) - -(defn sorted-set - "Returns a new sorted set with supplied keys. Any equal keys are - handled as if by repeated uses of conj." - ([] (cpp/jank.runtime.obj.persistent_sorted_set.empty)) - ([& keys] - (cpp/jank.runtime.obj.persistent_sorted_set.create_from_seq keys))) - -(defn sorted-set-by - "Returns a new sorted set with supplied keys, using the supplied - comparator. Any equal keys are handled as if by repeated uses of - conj." - ([comparator & keys] - (throw "not yet implemented: sorted-set-by"))) - -(defn disj - "disj[oin]. Returns a new set of the same (hashed/sorted) type, that - does not contain key(s)." - ([set] - set) - ([set key] - (cpp/jank.runtime.disj set key)) - ([set key & ks] - (let* [res (disj set key)] - (if (empty? ks) - res - (recur res (first ks) (next ks)))))) - -(defn set? - "Returns true if x implements IPersistentSet" - [x] - (cpp/jank.runtime.is_set x)) - -(defn set - "Returns a set of the distinct elements of coll." - [coll] - (if (set? coll) - (with-meta coll nil) - (persistent! (reduce (fn [acc e] - (conj! acc e)) - (transient #{}) - coll)))) - -;; Other. -(defn hash - "Returns the hash code of its argument. Note this is the hash code - consistent with =, and thus is different than .hashCode for Integer, - Short, Byte and Clojure collections." - [o] - (cpp/jank.runtime.to_hash o)) - -(defn- named? - [x] - (cpp/jank.runtime.is_named x)) - -(defn name - "Returns the name String of a string, symbol or keyword." - [x] - (cpp/jank.runtime.name x)) - -(defn namespace - "Returns the namespace String of a symbol or keyword, or nil if not present." - [x] - (cpp/jank.runtime.namespace_ x)) - -;; Sequences. -; This is defined to be lazy later on. -(defn drop - ([n coll] - (let [step (fn [n acc] - (let [s (seq acc)] - (if (and (pos? n) s) - (recur (dec n) (rest s)) - acc)))] - (step n coll)))) - -;; Vars. -(defn var? - "Returns true if v is a var." - [x] - (cpp/clojure.core_native.is_var x)) - -(defn var-get - "Gets the value in the var object." - [x] - (cpp/clojure.core_native.var_get x)) - -(defn alter-var-root - "Atomically alters the root binding of var v by applying f to its - current value plus any args" - [v f & args] - (cpp/clojure.core_native.alter_var_root v f args)) - -(defn bound? - "Returns true if all of the vars provided as arguments have any bound value, root or thread-local. - Implies that deref'ing the provided vars will succeed. Returns true if no vars are provided." - [& vars] - (every? #(cpp/clojure.core_native.is_var_bound %) vars)) - -(defn thread-bound? - "Returns true if all of the vars provided as arguments have thread-local bindings. - Implies that set!'ing the provided vars will succeed. Returns true if no vars are provided." - [& vars] - (every? #(cpp/clojure.core_native.is_var_thread_bound %) vars)) - -(defmacro ^:private assert-macro-args - [& pairs] - (list 'do - (list 'clojure.core/when-not (first pairs) - ; TODO: No need for ex-info, if we had a simpler exception type - (list 'throw (list 'clojure.core/ex-info - (list 'clojure.core/str - '&form - " requires " - (second pairs) - " in " - 'clojure.core/*ns* - ":" - (:line (meta '&form))) - {}))) - (let [more (next (next pairs))] - (when more - (list* 'clojure.core/assert-macro-args more))))) - -(defmacro if-let - "bindings => binding-form test - - If test is true, evaluates then with binding-form bound to the value of - test, if not, yields else" - ([bindings then] - `(if-let ~bindings ~then nil)) - ([bindings then else & oldform] - (assert-macro-args - (vector? bindings) "a vector for its binding" - (nil? oldform) "1 or 2 forms after binding vector" - (= 2 (count bindings)) "exactly 2 forms in binding vector") - (let [form (get bindings 0) - tst (get bindings 1)] - `(let [temp# ~tst] - (if temp# - (let [~form temp#] - ~then) - ~else))))) - -(defmacro when-let - "bindings => binding-form test - - When test is true, evaluates body with binding-form bound to the value of test" - [bindings & body] - (assert-macro-args - (vector? bindings) "a vector for its binding" - (= 2 (count bindings)) "exactly 2 forms in binding vector") - (let [form (get bindings 0) - tst (get bindings 1)] - `(let [temp# ~tst] - (when temp# - (let [~form temp#] - ~@body))))) - -(defmacro if-some - "bindings => binding-form test - - If test is not nil, evaluates then with binding-form bound to the - value of test, if not, yields else" - ([bindings then] - `(if-some ~bindings ~then nil)) - ([bindings then else & oldform] - (assert-macro-args - (vector? bindings) "a vector for its binding" - (nil? oldform) "1 or 2 forms after binding vector" - (= 2 (count bindings)) "exactly 2 forms in binding vector") - (let [form (get bindings 0) tst (get bindings 1)] - `(let [temp# ~tst] - (if (nil? temp#) - ~else - (let [~form temp#] - ~then)))))) - -(defmacro when-some - "bindings => binding-form test - - When test is not nil, evaluates body with binding-form bound to the - value of test" - [bindings & body] - (assert-macro-args - (vector? bindings) "a vector for its binding" - (= 2 (count bindings)) "exactly 2 forms in binding vector") - (let [form (get bindings 0) - tst (get bindings 1)] - `(let [temp# ~tst] - (if (nil? temp#) - nil - (let [~form temp#] - ~@body))))) - -(defmacro dotimes - "bindings => name n - - Repeatedly executes body (presumably for side-effects) with name - bound to integers from 0 through n-1." - [bindings & body] - (assert-macro-args - (vector? bindings) "a vector for its binding" - (= 2 (count bindings)) "exactly 2 forms in binding vector") - (let [i (first bindings) - n (second bindings)] - `(let [n# (int ~n)] - (loop [~i 0] - (when (< ~i n#) - ~@body - ; TODO: unchecked-inc - (recur (inc ~i))))))) - -(defn push-thread-bindings - "WARNING: This is a low-level function. Prefer high-level macros like - binding where ever possible. - - Takes a map of Var/value pairs. Binds each Var to the associated value for - the current thread. Each call *MUST* be accompanied by a matching call to - pop-thread-bindings wrapped in a try-finally! - - (push-thread-bindings bindings) - (try - ... - (finally - (pop-thread-bindings)))" - [bindings] - (cpp/jank.runtime.push_thread_bindings bindings)) - -(defn pop-thread-bindings - "Pop one set of bindings pushed with push-binding before. It is an error to - pop bindings without pushing before." - [] - (cpp/jank.runtime.pop_thread_bindings)) - -(defn get-thread-bindings - "Get a map with the Var/value pairs which is currently in effect for the - current thread." - [] - (cpp/jank.runtime.get_thread_bindings)) - -(defmacro binding - "binding => var-symbol init-expr - - Creates new bindings for the (already-existing) vars, with the - supplied initial values, executes the exprs in an implicit do, then - re-establishes the bindings that existed before. The new bindings - are made in parallel (unlike let); all init-exprs are evaluated - before the vars are bound to their new values." - [bindings & body] - (assert-macro-args - (vector? bindings) "a vector for its binding" - (even? (count bindings)) "an even number of forms in binding vector") - (let [->var-pairs (fn ->var-pairs [var-vals] - (loop [ret [] - vvs (seq var-vals)] - (if vvs - (recur (conj (conj ret `(var ~(first vvs))) (second vvs)) - (next (next vvs))) - (seq ret))))] - `(do - (push-thread-bindings (hash-map ~@(->var-pairs bindings))) - (try - (do ~@body) - (finally - (pop-thread-bindings)))))) - -;; Keywords. -(defn keyword? - "Return true if x is a Keyword" - [x] - (cpp/jank.runtime.is_keyword x)) -(defn simple-keyword? - "Return true if x is a keyword without a namespace" - [x] - (cpp/jank.runtime.is_simple_keyword x)) -(defn qualified-keyword? - "Return true if x is a keyword with a namespace" - [x] - (cpp/jank.runtime.is_qualified_keyword x)) - -(defn keyword - "Returns a Keyword with the given namespace and name. Do not use : - in the keyword strings, it will be added automatically." - ([name] - (cond - (keyword? name) name - (symbol? name) (cpp/jank.runtime.keyword nil (str name)) - (string? name) (cpp/jank.runtime.keyword nil name))) - ([ns name] - (cpp/jank.runtime.keyword ns name))) - -(defn ident? - "Returns true if x is a symbol or keyword" - [x] - (or (keyword? x) (symbol? x))) - -(defn simple-ident? - "Returns true if x is a symbol or keyword without a namespace" - [x] - (and (ident? x) (nil? (namespace x)))) - -(defn qualified-ident? - "Returns true if x is a symbol or keyword with a namespace" - [x] - (boolean (and (ident? x) (namespace x) true))) - -;; Sequences. -(defn iterate - "Returns a lazy (infinite!) sequence of x, (f x), (f (f x)) etc. - f must be free of side-effects" - [fn x] - (cpp/jank.runtime.iterate fn x)) - -(defn range - "Returns a lazy seq of nums from start (inclusive) to end - (exclusive), by step, where start defaults to 0, step to 1, and end to - infinity. When step is equal to 0, returns an infinite sequence of - start. When start is equal to end, returns empty list." - ([] - (iterate inc 0)) - ([end] - (if (integer? end) - (cpp/jank.runtime.obj.integer_range.create end) - (cpp/jank.runtime.obj.range.create end))) - ([start end] - (if (and (integer? start) (integer? end)) - (cpp/jank.runtime.obj.integer_range.create start end) - (cpp/jank.runtime.obj.range.create start end))) - ([start end step] - (if (and (integer? start) (integer? end) (integer? step)) - (cpp/jank.runtime.obj.integer_range.create start end step) - (cpp/jank.runtime.obj.range.create start end step)))) - -(defn nth - "Returns the value at the index. get returns nil if index out of - bounds, nth throws an exception unless not-found is supplied. nth - also works for strings, Java arrays, regex Matchers and Lists, and, - in O(n) time, for sequences." - ([coll index] - (cpp/jank.runtime.nth coll index)) - ([coll index not-found] - (cpp/jank.runtime.nth coll index not-found))) - -(defn nthnext - "Returns the nth next of coll, (seq coll) when n is 0." - [coll n] - ;; TODO add support for IDrop - (loop [n n xs (seq coll)] - (if (and xs (pos? n)) - (recur (dec n) (next xs)) - xs))) - -(defn nthrest - "Returns the nth rest of coll, coll when n is 0." - [coll n] - ;; TODO add support for IDrop - (if (pos? n) - (if-let [xs (seq coll)] - (recur (rest xs) (dec n)) - (or (seq coll) ())) - coll)) - -(defn take-nth - "Returns a lazy seq of every nth item in coll. Returns a stateful - transducer when no collection is provided." - ([n] - (fn [rf] - (let [iv (volatile! -1)] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] - (let [i (vswap! iv inc)] - (if (zero? (rem i n)) - (rf result input) - result))))))) - ([n coll] - (lazy-seq - (when-let [s (seq coll)] - (cons (first s) (take-nth n (drop n s))))))) - -(defn map - "Returns a lazy sequence consisting of the result of applying f to - the set of first items of each coll, followed by applying f to the - set of second items in each coll, until any one of the colls is - exhausted. Any remaining items in other colls are ignored. Function - f should accept number-of-colls arguments. Returns a transducer when - no collection is provided." - ([f] - (fn [rf] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] - (rf result (f input))) - ([result input & inputs] - (rf result (apply f input inputs)))))) - ([f coll] - (lazy-seq - (when-let [s (seq coll)] - (if (chunked-seq? s) - (let [c (chunk-first s) - size (int (count c)) - b (chunk-buffer size)] - (dotimes [i size] - (chunk-append b (f (nth c i)))) - (chunk-cons (chunk b) (map f (chunk-rest s)))) - (cons (f (first s)) (map f (rest s))))))) - ([f c1 c2] - (lazy-seq - (let [s1 (seq c1) - s2 (seq c2)] - (when (and s1 s2) - (cons (f (first s1) (first s2)) - (map f (rest s1) (rest s2))))))) - ([f c1 c2 c3] - (lazy-seq - (let [s1 (seq c1) - s2 (seq c2) - s3 (seq c3)] - (when (and s1 s2 s3) - (cons (f (first s1) (first s2) (first s3)) - (map f (rest s1) (rest s2) (rest s3))))))) - ([f c1 c2 c3 & colls] - (let [step (fn step [cs] - (lazy-seq - (let [ss (map seq cs)] - (when (every? identity ss) - (cons (map first ss) (step (map rest ss)))))))] - (map #(apply f %) (step (conj colls c3 c2 c1)))))) - -(defmacro doto - "Evaluates x then calls all of the methods and functions with the - value of x supplied at the front of the given arguments. The forms - are evaluated in order. Returns x." - [x & forms] - (let [gx (gensym)] - `(let [~gx ~x] - ~@(map (fn [f] - (with-meta - (if (seq? f) - `(~(first f) ~gx ~@(next f)) - `(~f ~gx)) - (meta f))) - forms) - ~gx))) - -(defn map-indexed - "Returns a lazy sequence consisting of the result of applying f to 0 - and the first item of coll, followed by applying f to 1 and the second - item in coll, etc, until coll is exhausted. Thus function f should - accept 2 arguments, index and item. Returns a stateful transducer when - no collection is provided." - ([f] - (fn [rf] - (let [i (volatile! -1)] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] - (rf result (f (vswap! i inc) input))))))) - ([f coll] - (let [mapi (fn mapi [idx coll] - (lazy-seq - (when-let [s (seq coll)] - (if (chunked-seq? s) - (let [c (chunk-first s) - size (int (count c)) - b (chunk-buffer size)] - (dotimes [i size] - (chunk-append b (f (+ idx i) (nth c i)))) - (chunk-cons (chunk b) (mapi (+ idx size) (chunk-rest s)))) - (cons (f idx (first s)) (mapi (inc idx) (rest s)))))))] - (mapi 0 coll)))) - -(defn keep - "Returns a lazy sequence of the non-nil results of (f item). Note, - this means false return values will be included. f must be free of - side-effects. Returns a transducer when no collection is provided." - ([f] - (fn [rf] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] - (let [v (f input)] - (if (nil? v) - result - (rf result v))))))) - ([f coll] - (lazy-seq - (when-let [s (seq coll)] - (if (chunked-seq? s) - (let [c (chunk-first s) - size (count c) - b (chunk-buffer size)] - (dotimes [i size] - (let [x (f (nth c i))] - (when-not (nil? x) - (chunk-append b x)))) - (chunk-cons (chunk b) (keep f (chunk-rest s)))) - (let [x (f (first s))] - (if (nil? x) - (keep f (rest s)) - (cons x (keep f (rest s)))))))))) - -(defn keep-indexed - "Returns a lazy sequence of the non-nil results of (f index item). Note, - this means false return values will be included. f must be free of - side-effects. Returns a stateful transducer when no collection is - provided." - ([f] - (fn [rf] - (let [iv (volatile! -1)] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] - (let [i (vswap! iv inc) - v (f i input)] - (if (nil? v) - result - (rf result v)))))))) - ([f coll] - (let [keepi (fn keepi [idx coll] - (lazy-seq - (when-let [s (seq coll)] - (if (chunked-seq? s) - (let [c (chunk-first s) - size (count c) - b (chunk-buffer size)] - (dotimes [i size] - (let [x (f (+ idx i) (nth c i))] - (when-not (nil? x) - (chunk-append b x)))) - (chunk-cons (chunk b) (keepi (+ idx size) (chunk-rest s)))) - (let [x (f idx (first s))] - (if (nil? x) - (keepi (inc idx) (rest s)) - (cons x (keepi (inc idx) (rest s)))))))))] - (keepi 0 coll)))) - -(defn take - "Returns a lazy sequence of the first n items in coll, or all items if - there are fewer than n. Returns a stateful transducer when - no collection is provided." - ([n] - (fn [rf] - (let [nv (volatile! n)] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] - (let [n (deref nv) - nn (vswap! nv dec) - result (if (pos? n) - (rf result input) - result)] - (if (not (pos? nn)) - (ensure-reduced result) - result))))))) - ([n coll] - (lazy-seq - (when (pos? n) - (when-let [s (seq coll)] - (cons (first s) (take (dec n) (rest s)))))))) - -(defn repeatedly - "Takes a function of no args, presumably with side effects, and - returns an infinite (or length n if supplied) lazy sequence of calls - to it" - ([f] (lazy-seq (cons (f) (repeatedly f)))) - ([n f] (take n (repeatedly f)))) - -(defn take-while - "Returns a lazy sequence of successive items from coll while - (pred item) returns logical true. pred must be free of side-effects. - Returns a transducer when no collection is provided" - ([pred] - (fn [rf] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] - (if (pred input) - (rf result input) - (reduced result)))))) - ([pred coll] - (lazy-seq - (when-let [s (seq coll)] - (when (pred (first s)) - (cons (first s) (take-while pred (rest s)))))))) - -(defn drop - "Returns a lazy sequence of all but the first n items in coll. - Returns a stateful transducer when no collection is provided." - ([n] - (fn [rf] - (let [nv (volatile! n)] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] - (let [n (deref nv)] - (vswap! nv dec) - (if (pos? n) - result - (rf result input)))))))) - ([n coll] - (let [step (fn [n coll] - (let [s (seq coll)] - (if (and (pos? n) s) - (recur (dec n) (rest s)) - s)))] - (lazy-seq (step n coll))))) - -(defn drop-last - "Return a lazy sequence of all but the last n (default 1) items in coll" - ([coll] (drop-last 1 coll)) - ([n coll] (map (fn [x _] x) coll (drop n coll)))) - -(defn drop-while - "Returns a lazy sequence of the items in coll starting from the - first item for which (pred item) returns logical false. Returns a - stateful transducer when no collection is provided." - ([pred] - (fn [rf] - (let [dv (volatile! true)] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] - (let [drop? (deref dv)] - (if (and drop? (pred input)) - result - (do - (vreset! dv nil) - (rf result input))))))))) - ([pred coll] - (let [step (fn [pred coll] - (let [s (seq coll)] - (if (and s (pred (first s))) - (recur pred (rest s)) - s)))] - (lazy-seq (step pred coll))))) - -(defn cycle - "Returns a lazy (infinite!) sequence of repetitions of the items in coll." - [coll] - ; TODO: Custom cycle object - (lazy-seq (concat coll (cycle coll)))) - -(defn repeat - "Returns a lazy (infinite!, or length n if supplied) sequence of val." - ([x] - (cpp/jank.runtime.obj.repeat.create x)) - ([n x] - (cpp/jank.runtime.obj.repeat.create n x))) - -(defn split-at - "Returns a vector of [(take n coll) (drop n coll)]" - [n coll] - [(take n coll) (drop n coll)]) - -(defn split-with - "Returns a vector of [(take-while pred coll) (drop-while pred coll)]" - [pred coll] - [(take-while pred coll) (drop-while pred coll)]) - -(defn interleave - "Returns a lazy seq of the first item in each coll, then the second etc." - ([] ()) - ([c1] (lazy-seq c1)) - ([c1 c2] - (lazy-seq - (let [s1 (seq c1) s2 (seq c2)] - (when (and s1 s2) - (cons (first s1) (cons (first s2) - (interleave (rest s1) (rest s2)))))))) - ([c1 c2 & colls] - (lazy-seq - (let [ss (map seq (conj colls c2 c1))] - (when (every? identity ss) - (concat (map first ss) (apply interleave (map rest ss)))))))) - -(defn interpose - "Returns a lazy seq of the elements of coll separated by sep. - Returns a stateful transducer when no collection is provided." - ([sep] - (fn [rf] - (let [started (volatile! false)] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] - (if (deref started) - (let [sepr (rf result sep)] - (if (reduced? sepr) - sepr - (rf sepr input))) - (do - (vreset! started true) - (rf result input)))))))) - ([sep coll] - (drop 1 (interleave (repeat sep) coll)))) - -(defn dorun - "When lazy sequences are produced via functions that have side - effects, any effects other than those needed to produce the first - element in the seq do not occur until the seq is consumed. dorun can - be used to force any effects. Walks through the successive nexts of - the seq, does not retain the head and returns nil." - ([coll] - (when-let [s (seq coll)] - (recur (next s)))) - ([n coll] - (when (and (seq coll) (pos? n)) - (recur (dec n) (next coll))))) - -(defn doall - "When lazy sequences are produced via functions that have side - effects, any effects other than those needed to produce the first - element in the seq do not occur until the seq is consumed. doall can - be used to force any effects. Walks through the successive nexts of - the seq, retains the head and returns it, thus causing the entire - seq to reside in memory at one time." - ([coll] - (dorun coll) - coll) - ([n coll] - (dorun n coll) - coll)) - -(defn partition - "Returns a lazy sequence of lists of n items each, at offsets step - apart. If step is not supplied, defaults to n, i.e. the partitions - do not overlap. If a pad collection is supplied, use its elements as - necessary to complete last partition upto n items. In case there are - not enough padding elements, return a partition with less than n items." - ([n coll] - (partition n n coll)) - ([n step coll] - (lazy-seq - (when-let [s (seq coll)] - (let [p (doall (take n s))] - (when (= n (count p)) - (cons p (partition n step (nthrest s step)))))))) - ([n step pad coll] - (lazy-seq - (when-let [s (seq coll)] - (let [p (doall (take n s))] - (if (= n (count p)) - (cons p (partition n step pad (nthrest s step))) - (list (take n (concat p pad))))))))) - -(defn partition-all - "Returns a lazy sequence of lists like partition, but may include - partitions with fewer than n items at the end. Returns a stateful - transducer when no collection is provided." - ([n] - (fn [rf] - ;; OPTIMIZE: jvm clojure uses an array here for perf - (let [part (volatile! [])] - (fn - ([] (rf)) - ([result] - (let [p (deref part) - result (if (empty? p) - result - (unreduced (rf result p)))] - (rf result))) - ([result input] - (let [p (vswap! part conj input)] - (if (= n (count p)) - (do (vreset! part []) - (rf result p)) - result))))))) - ([n coll] - (partition-all n n coll)) - ([n step coll] - (lazy-seq - (when-let [s (seq coll)] - (let [seg (doall (take n s))] - (cons seg (partition-all n step (nthrest s step)))))))) - -(defn partition-by - "Applies f to each value in coll, splitting it each time f returns a - new value. Returns a lazy seq of partitions. Returns a stateful - transducer when no collection is provided." - ([f] - (fn [rf] - ;; OPTIMIZE: jvm clojure uses an array here for perf - (let [vv (volatile! []) - pv (volatile! ::none)] - (fn - ([] (rf)) - ([result] - (let [v (deref vv) - result (if (empty? v) - result - (unreduced (rf result v)))] - (rf result))) - ([result input] - (let [pval (deref pv) - val (f input)] - (vreset! pv val) - (if (or (identical? pval ::none) - (= val pval)) - (do - (vswap! vv conj input) - result) - (let [v (deref vv) - ret (rf result v)] - (when-not (reduced? ret) - (vreset! vv [input])) - ret)))))))) - ([f coll] - (lazy-seq - (when-let [s (seq coll)] - (let [fst (first s) - fv (f fst) - run (cons fst (take-while #(= fv (f %)) (next s)))] - (cons run (partition-by f (lazy-seq (drop (count run) s))))))))) - -(defn frequencies - "Returns a map from distinct items in coll to the number of times - they appear." - [coll] - (persistent! - (reduce - (fn [counts x] - (assoc! counts x (inc (get counts x 0)))) - (transient {}) - coll))) - -(defn group-by - "Returns a map of the elements of coll keyed by the result of - f on each element. The value at each key will be a vector of the - corresponding elements, in the order they appeared in coll." - [f coll] - (persistent! - (reduce - (fn [ret x] - (let [k (f x)] - (assoc! ret k (conj (get ret k []) x)))) - (transient {}) - coll))) - -(defn reductions - "Returns a lazy seq of the intermediate values of the reduction (as - per reduce) of coll by f, starting with init." - ([f coll] - (lazy-seq - (if-let [s (seq coll)] - (reductions f (first s) (rest s)) - (list (f))))) - ([f init coll] - (if (reduced? init) - (list (deref init)) - (cons init - (lazy-seq - (when-let [s (seq coll)] - (reductions f (f init (first s)) (rest s)))))))) - -(defn into - "Returns a new coll consisting of to-coll with all of the items of - from-coll conjoined. A transducer may be supplied." - ([] []) - ([to] to) - ([to from] - (if (transientable? to) - (with-meta (persistent! (reduce conj! (transient to) from)) (meta to)) - (reduce conj to from))) - ([to xform from] - (if (transientable? to) - (with-meta (persistent! (transduce xform conj! (transient to) from)) (meta to)) - (transduce xform conj to from)))) - -; Redefine let and loop with destructuring. -(defn destructure - [bindings] - (let [bents (partition 2 bindings) - pb (fn pb [bvec b v] - (let [pvec - (fn pvec [bvec b val] - (let [gvec (gensym "vec") - gseq (gensym "seq") - gfirst (gensym "first") - has-rest (some #{'&} b)] - (loop [ret (let [ret (conj bvec gvec val)] - (if has-rest - (conj ret gseq (list `seq gvec)) - ret)) - n 0 - bs b - seen-rest? false] - (if (seq bs) - (let [firstb (first bs)] - (cond - (= firstb '&) (recur (pb ret (second bs) gseq) - n - (nnext bs) - true) - (= firstb :as) (pb ret (second bs) gvec) - :else (if seen-rest? - (throw "Unsupported binding form, only :as can follow & parameter") - (recur (pb (if has-rest - (conj ret - gfirst `(first ~gseq) - gseq `(next ~gseq)) - ret) - firstb - (if has-rest - gfirst - (list `nth gvec n nil))) - (inc n) - (next bs) - seen-rest?)))) - ret)))) - pmap - (fn pmap [bvec b v] - (let [gmap (gensym "map") - defaults (:or b)] - (loop [ret (-> bvec - (conj gmap) (conj v) - (conj gmap) (conj `(if (seq? ~gmap) - (if (next ~gmap) - (into {} ~gmap) - (if (seq ~gmap) - (first ~gmap) - {})) - ~gmap)) - ((fn pmap#ret [ret] - (if (:as b) - (conj ret (:as b) gmap) - ret)))) - bes (let [transforms - (reduce - (fn pmap#transforms [transforms mk] - (if (keyword? mk) - (let [mkns (namespace mk) - mkn (name mk)] - (cond (= mkn "keys") (assoc transforms mk #(keyword (or mkns (namespace %)) (name %))) - (= mkn "syms") (assoc transforms mk #(list `quote (symbol (or mkns (namespace %)) (name %)))) - (= mkn "strs") (assoc transforms mk str) - :else transforms)) - transforms)) - {} - (keys b))] - (reduce - (fn pmap#bes [bes entry] - (reduce #(assoc %1 %2 ((val entry) %2)) - (dissoc bes (key entry)) - ((key entry) bes))) - (dissoc b :as :or) - transforms))] - (if (seq bes) - (let [bb (key (first bes)) - bk (val (first bes)) - local (if (named? bb) - (with-meta (symbol nil (name bb)) (meta bb)) - bb) - bv (if (contains? defaults local) - (list `get gmap bk (defaults local)) - (list `get gmap bk))] - (recur (if (ident? bb) - (-> ret (conj local bv)) - (pb ret bb bv)) - (next bes))) - ret))))] - (cond - (symbol? b) (-> bvec (conj b) (conj v)) - (vector? b) (pvec bvec b v) - (map? b) (pmap bvec b v) - :else (throw (str "Unsupported binding form: " b))))) - process-entry (fn process-entry [bvec b] - (pb bvec (first b) (second b)))] - (if (every? symbol? (map first bents)) - bindings - (reduce process-entry [] bents)))) - -(defmacro let - "binding => binding-form init-expr - binding-form => name, or destructuring-form - destructuring-form => map-destructure-form, or seq-destructure-form - - Evaluates the exprs in a lexical context in which the symbols in - the binding-forms are bound to their respective init-exprs or parts - therein. - - See https://clojure.org/reference/special_forms#binding-forms for - more information about destructuring." - [bindings & body] - (assert-macro-args - (vector? bindings) "a vector for its binding" - (even? (count bindings)) "an even number of forms in binding vector") - `(let* ~(destructure bindings) ~@body)) - -(defn maybe-destructured - {:private true} - [params body] - (if (every? symbol? params) - (cons params body) - (loop [params params - new-params (with-meta [] (meta params)) - lets []] - (if params - (if (symbol? (first params)) - (recur (next params) (conj new-params (first params)) lets) - (let [gparam (gensym "p__")] - (recur (next params) (conj new-params gparam) - (-> lets (conj (first params)) (conj gparam))))) - `(~new-params - (let ~lets - ~@body)))))) - -(defmacro fn - "params => positional-params*, or positional-params* & rest-param - positional-param => binding-form - rest-param => binding-form - binding-form => name, or destructuring-form - - Defines a function. - - See https://clojure.org/reference/special_forms#fn for more information" - [& sigs] - (let [name (if (symbol? (first sigs)) (first sigs) nil) - sigs (if name (next sigs) sigs) - sigs (if (vector? (first sigs)) - (list sigs) - (if (seq? (first sigs)) - sigs - ; Assume single arity syntax - (throw (if (seq sigs) - (str "Parameter declaration " - (first sigs) - " should be a vector") - (str "Parameter declaration missing"))))) - psig (fn* [sig] - ; Ensure correct type before destructuring sig - (when (not (seq? sig)) - (throw (str "Invalid signature " sig - " should be a list"))) - (let [[params & body] sig - _ (when (not (vector? params)) - (throw (if (seq? (first sigs)) - (str "Parameter declaration " params - " should be a vector") - (str "Invalid signature " sig - " should be a list")))) - conds (when (and (next body) (map? (first body))) - (first body)) - body (if conds (next body) body) - conds (or conds (meta params)) - pre (:pre conds) - post (:post conds) - body (if post - `((let [~'% ~(if (< 1 (count body)) - `(do ~@body) - (first body))] - ~@(map (fn* [c] - `(assert ~c)) post) - ~'%)) - body) - body (if pre - (concat (map (fn* [c] - `(assert ~c)) pre) - body) - body)] - (maybe-destructured params body))) - new-sigs (map psig sigs)] - (with-meta - (if name - `(fn* ~name ~@new-sigs) - `(fn* ~@new-sigs)) - (meta &form)))) - -(defmacro loop - "Evaluates the exprs in a lexical context in which the symbols in - the binding-forms are bound to their respective init-exprs or parts - therein. Acts as a recur target." - [all-bindings & body] - (assert-macro-args - (vector? all-bindings) "a vector for its binding" - (even? (count all-bindings)) "an even number of forms in binding vector") - (let [db (destructure all-bindings)] - (if (= db all-bindings) - `(loop* ~all-bindings ~@body) - (let [values (take-nth 2 (drop 1 all-bindings)) - bindings (take-nth 2 all-bindings) - syms (map (fn [b] - (if (symbol? b) - b - (gensym))) - bindings) - final-bindings (reduce (fn [ret [b v g]] - (if (symbol? b) - (conj ret g v) - (conj ret g v b g))) - [] - (map vector bindings values syms))] - `(let ~final-bindings - (loop* ~(vec (interleave syms syms)) - (let ~(vec (interleave bindings syms)) - ~@body))))))) - -(defmacro for - "List comprehension. Takes a vector of one or more - binding-form/collection-expr pairs, each followed by zero or more - modifiers, and yields a lazy sequence of evaluations of expr. - Collections are iterated in a nested fashion, rightmost fastest, - and nested coll-exprs can refer to bindings created in prior - binding-forms. Supported modifiers are: :let [binding-form expr ...], - :while test, :when test. - - (take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))" - [seq-exprs body-expr] - (assert-macro-args - (vector? seq-exprs) "a vector for its binding" - (even? (count seq-exprs)) "an even number of forms in binding vector") - (let [to-groups (fn [seq-exprs] - (reduce (fn [groups [k v]] - (if (keyword? k) - (conj (pop groups) (conj (peek groups) [k v])) - (conj groups [k v]))) - [] (partition 2 seq-exprs))) - err (fn [& msg] (throw (apply str msg))) - emit-bind (fn emit-bind [[[bind expr & mod-pairs] - & [[_ next-expr] :as next-groups]]] - (let [giter (gensym "iter__") - gxs (gensym "s__") - do-mod (fn do-mod [[[k v :as pair] & etc]] - (cond - (= k :let) `(let ~v ~(do-mod etc)) - (= k :while) `(when ~v ~(do-mod etc)) - (= k :when) `(if ~v - ~(do-mod etc) - (recur (rest ~gxs))) - (keyword? k) (err "Invalid 'for' keyword " k) - next-groups - `(let [iterys# ~(emit-bind next-groups) - fs# (seq (iterys# ~next-expr))] - (if fs# - (concat fs# (~giter (rest ~gxs))) - (recur (rest ~gxs)))) - :else (do - `(cons ~body-expr - (~giter (rest ~gxs))))))] - (if next-groups - ; not the inner-most loop - `(fn ~giter [~gxs] - (lazy-seq - (loop [~gxs ~gxs] - (when-first [~bind ~gxs] - ~(do-mod mod-pairs))))) - ; inner-most loop - (let [gi (gensym "i__") - gb (gensym "b__") - do-cmod (fn do-cmod [[[k v :as pair] & etc]] - (cond - (= k :let) `(let ~v ~(do-cmod etc)) - (= k :while) `(when ~v ~(do-cmod etc)) - (= k :when) `(if ~v - ~(do-cmod etc) - (recur - ; TODO: unchecked-inc - (inc ~gi))) - (keyword? k) - (err "Invalid 'for' keyword " k) - :else - `(do (chunk-append ~gb ~body-expr) - ; TODO: unchecked-inc - (recur (inc ~gi)))))] - `(fn ~giter [~gxs] - (lazy-seq - (loop [~gxs ~gxs] - (when-let [~gxs (seq ~gxs)] - (if (chunked-seq? ~gxs) - (let [c# (chunk-first ~gxs) - size# (int (count c#)) - ~gb (chunk-buffer size#)] - (if (loop [~gi (int 0)] - (if (< ~gi size#) - (let [~bind (nth c# ~gi)] - ~(do-cmod mod-pairs)) - true)) - (chunk-cons - (chunk ~gb) - (~giter (chunk-rest ~gxs))) - (chunk-cons (chunk ~gb) nil))) - (let [~bind (first ~gxs)] - ~(do-mod mod-pairs)))))))))))] - `(let [iter# ~(emit-bind (to-groups seq-exprs))] - (iter# ~(second seq-exprs))))) - -(defn not-empty - "If coll is empty, returns nil, else coll" - [coll] - (when (seq coll) - coll)) - -(defn get-in - "Returns the value in a nested associative structure, - where ks is a sequence of keys. Returns nil if the key - is not present, or the not-found value if supplied." - ([m ks] - (reduce get m ks)) - ([m ks not-found] - (loop [m m - ks (seq ks)] - (if ks - (let [m (get m (first ks) ::none)] - (if (identical? ::none m) - not-found - (recur m (next ks)))) - m)))) - -(defn assoc-in - "Associates a value in a nested associative structure, where ks is a - sequence of keys and v is the new value and returns a new nested structure. - If any levels do not exist, hash-maps will be created." - [m [k & ks] v] - (if ks - (assoc m k (assoc-in (get m k) ks v)) - (assoc m k v))) - -(defn update-in - "'Updates' a value in a nested associative structure, where ks is a - sequence of keys and f is a function that will take the old value - and any supplied args and return the new value, and returns a new - nested structure. If any levels do not exist, hash-maps will be - created." - [m ks f & args] - (let [up (fn up [m ks f args] - (let [[k & ks] ks] - (if ks - (assoc m k (up (get m k) ks f args)) - (assoc m k (apply f (get m k) args)))))] - (up m ks f args))) - -(defn update - "'Updates' a value in an associative structure, where k is a - key and f is a function that will take the old value - and any supplied args and return the new value, and returns a new - structure. If the key does not exist, nil is passed as the old value." - ([m k f] - (assoc m k (f (get m k)))) - ([m k f x] - (assoc m k (f (get m k) x))) - ([m k f x y] - (assoc m k (f (get m k) x y))) - ([m k f x y z] - (assoc m k (f (get m k) x y z))) - ([m k f x y z & more] - (assoc m k (apply f (get m k) x y z more)))) - -(defmacro when-first - "bindings => x xs - - Roughly the same as (when (seq xs) (let [x (first xs)] body)) but xs is evaluated only once" - [bindings & body] - (assert-macro-args - (vector? bindings) "a vector for its binding" - (= 2 (count bindings)) "exactly 2 forms in binding vector") - (let [[x xs] bindings] - `(when-let [xs# (seq ~xs)] - (let [~x (first xs#)] - ~@body)))) - -(defn take-last - "Returns a seq of the last n items in coll. Depending on the type - of coll may be no better than linear time. For vectors, see also subvec." - [n coll] - (loop [s (seq coll) - lead (seq (drop n coll))] - (if lead - (recur (next s) (next lead)) - s))) - -(defn mapv - "Returns a vector consisting of the result of applying f to the - set of first items of each coll, followed by applying f to the set - of second items in each coll, until any one of the colls is - exhausted. Any remaining items in other colls are ignored. Function - f should accept number-of-colls arguments." - ([f coll] - (-> (reduce (fn [v o] - (conj! v (f o))) - (transient []) - coll) - persistent!)) - ([f c1 c2] - (into [] (map f c1 c2))) - ([f c1 c2 c3] - (into [] (map f c1 c2 c3))) - ([f c1 c2 c3 & colls] - (into [] (apply map f c1 c2 c3 colls)))) - -(defn filterv - "Returns a vector of the items in coll for which - (pred item) returns logical true. pred must be free of side-effects." - [pred coll] - (-> (reduce (fn [v o] - (if (pred o) - (conj! v o) - v)) - (transient []) - coll) - persistent!)) - -(defn mapcat - "Returns the result of applying concat to the result of applying map - to f and colls. Thus function f should return a collection. Returns - a transducer when no collections are provided" - ([f] (comp (map f) cat)) - ; TODO: Variadic. - ([f coll] - (apply concat (map f coll)))) - -(defn tree-seq - "Returns a lazy sequence of the nodes in a tree, via a depth-first walk. - branch? must be a fn of one arg that returns true if passed a node - that can have children (but may not). children must be a fn of one - arg that returns a sequence of the children. Will only be called on - nodes for which branch? returns true. Root is the root node of the - tree." - [branch? children root] - (let [walk (fn walk [node] - (lazy-seq - (cons node - (when (branch? node) - (mapcat walk (children node))))))] - (walk root))) - -(defn distinct - "Returns a lazy sequence of the elements of coll with duplicates removed. - Returns a stateful transducer when no collection is provided." - ([] - (fn [rf] - (let [seen (volatile! #{})] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] - (if (contains? (deref seen) input) - result - (do (vswap! seen conj input) - (rf result input)))))))) - ([coll] - (let [step (fn step [xs seen] - (lazy-seq - ((fn [[f :as xs] seen] - (when-let [s (seq xs)] - (if (contains? seen f) - (recur (rest s) seen) - (cons f (step (rest s) (conj seen f)))))) - xs seen)))] - (step coll #{})))) - -(defn distinct? - "Returns true if no two of the arguments are =" - ([x] true) - ([x y] (not (= x y))) - ([x y & more] - (if (not= x y) - (loop [s #{x y} - [x & etc :as xs] more] - (if xs - (if (contains? s x) - false - (recur (conj s x) etc)) - true)) - false))) - -(defn filter - "Returns a lazy sequence of the items in coll for which - (pred item) returns logical true. pred must be free of side-effects. - Returns a transducer when no collection is provided." - ([pred] - (fn [rf] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] - (if (pred input) - (rf result input) - result))))) - ([pred coll] - (lazy-seq - (when-let [s (seq coll)] - (if (chunked-seq? s) - (let [c (chunk-first s) - size (count c) - b (chunk-buffer size)] - (dotimes [i size] - (let [v (nth c i)] - (when (pred v) - (chunk-append b v)))) - (chunk-cons (chunk b) (filter pred (chunk-rest s)))) - (let [f (first s) r (rest s)] - (if (pred f) - (cons f (filter pred r)) - (filter pred r)))))))) - -(defn flatten - "Takes any nested combination of sequential things (lists, vectors, - etc.) and returns their contents as a single, flat lazy sequence. - (flatten nil) returns an empty sequence." - [x] - (filter (complement sequential?) - (rest (tree-seq sequential? seq x)))) - -(defn remove - "Returns a lazy sequence of the items in coll for which - (pred item) returns logical false. pred must be free of side-effects. - Returns a transducer when no collection is provided." - ([pred] - (filter (complement pred))) - ([pred coll] - (filter (complement pred) coll))) - -(defn dedupe - "Returns a lazy sequence removing consecutive duplicates in coll. - Returns a transducer when no collection is provided." - ([] - (fn [rf] - (let [pv (volatile! ::none)] - (fn - ([] (rf)) - ([result] (rf result)) - ([result input] - (let [prior (deref pv)] - (vreset! pv input) - (if (= prior input) - result - (rf result input)))))))) - ([coll] - (let [step (fn step [prior xs] - (lazy-seq - (when-some [[x & more] (seq xs)] - (if (= x prior) - (step prior more) - (cons x (step x more))))))] - (step ::none coll)))) - -(defmacro condp - "Takes a binary predicate, an expression, and a set of clauses. - Each clause can take the form of either: - - test-expr result-expr - - test-expr :>> result-fn - - Note :>> is an ordinary keyword. - - For each clause, (pred test-expr expr) is evaluated. If it returns - logical true, the clause is a match. If a binary clause matches, the - result-expr is returned, if a ternary clause matches, its result-fn, - which must be a unary function, is called with the result of the - predicate as its argument, the result of that call being the return - value of condp. A single default expression can follow the clauses, - and its value will be returned if no clause matches. If no default - expression is provided and no clause matches, an - IllegalArgumentException is thrown." - [pred expr & clauses] - (let [gpred (gensym "pred__") - gexpr (gensym "expr__") - emit (fn emit [pred expr args] - (let [[[a b c :as clause] more] - (split-at (if (= :>> (second args)) 3 2) args) - n (count clause)] - (cond - (= 0 n) `(throw (str "No matching clause: " ~expr)) - (= 1 n) a - (= 2 n) `(if (~pred ~a ~expr) - ~b - ~(emit pred expr more)) - :else `(if-let [p# (~pred ~a ~expr)] - (~c p#) - ~(emit pred expr more)))))] - `(let [~gpred ~pred - ~gexpr ~expr] - ~(emit gpred gexpr clauses)))) - -(defmacro cond-> - "Takes an expression and a set of test/form pairs. Threads expr (via ->) - through each form for which the corresponding test - expression is true. Note that, unlike cond branching, cond-> threading does - not short circuit after the first true test expression." - [expr & clauses] - (assert (even? (count clauses))) - (let [g (gensym) - steps (map (fn [test+step] - (let [test (first test+step) - step (second test+step)] - `(if ~test - (-> ~g ~step) - ~g))) - (partition 2 clauses))] - `(let [~g ~expr - ~@(interleave (repeat g) (butlast steps))] - ~(if (empty? steps) - g - (last steps))))) - -(defmacro cond->> - "Takes an expression and a set of test/form pairs. Threads expr (via ->>) - through each form for which the corresponding test expression - is true. Note that, unlike cond branching, cond->> threading does not short circuit - after the first true test expression." - [expr & clauses] - (assert (even? (count clauses))) - (let [g (gensym) - steps (map (fn [[test step]] `(if ~test (->> ~g ~step) ~g)) - (partition 2 clauses))] - `(let [~g ~expr - ~@(interleave (repeat g) (butlast steps))] - ~(if (empty? steps) - g - (last steps))))) - -(defmacro as-> - "Binds name to expr, evaluates the first form in the lexical context - of that binding, then binds name to that result, repeating for each - successive form, returning the result of the last form." - [expr name & forms] - `(let [~name ~expr - ~@(interleave (repeat name) (butlast forms))] - ~(if (empty? forms) - name - (last forms)))) - -(defmacro some-> - "When expr is not nil, threads it into the first form (via ->), - and when that result is not nil, through the next etc" - [expr & forms] - (let [g (gensym) - steps (map (fn [step] `(if (nil? ~g) nil (-> ~g ~step))) - forms)] - `(let [~g ~expr - ~@(interleave (repeat g) (butlast steps))] - ~(if (empty? steps) - g - (last steps))))) - -(defmacro some->> - "When expr is not nil, threads it into the first form (via ->>), - and when that result is not nil, through the next etc" - [expr & forms] - (let [g (gensym) - steps (map (fn [step] `(if (nil? ~g) nil (->> ~g ~step))) - forms)] - `(let [~g ~expr - ~@(interleave (repeat g) (butlast steps))] - ~(if (empty? steps) - g - (last steps))))) - -;; Functions. -(defn ifn? - "Returns true if x implements IFn. Note that many data structures - (e.g. sets and maps) implement IFn" - [x] - (cpp/jank.runtime.is_callable x)) -(defn fn? - "Returns true if x implements Fn, i.e. is an object created via fn." - [x] - (cpp/clojure.core_native.is_fn x)) - -;; Multimethods. -(defn- check-valid-options - "Throws an exception if the given option map contains keys not listed - as valid, else returns nil." - [options & valid-keys] - (when (seq (apply disj (apply hash-set (keys options)) valid-keys)) - (throw (apply str "Only these options are valid: " - (first valid-keys) - (map #(str ", " %) (rest valid-keys)))))) - -(defn- multi-fn? - [x] - (cpp/clojure.core_native.is_multi_fn x)) - -(defn- multi-fn* - [name dispatch_fn default hierarchy] - (cpp/clojure.core_native.multi_fn name dispatch_fn default hierarchy)) - -(def global-hierarchy) - -(defmacro defmulti - "Creates a new multimethod with the associated dispatch function. - The docstring and attr-map are optional. - - Options are key-value pairs and may be one of: - - :default - - The default dispatch value, defaults to :default - - :hierarchy - - The value used for hierarchical dispatch (e.g. ::square is-a ::shape) - - Hierarchies are type-like relationships that do not depend upon type - inheritance. By default Clojure's multimethods dispatch off of a - global hierarchy map. However, a hierarchy relationship can be - created with the derive function used to augment the root ancestor - created with make-hierarchy. - - Multimethods expect the value of the hierarchy option to be supplied as - a reference type e.g. a var (i.e. via the Var-quote dispatch macro #' - or the var special form)." - [mm-name & options] - (let [docstring (if (string? (first options)) - (first options) - nil) - options (if (string? (first options)) - (next options) - options) - m (if (map? (first options)) - (first options) - {}) - options (if (map? (first options)) - (next options) - options) - dispatch-fn (first options) - options (next options) - m (if docstring - (assoc m :doc docstring) - m) - m (if (meta mm-name) - (conj (meta mm-name) m) - m) - mm-name (with-meta mm-name m)] - (let [options (apply hash-map options) - default (get options :default :default) - hierarchy (get options :hierarchy #'global-hierarchy)] - (check-valid-options options :default :hierarchy) - ; TODO: This returns nil, due to an issue with let*. Why? - `(let [v# (def ~mm-name)] - (when-not (multi-fn? (deref v#)) - (def ~mm-name (multi-fn* '~(symbol *ns* mm-name) ~dispatch-fn ~default ~hierarchy))))))) - -(defn- defmethod* - [multifn dispatch-val f] - (cpp/clojure.core_native.defmethod multifn dispatch-val f)) - -(defmacro defmethod - "Creates and installs a new method of multimethod associated with dispatch-value. " - [multifn dispatch-val & fn-tail] - `(defmethod* ~multifn ~dispatch-val (fn ~@fn-tail))) - -(defn remove-all-methods - "Removes all of the methods of multimethod." - [multifn] - (cpp/clojure.core_native.remove_all_methods multifn)) - -(defn remove-method - "Removes the method of multimethod associated with dispatch-value." - [multifn dispatch-val] - (cpp/clojure.core_native.remove_method multifn dispatch-val)) - -(defn prefer-method - "Causes the multimethod to prefer matches of dispatch-val-x over dispatch-val-y - when there is a conflict" - [multifn dispatch-val-x dispatch-val-y] - (cpp/clojure.core_native.prefer_method multifn dispatch-val-x dispatch-val-y)) - -(defn methods - "Given a multimethod, returns a map of dispatch values -> dispatch fns" - [multifn] - (cpp/clojure.core_native.methods multifn)) - -(defn get-method - "Given a multimethod and a dispatch value, returns the dispatch fn - that would apply to that value, or nil if none apply and no default" - [multifn dispatch-val] - (cpp/clojure.core_native.get_method multifn dispatch-val)) - -(defn prefers - "Given a multimethod, returns a map of preferred value -> set of other values" - [multifn] - (cpp/clojure.core_native.prefers multifn)) - -;; Hierarchies. -(defn make-hierarchy - "Creates a hierarchy object for use with derive, isa? etc." - [] - {:parents {} - :descendants {} - :ancestors {}}) - -(def ^:private global-hierarchy (make-hierarchy)) - -(defn isa? - "Returns true if (= child parent), or child is directly or indirectly derived from - parent, either via a Java type inheritance relationship or a - relationship established via derive. h must be a hierarchy obtained - from make-hierarchy, if not supplied defaults to the global - hierarchy" - ([child parent] - (isa? global-hierarchy child parent)) - ([h child parent] - (or (= child parent) - (contains? (get (:ancestors h) child) parent) - (and (vector? parent) (vector? child) - (= (count parent) (count child)) - (loop [ret true - i 0] - (if (or (not ret) (= i (count parent))) - ret - (recur (isa? h (get child i) (get parent i)) (inc i)))))))) - -(defn parents - "Returns the immediate parents of tag, either via a Java type - inheritance relationship or a relationship established via derive. h - must be a hierarchy obtained from make-hierarchy, if not supplied - defaults to the global hierarchy" - ([tag] - (parents global-hierarchy tag)) - ([h tag] - (not-empty (get (:parents h) tag)))) - -(defn ancestors - "Returns the immediate and indirect parents of tag, either via a Java type - inheritance relationship or a relationship established via derive. h - must be a hierarchy obtained from make-hierarchy, if not supplied - defaults to the global hierarchy" - ([tag] - (ancestors global-hierarchy tag)) - ([h tag] - (not-empty (get (:ancestors h) tag)))) - -(defn descendants - "Returns the immediate and indirect children of tag, through a - relationship established via derive. h must be a hierarchy obtained - from make-hierarchy, if not supplied defaults to the global - hierarchy. Note: does not work on Java type inheritance - relationships." - ([tag] - (descendants global-hierarchy tag)) - ([h tag] - (not-empty (get (:descendants h) tag)))) - -(defn derive - "Establishes a parent/child relationship between parent and - tag. Parent must be a namespace-qualified symbol or keyword and - child can be either a namespace-qualified symbol or keyword or a - class. h must be a hierarchy obtained from make-hierarchy, if not - supplied defaults to, and modifies, the global hierarchy." - ([tag parent] - (assert (namespace parent)) - (assert (and (named? tag) (namespace tag))) - (alter-var-root #'global-hierarchy derive tag parent) - nil) - ([h tag parent] - (assert (not= tag parent)) - (assert (named? tag)) - (assert (named? parent)) - (let [tp (:parents h) - td (:descendants h) - ta (:ancestors h) - tf (fn [m source sources target targets] - (reduce (fn [ret k] - (assoc ret - k - (reduce conj - (get targets k #{}) - (cons target (targets target))))) - m - (cons source (sources source))))] - (or - (when-not (contains? (tp tag) parent) - (when (contains? (ta tag) parent) - (throw (str tag " already has " parent " as ancestor"))) - (when (contains? (ta parent) tag) - (throw (str "Cyclic derivation: " parent " has " tag " as ancestor"))) - {:parents (assoc (:parents h) tag (conj (get tp tag #{}) parent)) - :ancestors (tf (:ancestors h) tag td parent ta) - :descendants (tf (:descendants h) parent ta tag td)}) - h)))) - -(defn underive - "Removes a parent/child relationship between parent and - tag. h must be a hierarchy obtained from make-hierarchy, if not - supplied defaults to, and modifies, the global hierarchy." - ([tag parent] - (alter-var-root #'global-hierarchy underive tag parent) nil) - ([h tag parent] - (let [parent-map (:parents h) - child-parents (if (parent-map tag) - (disj (parent-map tag) parent) - #{}) - new-parents (if (not-empty child-parents) - (assoc parent-map tag child-parents) - (dissoc parent-map tag)) - deriv-seq (flatten (map #(cons (key %) (interpose (key %) (val %))) - (seq new-parents)))] - (if (contains? (parent-map tag) parent) - (reduce #(apply derive %1 %2) - (make-hierarchy) - (partition 2 deriv-seq)) - h)))) - -(defmacro defonce - "defs name to have the root value of the expr iff the named var has no root value, - else expr is unevaluated" - [name expr] - `(let [v# (def ~name)] - (when-not (bound? v#) - (def ~name ~expr)))) - -;; Case. -(def ^:private max-mask-bits 13) -(def ^:private max-switch-table-size (bit-shift-left 1 max-mask-bits)) - -(defn- i64? [n] - (and (integer? n) - (>= n (cpp/value "std::numeric_limits::min()")) - (<= n (cpp/value "std::numeric_limits::max()")))) - -(defn- i32? [n] - (and (integer? n) - (>= n (cpp/value "std::numeric_limits::min()")) - (<= n (cpp/value "std::numeric_limits::max()")))) - -(defn- shift-mask [shift mask x] - (-> x (bit-shift-right shift) (bit-and mask))) - -(defn- case-hash - "Returns the input if it is within the range of a 32-bit signed integer, otherwise returns the hash of the - input. The native hash returns a int32 int so this is to make sure that (case-hash (case-hash x)) == (case-hash x). - A key may be hashed more than once and we need to make sure its value does not change in later hashing." - [input] - (if (i32? input) - input - (hash input))) - -(defn- maybe-min-hash - "Takes a collection of hashes and returns [shift mask] or nil if none found" - [hashes] - (first - (filter - (fn [[s m]] - (apply distinct? (map #(shift-mask s m %) hashes))) - (for [mask - (map #(dec (bit-shift-left 1 %)) (range 1 (inc max-mask-bits))) - shift - (range 0 31)] - [shift mask])))) - -(defn- case-map-with-check - "Transforms a sequence of test constants and their corresponding branch expressions - into a sorted map for consumption by `case*`. This version is used when no hash collisions - are detected (i.e. the skip-check set is empty). - - Returns a sorted map where each key is the transformed test constant and each value is a `condp` form - that checks the original expression against the test constant before selecting the branch." - [expr-sym default case-f test-f tests thens] - (into (sorted-map) - (zipmap (map case-f tests) - (map - (fn [key then] - (let [key - (if (symbol? key) - (list 'quote key) - key)] - `(condp = ~expr-sym ~key ~then - ~default))) - (map test-f tests) - thens)))) - -(defn- case-map-collison-merged - "Transforms a sequence of test constants and their corresponding branch expressions - into a sorted map for consumption by `case*`. - - This version is selected when hash collisions have been detected (i.e. the skip-check set is nonempty) - and resolved (typically via merging in `merge-hash-collisions`). In these cases, the branch expressions - have already been pre-wrapped in `condp` forms to handle multiple colliding constants. Therefore, no additional - wrapping is needed here-the transformed test constants are mapped directly to their corresponding branch expressions. - - Returns a sorted map mapping each transformed test constant directly to its branch expression." - [case-f test-f tests thens] - (into (sorted-map) - (zipmap (map case-f tests) thens))) - -(defn- case-map - [expr-sym default case-f test-f tests thens skip-check] - (if (empty? skip-check) - (case-map-with-check expr-sym default case-f test-f tests thens) - (case-map-collison-merged case-f test-f tests thens))) - -(defn- fits-table? - "Returns true if the collection of ints can fit within the - max-table-switch-size, false otherwise." - [ints] - (< (- (apply max (seq ints)) (apply min (seq ints))) max-switch-table-size)) - -(defn- prep-ints - "Takes a sequence of int-sized test constants and a corresponding sequence of - then expressions. Returns a tuple of [shift mask case-map] where - case-map is a map of int case values to [test then] tuples" - [expr-sym default tests thens] - (if (fits-table? tests) - ; compact case ints, no shift-mask - [0 0 (case-map expr-sym default int int tests thens #{})] - (let [[shift mask] (or (maybe-min-hash (map int tests)) [0 0])] - (if (zero? mask) - ; sparse case ints, no shift-mask - [0 0 (case-map expr-sym default int int tests thens #{})] - ; compact case ints, with shift-mask - [shift - mask - (case-map expr-sym default #(shift-mask shift mask (int %)) int tests thens #{})])))) - -(defn- merge-hash-collisions - "Takes a case expression, default expression, and a sequence of test constants - and a corresponding sequence of then expressions. Returns a tuple of - [tests thens skip-check-set] where no tests have the same hash. Each set of - input test constants with the same hash is replaced with a single test - constant (the case int), and their respective thens are combined into: - (condp = expr - test-1 then-1 - ... - test-n then-n - default). - The skip-check is a set of case ints for which post-switch equivalence - checking must not be done (the cases holding the above condp thens)." - [expr-sym default tests thens] - (let [buckets - (loop [m {} - ks tests - vs thens] - (if (and ks vs) - (recur - (update m (case-hash (first ks)) (fnil conj []) [(first ks) (first vs)]) - (next ks) (next vs)) - m)) - assoc-multi - (fn [m h bucket] - (let [testexprs - (mapcat (fn [kv] [(list 'quote (first kv)) (second kv)]) bucket) - expr - `(condp = ~expr-sym ~@testexprs ~default)] - (assoc m h expr))) - hmap - (reduce - (fn [m [h bucket]] - (if (== 1 (count bucket)) - (assoc m (ffirst bucket) (second (first bucket))) - (assoc-multi m h bucket))) - {} buckets) - skip-check - (->> buckets - (filter #(< 1 (count (second %)))) - (map first) - (into #{}))] - [(keys hmap) (vals hmap) skip-check])) - -(defn- prep-hashes - "Takes a sequence of test constants and a corresponding sequence of then - expressions. Returns a tuple of [shift mask case-map] - where case-map is a map of int case values to [test then] tuples." - [expr-sym default tests thens skip-check] - (let [hashes (into #{} (map case-hash tests))] - (if (== (count tests) (count hashes)) - (if (fits-table? hashes) - ; compact case ints, no shift-mask - [0 0 - (case-map expr-sym default case-hash identity tests thens skip-check)] - (let [[shift mask] (or (maybe-min-hash hashes) [0 0])] - (if (zero? mask) - ; sparse case ints, no shift-mask - [0 0 - (case-map expr-sym default case-hash identity tests thens skip-check)] - ; compact case ints, with shift-mask - [shift mask - (case-map expr-sym default #(shift-mask shift mask (case-hash %)) identity tests thens skip-check)]))) - ; resolve hash collisions and try again - (let [[tests thens skip-check] - (merge-hash-collisions expr-sym default tests thens) - [shift mask case-map] - (prep-hashes expr-sym default tests thens skip-check) - skip-check - (if (zero? mask) - skip-check - (into #{} (map #(shift-mask shift mask %) skip-check)))] - [shift mask case-map])))) - -(defmacro case - "Takes an expression, and a set of clauses. - - Each clause can take the form of either: - - test-constant result-expr - - (test-constant1 ... test-constantN) result-expr - - The test-constants are not evaluated. They must be compile-time - literals, and need not be quoted. If the expression is equal to a - test-constant, the corresponding result-expr is returned. A single - default expression can follow the clauses, and its value will be - returned if no clause matches. If no default expression is provided - and no clause matches, an IllegalArgumentException is thrown. - - Unlike cond and condp, case does a constant-time dispatch, the - clauses are not considered sequentially. All manner of constant - expressions are acceptable in case, including numbers, strings, - symbols, keywords, and (Clojure) composites thereof. Note that since - lists are used to group multiple constants that map to the same - expression, a vector can be used to match a list if needed. The - test-constants need not be all of the same type." - {:added "1.2"} - - [e & clauses] - (let [ge - (gensym) - default - (if (odd? (count clauses)) - (last clauses) - `(throw (str "No matching clause: " ~ge)))] - (if (> 2 (count clauses)) - `(let [~ge ~e] ~default) - (let [pairs - (partition 2 clauses) - assoc-test - (fn assoc-test [m test expr] - (if (contains? m test) - (throw (str "Duplicate case test constant: " test)) - (assoc m test expr))) - pairs - (reduce - (fn [m [test expr]] - (if (seq? test) - (reduce #(assoc-test %1 %2 expr) m test) - (assoc-test m test expr))) - {} pairs) - tests - (keys pairs) - thens - (vals pairs) - mode - (cond - (every? i64? tests) - :ints - - (every? keyword? tests) - :identity - - :else - :hashes)] - (condp = mode - :ints - (let [[shift mask imap] (prep-ints ge default tests thens)] - `(let [~ge ~e] (case* ~ge ~shift ~mask ~default ~imap))) - :hashes - (let [[shift mask imap] - (prep-hashes ge default tests thens #{})] - `(let [~ge ~e] - (case* ~ge ~shift ~mask ~default ~imap))) - :identity - (let [[shift mask imap] - (prep-hashes ge default tests thens #{})] - `(let [~ge ~e] - (case* ~ge ~shift ~mask ~default ~imap)))))))) - -;; Miscellaneous. -; TODO: jank.core -(defn- sleep [ms] - (cpp/clojure.core_native.sleep ms)) -(defn- current-time [] - (cpp/clojure.core_native.current_time)) - -(defmacro time - "Evaluates expr and prints the time it took. Returns the value of expr." - [expr] - `(let [start# (current-time) - ret# ~expr - end# (current-time)] - (println (str "Elapsed time: " (/ (- end# start#) 1000000.0) " ms")) - ret#)) - -(defn with-redefs-fn - "Temporarily redefines Vars during a call to func. Each val of - binding-map will replace the root value of its key which must be - a Var. After func is called with no args, the root values of all - the Vars will be set back to their old values. These temporary - changes will be visible in all threads. Useful for mocking out - functions during testing." - [binding-map fun] - (let [root-bind (fn root-bind [m] - (doseq [kv m] - (cpp/clojure.core_native.var_bind_root (first kv) (second kv)))) - old-vals (zipmap (keys binding-map) - (map #(cpp/clojure.core_native.var_get_root %) (keys binding-map)))] - (try - (root-bind binding-map) - (fun) - (finally - (root-bind old-vals))))) - -(defmacro with-redefs - "binding => var-symbol temp-value-expr - - Temporarily redefines Vars while executing the body. The - temp-value-exprs will be evaluated and each resulting value will - replace in parallel the root value of its Var. After the body is - executed, the root values of all the Vars will be set back to their - old values. These temporary changes will be visible in all threads. - Useful for mocking out functions during testing." - [bindings & body] - (list `with-redefs-fn - (zipmap (map (fn [v] - (list 'var v)) - (take-nth 2 bindings)) - (take-nth 2 (next bindings))) - (list* `fn [] - body))) - -;; Namespaces. -(defn in-ns - "Sets *ns* to the namespace named by the symbol, creating it if needed." - [name] - (cpp/clojure.core_native.in_ns name)) - -(defn create-ns - "Create a new namespace named by the symbol if one doesn't already - exist, returns it or the already-existing namespace of the same - name." - [sym] - (cpp/clojure.core_native.intern_ns sym)) - - -(defn find-ns - "Returns the namespace named by the symbol or nil if it doesn't exist." - [sym] - (cpp/clojure.core_native.find_ns sym)) - -(defn find-var - "Returns the global var named by the namespace-qualified symbol, or - nil if no var with that name." - [sym] - (cpp/clojure.core_native.find_var sym)) - -(defn remove-ns - "Removes the namespace named by the symbol. Use with caution. - Cannot be used to remove the clojure namespace." - [sym] - (cpp/clojure.core_native.remove_ns sym)) - -(defn the-ns - "If passed a namespace, returns it. Else, when passed a symbol, - returns the namespace named by it, throwing an exception if not - found." - [ns-or-sym] - (if (cpp/clojure.core_native.is_ns ns-or-sym) - ns-or-sym - (let [found (find-ns ns-or-sym)] - (if (nil? found) - (throw (ex-info :not-an-ns-or-sym {:value ns-or-sym})) - found)))) - -(defn ns-name - "Returns the name of the namespace, a symbol." - [ns-sym] - (let [ns (the-ns ns-sym)] - (cpp/clojure.core_native.ns_name ns))) - -(defn ns-map - "Returns a map of all the mappings for the namespace." - [ns-sym] - (let [ns (the-ns ns-sym)] - (cpp/clojure.core_native.ns_map ns))) - -(defn ns-publics - "Returns a map of the public intern mappings for the namespace." - [ns-sym] - (let [ns (the-ns ns-sym)] - ; TODO: It may be faster to start with the whole map and dissoc. - ; TODO: Good use case for transients. - (reduce (fn [acc kv] - (let [k (first kv) - v (second kv)] - ; TODO: Check for visibility. - (if (var? v) - (if (= ns (cpp/clojure.core_native.var_ns v)) - (assoc acc k v) - acc) - acc))) - {} - (ns-map ns)))) - -(defn ns-resolve - "Returns the var to which a symbol will be resolved in the - namespace (unless found in the environment), else nil. Note that - if the symbol is fully qualified, the var to which it resolves - need not be present in the namespace." - ([ns sym] - (ns-resolve ns nil sym)) - ([ns env sym] - (when-not (contains? env sym) - (cpp/clojure.core_native.ns_resolve (the-ns ns) sym)))) - -(defn resolve - "Same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)" - ([sym] - (ns-resolve *ns* sym)) - ([env sym] - (ns-resolve *ns* env sym))) - -(defn- libspec? [x] - (or (symbol? x) - (and (vector? x) - (or (nil? (second x)) - (keyword? (second x)))))) - -(defn- prependss [x coll] - (if (symbol? x) - (cons x coll) - (concat x coll))) - -(defn- root-resource [lib] - (str "/" (name lib))) - -(defn- throw-if [pred msg] - (when pred - (throw (ex-info :assertion-failure {:msg msg})))) - -(defn alias - "Add an alias in the current namespace to another - namespace. Arguments are two symbols: the alias to be used, and - the symbolic name of the target namespace. Use :as in the ns macro in preference - to calling this directly." - [alias ns-sym] - (let [ns-obj (the-ns ns-sym)] - (cpp/clojure.core_native.alias *ns* ns-obj alias))) - -(defn refer - "refers to all public vars of ns, subject to filters. - filters can include at most one each of: - - :exclude list-of-symbols - :only list-of-symbols - :rename map-of-fromsymbol-tosymbol - - For each public interned var in the namespace named by the symbol, - adds a mapping from the name of the var to the var to the current - namespace. Throws an exception if name is already mapped to - something else in the current namespace. Filters can be used to - select a subset, via inclusion or exclusion, or to provide a mapping - to a symbol different from the var's name, in order to prevent - clashes. Use :use in the ns macro in preference to calling this directly." - [ns-sym & filters] - (let [ns (find-ns ns-sym) - _ (when (nil? ns) - (throw (ex-info :unknown-namespace {:value ns-sym}))) - filters (apply hash-map filters) - rename (or (:rename filters) {}) - exclude? (set (:exclude filters)) - sym->var (ns-publics ns) - to-refer (if (= :all (get filters :refer)) - (keys sym->var) - (or (get filters :refer) (get filters :only) (keys sym->var)))] - ; TODO: Loop - (reduce (fn [acc sym] - (when (not (exclude? sym)) - (let [v (get sym->var sym) - sym (rename sym sym)] - (when (nil? v) - (throw (ex-info :var-does-not-exist {:value sym}))) - (cpp/clojure.core_native.refer *ns* sym v)))) - nil - to-refer))) - -;; TODO: Should be a ref instead of atom -(defonce - ^{:private true - :dynamic true - :doc "An atom holding a sorted set of symbols representing loaded libs"} - *loaded-libs* (atom (sorted-set))) - -(defonce - ^{:private true - :dynamic true - :doc "A stack of paths currently being loaded by this thread"} - *pending-paths* ()) - -(defn- check-cyclic-dependency - "Detects and rejects non-trivial cyclic load dependencies. The - exception message shows the dependency chain with the cycle - highlighted. Ignores the trivial case of a file attempting to load - itself because that can occur when a gen-class'd class loads its - implementation." - [path] - (when (some #{path} (rest *pending-paths*)) - (let [pending (map #(if (= % path) (str "[ " % " ]") %) - (cons path *pending-paths*)) - chain (apply str (interpose "->" pending))] - (throw-if true (str "Cyclic load dependency: " chain))))) - -(defn load - "Loads Clojure code from resources in the module path. A path is interpreted as - module-path-relative if it begins with a slash or relative to the root - directory for the current namespace otherwise." - [& paths] - (doseq [path paths] - (check-cyclic-dependency path) - (when-not (= path (first *pending-paths*)) - (binding [*pending-paths* (conj *pending-paths* path)] - (clojure.core-native/load-module path))))) - -(defn- load-one - "Loads a lib given its name. If `need-ns?`, ensures that the associated - namespace exists after loading. If `require?`, records the load so any - duplicate loads can be skipped." - [lib need-ns? require?] - (load (root-resource lib)) - (throw-if (and need-ns? (not (find-ns lib))) - (str "namespace " lib " not found after loading " (root-resource lib))) - (when require? - (swap! *loaded-libs* conj lib))) - -(defn- load-all - "Loads a lib given its name and forces a load of any libs it directly or - indirectly loads. If need-ns?, ensures that the associated namespace - exists after loading. If require?, records the load so any duplicate loads - can be skipped." - [lib need-ns? require?] - (swap! *loaded-libs* #(reduce conj %1 %2) - (binding [*loaded-libs* (atom (sorted-set))] - (load-one lib need-ns? require?) - @*loaded-libs*))) - -(defn- load-lib - "Loads a lib with options" - [lib & options] - (let [opts (apply hash-map options) - ; TODO: Map destructuring. - as (:as opts) - reload (:reload opts) - reload-all (:reload-all opts) - require (:require opts) - use (:use opts) - verbose (:verbose opts) - as-alias (:as-alias opts) - loaded? (contains? @*loaded-libs* lib) - need-ns? (or as use) - load (cond reload-all load-all - reload load-one - (not loaded?) (cond need-ns? load-one - as-alias (fn [lib _need _require] - (create-ns lib)) - :else load-one)) - - filter-opts (select-keys opts [:exclude :only :rename :refer]) - undefined-on-entry? (not (find-ns lib))] - (if load - (try - (load lib need-ns? require) - (catch e - (when undefined-on-entry? - (remove-ns lib)) - (throw e))) - (throw-if (and need-ns? (not (find-ns lib))) - (str "namespace " lib " not found"))) - (when as - (alias as lib)) - (when as-alias - (alias as-alias lib)) - (when (or use (:refer filter-opts)) - (apply refer lib (mapcat seq filter-opts))))) - -(defn- load-libs - "Loads libs, interpreting libspecs, prefix lists, and flags for - forwarding to load-lib" - [& args] - (let [flags (filter keyword? args) - opts (interleave flags (repeat true)) - args (remove keyword? args)] - (let [supported #{:as :reload :reload-all :require :use :verbose :refer :as-alias} - unsupported (seq (remove supported flags))] - (throw-if unsupported - (str "Unsupported option(s) supplied: " unsupported))) - (throw-if (not (seq args)) "Nothing specified to load") - (doseq [arg args] - (throw-if (not (libspec? arg)) (str "not a libspec: " arg)) - (apply load-lib (prependss arg opts))))) - -(defn compile - "Compiles the namespace named by the symbol lib into a set of - classfiles. The source for the lib must be in a proper - module-path-relative directory. The output files will go into the - directory specified by *compile-path*, and that directory too must - be in the module path." - [path] - (cpp/clojure.core_native.compile path)) - -(defn require - "Loads libs, skipping any that are already loaded. Each argument is - either a libspec that identifies a lib, a prefix list that identifies - multiple libs whose names share a common prefix, or a flag that modifies - how all the identified libs are loaded. Use :require in the ns macro - in preference to calling this directly. - - Libs - - A 'lib' is a named set of resources in module path whose contents define a - library of Clojure code. Lib names are symbols and each lib is associated - with a Clojure namespace and a Java package that share its name. A lib's - name also locates its root directory within module path using Java's - package name to module path-relative path mapping. All resources in a lib - should be contained in the directory structure under its root directory. - All definitions a lib makes should be in its associated namespace. - - 'require loads a lib by loading its root resource. The root resource path - is derived from the lib name in the following manner: - Consider a lib named by the symbol 'x.y.z; it has the root directory - /x/y/, and its root resource is /x/y/z.clj, or - /x/y/z.cljc if /x/y/z.clj does not exist. The - root resource should contain code to create the lib's - namespace (usually by using the ns macro) and load any additional - lib resources. - - Libspecs - - A libspec is a lib name or a vector containing a lib name followed by - options expressed as sequential keywords and arguments. - - Recognized options: - :as takes a symbol as its argument and makes that symbol an alias to the - lib's namespace in the current namespace. - :as-alias takes a symbol as its argument and aliases like :as, however - the lib will not be loaded. If the lib has not been loaded, a new - empty namespace will be created (as with create-ns). - :refer takes a list of symbols to refer from the namespace or the :all - keyword to bring in all public vars. - - Prefix Lists - - It's common for Clojure code to depend on several libs whose names have - the same prefix. When specifying libs, prefix lists can be used to reduce - repetition. A prefix list contains the shared prefix followed by libspecs - with the shared prefix removed from the lib names. After removing the - prefix, the names that remain must not contain any periods. - - Flags - - A flag is a keyword. - Recognized flags: :reload, :reload-all, :verbose - :reload forces loading of all the identified libs even if they are - already loaded (has no effect on libspecs using :as-alias) - :reload-all implies :reload and also forces loading of all libs that the - identified libs directly or indirectly load via require or use - (has no effect on libspecs using :as-alias) - :verbose triggers printing information about each load, alias, and refer - - Example: - - The following would load the libraries clojure.zip and clojure.set - abbreviated as 's'. - - (require '(clojure zip [set :as s]))" - [& args] - (apply load-libs :require args)) - -(defn use - "Like 'require, but also refers to each lib's namespace using - clojure.core/refer. Use :use in the ns macro in preference to calling - this directly. - - 'use accepts additional options in libspecs: :exclude, :only, :rename. - The arguments and semantics for :exclude, :only, and :rename are the same - as those documented for clojure.core/refer." - [& args] - (apply load-libs :require :use args)) - -(defmacro ns - "Sets *ns* to the namespace named by name (unevaluated), creating it - if needed. References can be zero or more of: (:refer-clojure ...) - (:require ...) (:use ...) (:load ...) - with the syntax of refer-clojure/require/use/load respectively." - [name & references] - (let [process-reference (fn [reference] - (let [kname (first reference) - args (rest reference)] - (cons (symbol "clojure.core" (clojure.core/name kname)) - (map (fn [a] - (list 'quote a)) - args)))) - refer-full-clojure? (not-any? (fn [ref] - (= :refer-clojure (first ref))) - references)] - `(do - (clojure.core/in-ns '~name) - ; TODO: with-loading-context - (do ; with-loading-context - ~@(when (and (not= name 'clojure.core) refer-full-clojure?) - `((clojure.core/refer '~'clojure.core))) - ~@(map process-reference references)) - (if (= '~name '~'clojure.core) - nil - (do (swap! @#'*loaded-libs* conj '~name) nil))))) - -(defmacro refer-clojure - "Same as (refer 'clojure.core )" - [& filters] - `(clojure.core/refer '~'clojure.core ~@filters)) - -(defn intern - "Finds or creates a var named by the symbol name in the namespace - ns (which can be a symbol or a namespace), setting its root binding - to val if supplied. The namespace must exist. The var will adopt any - metadata from the name symbol. Returns the var." - ([ns name] - (let [v (cpp/clojure.core_native.intern_var - (cpp/jank.runtime.to_qualified_symbol - (the-ns ns) name))] - (when (meta name) (cpp/jank.runtime.reset_meta v (meta name))) - v)) - ([ns name val] - (let [v (cpp/clojure.core_native.intern_var - (cpp/jank.runtime.to_qualified_symbol - (the-ns ns) name))] - (cpp/clojure.core_native.var_bind_root v val) - (when (meta name) (cpp/jank.runtime.reset_meta v (meta name))) - v))) - -(defn nfirst - "Same as (next (first x))" - [x] - (next (first x))) - -(defn fnext - "Same as (first (next x))" - [x] - (first (next x))) - -(defn instance? - "Evaluates x and tests if it is an instance of the class - c. Returns true or false" - [c x] - ;; (. c (isInstance x)) - (throw "TODO: port instance?")) - -(def ^{:private true :dynamic true} - assert-valid-fdecl (fn [fdecl])) - -(defn to-array - "Returns an array of Objects containing the contents of coll, which - can be any Collection. Maps to java.util.Collection.toArray()." - [coll] - ;; (. clojure.lang.RT (toArray coll)) - (throw "TODO: port to-array")) - -(defn cast - "Throws a ClassCastException if x is not a c, else returns x." - [c x] - ;; (. c (cast x)) - (throw "TODO: port cast")) - -(defn sorted-map-by - "keyval => key val - Returns a new sorted map with supplied mappings, using the supplied - comparator. If any keys are equal, they are handled as if by - repeated uses of assoc." - ([comparator & keyvals] - ;; (clojure.lang.PersistentTreeMap/create comparator keyvals) - (throw "TODO: port sorted-map-by"))) - -(defn any? - "Returns true given any argument." - [x] true) - -(defn find-keyword - "Returns a Keyword with the given namespace and name if one already - exists. This function will not intern a new keyword. If the keyword - has not already been interned, it will return nil. Do not use : - in the keyword strings, it will be added automatically." - ([name] - ;; (cond (keyword? name) name - ;; (symbol? name) (clojure.lang.Keyword/find ^clojure.lang.Symbol name) - ;; (string? name) (clojure.lang.Keyword/find ^String name)) - (throw "TODO: port find-keyword")) - ([ns name] - ;; (clojure.lang.Keyword/find ns name) - (throw "TODO: port find-keyword"))) - -(defn delay? - "returns true if x is a Delay created with delay" - [x] - ;; (instance? clojure.lang.Delay x) - (throw "TODO: port delay?")) - -(defmacro if-not - "Evaluates test. If logical false, evaluates and returns then expr, - otherwise else expr, if supplied, else nil." - ([test then] `(if-not ~test ~then nil)) - ([test then else] - `(if (not ~test) ~then ~else))) - -(defn compare - "Comparator. Returns a negative number, zero, or a positive number - when x is logically 'less than', 'equal to', or 'greater than' - y. Same as Java x.compareTo(y) except it also works for nil, and - compares numbers and collections in a type-independent manner. x - must implement Comparable" - [x y] - (cpp/jank.runtime.compare x y)) - -(defn inc' - "Returns a number one greater than num. Supports arbitrary precision. - See also: inc" - [x] - ;; (. clojure.lang.Numbers (incP x)) - (throw "TODO: port inc'")) - -;; ;;math stuff -;; (defn ^:private nary-inline -;; ([op] (nary-inline op op)) -;; ([op unchecked-op] -;; (fn -;; ([x] (let [op (if *unchecked-math* unchecked-op op)] -;; `(. clojure.lang.Numbers (~op ~x)))) -;; ([x y] (let [op (if *unchecked-math* unchecked-op op)] -;; `(. clojure.lang.Numbers (~op ~x ~y)))) -;; ([x y & more] -;; (let [op (if *unchecked-math* unchecked-op op)] -;; (reduce1 -;; (fn [a b] `(. clojure.lang.Numbers (~op ~a ~b))) -;; `(. clojure.lang.Numbers (~op ~x ~y)) more)))))) - -;; (defn ^:private >1? [n] (clojure.lang.Numbers/gt n 1)) - -;; (defn ^:private >0? [n] (clojure.lang.Numbers/gt n 0)) - -(defn +' - "Returns the sum of nums. (+') returns 0. Supports arbitrary precision. - See also: +" - ([] 0) - ([x] - ;; (cast Number x) - (throw "TODO: port +'")) - ([x y] - ;; (. clojure.lang.Numbers (addP x y)) - (throw "TODO: port +'")) - ([x y & more] - (reduce +' (+' x y) more))) - -(defn *' - "Returns the product of nums. (*') returns 1. Supports arbitrary precision. - See also: *" - ([] 1) - ([x] - ;; (cast Number x) - (throw "TODO: port *'")) - ([x y] - ;; (. clojure.lang.Numbers (multiplyP x y)) - (throw "TODO: port *'")) - ([x y & more] - (reduce *' (*' x y) more))) - -(defn -' - "If no ys are supplied, returns the negation of x, else subtracts - the ys from x and returns the result. Supports arbitrary precision. - See also: -" - ([x] - ;; (. clojure.lang.Numbers (minusP x)) - (throw "TODO: port -'")) - ([x y] - ;; (. clojure.lang.Numbers (minusP x y)) - (throw "TODO: port -'")) - ([x y & more] - (reduce -' (-' x y) more))) - -(defn abs - "Returns the absolute value of a. - If a is Long/MIN_VALUE => Long/MIN_VALUE - If a is a double and zero => +0.0 - If a is a double and ##Inf or ##-Inf => ##Inf - If a is a double and ##NaN => ##NaN" - [a] - (cpp/jank.runtime.abs a)) - -(defn dec' - "Returns a number one less than num. Supports arbitrary precision. - See also: dec" - [x] - ;; (. clojure.lang.Numbers (decP x)) - (throw "TODO: port dec'")) - -(defn unchecked-inc-int - "Returns a number one greater than x, an int. - Note - uses a primitive operator subject to overflow." - [x] - ;; (. clojure.lang.Numbers (unchecked_int_inc x)) - (throw "TODO: port unchecked-inc-int")) - -(defn unchecked-inc - "Returns a number one greater than x, a long. - Note - uses a primitive operator subject to overflow." - [x] - ;; (. clojure.lang.Numbers (unchecked_inc x)) - (throw "TODO: port unchecked-inc")) - -(defn unchecked-dec-int - "Returns a number one less than x, an int. - Note - uses a primitive operator subject to overflow." - [x] - ;; (. clojure.lang.Numbers (unchecked_int_dec x)) - (throw "TODO: port unchecked-dec-int")) - -(defn unchecked-dec - "Returns a number one less than x, a long. - Note - uses a primitive operator subject to overflow." - [x] - ;; (. clojure.lang.Numbers (unchecked_dec x)) - (throw "TODO: port unchecked-dec")) - -(defn unchecked-negate-int - "Returns the negation of x, an int. - Note - uses a primitive operator subject to overflow." - [x] - ;; (. clojure.lang.Numbers (unchecked_int_negate x)) - (throw "TODO: port unchecked-negate-int")) - -(defn unchecked-negate - "Returns the negation of x, a long. - Note - uses a primitive operator subject to overflow." - [x] - ;; (. clojure.lang.Numbers (unchecked_minus x)) - (throw "TODO: port unchecked-negate")) - -(defn unchecked-add-int - "Returns the sum of x and y, both int. - Note - uses a primitive operator subject to overflow." - [x y] - ;; (. clojure.lang.Numbers (unchecked_int_add x y)) - (throw "TODO: port unchecked-add-int")) - -(defn unchecked-add - "Returns the sum of x and y, both long. - Note - uses a primitive operator subject to overflow." - [x y] - ;; (. clojure.lang.Numbers (unchecked_add x y)) - (throw "TODO: port unchecked-add")) - -(defn unchecked-subtract-int - "Returns the difference of x and y, both int. - Note - uses a primitive operator subject to overflow." - [x y] - ;; (. clojure.lang.Numbers (unchecked_int_subtract x y)) - (throw "TODO: port unchecked-subtract-int")) - -(defn unchecked-subtract - "Returns the difference of x and y, both long. - Note - uses a primitive operator subject to overflow." - [x y] - ;; (. clojure.lang.Numbers (unchecked_minus x y)) - (throw "TODO: port unchecked-subtract")) - -(defn unchecked-multiply-int - "Returns the product of x and y, both int. - Note - uses a primitive operator subject to overflow." - [x y] - ;; (. clojure.lang.Numbers (unchecked_int_multiply x y)) - (throw "TODO: port unchecked-multiply-int")) - -(defn unchecked-multiply - "Returns the product of x and y, both long. - Note - uses a primitive operator subject to overflow." - [x y] - ;; (. clojure.lang.Numbers (unchecked_multiply x y)) - (throw "TODO: port unchecked-multiply")) - -(defn unchecked-divide-int - "Returns the division of x by y, both int. - Note - uses a primitive operator subject to truncation." - [x y] - ;; (. clojure.lang.Numbers (unchecked_int_divide x y)) - (throw "TODO: port unchecked-divide-int")) - -(defn unchecked-remainder-int - "Returns the remainder of division of x by y, both int. - Note - uses a primitive operator subject to truncation." - [x y] - ;; (. clojure.lang.Numbers (unchecked_int_remainder x y)) - (throw "TODO: port unchecked-remainder-int")) - -(defn rationalize - "returns the rational value of num" - [num] - ;; (. clojure.lang.Numbers (rationalize num)) - (throw "TODO: port rationalize")) - -(defn int? - "Return true if x is a fixed precision integer" - [x] - (integer? x)) - -(defn pos-int? - "Return true if x is a positive fixed precision integer" - [x] (and (int? x) - (pos? x))) - -(defn neg-int? - "Return true if x is a negative fixed precision integer" - [x] (and (int? x) - (neg? x))) - -(defn nat-int? - "Return true if x is a non-negative fixed precision integer" - [x] (and (int? x) - (not (neg? x)))) - -(defn double? - "Return true if x is a Double" - [x] - (float? x)) - -;;map stuff - -(defn map-entry? - "Return true if x is a map entry" - [x] - (and (vector? x) - (== 2 (count x)))) - -(defn rseq - "Returns, in constant time, a seq of the items in rev (which - can be a vector or sorted-map), in reverse order. If rev is empty returns nil" - [#_clojure.lang.Reversible rev] - ;; (. rev (rseq)) - (throw "TODO: port rseq")) - -(defmacro locking - "Executes exprs in an implicit do, while holding the monitor of x. - Will release the monitor of x in all circumstances." - [x & body] - `(let [lockee# ~x] - (try - (let [locklocal# lockee#] - (monitor-enter locklocal#) - (try - (do ~@body) - (finally - (monitor-exit locklocal#))))))) - -;; (defmacro .. -;; "form => fieldName-symbol or (instanceMethodName-symbol args*) - -;; Expands into a member access (.) of the first member on the first -;; argument, followed by the next member on the result, etc. For -;; instance: - -;; (.. System (getProperties) (get \"os.name\")) - -;; expands to: - -;; (. (. System (getProperties)) (get \"os.name\")) - -;; but is easier to write, read, and understand." -;; ([x form] -;; ;; `(. ~x ~form) -;; (throw "TODO: port")) -;; ([x form & more] -;; ;; `(.. (. ~x ~form) ~@more)) -;; (throw "TODO: port")) - - -;;;;;;;;; var stuff - -(defn with-bindings* - "Takes a map of Var/value pairs. Installs for the given Vars the associated - values as thread-local bindings. Then calls f with the supplied arguments. - Pops the installed bindings after f returned. Returns whatever f returns." - [binding-map f & args] - (push-thread-bindings (if (= "persistent_array_map" (type binding-map)) - (into (hash-map) binding-map) - binding-map)) - (try - (apply f args) - (finally - (pop-thread-bindings)))) - -(defmacro with-bindings - "Takes a map of Var/value pairs. Installs for the given Vars the associated - values as thread-local bindings. Then executes body. Pops the installed - bindings after body was evaluated. Returns the value of body." - [binding-map & body] - `(with-bindings* ~binding-map (fn [] ~@body))) - -(defn bound-fn* - "Returns a function, which will install the same bindings in effect as in - the thread at the time bound-fn* was called and then call f with any given - arguments. This may be used to define a helper function which runs on a - different thread, but needs the same bindings in place." - [f] - (let [bindings (get-thread-bindings)] - (fn [& args] - (apply with-bindings* bindings f args)))) - -(defmacro bound-fn - "Returns a function defined by the given fntail, which will install the - same bindings in effect as in the thread at the time bound-fn was called. - This may be used to define a helper function which runs on a different - thread, but needs the same bindings in place." - [& fntail] - `(bound-fn* (fn ~@fntail))) - -(defn- binding-conveyor-fn - [f] - ;; (let [frame (clojure.lang.Var/cloneThreadBindingFrame)] - ;; (fn - ;; ([] - ;; (clojure.lang.Var/resetThreadBindingFrame frame) - ;; (f)) - ;; ([x] - ;; (clojure.lang.Var/resetThreadBindingFrame frame) - ;; (f x)) - ;; ([x y] - ;; (clojure.lang.Var/resetThreadBindingFrame frame) - ;; (f x y)) - ;; ([x y z] - ;; (clojure.lang.Var/resetThreadBindingFrame frame) - ;; (f x y z)) - ;; ([x y z & args] - ;; (clojure.lang.Var/resetThreadBindingFrame frame) - ;; (apply f x y z args)))) - (throw "TODO: port binding-conveyor-fn")) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Refs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defn- - setup-reference [#_clojure.lang.ARef r options] - ;; (let [opts (apply hash-map options)] - ;; (when (:meta opts) - ;; (.resetMeta r (:meta opts))) - ;; (when (:validator opts) - ;; (.setValidator r (:validator opts))) - ;; r) - (throw "TODO: port setup-reference")) - -(defn agent - "Creates and returns an agent with an initial value of state and - zero or more options (in any order): - - :meta metadata-map - - :validator validate-fn - - :error-handler handler-fn - - :error-mode mode-keyword - - If metadata-map is supplied, it will become the metadata on the - agent. validate-fn must be nil or a side-effect-free fn of one - argument, which will be passed the intended new state on any state - change. If the new state is unacceptable, the validate-fn should - return false or throw an exception. handler-fn is called if an - action throws an exception or if validate-fn rejects a new state -- - see set-error-handler! for details. The mode-keyword may be either - :continue (the default if an error-handler is given) or :fail (the - default if no error-handler is given) -- see set-error-mode! for - details." - ([state & options] - ;; (let [a (new clojure.lang.Agent state) - ;; opts (apply hash-map options)] - ;; (setup-reference a options) - ;; (when (:error-handler opts) - ;; (.setErrorHandler a (:error-handler opts))) - ;; (.setErrorMode a (or (:error-mode opts) - ;; (if (:error-handler opts) :continue :fail))) - ;; a) - (throw "TODO: port agent"))) - -(defn set-agent-send-executor! - "Sets the ExecutorService to be used by send" - [executor] - ;; (set! clojure.lang.Agent/pooledExecutor executor) - (throw "TODO: port set-agent-send-executor!")) - -(defn set-agent-send-off-executor! - "Sets the ExecutorService to be used by send-off" - [executor] - ;; (set! clojure.lang.Agent/soloExecutor executor) - (throw "TODO: port set-agent-send-off-executor!")) - -(defn send-via - "Dispatch an action to an agent. Returns the agent immediately. - Subsequently, in a thread supplied by executor, the state of the agent - will be set to the value of: - - (apply action-fn state-of-agent args)" - [executor #_clojure.lang.Agent a f & args] - ;; (.dispatch a (binding [*agent* a] (binding-conveyor-fn f)) args executor) - (throw "TODO: port send-via")) - -(defn send - "Dispatch an action to an agent. Returns the agent immediately. - Subsequently, in a thread from a thread pool, the state of the agent - will be set to the value of: - - (apply action-fn state-of-agent args)" - [#_clojure.lang.Agent a f & args] - ;; (apply send-via clojure.lang.Agent/pooledExecutor a f args) - (throw "TODO: port send")) - -(defn send-off - "Dispatch a potentially blocking action to an agent. Returns the - agent immediately. Subsequently, in a separate thread, the state of - the agent will be set to the value of: - - (apply action-fn state-of-agent args)" - [#_clojure.lang.Agent a f & args] - ;; (apply send-via clojure.lang.Agent/soloExecutor a f args) - (throw "TODO: port send-off")) - -(defn release-pending-sends - "Normally, actions sent directly or indirectly during another action - are held until the action completes (changes the agent's - state). This function can be used to dispatch any pending sent - actions immediately. This has no impact on actions sent during a - transaction, which are still held until commit. If no action is - occurring, does nothing. Returns the number of actions dispatched." - [] - ;; (clojure.lang.Agent/releasePendingSends) - (throw "TODO: port release-pending-sends")) - -(defn add-watch - "Adds a watch function to an agent/atom/var/ref reference. The watch - fn must be a fn of 4 args: a key, the reference, its old-state, its - new-state. Whenever the reference's state might have been changed, - any registered watches will have their functions called. The watch fn - will be called synchronously, on the agent's thread if an agent, - before any pending sends if agent or ref. Note that an atom's or - ref's state may have changed again prior to the fn call, so use - old/new-state rather than derefing the reference. Note also that watch - fns may be called from multiple threads simultaneously. Var watchers - are triggered only by root binding changes, not thread-local - set!s. Keys must be unique per reference, and can be used to remove - the watch with remove-watch, but are otherwise considered opaque by - the watch mechanism." - [reference key f] - (cpp/jank.runtime.add_watch reference key f)) - -(defn remove-watch - "Removes a watch (set by add-watch) from a reference" - [reference key] - (cpp/jank.runtime.remove_watch reference key)) - -(defn agent-error - "Returns the exception thrown during an asynchronous action of the - agent if the agent is failed. Returns nil if the agent is not - failed." - [#_clojure.lang.Agent a] - ;; (.getError a) - (throw "TODO: port agent-error")) - -(defn restart-agent - "When an agent is failed, changes the agent state to new-state and - then un-fails the agent so that sends are allowed again. If - a :clear-actions true option is given, any actions queued on the - agent that were being held while it was failed will be discarded, - otherwise those held actions will proceed. The new-state must pass - the validator if any, or restart will throw an exception and the - agent will remain failed with its old state and error. Watchers, if - any, will NOT be notified of the new state. Throws an exception if - the agent is not failed." - [#_clojure.lang.Agent a, new-state & options] - ;; (let [opts (apply hash-map options)] - ;; (.restart a new-state (if (:clear-actions opts) true false))) - (throw "TODO: port restart-agent")) - -(defn set-error-handler! - "Sets the error-handler of agent a to handler-fn. If an action - being run by the agent throws an exception or doesn't pass the - validator fn, handler-fn will be called with two arguments: the - agent and the exception." - [#_clojure.lang.Agent a, handler-fn] - ;; (.setErrorHandler a handler-fn) - (throw "TODO: port set-error-handler!")) - -(defn error-handler - "Returns the error-handler of agent a, or nil if there is none. - See set-error-handler!" - [#_clojure.lang.Agent a] - ;; (.getErrorHandler a) - (throw "TODO: port error-handler")) - -(defn set-error-mode! - "Sets the error-mode of agent a to mode-keyword, which must be - either :fail or :continue. If an action being run by the agent - throws an exception or doesn't pass the validator fn, an - error-handler may be called (see set-error-handler!), after which, - if the mode is :continue, the agent will continue as if neither the - action that caused the error nor the error itself ever happened. - - If the mode is :fail, the agent will become failed and will stop - accepting new 'send' and 'send-off' actions, and any previously - queued actions will be held until a 'restart-agent'. Deref will - still work, returning the state of the agent before the error." - [#_clojure.lang.Agent a, mode-keyword] - ;; (.setErrorMode a mode-keyword) - (throw "TODO: port set-error-mode!")) - -(defn error-mode - "Returns the error-mode of agent a. See set-error-mode!" - [#_clojure.lang.Agent a] - ;; (.getErrorMode a) - (throw "TODO: port error-mode")) - -(defn agent-errors - "DEPRECATED: Use 'agent-error' instead. - Returns a sequence of the exceptions thrown during asynchronous - actions of the agent." - [a] - (when-let [e (agent-error a)] - (list e))) - -(defn clear-agent-errors - "DEPRECATED: Use 'restart-agent' instead. - Clears any exceptions thrown during asynchronous actions of the - agent, allowing subsequent actions to occur." - [#_clojure.lang.Agent a] - ;; (restart-agent a (.deref a)) - (throw "TODO: port clear-agent-errors")) - -(defn shutdown-agents - "Initiates a shutdown of the thread pools that back the agent - system. Running actions will complete, but no new actions will be - accepted" - [] - ;; (. clojure.lang.Agent shutdown) - (throw "TODO: port shutdown-agents")) - -(defn ref - "Creates and returns a Ref with an initial value of x and zero or - more options (in any order): - - :meta metadata-map - - :validator validate-fn - - :min-history (default 0) - :max-history (default 10) - - If metadata-map is supplied, it will become the metadata on the - ref. validate-fn must be nil or a side-effect-free fn of one - argument, which will be passed the intended new state on any state - change. If the new state is unacceptable, the validate-fn should - return false or throw an exception. validate-fn will be called on - transaction commit, when all refs have their final values. - - Normally refs accumulate history dynamically as needed to deal with - read demands. If you know in advance you will need history you can - set :min-history to ensure it will be available when first needed (instead - of after a read fault). History is limited, and the limit can be set - with :max-history." - ([x] - ;; (new clojure.lang.Ref x) - (throw "TODO: port ref")) - ([x & options] - ;; (let [r ^clojure.lang.Ref (setup-reference (ref x) options) - ;; opts (apply hash-map options)] - ;; (when (:max-history opts) - ;; (.setMaxHistory r (:max-history opts))) - ;; (when (:min-history opts) - ;; (.setMinHistory r (:min-history opts))) - ;; r) - (throw "TODO: port ref"))) - -(defn- deref-future - ([#_java.util.concurrent.Future fut] - ;; (.get fut) - (throw "TODO: port deref-future")) - ([#_java.util.concurrent.Future fut timeout-ms timeout-val] - ;; (try (.get fut timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS) - ;; (catch java.util.concurrent.TimeoutException e - ;; timeout-val)) - (throw "TODO: port deref-future"))) - -(defn set-validator! - "Sets the validator-fn for a var/ref/agent/atom. validator-fn must be nil or a - side-effect-free fn of one argument, which will be passed the intended - new state on any state change. If the new state is unacceptable, the - validator-fn should return false or throw an exception. If the current state (root - value if var) is not acceptable to the new validator, an exception - will be thrown and the validator will not be changed." - [#_clojure.lang.IRef iref validator-fn] - ;; (. iref (setValidator validator-fn)) - (throw "TODO: port set-validator!")) - -(defn get-validator - "Gets the validator-fn for a var/ref/agent/atom." - [#_clojure.lang.IRef iref] - ;; (. iref (getValidator)) - (throw "TODO: port get-validator")) - -(defn commute - "Must be called in a transaction. Sets the in-transaction-value of - ref to: - - (apply fun in-transaction-value-of-ref args) - - and returns the in-transaction-value of ref. - - At the commit point of the transaction, sets the value of ref to be: - - (apply fun most-recently-committed-value-of-ref args) - - Thus fun should be commutative, or, failing that, you must accept - last-one-in-wins behavior. commute allows for more concurrency than - ref-set." - [#_clojure.lang.Ref ref fun & args] - ;; (. ref (commute fun args)) - (throw "TODO: port commute")) - -(defn alter - "Must be called in a transaction. Sets the in-transaction-value of - ref to: - - (apply fun in-transaction-value-of-ref args) - - and returns the in-transaction-value of ref." - [#_clojure.lang.Ref ref fun & args] - ;; (. ref (alter fun args)) - (throw "TODO: port alter")) - -(defn ref-set - "Must be called in a transaction. Sets the value of ref. - Returns val." - [#_clojure.lang.Ref ref val] - ;; (. ref (set val)) - (throw "TODO: port ref-set")) - -(defn ref-history-count - "Returns the history count of a ref" - [#_clojure.lang.Ref ref] - ;; (.getHistoryCount ref) - (throw "TODO: port ref-history-count")) - -(defn ref-min-history - "Gets the min-history of a ref, or sets it and returns the ref" - ([#_clojure.lang.Ref ref] - ;; (.getMinHistory ref) - (throw "TODO: port ref-min-history")) - ([#_clojure.lang.Ref ref n] - ;; (.setMinHistory ref n) - (throw "TODO: port ref-min-history"))) - -(defn ref-max-history - "Gets the max-history of a ref, or sets it and returns the ref" - ([#_clojure.lang.Ref ref] - ;; (.getMaxHistory ref) - (throw "TODO: port ref-max-history")) - ([#_clojure.lang.Ref ref n] - ;; (.setMaxHistory ref n) - (throw "TODO: port ref-max-history"))) - -(defn ensure - "Must be called in a transaction. Protects the ref from modification - by other transactions. Returns the in-transaction-value of - ref. Allows for more concurrency than (ref-set ref @ref)" - [#_clojure.lang.Ref ref] - ;; (. ref (touch)) - ;; (. ref (deref)) - (throw "TODO: port ensure")) - -(defmacro sync - "transaction-flags => TBD, pass nil for now - - Runs the exprs (in an implicit do) in a transaction that encompasses - exprs and any nested calls. Starts a transaction if none is already - running on this thread. Any uncaught exception will abort the - transaction and flow out of sync. The exprs may be run more than - once, but any effects on Refs will be atomic." - [flags-ignored-for-now & body] - ;; `(. clojure.lang.LockingTransaction - ;; (runInTransaction (fn [] ~@body))) - (throw "TODO: port sync")) - -(defmacro io! - "If an io! block occurs in a transaction, throws an - IllegalStateException, else runs body in an implicit do. If the - first expression in body is a literal string, will use that as the - exception message." - [& body] - ;; (let [message (when (string? (first body)) (first body)) - ;; body (if message (next body) body)] - ;; `(if (clojure.lang.LockingTransaction/isRunning) - ;; (throw (new IllegalStateException ~(or message "I/O in transaction"))) - ;; (do ~@body))) - (throw "TODO: port io!")) - -;;;;;;;;;;;;;;;;;;; sequence fns ;;;;;;;;;;;;;;;;;;;;;;; - -(defn sequence - "Coerces coll to a (possibly empty) sequence, if it is not already - one. Will not force a lazy seq. (sequence nil) yields (), When a - transducer is supplied, returns a lazy sequence of applications of - the transform to the items in coll(s), i.e. to the set of first - items of each coll, followed by the set of second - items in each coll, until any one of the colls is exhausted. Any - remaining items in other colls are ignored. The transform should accept - number-of-colls arguments" - ([coll] - (if (seq? coll) coll - (or (seq coll) ()))) - ([xform coll] - ;; (or (clojure.lang.RT/chunkIteratorSeq - ;; (clojure.lang.TransformerIterator/create xform (clojure.lang.RT/iter coll))) - ;; ()) - (throw "TODO: port sequence")) - ([xform coll & colls] - ;; (or (clojure.lang.RT/chunkIteratorSeq - ;; (clojure.lang.TransformerIterator/createMulti - ;; xform - ;; (map #(clojure.lang.RT/iter %) (cons coll colls)))) - ;; ()) - (throw "TODO: port sequence"))) - -(defn not-every? - "Returns false if (pred x) is logical true for every x in - coll, else true." - [pred coll] - (not (every? pred coll))) - -(defmacro declare - "defs the supplied var names with no bindings, useful for making forward declarations." - [& names] `(do ~@(map #(list 'def (vary-meta % assoc :declared true)) names))) - -(defn replicate - "DEPRECATED: Use 'repeat' instead. - Returns a lazy seq of n xs." - [n x] (take n (repeat x))) - -(defn merge - "Returns a map that consists of the rest of the maps conj-ed onto - the first. If a key occurs in more than one map, the mapping from - the latter (left-to-right) will be the mapping in the result." - [& maps] - (when (some identity maps) - (reduce #(conj (or %1 {}) %2) maps))) - -(defn merge-with - "Returns a map that consists of the rest of the maps conj-ed onto - the first. If a key occurs in more than one map, the mapping(s) - from the latter (left-to-right) will be combined with the mapping in - the result by calling (f val-in-result val-in-latter)." - [f & maps] - (when (some identity maps) - (let [merge-entry (fn [m e] - (let [k (key e) v (val e)] - (if (contains? m k) - (assoc m k (f (get m k) v)) - (assoc m k v)))) - merge2 (fn [m1 m2] - (reduce merge-entry (or m1 {}) (seq m2)))] - (reduce merge2 maps)))) - -(defn line-seq - "Returns the lines of text from rdr as a lazy sequence of strings. - rdr must implement java.io.BufferedReader." - [#_java.io.BufferedReader rdr] - ;; (when-let [line (.readLine rdr)] - ;; (cons line (lazy-seq (line-seq rdr)))) - (throw "TODO: port line-seq")) - -(defn comparator - "Returns an implementation of java.util.Comparator based upon pred." - [pred] - (fn [x y] - (cond (pred x y) -1 (pred y x) 1 :else 0))) - -(defn sort - "Returns a sorted sequence of the items in coll. If no comparator is - supplied, uses compare. comparator must implement - java.util.Comparator. Guaranteed to be stable: equal elements will - not be reordered. If coll is a Java array, it will be modified. To - avoid this, sort a copy of the array." - [coll] - (cpp/jank.runtime.sort coll)) - -(defn sort-by - "Returns a sorted sequence of the items in coll, where the sort - order is determined by comparing (keyfn item). If no comparator is - supplied, uses compare. comparator must implement - java.util.Comparator. Guaranteed to be stable: equal elements will - not be reordered. If coll is a Java array, it will be modified. To - avoid this, sort a copy of the array." - ([keyfn coll] - (sort-by keyfn compare coll)) - ([keyfn #_java.util.Comparator comp coll] - ;; (sort (fn [x y] (. comp (compare (keyfn x) (keyfn y)))) coll) - (throw "TODO: port sort-by"))) - -;; evaluation - -(defn eval - "Evaluates the form data structure (not text!) and returns the result." - [form] - (cpp/clojure.core_native.eval form)) - -(defn await - "Blocks the current thread (indefinitely!) until all actions - dispatched thus far, from this thread or agent, to the agent(s) have - occurred. Will block on failed agents. Will never return if - a failed agent is restarted with :clear-actions true or shutdown-agents was called." - [& agents] - ;; (io! "await in transaction" - ;; (when *agent* - ;; (throw (new Exception "Can't await in agent action"))) - ;; (let [latch (new java.util.concurrent.CountDownLatch (count agents)) - ;; count-down (fn [agent] (. latch (countDown)) agent)] - ;; (doseq [agent agents] - ;; (send agent count-down)) - ;; (. latch (await)))) - (throw "TODO: port await")) - -(defn await1 [#_clojure.lang.Agent a] - ;; (when (pos? (.getQueueCount a)) - ;; (await a)) - ;; a - (throw "TODO: port await1")) - -(defn await-for - "Blocks the current thread until all actions dispatched thus - far (from this thread or agent) to the agents have occurred, or the - timeout (in milliseconds) has elapsed. Returns logical false if - returning due to timeout, logical true otherwise." - [timeout-ms & agents] - ;; (io! "await-for in transaction" - ;; (when *agent* - ;; (throw (new Exception "Can't await in agent action"))) - ;; (let [latch (new java.util.concurrent.CountDownLatch (count agents)) - ;; count-down (fn [agent] (. latch (countDown)) agent)] - ;; (doseq [agent agents] - ;; (send agent count-down)) - ;; (. latch (await timeout-ms (. java.util.concurrent.TimeUnit MILLISECONDS))))) - (throw "TODO: port await-for")) - -(defn import - "import is not implemented for jank, but a var is still bound to its symbol for portability. import always throws an exception" - [& _] - (throw "import is not supported in jank, for C/C++ dependency interoperability use cpp/raw with #include, e.g. (cpp/raw \"#include \"dependency.h\")\")")) - -(defn into-array - "Returns an array with components set to the values in aseq. The array's - component type is type if provided, or the type of the first value in - aseq if present, or Object. All values in aseq must be compatible with - the component type. Class objects for the primitive types can be obtained - using, e.g., Integer/TYPE." - ([aseq] - ;; (clojure.lang.RT/seqToTypedArray (seq aseq)) - (throw "TODO: port into-array")) - ([type aseq] - ;; (clojure.lang.RT/seqToTypedArray type (seq aseq)) - (throw "TODO: port into-array"))) - -(defn- - array [& items] - (into-array items)) - -(defn class - "Returns the Class of x" - #_Class [#_Object x] - ;; (if (nil? x) x (. x (getClass))) - (throw "TODO: port class")) - -(defn num - "Coerce to Number" - [x] - ;; (. clojure.lang.Numbers (num x)) - (throw "TODO: port num")) - -(defn long - "Coerce to long" - [#_Number x] - ;; (clojure.lang.RT/longCast x) - (throw "TODO: port long")) - -(defn double - "Coerce to double" - [#_Number x] - ;; (clojure.lang.RT/doubleCast x) - (throw "TODO: port double")) - -(defn short - "Coerce to short" - [#_Number x] - ;; (clojure.lang.RT/shortCast x) - (throw "TODO: port short")) - -(defn byte - "Coerce to byte" - [#_Number x] - ;; (clojure.lang.RT/byteCast x) - (throw "TODO: port byte")) - -(defn char - "Coerce to char" - [x] - ;; (. clojure.lang.RT (charCast x)) - (throw "TODO: port char")) - -(defn unchecked-byte - "Coerce to byte. Subject to rounding or truncation." - [#_Number x] - ;; (clojure.lang.RT/uncheckedByteCast x) - (throw "TODO: port unchecked-byte")) - -(defn unchecked-short - "Coerce to short. Subject to rounding or truncation." - [#_Number x] - ;; (clojure.lang.RT/uncheckedShortCast x) - (throw "TODO: port unchecked-short")) - -(defn unchecked-char - "Coerce to char. Subject to rounding or truncation." - [x] - ;; (. clojure.lang.RT (uncheckedCharCast x)) - (throw "TODO: port unchecked-char")) - -(defn unchecked-int - "Coerce to int. Subject to rounding or truncation." - [#_Number x] - ;; (clojure.lang.RT/uncheckedIntCast x) - (throw "TODO: port unchecked-int")) - -(defn unchecked-long - "Coerce to long. Subject to rounding or truncation." - [#_Number x] - ;; (clojure.lang.RT/uncheckedLongCast x) - (throw "TODO: port unchecked-long")) - -(defn unchecked-float - "Coerce to float. Subject to rounding." - [#_Number x] - ;; (clojure.lang.RT/uncheckedFloatCast x) - (throw "TODO: port unchecked-float")) - -(defn unchecked-double - "Coerce to double. Subject to rounding." - [#_Number x] - ;; (clojure.lang.RT/uncheckedDoubleCast x) - (throw "TODO: port unchecked-double")) - -(defn ratio? - "Returns true if n is a Ratio" - [r] - (cpp/jank.runtime.is_ratio r)) - -(defn numerator - "Returns the numerator part of a Ratio." - [r] - (cpp/jank.runtime.numerator r)) - -(defn denominator - "Returns the denominator part of a Ratio." - [r] - (cpp/jank.runtime.denominator r)) - -(defn decimal? - "Returns true if n is a BigDecimal" - [n] - ;; (instance? BigDecimal n) - (cpp/jank.runtime.is_big_decimal n)) - -(defn rational? - "Returns true if n is a rational number" - [n] - (or (integer? n) (ratio? n) (decimal? n))) - -(defn bigint - "Coerce to BigInt" - [x] - ;; (cond - ;; (instance? clojure.lang.BigInt x) x - ;; (instance? BigInteger x) (clojure.lang.BigInt/fromBigInteger x) - ;; (decimal? x) (bigint (.toBigInteger ^BigDecimal x)) - ;; (float? x) (bigint (. BigDecimal valueOf (double x))) - ;; (ratio? x) (bigint (.bigIntegerValue ^clojure.lang.Ratio x)) - ;; (number? x) (clojure.lang.BigInt/valueOf (long x)) - ;; :else (bigint (BigInteger. x))) - (throw "TODO: port bigint")) - -(defn biginteger - "Coerce to BigInteger" - [x] - ;; (cond - ;; (instance? BigInteger x) x - ;; (instance? clojure.lang.BigInt x) (.toBigInteger ^clojure.lang.BigInt x) - ;; (decimal? x) (.toBigInteger ^BigDecimal x) - ;; (float? x) (.toBigInteger (. BigDecimal valueOf (double x))) - ;; (ratio? x) (.bigIntegerValue ^clojure.lang.Ratio x) - ;; (number? x) (BigInteger/valueOf (long x)) - ;; :else (BigInteger. x)) - (throw "TODO: port biginteger")) - -(defn bigdec - "Coerce to BigDecimal" - [x] - (cpp/jank.runtime.to_big_decimal x)) - -(def ^:dynamic ^:private print-initialized false) - -(defmulti print-method (fn [x writer] - (let [t (get (meta x) :type)] - (if (keyword? t) t (class x))))) - -(defmulti print-dup (fn [x writer] (class x))) - -(def ^:private #_String system-newline - ;; (System/getProperty "line.separator") - "\n") - -(defn newline - "Writes a platform-specific newline to *out*" - [] - ;; (. *out* (append system-newline)) - ;; nil - (throw "TODO: port newline")) - -(defn flush - "Flushes the output stream that is the current value of - *out*" - [] - ;; (. *out* (flush)) - ;; nil - (throw "TODO: port flesh")) - -(defn read - "Reads the next object from stream, which must be an instance of - java.io.PushbackReader or some derivee. stream defaults to the - current value of *in*. - - Opts is a persistent map with valid keys: - :read-cond - :allow to process reader conditionals, or - :preserve to keep all branches - :features - persistent set of feature keywords for reader conditionals - :eof - on eof, return value unless :eofthrow, then throw. - if not specified, will throw - - Note that read can execute code (controlled by *read-eval*), - and as such should be used only with trusted sources. - - For data structure interop use clojure.edn/read" - ([] - (read *in*)) - ([stream] - (read stream true nil)) - ([stream eof-error? eof-value] - (read stream eof-error? eof-value false)) - ([stream eof-error? eof-value recursive?] - ;; (. clojure.lang.LispReader (read stream (boolean eof-error?) eof-value recursive?)) - (throw "TODO: port read")) - ([opts stream] - ;; (. clojure.lang.LispReader (read stream opts)) - (throw "TODO: port read"))) - -(defn read+string - "Like read, and taking the same args. stream must be a LineNumberingPushbackReader. - Returns a vector containing the object read and the (whitespace-trimmed) string read." - ([] (read+string *in*)) - ([stream] (read+string stream true nil)) - ([stream eof-error? eof-value] (read+string stream eof-error? eof-value false)) - ([#_clojure.lang.LineNumberingPushbackReader stream eof-error? eof-value recursive?] - ;; (try - ;; (.captureString stream) - ;; (let [o (read stream eof-error? eof-value recursive?) - ;; s (.trim (.getString stream))] - ;; [o s]) - ;; (catch Throwable ex - ;; (.getString stream) - ;; (throw ex))) - (throw "TODO: port read+string")) - ([opts #_clojure.lang.LineNumberingPushbackReader stream] - ;; (try - ;; (.captureString stream) - ;; (let [o (read opts stream) - ;; s (.trim (.getString stream))] - ;; [o s]) - ;; (catch Throwable ex - ;; (.getString stream) - ;; (throw ex))) - (throw "TODO: port read+string"))) - -(defn read-line - "Reads the next line from stream that is the current value of *in* ." - [] - ;; (if (instance? clojure.lang.LineNumberingPushbackReader *in*) - ;; (.readLine ^clojure.lang.LineNumberingPushbackReader *in*) - ;; (.readLine ^java.io.BufferedReader *in*)) - (throw "TODO: port read-line")) - -(defn read-string - "Reads one object from the string s. Optionally include reader - options, as specified in read. - - Note that read-string can execute code (controlled by *read-eval*), - and as such should be used only with trusted sources. - - For data structure interop use clojure.edn/read-string" - ([s] - (read-string {} s)) - ([opts s] - (cpp/clojure.core_native.read_string opts s))) - -(defmacro with-open - "bindings => [name init ...] - - Evaluates body in a try expression with names bound to the values - of the inits, and a finally clause that calls (.close name) on each - name in reverse order." - [bindings & body] - (assert-macro-args - (vector? bindings) "a vector for its binding" - (even? (count bindings)) "an even number of forms in binding vector") - ;; (cond - ;; (= (count bindings) 0) `(do ~@body) - ;; (symbol? (bindings 0)) `(let ~(subvec bindings 0 2) - ;; (try - ;; (with-open ~(subvec bindings 2) ~@body) - ;; (finally - ;; (. ~(bindings 0) ~'close)))) - ;; :else (throw (IllegalArgumentException. - ;; "with-open only allows Symbols in bindings"))) - (throw "TODO: port with-open")) - -(defmacro memfn - "Expands into code that creates a fn that expects to be passed an - object and any args and calls the named instance method on the - object passing the args. Use when you want to treat a Java method as - a first-class fn. name may be type-hinted with the method receiver's - type in order to avoid reflective calls." - [name & args] - ;; (let [t (with-meta (gensym "target") - ;; (meta name))] - ;; `(fn [~t ~@args] - ;; (. ~t (~name ~@args)))) - (throw "TODO: port memfn")) - -(defn alength - "Returns the length of the Java array. Works on arrays of all - types." - [array] - ;; (. clojure.lang.RT (alength array)) - (throw "TODO: port alength")) - -(defn aclone - "Returns a clone of the Java array. Works on arrays of known - types." - [array] - ;; (. clojure.lang.RT (aclone array)) - (throw "TODO: port aclone")) - -(defn aget - "Returns the value at the index/indices. Works on Java arrays of all - types." - ([array idx] - ;; (clojure.lang.Reflector/prepRet (.getComponentType (class array)) (. Array (get array idx))) - (throw "TODO: port aget")) - ([array idx & idxs] - (apply aget (aget array idx) idxs))) - -(defmacro aset - "Sets the value at the index/indices. Returns val." - [array idx & more] - (if (= 1 (count more)) - ;; Simple case: (aset array index value) - (let [val (first more)] - `(do - (cpp/= (cpp/aget ~array ~idx) ~val) - ~val)) - ;; Nested case: (aset array idx1 idx2 & idxv) - not yet implemented - `(throw "TODO: Nested array indexing not yet implemented"))) - -(defmacro - ^{:private true} - def-aset [name method coerce] - `(defn ~name - {:arglists '([~'array ~'idx ~'val] [~'array ~'idx ~'idx2 & ~'idxv])} - ([array# idx# val#] - ;; (. Array (~method array# idx# (~coerce val#))) - ;; val# - (throw ~(str "TODO: port " name))) - ([array# idx# idx2# & idxv#] - (apply ~name (aget array# idx#) idx2# idxv#)))) - -(def-aset - ^{:doc "Sets the value at the index/indices. Works on arrays of int. Returns val."} - aset-int setInt int) - -(def-aset - ^{:doc "Sets the value at the index/indices. Works on arrays of long. Returns val."} - aset-long setLong long) - -(def-aset - ^{:doc "Sets the value at the index/indices. Works on arrays of boolean. Returns val."} - aset-boolean setBoolean boolean) - -(def-aset - ^{:doc "Sets the value at the index/indices. Works on arrays of float. Returns val."} - aset-float setFloat float) - -(def-aset - ^{:doc "Sets the value at the index/indices. Works on arrays of double. Returns val."} - aset-double setDouble double) - -(def-aset - ^{:doc "Sets the value at the index/indices. Works on arrays of short. Returns val."} - aset-short setShort short) - -(def-aset - ^{:doc "Sets the value at the index/indices. Works on arrays of byte. Returns val."} - aset-byte setByte byte) - -(def-aset - ^{:doc "Sets the value at the index/indices. Works on arrays of char. Returns val."} - aset-char setChar char) - -(defn make-array - "Creates and returns an array of instances of the specified class of - the specified dimension(s). Note that a class object is required. - Class objects can be obtained by using their name. - Class objects for the primitive types can be obtained using, e.g., Integer/TYPE." - ([#_Class type len] - ;; (. Array (newInstance type (int len))) - (throw "TODO: port make-array")) - ([#_Class type dim & more-dims] - ;; (let [dims (cons dim more-dims) - ;; ^"[I" dimarray (make-array (. Integer TYPE) (count dims))] - ;; (dotimes [i (alength dimarray)] - ;; (aset-int dimarray i (nth dims i))) - ;; (. Array (newInstance type dimarray)))) - (throw "TODO: port make-array"))) - -(defn to-array-2d - "Returns a (potentially-ragged) 2-dimensional array of Objects - containing the contents of coll, which can be any Collection of any - Collection." - [#_java.util.Collection coll] - ;; (let [ret (make-array (. Class (forName "[Ljava.lang.Object;")) (. coll (size)))] - ;; (loop [i 0 xs (seq coll)] - ;; (when xs - ;; (aset ret i (to-array (first xs))) - ;; (recur (inc i) (next xs)))) - ;; ret) - (throw "TODO: port to-array-2d")) - -(defn create-struct - "Returns a structure basis object." - [& keys] - ;; (. clojure.lang.PersistentStructMap (createSlotMap keys)) - (throw "TODO: port create-struct")) - -(defmacro defstruct - "Same as (def name (create-struct keys...))" - [name & keys] - `(def ~name (create-struct ~@keys))) - -(defn struct-map - "Returns a new structmap instance with the keys of the - structure-basis. keyvals may contain all, some or none of the basis - keys - where values are not supplied they will default to nil. - keyvals can also contain keys not in the basis." - [s & inits] - ;; (. clojure.lang.PersistentStructMap (create s inits)) - (throw "TODO: port struct-map")) - -(defn struct - "Returns a new structmap instance with the keys of the - structure-basis. vals must be supplied for basis keys in order - - where values are not supplied they will default to nil." - [s & vals] - ;; (. clojure.lang.PersistentStructMap (construct s vals)) - (throw "TODO: port struct")) - -(defn accessor - "Returns a fn that, given an instance of a structmap with the basis, - returns the value at the key. The key must be in the basis. The - returned function should be (slightly) more efficient than using - get, but such use of accessors should be limited to known - performance-critical areas." - [s key] - ;; (. clojure.lang.PersistentStructMap (getAccessor s key)) - (throw "TODO: port accessor")) - -(defn load-reader - "Sequentially read and evaluate the set of forms contained in the - stream/file" - [rdr] - ;; (. clojure.lang.Compiler (load rdr)) - (throw "TODO: port load-reader")) - -(defn load-string - "Sequentially read and evaluate the set of forms contained in the - string" - [s] - ;; (let [rdr (-> (java.io.StringReader. s) - ;; (clojure.lang.LineNumberingPushbackReader.))] - ;; (load-reader rdr)) - (throw "TODO: port load-string")) - -(defn- - filter-key [keyfn pred amap] - (loop [ret {} es (seq amap)] - (if es - (if (pred (keyfn (first es))) - (recur (assoc ret (key (first es)) (val (first es))) (next es)) - (recur ret (next es))) - ret))) - -(defn all-ns - "Returns a sequence of all namespaces." - [] - ;; (clojure.lang.Namespace/all) - (throw "TODO: port all-ns")) - -(defn ns-unmap - "Removes the mappings for the symbol from the namespace." - [ns sym] - (cpp/clojure.core_native.ns_unmap (the-ns ns) sym)) - -(defn ns-imports - "Returns a map of the import mappings for the namespace." - [ns] - ;; (filter-key val (partial instance? Class) (ns-map ns)) - (throw "TODO: port ns-imports")) - -(defn ns-interns - "Returns a map of the intern mappings for the namespace." - [ns] - (let [ns (the-ns ns)] - (filter-key val (fn [v] (and (var? v) - (= (ns-name ns) (-> v symbol namespace symbol)))) - (ns-map ns)))) - -(defn ns-refers - "Returns a map of the refer mappings for the namespace." - [ns] - ;; (let [ns (the-ns ns)] - ;; (filter-key val (fn [^clojure.lang.Var v] (and (instance? clojure.lang.Var v) - ;; (not= ns (.ns v)))) - ;; (ns-map ns))) - (throw "TODO: port ns-refers")) - -(defn ns-aliases - "Returns a map of the aliases for the namespace." - [ns] - ;; (.getAliases (the-ns ns)) - (throw "TODO: port ns-aliases")) - -(defn ns-unalias - "Removes the alias for the symbol from the namespace." - [ns sym] - (cpp/clojure.core_native.ns_unalias (the-ns ns) sym)) - -(defn var-set - "Sets the value in the var object to val. The var must be - thread-locally bound." - [#_clojure.lang.Var x val] - ;; (. x (set val)) - (throw "TODO: port var-set")) - -(defmacro with-local-vars - "varbinding=> symbol init-expr - - Executes the exprs in a context in which the symbols are bound to - vars with per-thread bindings to the init-exprs. The symbols refer - to the var objects themselves, and must be accessed with var-get and - var-set" - [name-vals-vec & body] - (assert-macro-args - (vector? name-vals-vec) "a vector for its binding" - (even? (count name-vals-vec)) "an even number of forms in binding vector") - ;; `(let [~@(interleave (take-nth 2 name-vals-vec) - ;; (repeat '(.. clojure.lang.Var create setDynamic)))] - ;; (. clojure.lang.Var (pushThreadBindings (hash-map ~@name-vals-vec))) - ;; (try - ;; (do ~@body) - ;; (finally (. clojure.lang.Var (popThreadBindings))))) - (throw "TODO: port with-local-vars")) - -(defn array-map - "Constructs an array-map. If any keys are equal, they are handled as - if by repeated uses of assoc." - ([] - ;; (. clojure.lang.PersistentArrayMap EMPTY) - (throw "TODO: port array-map")) - ([& keyvals] - ;; (let [ary (to-array keyvals)] - ;; (if (odd? (alength ary)) - ;; (throw (IllegalArgumentException. (str "No value supplied for key: " (last keyvals)))) - ;; (clojure.lang.PersistentArrayMap/createAsIfByAssoc ary))) - (throw "TODO: port array-map"))) - -(defn seq-to-map-for-destructuring - "Builds a map from a seq as described in - https://clojure.org/reference/special_forms#keyword-arguments" - [s] - ;; (if (next s) - ;; (clojure.lang.PersistentArrayMap/createAsIfByAssoc (to-array s)) - ;; (if (seq s) (first s) clojure.lang.PersistentArrayMap/EMPTY)) - (throw "TODO: port seq-to-map-for-destructuring")) - -(defmacro lazy-cat - "Expands to code which yields a lazy sequence of the concatenation - of the supplied colls. Each coll expr is not evaluated until it is - needed. - - (lazy-cat xs ys zs) === (concat (lazy-seq xs) (lazy-seq ys) (lazy-seq zs))" - [& colls] - `(concat ~@(map #(list `lazy-seq %) colls))) - -(defmacro with-out-str - "Evaluates exprs in a context in which *out* is bound to a fresh - StringWriter. Returns the string created by any nested printing - calls." - [& body] - ;; `(let [s# (new java.io.StringWriter)] - ;; (binding [*out* s#] - ;; ~@body - ;; (str s#))) - (throw "TODO: port with-out-str")) - -(defmacro with-in-str - "Evaluates body in a context in which *in* is bound to a fresh - StringReader initialized with the string s." - [s & body] - `(with-open [s# (-> (java.io.StringReader. ~s) clojure.lang.LineNumberingPushbackReader.)] - (binding [*in* s#] - ~@body))) - -(defn prn-str - "prn to a string, returning it" - [& xs] - ;; (with-out-str - ;; (apply prn xs)) - (throw "TODO: port prn-str")) - - -(defn print-str - "print to a string, returning it" - [& xs] - ;; (with-out-str - ;; (apply print xs)) - (throw "TODO: port print-str")) - -(defn println-str - "println to a string, returning it" - [& xs] - ;; (with-out-str - ;; (apply println xs)) - (throw "TODO: port println-str")) - -(defn ^:private elide-top-frames - [#_Throwable ex class-name] - ;; (let [tr (.getStackTrace ex)] - ;; (doto ex - ;; (.setStackTrace - ;; (when tr - ;; (into-array StackTraceElement - ;; (drop-while #(= class-name (.getClassName ^StackTraceElement %1)) tr)))))) - (throw "TODO: port elide-top-frames")) - -(defn test - "test [v] finds fn at key :test in var metadata and calls it, - presuming failure will throw exception" - [v] - (let [f (:test (meta v))] - (if f - (do (f) :ok) - :no-test))) - -(defn re-pattern - "Returns an instance of java.util.regex.Pattern, for use, e.g. in - re-matcher." - [s] - (cpp/jank.runtime.re_pattern s)) - -(defn re-matcher - "Returns an instance of java.util.regex.Matcher, for use, e.g. in - re-find." - [re s] - (cpp/jank.runtime.re_matcher re s)) - -(defn re-groups - "Returns the groups from the most recent match/find. If there are no - nested groups, returns a string of the entire match. If there are - nested groups, returns a vector of the groups, the first element - being the entire match." - [m] - (cpp/jank.runtime.re_groups m)) - -(defn re-matches - "Returns the match, if any, of string to pattern, using - java.util.regex.Matcher.matches(). Uses re-groups to return the - groups." - [re s] - (cpp/jank.runtime.re_matches re s)) - -(defn re-find - "Returns the next regex match, if any, of string to pattern, using - java.util.regex.Matcher.find(). Uses re-groups to return the - groups." - ([m] - (cpp/jank.runtime.re_find m)) - ([re s] - (let [m (re-matcher re s)] - (re-find m)))) - -(defn re-seq - "Returns a lazy sequence of successive matches of pattern in string, - using java.util.regex.Matcher.find(), each such match processed with - re-groups." - [re s] - (let [m (cpp/jank.runtime.re_matcher re s)] - ((fn step [] - (when (re-find m) - (cons (re-groups m) (lazy-seq (step)))))))) - -(defn rand-int - "Returns a random integer between 0 (inclusive) and n (exclusive)." - [n] (int (rand n))) - -(defn file-seq - "A tree seq on java.io.Files" - [dir] - ;; (tree-seq - ;; (fn [^java.io.File f] (. f (isDirectory))) - ;; (fn [^java.io.File d] (seq (. d (listFiles)))) - ;; dir) - (throw "TODO: port file-seq")) - -(defn xml-seq - "A tree seq on the xml elements as per xml/parse" - [root] - (tree-seq - (complement string?) - (comp seq :content) - root)) - -(defn special-symbol? - "Returns true if s names a special form" - [s] - ;; (contains? (. clojure.lang.Compiler specials) s) - (throw "TODO: port special-symbol?")) - -(defn max-key - "Returns the x for which (k x), a number, is greatest. - - If there are multiple such xs, the last one is returned." - ([k x] x) - ([k x y] (if (> (k x) (k y)) x y)) - ([k x y & more] - (let [kx (k x) ky (k y) - [v kv] (if (> kx ky) [x kx] [y ky])] - (loop [v v kv kv more more] - (if more - (let [w (first more) - kw (k w)] - (if (>= kw kv) - (recur w kw (next more)) - (recur v kv (next more)))) - v))))) - -(defn min-key - "Returns the x for which (k x), a number, is least. - - If there are multiple such xs, the last one is returned." - ([k x] x) - ([k x y] (if (< (k x) (k y)) x y)) - ([k x y & more] - (let [kx (k x) ky (k y) - [v kv] (if (< kx ky) [x kx] [y ky])] - (loop [v v kv kv more more] - (if more - (let [w (first more) - kw (k w)] - (if (<= kw kv) - (recur w kw (next more)) - (recur v kv (next more)))) - v))))) - -(defn replace - "Given a map of replacement pairs and a vector/collection, returns a - vector/seq with any elements = a key in smap replaced with the - corresponding val in smap. Returns a transducer when no collection - is provided." - ([smap] - (map #(if-let [e (find smap %)] (val e) %))) - ([smap coll] - (if (vector? coll) - (reduce (fn [v i] - (if-let [e (find smap (nth v i))] - (assoc v i (val e)) - v)) - coll (range (count coll))) - (map #(if-let [e (find smap %)] (val e) %) coll)))) - -(defmacro dosync - "Runs the exprs (in an implicit do) in a transaction that encompasses - exprs and any nested calls. Starts a transaction if none is already - running on this thread. Any uncaught exception will abort the - transaction and flow out of dosync. The exprs may be run more than - once, but any effects on Refs will be atomic." - [& exprs] - `(sync nil ~@exprs)) - -(defmacro with-precision - "Sets the precision and rounding mode to be used for BigDecimal operations. - - Usage: (with-precision 10 (/ 1M 3)) - or: (with-precision 10 :rounding HALF_DOWN (/ 1M 3)) - - The rounding mode is one of CEILING, FLOOR, HALF_UP, HALF_DOWN, - HALF_EVEN, UP, DOWN and UNNECESSARY; it defaults to HALF_UP." - [precision & exprs] - ;; (let [[body rm] (if (= (first exprs) :rounding) - ;; [(next (next exprs)) - ;; `((. java.math.RoundingMode ~(second exprs)))] - ;; [exprs nil])] - ;; `(binding [*math-context* (java.math.MathContext. ~precision ~@rm)] - ;; ~@body)) - (throw "TODO: port with-precision")) - -(defn- mk-bound-fn - [#_clojure.lang.Sorted sc test key] - ;; (fn [e] - ;; (test (.. sc comparator (compare (. sc entryKey e) key)) 0)) - (throw "TODO: port mk-bound-fn")) - -(defn subseq - "sc must be a sorted collection, test(s) one of <, <=, > or - >=. Returns a seq of those entries with keys ek for - which (test (.. sc comparator (compare ek key)) 0) is true" - ([#_clojure.lang.Sorted sc test key] - ;; (let [include (mk-bound-fn sc test key)] - ;; (if (#{> >=} test) - ;; (when-let [[e :as s] (. sc seqFrom key true)] - ;; (if (include e) s (next s))) - ;; (take-while include (. sc seq true)))) - (throw "TODO: port subseq")) - ([#_clojure.lang.Sorted sc start-test start-key end-test end-key] - ;; (when-let [[e :as s] (. sc seqFrom start-key true)] - ;; (take-while (mk-bound-fn sc end-test end-key) - ;; (if ((mk-bound-fn sc start-test start-key) e) s (next s)))) - (throw "TODO: port subseq"))) - -(defn rsubseq - "sc must be a sorted collection, test(s) one of <, <=, > or - >=. Returns a reverse seq of those entries with keys ek for - which (test (.. sc comparator (compare ek key)) 0) is true" - ([#_clojure.lang.Sorted sc test key] - ;; (let [include (mk-bound-fn sc test key)] - ;; (if (#{< <=} test) - ;; (when-let [[e :as s] (. sc seqFrom key false)] - ;; (if (include e) s (next s))) - ;; (take-while include (. sc seq false)))) - (throw "TODO: port rsubseq")) - ([#_clojure.lang.Sorted sc start-test start-key end-test end-key] - ;; (when-let [[e :as s] (. sc seqFrom end-key false)] - ;; (take-while (mk-bound-fn sc start-test start-key) - ;; (if ((mk-bound-fn sc end-test end-key) e) s (next s)))) - (throw "TODO: port rsubseq"))) - -(defn add-classpath - "DEPRECATED - - Adds the url (String or URL object) to the classpath per - URLClassLoader.addURL" - [url] - (println "WARNING: add-classpath is deprecated") - ;; (clojure.lang.RT/addURL url) - (throw "TODO: port add-classpath")) - -(defn mix-collection-hash - "Mix final collection hash for ordered or unordered collections. - hash-basis is the combined collection hash, count is the number - of elements included in the basis. Note this is the hash code - consistent with =, different from .hashCode. - See http://clojure.org/data_structures#hash for full algorithms." - #_long - [#_long hash-basis #_long count] - ;; (clojure.lang.Murmur3/mixCollHash hash-basis count) - (throw "TODO: port mix-collection-hash")) - -(defn hash-ordered-coll - "Returns the hash code, consistent with =, for an external ordered - collection implementing Iterable. - See http://clojure.org/data_structures#hash for full algorithms." - #_long - [coll] - ;; (clojure.lang.Murmur3/hashOrdered coll) - (throw "TODO: port hash-ordered-coll")) - -(defn hash-unordered-coll - "Returns the hash code, consistent with =, for an external unordered - collection implementing Iterable. For maps, the iterator should - return map entries whose hash is computed as - (hash-ordered-coll [k v]). - See http://clojure.org/data_structures#hash for full algorithms." - [coll] - (cpp/clojure.core_native.hash_unordered coll)) - -(defmacro definline - "Experimental - like defmacro, except defines a named function whose - body is the expansion, calls to which may be expanded inline as if - it were a macro. Cannot be used with variadic (&) args." - [name & decl] - (let [[pre-args [args expr]] (split-with (comp not vector?) decl)] - `(do - (defn ~name ~@pre-args ~args ~(apply (eval (list `fn args expr)) args)) - (alter-meta! (var ~name) assoc :inline (fn ~name ~args ~expr)) - (var ~name)))) - -(defmacro amap - "Maps an expression across an array a, using an index named idx, and - return value named ret, initialized to a clone of a, then setting - each element of ret to the evaluation of expr, returning the new - array ret." - [a idx ret expr] - `(let [a# ~a l# (alength a#) - ~ret (aclone a#)] - (loop [~idx 0] - (if (< ~idx l#) - (do - (aset ~ret ~idx ~expr) - (recur (unchecked-inc ~idx))) - ~ret)))) - -(defmacro areduce - "Reduces an expression across an array a, using an index named idx, - and return value named ret, initialized to init, setting ret to the - evaluation of expr at each step, returning ret." - [a idx ret init expr] - `(let [a# ~a l# (alength a#)] - (loop [~idx 0 ~ret ~init] - (if (< ~idx l#) - (recur (unchecked-inc-int ~idx) ~expr) - ~ret)))) - -(defn float-array - "Creates an array of floats" - ([size-or-seq] - ;; (. clojure.lang.Numbers float_array size-or-seq) - (throw "TODO: port float-array")) - ([size init-val-or-seq] - ;; (. clojure.lang.Numbers float_array size init-val-or-seq) - (throw "TODO: port float-array") )) - -(defn boolean-array - "Creates an array of booleans" - ([size-or-seq] - ;; (. clojure.lang.Numbers boolean_array size-or-seq) - (throw "TODO: port boolean-array")) - ([size init-val-or-seq] - ;; (. clojure.lang.Numbers boolean_array size init-val-or-seq) - (throw "TODO: port boolean-array"))) - -(defn byte-array - "Creates an array of bytes" - ([size-or-seq] - ;; (. clojure.lang.Numbers byte_array size-or-seq) - (throw "TODO: port byte-array")) - ([size init-val-or-seq] - ;; (. clojure.lang.Numbers byte_array size init-val-or-seq) - (throw "TODO: port byte-array"))) - -(defn char-array - "Creates an array of chars" - ([size-or-seq] - ;; (. clojure.lang.Numbers char_array size-or-seq) - (throw "TODO: port char-array")) - ([size init-val-or-seq] - ;; (. clojure.lang.Numbers char_array size init-val-or-seq) - (throw "TODO: port char-array"))) - -(defn short-array - "Creates an array of shorts" - ([size-or-seq] - ;; (. clojure.lang.Numbers short_array size-or-seq) - (throw "TODO: port short-array")) - ([size init-val-or-seq] - ;; (. clojure.lang.Numbers short_array size init-val-or-seq) - (throw "TODO: port short-array"))) - -(defn double-array - "Creates an array of doubles" - ([size-or-seq] - ;; (. clojure.lang.Numbers double_array size-or-seq) - (throw "TODO: port double-array")) - ([size init-val-or-seq] - ;; (. clojure.lang.Numbers double_array size init-val-or-seq) - (throw "TODO: port double-array"))) - -(defn object-array - "Creates an array of objects" - ([size-or-seq] - ;; (. clojure.lang.RT object_array size-or-seq) - (throw "TODO: port object-array"))) - -(defn int-array - "Creates an array of ints" - ([size-or-seq] - ;; (. clojure.lang.Numbers int_array size-or-seq) - (throw "TODO: port int-array")) - ([size init-val-or-seq] - ;; (. clojure.lang.Numbers int_array size init-val-or-seq) - (throw "TODO: port int-array"))) - -(defn long-array - "Creates an array of longs" - ([size-or-seq] - ;; (. clojure.lang.Numbers long_array size-or-seq) - (throw "TODO: port long-array")) - ([size init-val-or-seq] - ;; (. clojure.lang.Numbers long_array size init-val-or-seq) - (throw "TODO: port long-array"))) - -;; definline doesn't work without eval - -;; (definline booleans -;; "Casts to boolean[]" -;; [xs] -;; ;; `(. clojure.lang.Numbers booleans ~xs) -;; (throw "TODO: port")) - -;; (definline bytes -;; "Casts to bytes[]" -;; [xs] -;; ;; `(. clojure.lang.Numbers bytes ~xs) -;; (throw "TODO: port")) - -;; (definline chars -;; "Casts to chars[]" -;; [xs] -;; ;; `(. clojure.lang.Numbers chars ~xs) -;; (throw "TODO: port")) - -;; (definline shorts -;; "Casts to shorts[]" -;; [xs] -;; ;; `(. clojure.lang.Numbers shorts ~xs) -;; (throw "TODO: port")) - -;; (definline floats -;; "Casts to float[]" -;; [xs] -;; ;; `(. clojure.lang.Numbers floats ~xs) -;; (throw "TODO: port")) - -;; (definline ints -;; "Casts to int[]" -;; [xs] -;; ;; `(. clojure.lang.Numbers ints ~xs) -;; (throw "TODO: port")) - -;; (definline doubles -;; "Casts to double[]" -;; [xs] -;; ;; `(. clojure.lang.Numbers doubles ~xs) -;; (throw "TODO: port")) - -;; (definline longs -;; "Casts to long[]" -;; [xs] -;; ;; `(. clojure.lang.Numbers longs ~xs) -;; (throw "TODO: port")) - -(defn bytes? - "Return true if x is a byte array" - [x] - ;; (if (nil? x) - ;; false - ;; (-> x class .getComponentType (= Byte/TYPE))) - (throw "TODO: port bytes?")) - -(defn seque - "Creates a queued seq on another (presumably lazy) seq s. The queued - seq will produce a concrete seq in the background, and can get up to - n items ahead of the consumer. n-or-q can be an integer n buffer - size, or an instance of java.util.concurrent BlockingQueue. Note - that reading from a seque can block if the reader gets ahead of the - producer." - ([s] (seque 100 s)) - ([n-or-q s] - ;; (let [^BlockingQueue q (if (instance? BlockingQueue n-or-q) - ;; n-or-q - ;; (LinkedBlockingQueue. (int n-or-q))) - ;; NIL (Object.) ;nil sentinel since LBQ doesn't support nils - ;; agt (agent (lazy-seq s)) ; never start with nil; that signifies we've already put eos - ;; log-error (fn [q e] - ;; (if (.offer q q) - ;; (throw e) - ;; e)) - ;; fill (fn [s] - ;; (when s - ;; (if (instance? Exception s) ; we failed to .offer an error earlier - ;; (log-error q s) - ;; (try - ;; (loop [[x & xs :as s] (seq s)] - ;; (if s - ;; (if (.offer q (if (nil? x) NIL x)) - ;; (recur xs) - ;; s) - ;; (when-not (.offer q q) ; q itself is eos sentinel - ;; ()))) ; empty seq, not nil, so we know to put eos next time - ;; (catch Exception e - ;; (log-error q e)))))) - ;; drain (fn drain [] - ;; (lazy-seq - ;; (let [x (.take q)] - ;; (if (identical? x q) ;q itself is eos sentinel - ;; (do @agt nil) ;touch agent just to propagate errors - ;; (do - ;; (send-off agt fill) - ;; (release-pending-sends) - ;; (cons (if (identical? x NIL) nil x) (drain)))))))] - ;; (send-off agt fill) - ;; (drain)) - (throw "TODO: port seque"))) - -(defn class? - "Returns true if x is an instance of Class" - [x] - ;; (instance? Class x) - (throw "TODO: port class?")) - -(defn- is-annotation? [c] - ;; (and (class? c) - ;; (.isAssignableFrom java.lang.annotation.Annotation c)) - (throw "TODO: port is-annotation?")) - -(defn- is-runtime-annotation? [#_Class c] - ;; (boolean - ;; (and (is-annotation? c) - ;; (when-let [^java.lang.annotation.Retention r - ;; (.getAnnotation c java.lang.annotation.Retention)] - ;; (= (.value r) java.lang.annotation.RetentionPolicy/RUNTIME)))) - (throw "TODO: port is-runtime-annotation?")) - -(defn- descriptor [#_Class c] - ;; (clojure.asm.Type/getDescriptor c) - (throw "TODO: port descriptor")) - -(declare process-annotation) - -(defn- add-annotation [#_clojure.asm.AnnotationVisitor av name v] - ;; (cond - ;; (vector? v) (let [avec (.visitArray av name)] - ;; (doseq [vval v] - ;; (add-annotation avec "value" vval)) - ;; (.visitEnd avec)) - ;; (symbol? v) (let [ev (eval v)] - ;; (cond - ;; (instance? java.lang.Enum ev) - ;; (.visitEnum av name (descriptor (class ev)) (str ev)) - ;; (class? ev) (.visit av name (clojure.asm.Type/getType ev)) - ;; :else (throw (IllegalArgumentException. - ;; (str "Unsupported annotation value: " v " of class " (class ev)))))) - ;; (seq? v) (let [[nested nv] v - ;; c (resolve nested) - ;; nav (.visitAnnotation av name (descriptor c))] - ;; (process-annotation nav nv) - ;; (.visitEnd nav)) - ;; :else (.visit av name v)) - (throw "TODO: port add-annotation")) - -(defn- process-annotation [av v] - (if (map? v) - (doseq [[k v] v] - (add-annotation av (name k) v)) - (add-annotation av "value" v))) - -(defn- add-annotations - ([visitor m] (add-annotations visitor m nil)) - ([visitor m i] - ;; (doseq [[k v] m] - ;; (when (symbol? k) - ;; (when-let [c (resolve k)] - ;; (when (is-annotation? c) - ;; ;this is known duck/reflective as no common base of ASM Visitors - ;; (let [av (if i - ;; (.visitParameterAnnotation visitor i (descriptor c) - ;; (is-runtime-annotation? c)) - ;; (.visitAnnotation visitor (descriptor c) - ;; (is-runtime-annotation? c)))] - ;; (process-annotation av v) - ;; (.visitEnd av)))))) - (throw "TODO: port add-annotations"))) - -(defn bases - "Returns the immediate superclass and direct interfaces of c, if any" - [#_Class c] - ;; (when c - ;; (let [i (seq (.getInterfaces c)) - ;; s (.getSuperclass c)] - ;; (if s (cons s i) i))) - (throw "TODO: port bases")) - -(defn supers - "Returns the immediate and indirect superclasses and interfaces of c, if any" - [#_Class class] - (loop [ret (set (bases class)) cs ret] - (if (seq cs) - (let [c (first cs) bs (bases c)] - (recur (into ret bs) (into (disj cs c) bs))) - (not-empty ret)))) - - -(defn resultset-seq - "Creates and returns a lazy sequence of structmaps corresponding to - the rows in the java.sql.ResultSet rs" - [#_java.sql.ResultSet rs] - ;; (let [rsmeta (. rs (getMetaData)) - ;; idxs (range 1 (inc (. rsmeta (getColumnCount)))) - ;; keys (map (comp keyword #(.toLowerCase ^String %)) - ;; (map (fn [i] (. rsmeta (getColumnLabel i))) idxs)) - ;; check-keys - ;; (or (apply distinct? keys) - ;; (throw (Exception. "ResultSet must have unique column labels"))) - ;; row-struct (apply create-struct keys) - ;; row-values (fn [] (map (fn [^Integer i] (. rs (getObject i))) idxs)) - ;; rows (fn thisfn [] - ;; (when (. rs (next)) - ;; (cons (apply struct row-struct (row-values)) (lazy-seq (thisfn)))))] - ;; (rows)) - (throw "TODO: port resultset-seq")) - -(defn iterator-seq - "Returns a seq on a java.util.Iterator. Note that most collections - providing iterators implement Iterable and thus support seq directly. - Seqs cache values, thus iterator-seq should not be used on any - iterator that repeatedly returns the same mutable object." - [iter] - ;; (clojure.lang.RT/chunkIteratorSeq iter) - (throw "TODO: port iterator-seq")) - -(defn enumeration-seq - "Returns a seq on a java.util.Enumeration" - [e] - ;; (clojure.lang.EnumerationSeq/create e) - (throw "TODO: port enumeration-seq")) - -(defn format - "Formats a string using java.lang.String.format, see java.util.Formatter for format - string syntax" - #_String [fmt & args] - ;; (String/format fmt (to-array args)) - (throw "TODO: port format")) - -(defn printf - "Prints formatted output, as per format" - [fmt & args] - (print (apply format fmt args))) - -(declare gen-class) - -(defmacro with-loading-context [& body] - ;; `((fn loading# [] - ;; (. clojure.lang.Var (pushThreadBindings {clojure.lang.Compiler/LOADER - ;; (.getClassLoader (.getClass ^Object loading#))})) - ;; (try - ;; (do ~@body) - ;; (finally - ;; (. clojure.lang.Var (popThreadBindings)))))) - (throw "TODO: port with-loading-context")) - -(defonce - ^{:private true - :dynamic true - :doc "True while a verbose load is pending"} - *loading-verbosely* false) - -(defn- root-directory - "Returns the root resource path for a lib" - [lib] - ;; (let [d (root-resource lib)] - ;; (subs d 0 (.lastIndexOf d "/"))) - (throw "TODO: port root-resource")) - -(defn- serialized-require - "Like 'require', but serializes loading. - Interim function preferred over 'require' for known asynchronous loads. - Future changes may make these equivalent." - [& args] - ;; (locking clojure.lang.RT/REQUIRE_LOCK - ;; (apply require args)) - (throw "TODO: port serialized-require")) - -(defn requiring-resolve - "Resolves namespace-qualified sym per 'resolve'. If initial resolve -fails, attempts to require sym's namespace and retries." - [sym] - ;; (if (qualified-symbol? sym) - ;; (or (resolve sym) - ;; (do (-> sym namespace symbol serialized-require) - ;; (resolve sym))) - ;; (throw (IllegalArgumentException. (str "Not a qualified symbol: " sym)))) - (throw "TODO: port requiring-resolve")) - -(defn loaded-libs - "Returns a sorted set of symbols naming the currently loaded libs" - [] @*loaded-libs*) - -(defn sorted? - "Returns true if coll implements Sorted" - [coll] - (cpp/jank.runtime.is_sorted coll)) - -(defn counted? - "Returns true if coll implements count in constant time" - [coll] - (cpp/jank.runtime.is_counted coll)) - -(defn reversible? - "Returns true if coll implements Reversible" - [coll] - ;; (instance? clojure.lang.Reversible coll) - (throw "TODO: port reversible?")) - -(defn indexed? - "Return true if coll implements Indexed, indicating efficient lookup by index" - [coll] - ;; (instance? clojure.lang.Indexed coll) - (throw "TODO: port indexed?")) - -(def ^:dynamic - ^{:doc "bound in a repl thread to the most recent value printed"} - *1) - -(def ^:dynamic - ^{:doc "bound in a repl thread to the second most recent value printed"} - *2) - -(def ^:dynamic - ^{:doc "bound in a repl thread to the third most recent value printed"} - *3) - -(def ^:dynamic - ^{:doc "bound in a repl thread to the most recent exception caught by the repl"} - *e) - -(def ^:dynamic - ^{:doc "Bound to true in a repl thread"} - *repl* false) - -(defn trampoline - "trampoline can be used to convert algorithms requiring mutual - recursion without stack consumption. Calls f with supplied args, if - any. If f returns a fn, calls that fn with no arguments, and - continues to repeat, until the return value is not a fn, then - returns that non-fn value. Note that if you want to return a fn as a - final value, you must wrap it in some data structure and unpack it - after trampoline returns." - ([f] - (let [ret (f)] - (if (fn? ret) - (recur ret) - ret))) - ([f & args] - (trampoline #(apply f args)))) - -(defmacro while - "Repeatedly executes body while test expression is true. Presumes - some side-effect will cause test to become false/nil. Returns nil" - [test & body] - `(loop [] - (when ~test - ~@body - (recur)))) - -(defn memoize - "Returns a memoized version of a referentially transparent function. The - memoized version of the function keeps a cache of the mapping from arguments - to results and, when calls with the same arguments are repeated often, has - higher performance at the expense of higher memory use." - [f] - (let [mem (atom {})] - (fn [& args] - (if-let [e (find @mem args)] - (val e) - (let [ret (apply f args)] - (swap! mem assoc args ret) - ret))))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; var documentation ;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defmacro add-doc-and-meta {:private true} [name docstring meta] - `(alter-meta! (var ~name) merge (assoc ~meta :doc ~docstring))) - -;; (add-doc-and-meta *file* -;; "The path of the file being evaluated, as a String. - -;; When there is no file, e.g. in the REPL, the value is not defined." -;; {}) - -;; (add-doc-and-meta *command-line-args* -;; "A sequence of the supplied command line arguments, or nil if -;; none were supplied" -;; {}) - -;; (add-doc-and-meta *warn-on-reflection* -;; "When set to true, the compiler will emit warnings when reflection is -;; needed to resolve Java method calls or field accesses. - -;; Defaults to false." -;; {}) - -;; (add-doc-and-meta *compile-path* -;; "Specifies the directory where 'compile' will write out .class -;; files. This directory must be in the classpath for 'compile' to -;; work. - -;; Defaults to \"classes\"" -;; {}) - -;; (add-doc-and-meta *compile-files* -;; "Set to true when compiling files, false otherwise." -;; {}) - -;; (add-doc-and-meta *unchecked-math* -;; "While bound to true, compilations of +, -, *, inc, dec and the -;; coercions will be done without overflow checks. While bound -;; to :warn-on-boxed, same behavior as true, and a warning is emitted -;; when compilation uses boxed math. Default: false." -;; {}) - -;; (add-doc-and-meta *compiler-options* -;; "A map of keys to options. -;; Note, when binding dynamically make sure to merge with previous value. -;; Supported options: -;; :elide-meta - a collection of metadata keys to elide during compilation. -;; :disable-locals-clearing - set to true to disable clearing, useful for using a debugger -;; :direct-linking - set to true to use direct static invocation of functions, rather than vars -;; Note that call sites compiled with direct linking will not be affected by var redefinition. -;; Use ^:redef (or ^:dynamic) on a var to prevent direct linking and allow redefinition. -;; See https://clojure.org/reference/compilation for more information." -;; {}) - -;; (add-doc-and-meta *in* -;; "A java.io.Reader object representing standard input for read operations. - -;; Defaults to System/in, wrapped in a LineNumberingPushbackReader" -;; {}) - -;; (add-doc-and-meta *err* -;; "A java.io.Writer object representing standard error for print operations. - -;; Defaults to System/err, wrapped in a PrintWriter" -;; {}) - -;; (add-doc-and-meta *flush-on-newline* -;; "When set to true, output will be flushed whenever a newline is printed. - -;; Defaults to true." -;; {}) - -;; (add-doc-and-meta *print-meta* -;; "If set to logical true, when printing an object, its metadata will also -;; be printed in a form that can be read back by the reader. - -;; Defaults to false." -;; {}) - -;; (add-doc-and-meta *print-dup* -;; "When set to logical true, objects will be printed in a way that preserves -;; their type when read in later. - -;; Defaults to false." -;; {}) - -;; (add-doc-and-meta *print-readably* -;; "When set to logical false, strings and characters will be printed with -;; non-alphanumeric characters converted to the appropriate escape sequences. - -;; Defaults to true" -;; {}) - -;; (add-doc-and-meta *read-eval* -;; "Defaults to true (or value specified by system property, see below) -;; ***This setting implies that the full power of the reader is in play, -;; including syntax that can cause code to execute. It should never be -;; used with untrusted sources. See also: clojure.edn/read.*** - -;; When set to logical false in the thread-local binding, -;; the eval reader (#=) and record/type literal syntax are disabled in read/load. -;; Example (will fail): (binding [*read-eval* false] (read-string \"#=(* 2 21)\")) - -;; The default binding can be controlled by the system property -;; 'clojure.read.eval' System properties can be set on the command line -;; like this: - -;; java -Dclojure.read.eval=false ... - -;; The system property can also be set to 'unknown' via -;; -Dclojure.read.eval=unknown, in which case the default binding -;; is :unknown and all reads will fail in contexts where *read-eval* -;; has not been explicitly bound to either true or false. This setting -;; can be a useful diagnostic tool to ensure that all of your reads -;; occur in considered contexts. You can also accomplish this in a -;; particular scope by binding *read-eval* to :unknown -;; " -;; {}) - -;; (add-doc-and-meta *assert* -;; "When set to logical false, 'assert' will omit assertion checks in -;; compiled code. Defaults to true." -;; {}) - -(defn future? - "Returns true if x is a future" - [x] - ;; (instance? java.util.concurrent.Future x) - (throw "TODO: port future?")) - -(defn future-done? - "Returns true if future f is done" - [#_java.util.concurrent.Future f] - ;; (.isDone f) - (throw "TODO: port future-done?")) - -(defmacro letfn - "fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+) - - Takes a vector of function specs and a body, and generates a set of - bindings of functions to their names. All of the names are available - in all of the definitions of the functions, as well as the body." - {:forms '[(letfn [fnspecs*] exprs*)], - :special-form true} - [fnspecs & body] - `(letfn* ~(vec (interleave (map first fnspecs) - (map #(cons `fn %) fnspecs))) - ~@body)) - -(defn stream-reduce! - "Works like reduce but takes a java.util.stream.BaseStream as its source. - Honors 'reduced', is a terminal operation on the stream" - ([f #_java.util.stream.BaseStream s] - ;; (clojure.core.protocols/iterator-reduce! (.iterator s) f) - (throw "TODO: port stream-reduce!")) - ([f init #_java.util.stream.BaseStream s] - ;; (clojure.core.protocols/iterator-reduce! (.iterator s) f init) - (throw "TODO: port stream-reduce!"))) - -(defn stream-seq! - "Takes a java.util.stream.BaseStream instance s and returns a seq of its - contents. This is a terminal operation on the stream." - [#_java.util.stream.BaseStream stream] - ;; (iterator-seq (.iterator stream)) - (throw "TODO: port stream-seq!")) - -(defn stream-transduce! - "Works like transduce but takes a java.util.stream.BaseStream as its source. - This is a terminal operation on the stream." - ([xform f #_java.util.stream.BaseStream stream] - (stream-transduce! xform f (f) stream)) - ([xform f init #_java.util.stream.BaseStream stream] - (let [f (xform f) - ret (stream-reduce! f init stream)] - (f ret)))) - -(defn stream-into! - "Returns a new coll consisting of coll with all of the items of the - stream conjoined. This is a terminal operation on the stream." - ([to #_java.util.stream.BaseStream stream] - ;; (if (instance? clojure.lang.IEditableCollection to) - ;; (with-meta (persistent! (stream-reduce! conj! (transient to) stream)) (meta to)) - ;; (stream-reduce! conj to stream)) - (throw "TODO: port stream-into!")) - ([to xform #_java.util.stream.BaseStream stream] - ;; (if (instance? clojure.lang.IEditableCollection to) - ;; (with-meta (persistent! (stream-transduce! xform conj! (transient to) stream)) (meta to)) - ;; (stream-transduce! xform conj to stream)) - (throw "TODO: port stream-into!"))) - - -(defmacro ^:private when-class [class-name & body] - ;; `(try - ;; (Class/forName ^String ~class-name) - ;; ~@body - ;; (catch ClassNotFoundException _#)) - (throw "TODO: port when-class")) - -;; (defprotocol Inst -;; (inst-ms* [inst])) - -;; (extend-protocol Inst -;; java.util.Date -;; (inst-ms* [inst] (.getTime ^java.util.Date inst))) - -(defn inst-ms - "Return the number of milliseconds since January 1, 1970, 00:00:00 GMT" - [inst] - (cpp/jank.runtime.inst_ms inst)) - -(defn inst? - "Return true if x satisfies Inst" - [x] - (cpp/jank.runtime.is_inst x)) - -;; (extend-protocol clojure.core/Inst -;; java.time.Instant -;; (inst-ms* [inst] (.toEpochMilli ^java.time.Instant inst))) - -(defn uuid? - "Return true if x is a java.util.UUID" - [x] - (cpp/jank.runtime.is_uuid x)) - -(defn random-uuid - "Returns a pseudo-randomly generated java.util.UUID instance (i.e. type 4). - - See: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID--" - [] - (cpp/jank.runtime.random_uuid)) - -;; (extend-protocol clojure.core.protocols/IKVReduce -;; nil -;; (kv-reduce -;; [_ f init] -;; init) - -;; ;;slow path default -;; java.lang.Object -;; (kv-reduce -;; [amap f init] -;; (reduce (fn [ret ^java.util.Map$Entry me] -;; (f ret -;; (.getKey me) -;; (.getValue me))) -;; init -;; amap)) - -;; clojure.lang.IKVReduce -;; (kv-reduce -;; [amap f init] -;; (.kvreduce amap f init))) - -(defn reduce-kv - "Reduces an associative collection. f should be a function of 3 - arguments. Returns the result of applying f to init, the first key - and the first value in coll, then applying f to that result and the - 2nd key and value, etc. If coll contains no entries, returns init - and f is not called. Note that reduce-kv is supported on vectors, - where the keys will be the ordinals." - ([f init coll] - ;; (clojure.core.protocols/kv-reduce coll f init) - (reduce (fn [s [k v]] (f s k v)) init coll))) - -(defn- normalize-slurp-opts - [opts] - (if (string? (first opts)) - (do - (println "WARNING: (slurp f enc) is deprecated, use (slurp f :encoding enc).") - [:encoding (first opts)]) - opts)) - -(defn slurp - "Opens a reader on f and reads all its contents, returning a string. - See clojure.java.io/reader for a complete list of supported arguments." - ([f & opts] - (let [opts (normalize-slurp-opts opts) - fname (cpp/cast (cpp/type "char const*") f) - file (cpp/std.ifstream. fname)] - (if-not (cpp/.is_open file) - (throw (str f " (No such file or directory)")) - (let [size (cpp/std.filesystem.file_size fname) - out (cpp/std.string. size (cpp/char 0))] - (cpp/.read file (cpp/& (cpp/.front out)) size) - out))))) - -(defn spit - "Opposite of slurp. Opens f with writer, writes content, then - closes f. Options passed to clojure.java.io/writer." - [f content & options] - (let [file (cpp/std.ofstream.)] - (cpp/.open file (cpp/cast (cpp/type "char const*") f)) - (cpp/<< file (cpp/cast (cpp/type "char const*") content)) - (cpp/.close file) - nil)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; futures (needs proxy);;;;;;;;;;;;;;;;;; -(defn future-call - "Takes a function of no args and yields a future object that will - invoke the function in another thread, and will cache the result and - return it on all subsequent calls to deref/@. If the computation has - not yet finished, calls to deref/@ will block, unless the variant - of deref with timeout is used. See also - realized?." - [f] - ;; (let [f (binding-conveyor-fn f) - ;; fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)] - ;; (reify - ;; clojure.lang.IDeref - ;; (deref [_] (deref-future fut)) - ;; clojure.lang.IBlockingDeref - ;; (deref - ;; [_ timeout-ms timeout-val] - ;; (deref-future fut timeout-ms timeout-val)) - ;; clojure.lang.IPending - ;; (isRealized [_] (.isDone fut)) - ;; java.util.concurrent.Future - ;; (get [_] (.get fut)) - ;; (get [_ timeout unit] (.get fut timeout unit)) - ;; (isCancelled [_] (.isCancelled fut)) - ;; (isDone [_] (.isDone fut)) - ;; (cancel [_ interrupt?] (.cancel fut interrupt?)))) - (throw "TODO: port future-call")) - -(defmacro future - "Takes a body of expressions and yields a future object that will - invoke the body in another thread, and will cache the result and - return it on all subsequent calls to deref/@. If the computation has - not yet finished, calls to deref/@ will block, unless the variant of - deref with timeout is used. See also - realized?." - [& body] - ;; `(future-call (^{:once true} fn* [] ~@body)) - (throw "TODO: port future")) - -(defn future-cancel - "Cancels the future, if possible." - [#_java.util.concurrent.Future f] - ;; (.cancel f true) - (throw "TODO: port future-cancel")) - -(defn future-cancelled? - "Returns true if future f is cancelled" - [#_java.util.concurrent.Future f] - ;; (.isCancelled f) - (throw "TODO: port future-cancelled?")) - -(defn pmap - "Like map, except f is applied in parallel. Semi-lazy in that the - parallel computation stays ahead of the consumption, but doesn't - realize the entire result unless required. Only useful for - computationally intensive functions where the time of f dominates - the coordination overhead." - ([f coll] - ;; (let [n (+ 2 (.. Runtime getRuntime availableProcessors)) - ;; rets (map #(future (f %)) coll) - ;; step (fn step [[x & xs :as vs] fs] - ;; (lazy-seq - ;; (if-let [s (seq fs)] - ;; (cons (deref x) (step xs (rest s))) - ;; (map deref vs))))] - ;; (step rets (drop n rets))) - (throw "TODO: port pmap")) - ([f coll & colls] - ;; (let [step (fn step [cs] - ;; (lazy-seq - ;; (let [ss (map seq cs)] - ;; (when (every? identity ss) - ;; (cons (map first ss) (step (map rest ss)))))))] - ;; (pmap #(apply f %) (step (cons coll colls)))) - (throw "TODO: port pmap"))) - - -(defn pcalls - "Executes the no-arg fns in parallel, returning a lazy sequence of - their values" - [& fns] (pmap #(%) fns)) - -(defmacro pvalues - "Returns a lazy sequence of the values of the exprs, which are - evaluated in parallel" - [& exprs] - `(pcalls ~@(map #(list `fn [] %) exprs))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; clojure version number ;;;;;;;;;;;;;;;;;;;;;; - -;; (let [^java.util.Properties -;; properties (with-open [version-stream (.getResourceAsStream -;; (clojure.lang.RT/baseLoader) -;; "clojure/version.properties")] -;; (doto (new java.util.Properties) -;; (.load version-stream))) -;; version-string (.getProperty properties "version") -;; [_ major minor incremental qualifier snapshot] -;; (re-matches -;; #"(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9_]+))?(?:-(SNAPSHOT))?" -;; version-string) -;; clojure-version {:major (Integer/valueOf ^String major) -;; :minor (Integer/valueOf ^String minor) -;; :incremental (Integer/valueOf ^String incremental) -;; :qualifier (if (= qualifier "SNAPSHOT") nil qualifier)}] -;; (def ^:dynamic *clojure-version* -;; (if (.contains version-string "SNAPSHOT") -;; (clojure.lang.RT/assoc clojure-version :interim true) -;; clojure-version))) - -;; (add-doc-and-meta *clojure-version* -;; "The version info for Clojure core, as a map containing :major :minor -;; :incremental and :qualifier keys. Feature releases may increment -;; :minor and/or :major, bugfix releases will increment :incremental. -;; Possible values of :qualifier include \"GA\", \"SNAPSHOT\", \"RC-x\" \"BETA-x\"" -;; {:added "1.0"}) - -(defn clojure-version - "Returns clojure version as a printable string." - [] - (cpp/clojure.core_native.jank_version)) - -(defn promise - "Returns a promise object that can be read with deref/@, and set, - once only, with deliver. Calls to deref/@ prior to delivery will - block, unless the variant of deref with timeout is used. All - subsequent derefs will return the same delivered value without - blocking. See also - realized?." - [] - ;; (let [d (java.util.concurrent.CountDownLatch. 1) - ;; v (atom d)] - ;; (reify - ;; clojure.lang.IDeref - ;; (deref [_] (.await d) @v) - ;; clojure.lang.IBlockingDeref - ;; (deref - ;; [_ timeout-ms timeout-val] - ;; (if (.await d timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS) - ;; @v - ;; timeout-val)) - ;; clojure.lang.IPending - ;; (isRealized [this] - ;; (zero? (.getCount d))) - ;; clojure.lang.IFn - ;; (invoke - ;; [this x] - ;; (when (and (pos? (.getCount d)) - ;; (compare-and-set! v d x)) - ;; (.countDown d) - ;; this)))) - (throw "TODO: port promise")) - -(defn deliver - "Delivers the supplied value to the promise, releasing any pending - derefs. A subsequent call to deliver on a promise will have no effect." - [promise val] (promise val)) - -(defn rand-nth - "Return a random element of the (sequential) collection. Will have - the same performance characteristics as nth for the given - collection." - [coll] - (nth coll (rand-int (count coll)))) - -(defn splitv-at - "Returns a vector of [(into [] (take n) coll) (drop n coll)]" - [n coll] - [(into [] (take n) coll) (drop n coll)]) - -(defn partitionv - "Returns a lazy sequence of vectors of n items each, at offsets step - apart. If step is not supplied, defaults to n, i.e. the partitions - do not overlap. If a pad collection is supplied, use its elements as - necessary to complete last partition upto n items. In case there are - not enough padding elements, return a partition with less than n items." - ([n coll] - (partitionv n n coll)) - ([n step coll] - (lazy-seq - (when-let [s (seq coll)] - (let [p (into [] (take n) s)] - (when (= n (count p)) - (cons p (partitionv n step (nthrest s step)))))))) - ([n step pad coll] - (lazy-seq - (when-let [s (seq coll)] - (let [p (into [] (take n) s)] - (if (= n (count p)) - (cons p (partitionv n step pad (nthrest s step))) - (list (into [] (take n) (concat p pad))))))))) - -(defn partitionv-all - "Returns a lazy sequence of vector partitions, but may include - partitions with fewer than n items at the end. - Returns a stateful transducer when no collection is provided." - ([n] - (partition-all n)) - ([n coll] - (partitionv-all n n coll)) - ([n step coll] - (lazy-seq - (when-let [s (seq coll)] - (let [seg (into [] (take n) coll)] - (cons seg (partitionv-all n step (drop step s)))))))) - -(defn shuffle - "Return a random permutation of coll" - [coll] - (cpp/jank.runtime.shuffle coll)) - -(defn bounded-count - "If coll is counted? returns its count, else will count at most the first n - elements of coll using its seq" - [n coll] - (if (counted? coll) - (count coll) - (loop [i 0 s (seq coll)] - (if (and s (< i n)) - (recur (inc i) (next s)) - i)))) - -(defn bounded-count - "If coll is counted? returns its count, else will count at most the first n - elements of coll using its seq" - [n coll] - (if (counted? coll) - (count coll) - (loop [i 0 s (seq coll)] - (if (and s (< i n)) - (recur (inc i) (next s)) - i)))) - -(defn- ^{:dynamic true} assert-valid-fdecl - "A good fdecl looks like (([a] ...) ([a b] ...)) near the end of defn." - [fdecl] - (when (empty? fdecl) (throw "Parameter declaration missing")) - (let [argdecls (map - #(if (seq? %) - (first %) - (throw (if (seq? (first fdecl)) - (str "Invalid signature \"" - % - "\" should be a list") - (str "Parameter declaration \"" - % - "\" should be a vector")))) - fdecl) - bad-args (seq (remove #(vector? %) argdecls))] - (when bad-args - (throw (str "Parameter declaration \"" (first bad-args) - "\" should be a vector"))))) - -(defn realized? - "Returns true if a value has been produced for a promise, delay, future or lazy sequence." - [#_clojure.lang.IPending x] - ;; (.isRealized x) - (throw "TODO: port realized?")) - -(defn random-sample - "Returns items from coll with random probability of prob (0.0 - - 1.0). Returns a transducer when no collection is provided." - ([prob] - (filter (fn [_] (< (rand) prob)))) - ([prob coll] - (filter (fn [_] (< (rand) prob)) coll))) - -;; (deftype Eduction [xform coll] -;; Iterable -;; (iterator [_] -;; (clojure.lang.TransformerIterator/create xform (clojure.lang.RT/iter coll))) - -;; clojure.lang.IReduceInit -;; (reduce [_ f init] -;; ;; NB (completing f) isolates completion of inner rf from outer rf -;; (transduce xform (completing f) init coll)) - -;; clojure.lang.Sequential) - -;; (defn eduction -;; "Returns a reducible/iterable application of the transducers -;; to the items in coll. Transducers are applied in order as if -;; combined with comp. Note that these applications will be -;; performed every time reduce/iterator is called." -;; [& xforms] -;; (Eduction. (apply comp (butlast xforms)) (last xforms))) - -;; (defmethod print-method Eduction [c, ^Writer w] -;; (if *print-readably* -;; (do -;; (print-sequential "(" pr-on " " ")" c w)) -;; (print-object c w))) - -(defn iteration - "Creates a seqable/reducible via repeated calls to step, - a function of some (continuation token) 'k'. The first call to step - will be passed initk, returning 'ret'. Iff (somef ret) is true, - (vf ret) will be included in the iteration, else iteration will - terminate and vf/kf will not be called. If (kf ret) is non-nil it - will be passed to the next step call, else iteration will terminate. - - This can be used e.g. to consume APIs that return paginated or batched data. - - step - (possibly impure) fn of 'k' -> 'ret' - - :somef - fn of 'ret' -> logical true/false, default 'some?' - :vf - fn of 'ret' -> 'v', a value produced by the iteration, default 'identity' - :kf - fn of 'ret' -> 'next-k' or nil (signaling 'do not continue'), default 'identity' - :initk - the first value passed to step, default 'nil' - - It is presumed that step with non-initk is unreproducible/non-idempotent. - If step with initk is unreproducible it is on the consumer to not consume twice." - [step & {:keys [somef vf kf initk] - :or {vf identity - kf identity - somef some? - initk nil}}] - ;; (reify - ;; clojure.lang.Seqable - ;; (seq [_] - ;; ((fn next [ret] - ;; (when (somef ret) - ;; (cons (vf ret) - ;; (when-some [k (kf ret)] - ;; (lazy-seq (next (step k))))))) - ;; (step initk))) - ;; clojure.lang.IReduceInit - ;; (reduce [_ rf init] - ;; (loop [acc init - ;; ret (step initk)] - ;; (if (somef ret) - ;; (let [acc (rf acc (vf ret))] - ;; (if (reduced? acc) - ;; @acc - ;; (if-some [k (kf ret)] - ;; (recur acc (step k)) - ;; acc))) - ;; acc)))) - (throw "TODO: port iteration")) - -(defn tagged-literal? - "Return true if the value is the data representation of a tagged literal" - [value] - (cpp/jank.runtime.is_tagged_literal value)) - -(defn tagged-literal - "Construct a data representation of a tagged literal from a - tag symbol and a form." - [tag form] - (cpp/jank.runtime.tagged_literal tag form)) - -(defn reader-conditional? - "Return true if the value is the data representation of a reader conditional" - [value] - ;; (instance? clojure.lang.ReaderConditional value) - (throw "TODO: port reader-conditional?")) - -(defn reader-conditional - "Construct a data representation of a reader conditional. - If true, splicing? indicates read-cond-splicing." - [form #_Boolean splicing?] - ;; (clojure.lang.ReaderConditional/create form splicing?) - (throw "TODO: port reader-conditional")) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; data readers ;;;;;;;;;;;;;;;;;; - -(def default-data-readers - "Default map of data reader functions provided by Clojure. May be - overridden by binding *data-readers*." - (merge - ;; {'uuid #'clojure.uuid/default-uuid-reader} - ;; (when-class "java.sql.Timestamp" - ;; {'inst #'clojure.instant/read-instant-date}) - )) - -(def ^:dynamic *data-readers* - "Map from reader tag symbols to data reader Vars. - - When Clojure starts, it searches for files named 'data_readers.clj' - and 'data_readers.cljc' at the root of the classpath. Each such file - must contain a literal map of symbols, like this: - - {foo/bar my.project.foo/bar - foo/baz my.project/baz} - - The first symbol in each pair is a tag that will be recognized by - the Clojure reader. The second symbol in the pair is the - fully-qualified name of a Var which will be invoked by the reader to - parse the form following the tag. For example, given the - data_readers.clj file above, the Clojure reader would parse this - form: - - #foo/bar [1 2 3] - - by invoking the Var #'my.project.foo/bar on the vector [1 2 3]. The - data reader function is invoked on the form AFTER it has been read - as a normal Clojure data structure by the reader. - - Reader tags without namespace qualifiers are reserved for - Clojure. Default reader tags are defined in - clojure.core/default-data-readers but may be overridden in - data_readers.clj, data_readers.cljc, or by rebinding this Var." - {}) - -(def ^:dynamic *default-data-reader-fn* - "When no data reader is found for a tag and *default-data-reader-fn* - is non-nil, it will be called with two arguments, - the tag and the value. If *default-data-reader-fn* is nil (the - default), an exception will be thrown for the unknown tag." - nil) - -(defn- data-reader-urls [] - ;; (let [cl (.. Thread currentThread getContextClassLoader)] - ;; (concat - ;; (enumeration-seq (.getResources cl "data_readers.clj")) - ;; (enumeration-seq (.getResources cl "data_readers.cljc")))) - (throw "TODO: port data-reader-urls")) - -(defn- data-reader-var [sym] - (intern (create-ns (symbol (namespace sym))) - (symbol (name sym)))) - -(defn- load-data-reader-file [mappings #_java.net.URL url] - ;; (with-open [rdr (clojure.lang.LineNumberingPushbackReader. - ;; (java.io.InputStreamReader. - ;; (.openStream url) "UTF-8"))] - ;; (binding [*file* (.getFile url)] - ;; (let [read-opts (if (.endsWith (.getPath url) "cljc") - ;; {:eof nil :read-cond :allow} - ;; {:eof nil}) - ;; new-mappings (read read-opts rdr)] - ;; (when (not (map? new-mappings)) - ;; (throw (ex-info (str "Not a valid data-reader map") - ;; {:url url}))) - ;; (reduce - ;; (fn [m [k v]] - ;; (when (not (symbol? k)) - ;; (throw (ex-info (str "Invalid form in data-reader file") - ;; {:url url - ;; :form k}))) - ;; (let [v-var (data-reader-var v)] - ;; (when (and (contains? mappings k) - ;; (not= (mappings k) v-var)) - ;; (throw (ex-info "Conflicting data-reader mapping" - ;; {:url url - ;; :conflict k - ;; :mappings m}))) - ;; (assoc m k v-var))) - ;; mappings - ;; new-mappings)))) - (throw "TODO: port load-data-reader-file")) - -(defn- load-data-readers [] - ;; (alter-var-root #'*data-readers* - ;; (fn [mappings] - ;; (reduce load-data-reader-file - ;; mappings (data-reader-urls)))) - (throw "TODO: port load-data-readers")) - -;; (try -;; (load-data-readers) -;; (catch #_Throwable t -;; (.printStackTrace t) -;; (throw t))) - -(defonce ^:private tapset (atom #{})) - -;; (defonce ^:private ^java.util.concurrent.ArrayBlockingQueue tapq (java.util.concurrent.ArrayBlockingQueue. 1024)) - -(defonce ^:private tap-loop - ;; (delay - ;; (doto (Thread. - ;; #(let [t (.take tapq) - ;; x (if (identical? ::tap-nil t) nil t) - ;; taps @tapset] - ;; (doseq [tap taps] - ;; (try - ;; (tap x) - ;; (catch Throwable ex))) - ;; (recur)) - ;; "clojure.core/tap-loop") - ;; (.setDaemon true) - ;; (.start))) - nil) - -(defn add-tap - "adds f, a fn of one argument, to the tap set. This function will be called with anything sent via tap>. - This function may (briefly) block (e.g. for streams), and will never impede calls to tap>, - but blocking indefinitely may cause tap values to be dropped. - Remember f in order to remove-tap" - [f] - (force tap-loop) - (swap! tapset conj f) - nil) - -(defn remove-tap - "Remove f from the tap set." - [f] - (swap! tapset disj f) - nil) - -(defn tap> - "sends x to any taps. Will not block. Returns true if there was room in the queue, - false if not (dropped)." - [x] - (force tap-loop) - ;; (.offer tapq (if (nil? x) ::tap-nil x)) - (throw "TODO: port tap>")) - -(defn update-vals - "m f => {k (f v) ...} - - Given a map m and a function f of 1-argument, returns a new map where the keys of m - are mapped to result of applying f to the corresponding values of m." - [m f] - (with-meta - (persistent! - (reduce-kv (fn [acc k v] (assoc! acc k (f v))) - (if (transientable? m) - (transient m) - (transient {})) - m)) - (meta m))) - -(defn update-keys - "m f => {(f k) v ...} - - Given a map m and a function f of 1-argument, returns a new map whose - keys are the result of applying f to the keys of m, mapped to the - corresponding values of m. - f must return a unique key for each key of m, else the behavior is undefined." - [m f] - (let [ret (persistent! - (reduce-kv (fn [acc k v] (assoc! acc (f k) v)) - (transient {}) - m))] - (with-meta ret (meta m)))) - -(defn- parsing-err - "Construct message for parsing for non-string parsing error" - [val] - (str "Expected string, got " (if (nil? val) "nil" (type val)))) - -(defn parse-long - "Parse string of decimal digits with optional leading -/+ and return a - Long value, or nil if parse fails" - [s] - (cpp/jank.runtime.parse_long s)) - -(defn parse-double - "Parse string with floating point components and return a Double value, - or nil if parse fails. - - Grammar: https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#valueOf-java.lang.String-" - [s] - (cpp/jank.runtime.parse_double s)) - -(defn parse-uuid - "Parse a string representing a UUID and return a java.util.UUID instance, - or nil if parse fails. - - Grammar: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#toString--" - [s] - (cpp/jank.runtime.parse_uuid s)) - -(defn parse-boolean - "Parse strings \"true\" or \"false\" and return a boolean, or nil if invalid" - [s] - (if (string? s) - (case s - "true" true - "false" false - nil) - (throw (parsing-err s)))) - -(defn NaN? - "Returns true if num is NaN, else false" - [num] - (cpp/jank.runtime.is_nan num)) - -(defn infinite? - "Returns true if num is negative or positive infinity, else false" - [num] - (cpp/jank.runtime.is_infinite num)) +;;; Transients. +;(defn- transientable? +; "Returns a whether the collection can be made transient." +; [coll] +; (cpp/jank.runtime.is_transientable coll)) +; +;(defn transient +; "Returns a new, transient version of the collection, in constant time." +; [coll] +; (cpp/jank.runtime.transient coll)) +; +;(defn persistent! +; "Returns a new, persistent version of the transient collection, in +; constant time. The transient collection cannot be used after this +; call, any such use will throw an exception." +; [coll] +; (cpp/jank.runtime.persistent coll)) +; +;(defn conj! +; "Adds x to the transient collection, and return coll. The 'addition' +; may happen at different 'places' depending on the concrete type." +; ([] +; (transient [])) +; ([coll] +; coll) +; ([coll x] +; (cpp/jank.runtime.conj_in_place coll x))) +; +;(defn assoc! +; "When applied to a transient map, adds mapping of key(s) to +; val(s). When applied to a transient vector, sets the val at index. +; Note - index must be <= (count vector). Returns coll." +; ([coll k v] +; (cpp/jank.runtime.assoc_in_place coll k v)) +; ([coll k v & kvs] +; (let [ret (assoc! coll k v)] +; (if kvs +; (recur ret (first kvs) (second kvs) (nnext kvs)) +; ret)))) +; +;(defn dissoc! +; "Returns a transient map that doesn't contain a mapping for key(s)." +; ([coll k] +; (cpp/jank.runtime.dissoc_in_place coll k)) +; ([coll k & ks] +; (let [ret (dissoc! coll k)] +; (if ks +; (recur ret (first ks) (next ks)) +; ret)))) +; +;(defn pop! +; "Removes the last item from a transient vector. If +; the collection is empty, throws an exception. Returns coll" +; [coll] +; (cpp/jank.runtime.pop_in_place coll)) +; +;(defn disj! +; "disj[oin]. Returns a transient set of the same (hashed/sorted) type, that +; does not contain key(s)." +; ([set] set) +; ([set elem] +; (cpp/jank.runtime.dissoc_in_place set elem)) +; ([set elem & elems] +; (let [ret (disj! set elem)] +; (if elems +; (recur ret (first elems) (next elems)) +; ret)))) +; +;;; Functions. +;(defn- spread +; [arglist] +; (cond +; (nil? arglist) nil +; (nil? (next arglist)) (seq (first arglist)) +; :else (cons (first arglist) (spread (next arglist))))) +; +;(defn list* +; "Creates a new seq containing the items prepended to the rest, the +; last of which will be treated as a sequence." +; ([args] +; (seq args)) +; ([a args] +; (cons a args)) +; ([a b args] +; (cons a (cons b args))) +; ([a b c args] +; (cons a (cons b (cons c args)))) +; ([a b c d & more] +; (cons a (cons b (cons c (cons d (spread more))))))) +; +;(defn apply +; "Applies fn f to the argument list formed by prepending intervening arguments to args." +; ([f args] +; (cpp/jank.runtime.apply_to f args)) +; ([f x args] +; (cpp/jank.runtime.apply_to f (list* x args))) +; ([f x y args] +; (cpp/jank.runtime.apply_to f (list* x y args))) +; ([f x y z args] +; (cpp/jank.runtime.apply_to f (list* x y z args))) +; ([f a b c d & args] +; (cpp/jank.runtime.apply_to f (cons a (cons b (cons c (cons d (spread args)))))))) +; +;(defn constantly +; "Returns a function that takes any number of arguments and returns x." +; [x] +; (fn [& args] +; x)) +; +;(defn identity +; "Returns its argument." +; [x] +; x) +; +;(defn complement +; "Takes a fn f and returns a fn that takes the same arguments as f, +; has the same effects, if any, and returns the opposite truth value." +; [f] +; (fn +; ([] (not (f))) +; ([x] (not (f x))) +; ([x y] (not (f x y))) +; ([x y & zs] (not (apply f x y zs))))) +; +;; Utils. +;(defn deref +; "Also reader macro: @ref/@agent/@var/@atom/@delay/@future/@promise. Within a transaction, +; returns the in-transaction-value of ref, else returns the +; most-recently-committed value of ref. When applied to a var, agent +; or atom, returns its current state. When applied to a delay, forces +; it if not already forced. When applied to a future, will block if +; computation not complete. When applied to a promise, will block +; until a value is delivered. The variant taking a timeout can be +; used for blocking references (futures and promises), and will return +; timeout-val if the timeout (in milliseconds) is reached before a +; value is available. See also - realized?." +; ([ref] +; (cpp/jank.runtime.deref ref)) +; ; TODO: Blocking. +; ([ref timeout-ms timeout-val] +; ;(if (instance? clojure.lang.IBlockingDeref ref) +; ; (.deref ^clojure.lang.IBlockingDeref ref timeout-ms timeout-val) +; ; (deref-future ref timeout-ms timeout-val)) +; )) +; +;(defn reduced +; "Wraps x in a way such that a reduce will terminate with the value x" +; [x] +; (cpp/jank.runtime.reduced x)) +; +;(defn reduced? +; "Returns true if x is the result of a call to reduced" +; [x] +; (cpp/jank.runtime.is_reduced x)) +; +;(defn ensure-reduced +; "If x is already reduced?, returns it, else returns (reduced x)" +; [x] +; (if (reduced? x) +; x +; (reduced x))) +; +;(defn unreduced +; "If x is reduced?, returns (deref x), else returns x" +; [x] +; (if (reduced? x) +; (deref x) +; x)) +; +;(defn reduce +; "f should be a function of 2 arguments. If val is not supplied, +; returns the result of applying f to the first 2 items in coll, then +; applying f to that result and the 3rd item, etc. If coll contains no +; items, f must accept no arguments as well, and reduce returns the +; result of calling f with no arguments. If coll has only 1 item, it +; is returned and f is not called. If val is supplied, returns the +; result of applying f to val and the first item in coll, then +; applying f to that result and the 2nd item, etc. If coll contains no +; items, returns val and f is not called." +; ([f coll] +; (let [s (seq coll)] +; (if s +; (reduce f (first s) (next s)) +; (f)))) +; ([f init coll] +; ; TODO: Chunking support. +; (cpp/jank.runtime.reduce f init coll))) +; +;(defn completing +; "Takes a reducing function f of 2 args and returns a fn suitable for +; transduce by adding an arity-1 signature that calls cf (default - +; identity) on the result argument." +; ([f] (completing f identity)) +; ([f cf] +; (fn +; ([] (f)) +; ([x] (cf x)) +; ([x y] (f x y))))) +; +;(defn transduce +; "reduce with a transformation of rf (xf). If init is not +; supplied, (rf) will be called to produce it. f should be a reducing +; step function that accepts both 1 and 2 arguments, if it accepts +; only 2 you can add the arity-1 with 'completing'. Returns the result +; of applying (the transformed) xf to init and the first item in coll, +; then applying xf to that result and the 2nd item, etc. If coll +; contains no items, returns init and rf is not called. Note that +; certain transforms may inject or skip items." +; ([xform rf coll] +; (transduce xform rf (rf) coll)) +; ([xform rf init coll] +; (let [f (xform rf) +; ret (reduce f init coll)] +; (f ret)))) +; +;;; TODO: private +;(defn preserving-reduced +; [rf] +; #(let [ret (rf %1 %2)] +; (if (reduced? ret) +; (reduced ret) +; ret))) +; +;(defn cat +; "A transducer which concatenates the contents of each input, which must be a +; collection, into the reduction." +; [rf] +; (let [rrf (preserving-reduced rf)] +; (fn +; ([] (rf)) +; ([result] (rf result)) +; ([result input] +; (reduce rrf result input))))) +; +;(defn run! +; "Runs the supplied procedure (via reduce), for purposes of side +; effects, on successive items in the collection. Returns nil" +; [proc coll] +; (reduce #(proc %2) nil coll) +; nil) +; +;(defn comp +; "Takes a set of functions and returns a fn that is the composition +; of those fns. The returned fn takes a variable number of args, +; applies the rightmost of fns to the args, the next +; fn (right-to-left) to the result, etc." +; ([] identity) +; ([f] f) +; ([f g] +; (let [a 1] (fn +; ([] (f (g))) +; ([x] (f (g x))) +; ([x y] (f (g x y))) +; ([x y z] (f (g x y z))) +; ([x y z & args] (f (apply g x y z args)))))) +; ([f g & fs] +; (reduce comp (list* f g fs)))) +; +;(defn peek +; "For a list or queue, same as first, for a vector, same as, but much +; more efficient than, last. If the collection is empty, returns nil." +; [coll] +; (cpp/jank.runtime.peek coll)) +; +;(defn pop +; "For a list or queue, returns a new list/queue without the first +; item, for a vector, returns a new vector without the last item. If +; the collection is empty, throws an exception. Note - not the same +; as next/butlast." +; [coll] +; (cpp/jank.runtime.pop coll)) +; +;(defn vary-meta +; "Returns an object of the same type and value as obj, with +; (apply f (meta obj) args) as its metadata." +; [o f & args] +; (with-meta o (apply f (meta o) args))) +; +;(defn alter-meta! +; "Atomically sets the metadata for a namespace/var/ref/agent/atom to be: +; +; (apply f its-current-meta args) +; +; f must be free of side-effects" +; [o f & args] +; ; TODO: Atomics. +; (reset-meta! o (apply f (meta o) args))) +; +;;; Atoms. +;(defn atom +; "Creates and returns an Atom with an initial value of x and zero or +; more options (in any order): +; +; :meta metadata-map +; +; :validator validate-fn +; +; If metadata-map is supplied, it will become the metadata on the +; atom. validate-fn must be nil or a side-effect-free fn of one +; argument, which will be passed the intended new state on any state +; change. If the new state is unacceptable, the validate-fn should +; return false or throw an exception." +; ([x] +; (cpp/jank.runtime.atom x)) +; ; TODO: Validators. +; #_([x & options] +; (setup-reference (atom x) options))) +; +;(defn swap! +; "Atomically swaps the value of atom to be: +; (apply f current-value-of-atom args). Note that f may be called +; multiple times, and thus should be free of side effects. Returns +; the value that was swapped in." +; ([atom f] +; (cpp/jank.runtime.swap_atom atom f)) +; ([atom f x] +; (cpp/jank.runtime.swap_atom atom f x)) +; ([atom f x y] +; (cpp/jank.runtime.swap_atom atom f x y)) +; ([atom f x y & args] +; (cpp/jank.runtime.swap_atom atom f x y args))) +; +;(defn swap-vals! +; "Atomically swaps the value of atom to be: +; (apply f current-value-of-atom args). Note that f may be called +; multiple times, and thus should be free of side effects. +; Returns [old new], the value of the atom before and after the swap." +; ([atom f] +; (cpp/jank.runtime.swap_vals atom f)) +; ([atom f x] +; (cpp/jank.runtime.swap_vals atom f x)) +; ([atom f x y] +; (cpp/jank.runtime.swap_vals atom f x y)) +; ([atom f x y & args] +; (cpp/jank.runtime.swap_vals atom f x y args))) +; +;(defn compare-and-set! +; "Atomically sets the value of atom to newval if and only if the +; current value of the atom is identical to oldval. Returns true if +; set happened, else false" +; [atom oldval newval] +; (cpp/jank.runtime.compare_and_set atom oldval newval)) +; +;(defn reset! +; "Sets the value of atom to newval without regard for the +; current value. Returns newval." +; [atom newval] +; (cpp/jank.runtime.reset atom newval)) +; +;(defn reset-vals! +; "Sets the value of atom to newval. Returns [old new], the value of the +; atom before and after the reset." +; [atom newval] +; (cpp/jank.runtime.reset_vals atom newval)) +; +;;; Volatiles. +;(defn volatile! +; "Creates and returns a volatile with an initial value of val." +; [val] +; (cpp/jank.runtime.volatile_ val)) +; +;(defn vreset! +; "Sets the value of volatile to newval without regard for the +; current value. Returns newval." +; [vol newval] +; (cpp/jank.runtime.vreset vol newval)) +; +;; TODO: In Clojure, this is a macro (for perf reasons). +;(defn vswap! +; "Non-atomically swaps the value of the volatile as if: +; (apply f current-value-of-vol args). Returns the value that +; was swapped in." +; ([vol f] +; (cpp/jank.runtime.vswap vol f)) +; ([vol f & args] +; (cpp/jank.runtime.vswap vol f args))) +; +;(defn volatile? +; "Returns true if x is a volatile." +; [x] +; (cpp/jank.runtime.is_volatile x)) +; +;(defn- delay* [f] (cpp/clojure.core_native.delay f)) +; +;(defmacro delay +; "Takes a body of expressions and yields a Delay object that will +; invoke the body only the first time it is forced (with force or deref/@), and +; will cache the result and return it on all subsequent force +; calls. See also - realized?" +; [& body] +; (list `delay* (cons `fn (cons '[] body)))) +; +;(defn force +; "If x is a Delay, returns the (possibly cached) value of its expression, else returns x" +; [x] +; (cpp/jank.runtime.force x)) +; +;;; Primitives. +;;;; Arithmetic. +;(defn +; ^{:arities {2 {:supports-unboxed-input? true +; :unboxed-output? true}}} +; + +; ([] +; 0) +; ([x] +; x) +; ([l r] +; (cpp/jank.runtime.add l r)) +; ([l r & args] +; (let [res (cpp/jank.runtime.add l r)] +; (if (empty? args) +; res +; (recur res (first args) (next args)))))) +; +;(defn +; ^{:arities {2 {:supports-unboxed-input? true +; :unboxed-output? true}}} +; - +; ([x] +; (- 0 x)) +; ([l r] +; (cpp/jank.runtime.sub l r)) +; ([l r & args] +; (let [res (cpp/jank.runtime.sub l r)] +; (if (empty? args) +; res +; (recur res (first args) (next args)))))) +; +;(defn +; ^{:arities {2 {:supports-unboxed-input? true +; :unboxed-output? true}}} +; * +; ([] +; 1) +; ([x] +; x) +; ([l r] +; (cpp/jank.runtime.mul l r)) +; ([l r & args] +; (let [res (cpp/jank.runtime.mul l r)] +; (if (empty? args) +; res +; (recur res (first args) (next args)))))) +; +;(defn +; ^{:arities {2 {:supports-unboxed-input? true +; :unboxed-output? true}}} +; / +; ([x] +; (/ 1 x)) +; ([l r] +; (cpp/jank.runtime.div l r)) +; ([l r & args] +; (let [res (cpp/jank.runtime.div l r)] +; (if (empty? args) +; res +; (recur res (first args) (next args)))))) +; +;;; Bit operations. +;; TODO: Unboxing and inlining for these. +;(defn bit-not +; "Bitwise complement" +; [x] +; (cpp/jank.runtime.bit_not x)) +; +;(defn bit-and +; "Bitwise and" +; ([x y] +; (cpp/jank.runtime.bit_and x y)) +; ([x y & more] +; (reduce bit-and (bit-and x y) more))) +; +;(defn bit-or +; "Bitwise or" +; ([x y] +; (cpp/jank.runtime.bit_or x y)) +; ([x y & more] +; (reduce bit-or (bit-or x y) more))) +; +;(defn bit-xor +; "Bitwise exclusive or" +; ([x y] +; (cpp/jank.runtime.bit_xor x y)) +; ([x y & more] +; (reduce bit-xor (bit-xor x y) more))) +; +;(defn bit-and-not +; "Bitwise and with complement" +; ([x y] +; (cpp/jank.runtime.bit_and_not x y)) +; ([x y & more] +; (reduce bit-and-not (bit-and-not x y) more))) +; +;(defn bit-clear +; "Clear bit at index n" +; [x n] +; (cpp/jank.runtime.bit_clear x n)) +; +;(defn bit-set +; "Set bit at index n" +; [x n] +; (cpp/jank.runtime.bit_set x n)) +; +;(defn bit-flip +; "Flip bit at index n" +; [x n] +; (cpp/jank.runtime.bit_flip x n)) +; +;(defn bit-test +; "Test bit at index n" +; [x n] +; (cpp/jank.runtime.bit_test x n)) +; +;(defn bit-shift-left +; "Bitwise shift left" +; [x n] +; (cpp/jank.runtime.bit_shift_left x n)) +; +;(defn bit-shift-right +; "Bitwise shift right" +; [x n] +; (cpp/jank.runtime.bit_shift_right x n)) +; +;(defn unsigned-bit-shift-right +; "Bitwise shift right, without sign-extension." +; [x n] +; (cpp/jank.runtime.bit_unsigned_shift_right x n)) +; +;(defn not= +; ([x] +; false) +; ([x y] +; (not (= x y))) +; ([x y & more] +; (not (apply = x y more)))) +; +;(defn +; ^{:arities {2 {:supports-unboxed-input? true +; :unboxed-output? true}}} +; < +; ([x] +; true) +; ([l r] +; (cpp/jank.runtime.lt l r)) +; ([l r & args] +; (if (cpp/jank.runtime.lt l r) +; (if (next args) +; (recur r (first args) (next args)) +; (cpp/jank.runtime.lt r (first args))) +; false))) +; +;(defn +; ^{:arities {2 {:supports-unboxed-input? true +; :unboxed-output? true}}} +; <= +; ([x] +; true) +; ([l r] +; (cpp/jank.runtime.lte l r)) +; ([l r & args] +; (if (cpp/jank.runtime.lte l r) +; (if (next args) +; (recur r (first args) (next args)) +; (cpp/jank.runtime.lte r (first args))) +; false))) +; +;(defn +; ^{:arities {2 {:supports-unboxed-input? true +; :unboxed-output? true}}} +; > +; ([x] +; true) +; ([l r] +; (cpp/jank.runtime.lt r l)) +; ([l r & args] +; (if (cpp/jank.runtime.lt r l) +; (if (next args) +; (recur r (first args) (next args)) +; (cpp/jank.runtime.lt (first args) r)) +; false))) +; +;(defn +; ^{:arities {2 {:supports-unboxed-input? true +; :unboxed-output? true}}} +; >= +; ([x] +; true) +; ([l r] +; (cpp/jank.runtime.lte r l)) +; ([l r & args] +; (if (cpp/jank.runtime.lte r l) +; (if (next args) +; (recur r (first args) (next args)) +; (cpp/jank.runtime.lte (first args) r)) +; false))) +; +;(defn +; ^{:arities {2 {:supports-unboxed-input? true +; :unboxed-output? true}}} +; min +; ([x] +; x) +; ([l r] +; (cpp/jank.runtime.min l r)) +; ([l r & args] +; (let [res (cpp/jank.runtime.min l r)] +; (if (empty? args) +; res +; (recur res (first args) (next args)))))) +; +;(defn +; ^{:arities {2 {:supports-unboxed-input? true +; :unboxed-output? true}}} +; max +; ([x] +; x) +; ([l r] +; (cpp/jank.runtime.max l r)) +; ([l r & args] +; (let [res (cpp/jank.runtime.max l r)] +; (if (empty? args) +; res +; (recur res (first args) (next args)))))) +; +;(defn inc +; "Returns a number one greater than num. Does not auto-promote +; longs, will throw on overflow. See also: inc'" +; [x] +; (cpp/jank.runtime.inc x)) +;(defn dec +; "Returns a number one less than num. Does not auto-promote +; longs, will throw on overflow. See also: dec" +; [x] +; (cpp/jank.runtime.dec x)) +; +;(defn pos? +; "Returns true if num is greater than zero, else false" +; [num] +; (cpp/jank.runtime.is_pos num)) +;(defn neg? +; "Returns true if num is less than zero, else false" +; [num] +; (cpp/jank.runtime.is_neg num)) +;(defn zero? +; "Returns true if num is zero, else false" +; [num] +; (cpp/jank.runtime.is_zero num)) +; +;(defn rem +; "Returns the remainder of dividing numerator by denominator." +; [num div] +; (cpp/jank.runtime.rem num div)) +;(defn quot +; "quot[ient] of dividing numerator by denominator." +; [num div] +; (cpp/jank.runtime.quot num div)) +; +;(defn mod +; "Modulus of num and div. Truncates toward negative infinity." +; [num div] +; (let [m (rem num div)] +; (if (or (zero? m) (= (pos? num) (pos? div))) +; m +; (+ m div)))) +; +;;; Numbers. +;(defn integer? +; "Returns true if n is an integer" +; [n] +; (cpp/jank.runtime.is_integer n)) +;(defn float? +; "Returns true if n is a floating point number" +; [n] +; (cpp/jank.runtime.is_real n)) +;(defn boolean? +; "Returns true if x is a boolean" +; [x] +; (cpp/jank.runtime.is_boolean x)) +;(defn number? +; "Returns true if x is a number" +; [x] +; (cpp/jank.runtime.is_number x)) +; +;(defn even? +; "Returns true if n is even, throws an exception if n is not an integer" +; [n] +; (cpp/jank.runtime.is_even n)) +;(defn odd? +; "Returns true if n is odd, throws an exception if n is not an integer" +; [n] +; (cpp/jank.runtime.is_odd n)) +; +;;; Random. +;(defn rand +; "Returns a random floating point number between 0 (inclusive) and +; n (default 1) (exclusive)." +; ([] +; (cpp/jank.runtime.rand)) +; ([n] +; (* (rand) n))) +; +;;; Strings. +;(defn subs +; "Returns the substring of s beginning at start inclusive, and ending +; at end (defaults to length of string), exclusive." +; ([s start] +; (cpp/jank.runtime.subs s start)) +; ([s start end] +; (cpp/jank.runtime.subs s start end))) +; +;;; Sequences (again). +;(defn sequential? +; "Returns true if coll implements sequential" +; [coll] +; (cpp/jank.runtime.is_sequential coll)) +; +;(defn reverse +; "Returns a seq of the items in coll in reverse order. Not lazy." +; [coll] +; (reduce conj '() coll)) +; +;(defn every? +; "Returns true if (pred x) is logical true for every x in coll, else false." +; [pred coll] +; (cond +; (nil? (seq coll)) true +; (pred (first coll)) (recur pred (next coll)) +; :else false)) +; +;(defn vector +; "Creates a new vector containing the args." +; ([] +; []) +; ([a] +; [a]) +; ([a b] +; [a b]) +; ([a b c] +; [a b c]) +; ([a b c d] +; [a b c d]) +; ([a b c d e] +; [a b c d e]) +; ([a b c d e f] +; [a b c d e f]) +; ([a b c d e f & args] +; ; TODO: LazilyPersistentVector +; (vec (concat* [a b c d e f] args)))) +; +;(defn- lazy-seq* [o] (cpp/clojure.core_native.lazy_seq o)) +; +;(defmacro lazy-seq +; "Takes a body of expressions that returns an ISeq or nil, and yields +; a Seqable object that will invoke the body only the first time seq +; is called, and will cache the result and return it on all subsequent +; seq calls. See also - realized?" +; [& body] +; (list `lazy-seq* (list* `fn `lazy-seq# [] body))) +; +;(defn chunk-buffer +; [capacity] +; (cpp/jank.runtime.chunk_buffer capacity)) +; +;(defn chunk-append +; [b x] +; (cpp/jank.runtime.chunk_append b x)) +; +;(defn chunk +; [b] +; (cpp/jank.runtime.chunk b)) +; +;(defn chunk-first +; [s] +; (cpp/jank.runtime.chunk_first s)) +; +;(defn chunk-next +; [s] +; (cpp/jank.runtime.chunk_next s)) +; +;(defn chunk-rest +; [s] +; (cpp/jank.runtime.chunk_rest s)) +; +;(defn chunk-cons [chunk rest] +; (if (empty? chunk) +; rest +; (cpp/jank.runtime.chunk_cons chunk rest))) +; +;(defn chunked-seq? +; [s] +; (cpp/jank.runtime.is_chunked_seq s)) +; +;; TODO: Support more bindings +;; TODO: Support `for` functionality +;(defmacro doseq +; "Repeatedly executes body (presumably for side-effects) with +; bindings and filtering as provided by `for`. Does not retain +; the head of the sequence. Returns nil." +; [bindings & body] +; (let [arg (first bindings) +; s (second bindings)] +; (list 'clojure.core/reduce (concat* (list 'clojure.core/fn ['_ arg]) +; body +; [nil]) +; nil +; s))) +; +;(defn concat +; "Returns a lazy seq representing the concatenation of the elements in the supplied colls." +; ([] (lazy-seq nil)) +; ([x] (lazy-seq x)) +; ([x y] +; (lazy-seq +; (let [s (seq x)] +; (if s +; (if (chunked-seq? s) +; (chunk-cons (chunk-first s) (concat (chunk-rest s) y)) +; (cons (first s) (concat (rest s) y))) +; y)))) +; ([x y & zs] +; (let [cat* (fn cat* [xys zs] +; (lazy-seq +; (let [xys (seq xys)] +; (if xys +; (if (chunked-seq? xys) +; (chunk-cons (chunk-first xys) +; (cat* (chunk-rest xys) zs)) +; (cons (first xys) (cat* (rest xys) zs))) +; (when zs +; (cat* (first zs) (next zs)))))))] +; (cat* (concat x y) zs)))) +; +;(defn juxt +; "Takes a set of functions and returns a fn that is the juxtaposition +; of those fns. The returned fn takes a variable number of args, and +; returns a vector containing the result of applying each fn to the +; args (left-to-right). +; ((juxt a b c) x) => [(a x) (b x) (c x)]" +; ([f] +; (fn +; ([] [(f)]) +; ([x] [(f x)]) +; ([x y] [(f x y)]) +; ([x y z] [(f x y z)]) +; ([x y z & args] [(apply f x y z args)]))) +; ([f g] +; (fn +; ([] [(f) (g)]) +; ([x] [(f x) (g x)]) +; ([x y] [(f x y) (g x y)]) +; ([x y z] [(f x y z) (g x y z)]) +; ([x y z & args] [(apply f x y z args) (apply g x y z args)]))) +; ([f g h] +; (fn +; ([] [(f) (g) (h)]) +; ([x] [(f x) (g x) (h x)]) +; ([x y] [(f x y) (g x y) (h x y)]) +; ([x y z] [(f x y z) (g x y z) (h x y z)]) +; ([x y z & args] [(apply f x y z args) (apply g x y z args) (apply h x y z args)]))) +; ([f g h & fs] +; (let [fs (list* f g h fs)] +; (fn +; ([] (reduce #(conj %1 (%2)) [] fs)) +; ([x] (reduce #(conj %1 (%2 x)) [] fs)) +; ([x y] (reduce #(conj %1 (%2 x y)) [] fs)) +; ([x y z] (reduce #(conj %1 (%2 x y z)) [] fs)) +; ([x y z & args] (reduce #(conj %1 (apply %2 x y z args)) [] fs)))))) +; +;(defn partial +; "Takes a function f and fewer than the normal arguments to f, and +; returns a fn that takes a variable number of additional args. When +; called, the returned function calls f with args + additional args." +; ([f] f) +; ([f arg1] +; (fn +; ([] (f arg1)) +; ([x] (f arg1 x)) +; ([x y] (f arg1 x y)) +; ([x y z] (f arg1 x y z)) +; ([x y z & args] (apply f arg1 x y z args)))) +; ([f arg1 arg2] +; (fn +; ([] (f arg1 arg2)) +; ([x] (f arg1 arg2 x)) +; ([x y] (f arg1 arg2 x y)) +; ([x y z] (f arg1 arg2 x y z)) +; ([x y z & args] (apply f arg1 arg2 x y z args)))) +; ([f arg1 arg2 arg3] +; (fn +; ([] (f arg1 arg2 arg3)) +; ([x] (f arg1 arg2 arg3 x)) +; ([x y] (f arg1 arg2 arg3 x y)) +; ([x y z] (f arg1 arg2 arg3 x y z)) +; ([x y z & args] (apply f arg1 arg2 arg3 x y z args)))) +; ([f arg1 arg2 arg3 & more] +; (fn [& args] (apply f arg1 arg2 arg3 (concat more args))))) +; +;(defn fnil +; "Takes a function f, and returns a function that calls f, replacing +; a nil first argument to f with the supplied value x. Higher arity +; versions can replace arguments in the second and third +; positions (y, z). Note that the function f can take any number of +; arguments, not just the one(s) being nil-patched." +; ([f x] +; (fn +; ([a] (f (if (nil? a) x a))) +; ([a b] (f (if (nil? a) x a) b)) +; ([a b c] (f (if (nil? a) x a) b c)) +; ([a b c & ds] (apply f (if (nil? a) x a) b c ds)))) +; ([f x y] +; (fn +; ([a b] (f (if (nil? a) x a) (if (nil? b) y b))) +; ([a b c] (f (if (nil? a) x a) (if (nil? b) y b) c)) +; ([a b c & ds] (apply f (if (nil? a) x a) (if (nil? b) y b) c ds)))) +; ([f x y z] +; (fn +; ([a b] (f (if (nil? a) x a) (if (nil? b) y b))) +; ([a b c] (f (if (nil? a) x a) (if (nil? b) y b) (if (nil? c) z c))) +; ([a b c & ds] (apply f (if (nil? a) x a) (if (nil? b) y b) (if (nil? c) z c) ds))))) +; +;(defn some +; "Returns the first logical true value of (pred x) for any x in coll, +; else nil. One common idiom is to use a set as pred, for example +; this will return :fred if :fred is in the sequence, otherwise nil: +; (some #{:fred} coll)" +; [pred coll] +; (let [s (seq coll)] +; (when s +; (or (pred (first s)) (recur pred (next s)))))) +; +; +;(defn every-pred +; "Takes a set of predicates and returns a function f that returns true if all of its +; composing predicates return a logical true value against all of its arguments, else it returns +; false. Note that f is short-circuiting in that it will stop execution on the first +; argument that triggers a logical false result against the original predicates." +; ([p] +; (fn ep1 +; ([] true) +; ([x] (boolean (p x))) +; ([x y] (boolean (and (p x) (p y)))) +; ([x y z] (boolean (and (p x) (p y) (p z)))) +; ([x y z & args] (boolean (and (ep1 x y z) +; (every? p args)))))) +; ([p1 p2] +; (fn ep2 +; ([] true) +; ([x] (boolean (and (p1 x) (p2 x)))) +; ([x y] (boolean (and (p1 x) (p1 y) (p2 x) (p2 y)))) +; ([x y z] (boolean (and (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z)))) +; ([x y z & args] (boolean (and (ep2 x y z) +; (every? #(and (p1 %) (p2 %)) args)))))) +; ([p1 p2 p3] +; (fn ep3 +; ([] true) +; ([x] (boolean (and (p1 x) (p2 x) (p3 x)))) +; ([x y] (boolean (and (p1 x) (p1 y) (p2 x) (p2 y) (p3 x) (p3 y)))) +; ([x y z] (boolean (and (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z) (p3 x) (p3 y) (p3 z)))) +; ([x y z & args] (boolean (and (ep3 x y z) +; (every? #(and (p1 %) (p2 %) (p3 %)) args)))))) +; ([p1 p2 p3 & ps] +; (let [ps (list* p1 p2 p3 ps)] +; (fn epn +; ([] true) +; ([x] (every? #(% x) ps)) +; ([x y] (every? #(and (% x) (% y)) ps)) +; ([x y z] (every? #(and (% x) (% y) (% z)) ps)) +; ([x y z & args] (boolean (and (epn x y z) +; (every? #(every? % args) ps)))))))) +; +;(defn some-fn +; "Takes a set of predicates and returns a function f that returns the first logical true value +; returned by one of its composing predicates against any of its arguments, else it returns +; logical false. Note that f is short-circuiting in that it will stop execution on the first +; argument that triggers a logical true result against the original predicates." +; ([p] +; (fn sp1 +; ([] nil) +; ([x] (p x)) +; ([x y] (or (p x) (p y))) +; ([x y z] (or (p x) (p y) (p z))) +; ([x y z & args] (or (sp1 x y z) +; (some p args))))) +; ([p1 p2] +; (fn sp2 +; ([] nil) +; ([x] (or (p1 x) (p2 x))) +; ([x y] (or (p1 x) (p1 y) (p2 x) (p2 y))) +; ([x y z] (or (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z))) +; ([x y z & args] (or (sp2 x y z) +; (some #(or (p1 %) (p2 %)) args))))) +; ([p1 p2 p3] +; (fn sp3 +; ([] nil) +; ([x] (or (p1 x) (p2 x) (p3 x))) +; ([x y] (or (p1 x) (p1 y) (p2 x) (p2 y) (p3 x) (p3 y))) +; ([x y z] (or (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z) (p3 x) (p3 y) (p3 z))) +; ([x y z & args] (or (sp3 x y z) +; (some #(or (p1 %) (p2 %) (p3 %)) args))))) +; ([p1 p2 p3 & ps] +; (let [ps (list* p1 p2 p3 ps)] +; (fn spn +; ([] nil) +; ([x] (some #(% x) ps)) +; ([x y] (some #(or (% x) (% y)) ps)) +; ([x y z] (some #(or (% x) (% y) (% z)) ps)) +; ([x y z & args] (or (spn x y z) +; (some #(some % args) ps))))))) +; +; +;(defn not-any? [pred coll] +; (not (some pred coll))) +; +;(defmacro -> +; "Threads the expr through the forms. Inserts x as the +; second item in the first form, making a list of it if it is not a +; list already. If there are more forms, inserts the first form as the +; second item in second form, etc." +; [x & forms] +; (loop* [x x +; forms forms] +; (if forms +; (let [form (first forms) +; threaded (if (seq? form) +; (with-meta `(~(first form) ~x ~@(next form)) (meta form)) +; (list form x))] +; (recur threaded (next forms))) +; x))) +; +;(defmacro ->> +; "Threads the expr through the forms. Inserts x as the +; last item in the first form, making a list of it if it is not a +; list already. If there are more forms, inserts the first form as the +; last item in second form, etc." +; [x & forms] +; (loop* [x x +; forms forms] +; (if forms +; (let [form (first forms) +; threaded (if (seq? form) +; (with-meta `(~(first form) ~@(next form) ~x) (meta form)) +; (list form x))] +; (recur threaded (next forms))) +; x))) +; +;;; Maps. +;(defn key +; "Returns the key of the map entry." +; [e] +; (first e)) +; +;(defn val +; "Returns the value in the map entry." +; [e] +; (second e)) +; +;(defn keys +; "Returns a sequence of the map's keys, in the same order as (seq map)." +; [m] +; ; TODO: Use a proper key seq instead. +; (reduce (fn [acc kv] +; (conj acc (first kv))) +; [] +; m)) +; +;(defn vals +; "Returns a sequence of the map's values, in the same order as (seq map)." +; [m] +; ; TODO: Use a proper val seq instead. +; (reduce (fn [acc kv] +; (conj acc (second kv))) +; [] +; m)) +; +;(defn get +; "Returns the value mapped to key, not-found or nil if key not present +; in associative collection, set, string, array, or ILookup instance." +; ([map key] +; (cpp/jank.runtime.get map key)) +; ([map key not-found] +; (cpp/jank.runtime.get map key not-found))) +;(defn get-in +; "Returns the value in a nested associative structure, +; where ks is a sequence of keys. Returns nil if the key +; is not present, or the not-found value if supplied." +; ([m ks] +; (cpp/jank.runtime.get_in m ks)) +; ([m ks not-found] +; (cpp/jank.runtime.get_in m ks not-found))) +; +;(defn dissoc +; "dissoc[iate]. Returns a new map of the same (hashed/sorted) type, +; that does not contain a mapping for key(s)." +; ([m] +; m) +; ([m k] +; (cpp/jank.runtime.dissoc m k)) +; ([m k & ks] +; (let* [ret (dissoc m k)] +; (if ks +; (recur ret (first ks) (next ks)) +; ret)))) +; +;(defn contains? +; "Returns true if key is present in the given collection, otherwise +; returns false. Note that for numerically indexed collections like +; vectors and Java arrays, this tests if the numeric key is within the +; range of indexes. 'contains?' operates constant or logarithmic time; +; it will not perform a linear search for a value. See also 'some'." +; [coll key] +; (cpp/jank.runtime.contains coll key)) +; +;(defn find +; "Returns the map entry for key, or nil if key not present." +; [map key] +; (cpp/jank.runtime.find map key)) +; +;(defn select-keys +; "Returns a map containing only those entries in map whose key is in keys" +; [m ks] +; (reduce (fn [acc k] +; (let [e (find m k)] +; (if e +; (conj acc e) +; acc))) +; {} +; ks)) +; +;(defn zipmap +; "Returns a map with the keys mapped to the corresponding vals." +; [keys vals] +; (loop* [map (transient (hash-map)) +; ks (seq keys) +; vs (seq vals)] +; (if (and ks vs) +; (recur (assoc! map (first ks) (first vs)) +; (next ks) +; (next vs)) +; (persistent! map)))) +; +;;; Sets. +;(defn hash-set +; "Returns a new hash set with supplied keys. Any equal keys are +; handled as if by repeated uses of conj." +; ([] (cpp/jank.runtime.obj.persistent_hash_set.empty)) +; ([& keys] +; (cpp/jank.runtime.obj.persistent_hash_set.create_from_seq keys))) +; +;(defn sorted-set +; "Returns a new sorted set with supplied keys. Any equal keys are +; handled as if by repeated uses of conj." +; ([] (cpp/jank.runtime.obj.persistent_sorted_set.empty)) +; ([& keys] +; (cpp/jank.runtime.obj.persistent_sorted_set.create_from_seq keys))) +; +;(defn sorted-set-by +; "Returns a new sorted set with supplied keys, using the supplied +; comparator. Any equal keys are handled as if by repeated uses of +; conj." +; ([comparator & keys] +; (throw "not yet implemented: sorted-set-by"))) +; +;(defn disj +; "disj[oin]. Returns a new set of the same (hashed/sorted) type, that +; does not contain key(s)." +; ([set] +; set) +; ([set key] +; (cpp/jank.runtime.disj set key)) +; ([set key & ks] +; (let* [res (disj set key)] +; (if (empty? ks) +; res +; (recur res (first ks) (next ks)))))) +; +;(defn set? +; "Returns true if x implements IPersistentSet" +; [x] +; (cpp/jank.runtime.is_set x)) +; +;(defn set +; "Returns a set of the distinct elements of coll." +; [coll] +; (if (set? coll) +; (with-meta coll nil) +; (persistent! (reduce (fn [acc e] +; (conj! acc e)) +; (transient #{}) +; coll)))) +; +;;; Other. +;(defn hash +; "Returns the hash code of its argument. Note this is the hash code +; consistent with =, and thus is different than .hashCode for Integer, +; Short, Byte and Clojure collections." +; [o] +; (cpp/jank.runtime.to_hash o)) +; +;(defn- named? +; [x] +; (cpp/jank.runtime.is_named x)) +; +;(defn name +; "Returns the name String of a string, symbol or keyword." +; [x] +; (cpp/jank.runtime.name x)) +; +;(defn namespace +; "Returns the namespace String of a symbol or keyword, or nil if not present." +; [x] +; (cpp/jank.runtime.namespace_ x)) +; +;;; Sequences. +;; This is defined to be lazy later on. +;(defn drop +; ([n coll] +; (let [step (fn [n acc] +; (let [s (seq acc)] +; (if (and (pos? n) s) +; (recur (dec n) (rest s)) +; acc)))] +; (step n coll)))) +; +;;; Vars. +;(defn var? +; "Returns true if v is a var." +; [x] +; (cpp/clojure.core_native.is_var x)) +; +;(defn var-get +; "Gets the value in the var object." +; [x] +; (cpp/clojure.core_native.var_get x)) +; +;(defn alter-var-root +; "Atomically alters the root binding of var v by applying f to its +; current value plus any args" +; [v f & args] +; (cpp/clojure.core_native.alter_var_root v f args)) +; +;(defn bound? +; "Returns true if all of the vars provided as arguments have any bound value, root or thread-local. +; Implies that deref'ing the provided vars will succeed. Returns true if no vars are provided." +; [& vars] +; (every? #(cpp/clojure.core_native.is_var_bound %) vars)) +; +;(defn thread-bound? +; "Returns true if all of the vars provided as arguments have thread-local bindings. +; Implies that set!'ing the provided vars will succeed. Returns true if no vars are provided." +; [& vars] +; (every? #(cpp/clojure.core_native.is_var_thread_bound %) vars)) +; +;(defmacro ^:private assert-macro-args +; [& pairs] +; (list 'do +; (list 'clojure.core/when-not (first pairs) +; ; TODO: No need for ex-info, if we had a simpler exception type +; (list 'throw (list 'clojure.core/ex-info +; (list 'clojure.core/str +; '&form +; " requires " +; (second pairs) +; " in " +; 'clojure.core/*ns* +; ":" +; (:line (meta '&form))) +; {}))) +; (let [more (next (next pairs))] +; (when more +; (list* 'clojure.core/assert-macro-args more))))) +; +;(defmacro if-let +; "bindings => binding-form test +; +; If test is true, evaluates then with binding-form bound to the value of +; test, if not, yields else" +; ([bindings then] +; `(if-let ~bindings ~then nil)) +; ([bindings then else & oldform] +; (assert-macro-args +; (vector? bindings) "a vector for its binding" +; (nil? oldform) "1 or 2 forms after binding vector" +; (= 2 (count bindings)) "exactly 2 forms in binding vector") +; (let [form (get bindings 0) +; tst (get bindings 1)] +; `(let [temp# ~tst] +; (if temp# +; (let [~form temp#] +; ~then) +; ~else))))) +; +;(defmacro when-let +; "bindings => binding-form test +; +; When test is true, evaluates body with binding-form bound to the value of test" +; [bindings & body] +; (assert-macro-args +; (vector? bindings) "a vector for its binding" +; (= 2 (count bindings)) "exactly 2 forms in binding vector") +; (let [form (get bindings 0) +; tst (get bindings 1)] +; `(let [temp# ~tst] +; (when temp# +; (let [~form temp#] +; ~@body))))) +; +;(defmacro if-some +; "bindings => binding-form test +; +; If test is not nil, evaluates then with binding-form bound to the +; value of test, if not, yields else" +; ([bindings then] +; `(if-some ~bindings ~then nil)) +; ([bindings then else & oldform] +; (assert-macro-args +; (vector? bindings) "a vector for its binding" +; (nil? oldform) "1 or 2 forms after binding vector" +; (= 2 (count bindings)) "exactly 2 forms in binding vector") +; (let [form (get bindings 0) tst (get bindings 1)] +; `(let [temp# ~tst] +; (if (nil? temp#) +; ~else +; (let [~form temp#] +; ~then)))))) +; +;(defmacro when-some +; "bindings => binding-form test +; +; When test is not nil, evaluates body with binding-form bound to the +; value of test" +; [bindings & body] +; (assert-macro-args +; (vector? bindings) "a vector for its binding" +; (= 2 (count bindings)) "exactly 2 forms in binding vector") +; (let [form (get bindings 0) +; tst (get bindings 1)] +; `(let [temp# ~tst] +; (if (nil? temp#) +; nil +; (let [~form temp#] +; ~@body))))) +; +;(defmacro dotimes +; "bindings => name n +; +; Repeatedly executes body (presumably for side-effects) with name +; bound to integers from 0 through n-1." +; [bindings & body] +; (assert-macro-args +; (vector? bindings) "a vector for its binding" +; (= 2 (count bindings)) "exactly 2 forms in binding vector") +; (let [i (first bindings) +; n (second bindings)] +; `(let [n# (int ~n)] +; (loop [~i 0] +; (when (< ~i n#) +; ~@body +; ; TODO: unchecked-inc +; (recur (inc ~i))))))) +; +;(defn push-thread-bindings +; "WARNING: This is a low-level function. Prefer high-level macros like +; binding where ever possible. +; +; Takes a map of Var/value pairs. Binds each Var to the associated value for +; the current thread. Each call *MUST* be accompanied by a matching call to +; pop-thread-bindings wrapped in a try-finally! +; +; (push-thread-bindings bindings) +; (try +; ... +; (finally +; (pop-thread-bindings)))" +; [bindings] +; (cpp/jank.runtime.push_thread_bindings bindings)) +; +;(defn pop-thread-bindings +; "Pop one set of bindings pushed with push-binding before. It is an error to +; pop bindings without pushing before." +; [] +; (cpp/jank.runtime.pop_thread_bindings)) +; +;(defn get-thread-bindings +; "Get a map with the Var/value pairs which is currently in effect for the +; current thread." +; [] +; (cpp/jank.runtime.get_thread_bindings)) +; +;(defmacro binding +; "binding => var-symbol init-expr +; +; Creates new bindings for the (already-existing) vars, with the +; supplied initial values, executes the exprs in an implicit do, then +; re-establishes the bindings that existed before. The new bindings +; are made in parallel (unlike let); all init-exprs are evaluated +; before the vars are bound to their new values." +; [bindings & body] +; (assert-macro-args +; (vector? bindings) "a vector for its binding" +; (even? (count bindings)) "an even number of forms in binding vector") +; (let [->var-pairs (fn ->var-pairs [var-vals] +; (loop [ret [] +; vvs (seq var-vals)] +; (if vvs +; (recur (conj (conj ret `(var ~(first vvs))) (second vvs)) +; (next (next vvs))) +; (seq ret))))] +; `(do +; (push-thread-bindings (hash-map ~@(->var-pairs bindings))) +; (try +; (do ~@body) +; (finally +; (pop-thread-bindings)))))) +; +;;; Keywords. +;(defn keyword? +; "Return true if x is a Keyword" +; [x] +; (cpp/jank.runtime.is_keyword x)) +;(defn simple-keyword? +; "Return true if x is a keyword without a namespace" +; [x] +; (cpp/jank.runtime.is_simple_keyword x)) +;(defn qualified-keyword? +; "Return true if x is a keyword with a namespace" +; [x] +; (cpp/jank.runtime.is_qualified_keyword x)) +; +;(defn keyword +; "Returns a Keyword with the given namespace and name. Do not use : +; in the keyword strings, it will be added automatically." +; ([name] +; (cond +; (keyword? name) name +; (symbol? name) (cpp/jank.runtime.keyword nil (str name)) +; (string? name) (cpp/jank.runtime.keyword nil name))) +; ([ns name] +; (cpp/jank.runtime.keyword ns name))) +; +;(defn ident? +; "Returns true if x is a symbol or keyword" +; [x] +; (or (keyword? x) (symbol? x))) +; +;(defn simple-ident? +; "Returns true if x is a symbol or keyword without a namespace" +; [x] +; (and (ident? x) (nil? (namespace x)))) +; +;(defn qualified-ident? +; "Returns true if x is a symbol or keyword with a namespace" +; [x] +; (boolean (and (ident? x) (namespace x) true))) +; +;;; Sequences. +;(defn iterate +; "Returns a lazy (infinite!) sequence of x, (f x), (f (f x)) etc. +; f must be free of side-effects" +; [fn x] +; (cpp/jank.runtime.iterate fn x)) +; +;(defn range +; "Returns a lazy seq of nums from start (inclusive) to end +; (exclusive), by step, where start defaults to 0, step to 1, and end to +; infinity. When step is equal to 0, returns an infinite sequence of +; start. When start is equal to end, returns empty list." +; ([] +; (iterate inc 0)) +; ([end] +; (if (integer? end) +; (cpp/jank.runtime.obj.integer_range.create end) +; (cpp/jank.runtime.obj.range.create end))) +; ([start end] +; (if (and (integer? start) (integer? end)) +; (cpp/jank.runtime.obj.integer_range.create start end) +; (cpp/jank.runtime.obj.range.create start end))) +; ([start end step] +; (if (and (integer? start) (integer? end) (integer? step)) +; (cpp/jank.runtime.obj.integer_range.create start end step) +; (cpp/jank.runtime.obj.range.create start end step)))) +; +;(defn nth +; "Returns the value at the index. get returns nil if index out of +; bounds, nth throws an exception unless not-found is supplied. nth +; also works for strings, Java arrays, regex Matchers and Lists, and, +; in O(n) time, for sequences." +; ([coll index] +; (cpp/jank.runtime.nth coll index)) +; ([coll index not-found] +; (cpp/jank.runtime.nth coll index not-found))) +; +;(defn nthnext +; "Returns the nth next of coll, (seq coll) when n is 0." +; [coll n] +; ;; TODO add support for IDrop +; (loop [n n xs (seq coll)] +; (if (and xs (pos? n)) +; (recur (dec n) (next xs)) +; xs))) +; +;(defn nthrest +; "Returns the nth rest of coll, coll when n is 0." +; [coll n] +; ;; TODO add support for IDrop +; (if (pos? n) +; (if-let [xs (seq coll)] +; (recur (rest xs) (dec n)) +; (or (seq coll) ())) +; coll)) +; +;(defn take-nth +; "Returns a lazy seq of every nth item in coll. Returns a stateful +; transducer when no collection is provided." +; ([n] +; (fn [rf] +; (let [iv (volatile! -1)] +; (fn +; ([] (rf)) +; ([result] (rf result)) +; ([result input] +; (let [i (vswap! iv inc)] +; (if (zero? (rem i n)) +; (rf result input) +; result))))))) +; ([n coll] +; (lazy-seq +; (when-let [s (seq coll)] +; (cons (first s) (take-nth n (drop n s))))))) +; +;(defn map +; "Returns a lazy sequence consisting of the result of applying f to +; the set of first items of each coll, followed by applying f to the +; set of second items in each coll, until any one of the colls is +; exhausted. Any remaining items in other colls are ignored. Function +; f should accept number-of-colls arguments. Returns a transducer when +; no collection is provided." +; ([f] +; (fn [rf] +; (fn +; ([] (rf)) +; ([result] (rf result)) +; ([result input] +; (rf result (f input))) +; ([result input & inputs] +; (rf result (apply f input inputs)))))) +; ([f coll] +; (lazy-seq +; (when-let [s (seq coll)] +; (if (chunked-seq? s) +; (let [c (chunk-first s) +; size (int (count c)) +; b (chunk-buffer size)] +; (dotimes [i size] +; (chunk-append b (f (nth c i)))) +; (chunk-cons (chunk b) (map f (chunk-rest s)))) +; (cons (f (first s)) (map f (rest s))))))) +; ([f c1 c2] +; (lazy-seq +; (let [s1 (seq c1) +; s2 (seq c2)] +; (when (and s1 s2) +; (cons (f (first s1) (first s2)) +; (map f (rest s1) (rest s2))))))) +; ([f c1 c2 c3] +; (lazy-seq +; (let [s1 (seq c1) +; s2 (seq c2) +; s3 (seq c3)] +; (when (and s1 s2 s3) +; (cons (f (first s1) (first s2) (first s3)) +; (map f (rest s1) (rest s2) (rest s3))))))) +; ([f c1 c2 c3 & colls] +; (let [step (fn step [cs] +; (lazy-seq +; (let [ss (map seq cs)] +; (when (every? identity ss) +; (cons (map first ss) (step (map rest ss)))))))] +; (map #(apply f %) (step (conj colls c3 c2 c1)))))) +; +;(defmacro doto +; "Evaluates x then calls all of the methods and functions with the +; value of x supplied at the front of the given arguments. The forms +; are evaluated in order. Returns x." +; [x & forms] +; (let [gx (gensym)] +; `(let [~gx ~x] +; ~@(map (fn [f] +; (with-meta +; (if (seq? f) +; `(~(first f) ~gx ~@(next f)) +; `(~f ~gx)) +; (meta f))) +; forms) +; ~gx))) +; +;(defn map-indexed +; "Returns a lazy sequence consisting of the result of applying f to 0 +; and the first item of coll, followed by applying f to 1 and the second +; item in coll, etc, until coll is exhausted. Thus function f should +; accept 2 arguments, index and item. Returns a stateful transducer when +; no collection is provided." +; ([f] +; (fn [rf] +; (let [i (volatile! -1)] +; (fn +; ([] (rf)) +; ([result] (rf result)) +; ([result input] +; (rf result (f (vswap! i inc) input))))))) +; ([f coll] +; (let [mapi (fn mapi [idx coll] +; (lazy-seq +; (when-let [s (seq coll)] +; (if (chunked-seq? s) +; (let [c (chunk-first s) +; size (int (count c)) +; b (chunk-buffer size)] +; (dotimes [i size] +; (chunk-append b (f (+ idx i) (nth c i)))) +; (chunk-cons (chunk b) (mapi (+ idx size) (chunk-rest s)))) +; (cons (f idx (first s)) (mapi (inc idx) (rest s)))))))] +; (mapi 0 coll)))) +; +;(defn keep +; "Returns a lazy sequence of the non-nil results of (f item). Note, +; this means false return values will be included. f must be free of +; side-effects. Returns a transducer when no collection is provided." +; ([f] +; (fn [rf] +; (fn +; ([] (rf)) +; ([result] (rf result)) +; ([result input] +; (let [v (f input)] +; (if (nil? v) +; result +; (rf result v))))))) +; ([f coll] +; (lazy-seq +; (when-let [s (seq coll)] +; (if (chunked-seq? s) +; (let [c (chunk-first s) +; size (count c) +; b (chunk-buffer size)] +; (dotimes [i size] +; (let [x (f (nth c i))] +; (when-not (nil? x) +; (chunk-append b x)))) +; (chunk-cons (chunk b) (keep f (chunk-rest s)))) +; (let [x (f (first s))] +; (if (nil? x) +; (keep f (rest s)) +; (cons x (keep f (rest s)))))))))) +; +;(defn keep-indexed +; "Returns a lazy sequence of the non-nil results of (f index item). Note, +; this means false return values will be included. f must be free of +; side-effects. Returns a stateful transducer when no collection is +; provided." +; ([f] +; (fn [rf] +; (let [iv (volatile! -1)] +; (fn +; ([] (rf)) +; ([result] (rf result)) +; ([result input] +; (let [i (vswap! iv inc) +; v (f i input)] +; (if (nil? v) +; result +; (rf result v)))))))) +; ([f coll] +; (let [keepi (fn keepi [idx coll] +; (lazy-seq +; (when-let [s (seq coll)] +; (if (chunked-seq? s) +; (let [c (chunk-first s) +; size (count c) +; b (chunk-buffer size)] +; (dotimes [i size] +; (let [x (f (+ idx i) (nth c i))] +; (when-not (nil? x) +; (chunk-append b x)))) +; (chunk-cons (chunk b) (keepi (+ idx size) (chunk-rest s)))) +; (let [x (f idx (first s))] +; (if (nil? x) +; (keepi (inc idx) (rest s)) +; (cons x (keepi (inc idx) (rest s)))))))))] +; (keepi 0 coll)))) +; +;(defn take +; "Returns a lazy sequence of the first n items in coll, or all items if +; there are fewer than n. Returns a stateful transducer when +; no collection is provided." +; ([n] +; (fn [rf] +; (let [nv (volatile! n)] +; (fn +; ([] (rf)) +; ([result] (rf result)) +; ([result input] +; (let [n (deref nv) +; nn (vswap! nv dec) +; result (if (pos? n) +; (rf result input) +; result)] +; (if (not (pos? nn)) +; (ensure-reduced result) +; result))))))) +; ([n coll] +; (lazy-seq +; (when (pos? n) +; (when-let [s (seq coll)] +; (cons (first s) (take (dec n) (rest s)))))))) +; +;(defn repeatedly +; "Takes a function of no args, presumably with side effects, and +; returns an infinite (or length n if supplied) lazy sequence of calls +; to it" +; ([f] (lazy-seq (cons (f) (repeatedly f)))) +; ([n f] (take n (repeatedly f)))) +; +;(defn take-while +; "Returns a lazy sequence of successive items from coll while +; (pred item) returns logical true. pred must be free of side-effects. +; Returns a transducer when no collection is provided" +; ([pred] +; (fn [rf] +; (fn +; ([] (rf)) +; ([result] (rf result)) +; ([result input] +; (if (pred input) +; (rf result input) +; (reduced result)))))) +; ([pred coll] +; (lazy-seq +; (when-let [s (seq coll)] +; (when (pred (first s)) +; (cons (first s) (take-while pred (rest s)))))))) +; +;(defn drop +; "Returns a lazy sequence of all but the first n items in coll. +; Returns a stateful transducer when no collection is provided." +; ([n] +; (fn [rf] +; (let [nv (volatile! n)] +; (fn +; ([] (rf)) +; ([result] (rf result)) +; ([result input] +; (let [n (deref nv)] +; (vswap! nv dec) +; (if (pos? n) +; result +; (rf result input)))))))) +; ([n coll] +; (let [step (fn [n coll] +; (let [s (seq coll)] +; (if (and (pos? n) s) +; (recur (dec n) (rest s)) +; s)))] +; (lazy-seq (step n coll))))) +; +;(defn drop-last +; "Return a lazy sequence of all but the last n (default 1) items in coll" +; ([coll] (drop-last 1 coll)) +; ([n coll] (map (fn [x _] x) coll (drop n coll)))) +; +;(defn drop-while +; "Returns a lazy sequence of the items in coll starting from the +; first item for which (pred item) returns logical false. Returns a +; stateful transducer when no collection is provided." +; ([pred] +; (fn [rf] +; (let [dv (volatile! true)] +; (fn +; ([] (rf)) +; ([result] (rf result)) +; ([result input] +; (let [drop? (deref dv)] +; (if (and drop? (pred input)) +; result +; (do +; (vreset! dv nil) +; (rf result input))))))))) +; ([pred coll] +; (let [step (fn [pred coll] +; (let [s (seq coll)] +; (if (and s (pred (first s))) +; (recur pred (rest s)) +; s)))] +; (lazy-seq (step pred coll))))) +; +;(defn cycle +; "Returns a lazy (infinite!) sequence of repetitions of the items in coll." +; [coll] +; ; TODO: Custom cycle object +; (lazy-seq (concat coll (cycle coll)))) +; +;(defn repeat +; "Returns a lazy (infinite!, or length n if supplied) sequence of val." +; ([x] +; (cpp/jank.runtime.obj.repeat.create x)) +; ([n x] +; (cpp/jank.runtime.obj.repeat.create n x))) +; +;(defn split-at +; "Returns a vector of [(take n coll) (drop n coll)]" +; [n coll] +; [(take n coll) (drop n coll)]) +; +;(defn split-with +; "Returns a vector of [(take-while pred coll) (drop-while pred coll)]" +; [pred coll] +; [(take-while pred coll) (drop-while pred coll)]) +; +;(defn interleave +; "Returns a lazy seq of the first item in each coll, then the second etc." +; ([] ()) +; ([c1] (lazy-seq c1)) +; ([c1 c2] +; (lazy-seq +; (let [s1 (seq c1) s2 (seq c2)] +; (when (and s1 s2) +; (cons (first s1) (cons (first s2) +; (interleave (rest s1) (rest s2)))))))) +; ([c1 c2 & colls] +; (lazy-seq +; (let [ss (map seq (conj colls c2 c1))] +; (when (every? identity ss) +; (concat (map first ss) (apply interleave (map rest ss)))))))) +; +;(defn interpose +; "Returns a lazy seq of the elements of coll separated by sep. +; Returns a stateful transducer when no collection is provided." +; ([sep] +; (fn [rf] +; (let [started (volatile! false)] +; (fn +; ([] (rf)) +; ([result] (rf result)) +; ([result input] +; (if (deref started) +; (let [sepr (rf result sep)] +; (if (reduced? sepr) +; sepr +; (rf sepr input))) +; (do +; (vreset! started true) +; (rf result input)))))))) +; ([sep coll] +; (drop 1 (interleave (repeat sep) coll)))) +; +;(defn dorun +; "When lazy sequences are produced via functions that have side +; effects, any effects other than those needed to produce the first +; element in the seq do not occur until the seq is consumed. dorun can +; be used to force any effects. Walks through the successive nexts of +; the seq, does not retain the head and returns nil." +; ([coll] +; (when-let [s (seq coll)] +; (recur (next s)))) +; ([n coll] +; (when (and (seq coll) (pos? n)) +; (recur (dec n) (next coll))))) +; +;(defn doall +; "When lazy sequences are produced via functions that have side +; effects, any effects other than those needed to produce the first +; element in the seq do not occur until the seq is consumed. doall can +; be used to force any effects. Walks through the successive nexts of +; the seq, retains the head and returns it, thus causing the entire +; seq to reside in memory at one time." +; ([coll] +; (dorun coll) +; coll) +; ([n coll] +; (dorun n coll) +; coll)) +; +;(defn partition +; "Returns a lazy sequence of lists of n items each, at offsets step +; apart. If step is not supplied, defaults to n, i.e. the partitions +; do not overlap. If a pad collection is supplied, use its elements as +; necessary to complete last partition upto n items. In case there are +; not enough padding elements, return a partition with less than n items." +; ([n coll] +; (partition n n coll)) +; ([n step coll] +; (lazy-seq +; (when-let [s (seq coll)] +; (let [p (doall (take n s))] +; (when (= n (count p)) +; (cons p (partition n step (nthrest s step)))))))) +; ([n step pad coll] +; (lazy-seq +; (when-let [s (seq coll)] +; (let [p (doall (take n s))] +; (if (= n (count p)) +; (cons p (partition n step pad (nthrest s step))) +; (list (take n (concat p pad))))))))) +; +;(defn partition-all +; "Returns a lazy sequence of lists like partition, but may include +; partitions with fewer than n items at the end. Returns a stateful +; transducer when no collection is provided." +; ([n] +; (fn [rf] +; ;; OPTIMIZE: jvm clojure uses an array here for perf +; (let [part (volatile! [])] +; (fn +; ([] (rf)) +; ([result] +; (let [p (deref part) +; result (if (empty? p) +; result +; (unreduced (rf result p)))] +; (rf result))) +; ([result input] +; (let [p (vswap! part conj input)] +; (if (= n (count p)) +; (do (vreset! part []) +; (rf result p)) +; result))))))) +; ([n coll] +; (partition-all n n coll)) +; ([n step coll] +; (lazy-seq +; (when-let [s (seq coll)] +; (let [seg (doall (take n s))] +; (cons seg (partition-all n step (nthrest s step)))))))) +; +;(defn partition-by +; "Applies f to each value in coll, splitting it each time f returns a +; new value. Returns a lazy seq of partitions. Returns a stateful +; transducer when no collection is provided." +; ([f] +; (fn [rf] +; ;; OPTIMIZE: jvm clojure uses an array here for perf +; (let [vv (volatile! []) +; pv (volatile! ::none)] +; (fn +; ([] (rf)) +; ([result] +; (let [v (deref vv) +; result (if (empty? v) +; result +; (unreduced (rf result v)))] +; (rf result))) +; ([result input] +; (let [pval (deref pv) +; val (f input)] +; (vreset! pv val) +; (if (or (identical? pval ::none) +; (= val pval)) +; (do +; (vswap! vv conj input) +; result) +; (let [v (deref vv) +; ret (rf result v)] +; (when-not (reduced? ret) +; (vreset! vv [input])) +; ret)))))))) +; ([f coll] +; (lazy-seq +; (when-let [s (seq coll)] +; (let [fst (first s) +; fv (f fst) +; run (cons fst (take-while #(= fv (f %)) (next s)))] +; (cons run (partition-by f (lazy-seq (drop (count run) s))))))))) +; +;(defn frequencies +; "Returns a map from distinct items in coll to the number of times +; they appear." +; [coll] +; (persistent! +; (reduce +; (fn [counts x] +; (assoc! counts x (inc (get counts x 0)))) +; (transient {}) +; coll))) +; +;(defn group-by +; "Returns a map of the elements of coll keyed by the result of +; f on each element. The value at each key will be a vector of the +; corresponding elements, in the order they appeared in coll." +; [f coll] +; (persistent! +; (reduce +; (fn [ret x] +; (let [k (f x)] +; (assoc! ret k (conj (get ret k []) x)))) +; (transient {}) +; coll))) +; +;(defn reductions +; "Returns a lazy seq of the intermediate values of the reduction (as +; per reduce) of coll by f, starting with init." +; ([f coll] +; (lazy-seq +; (if-let [s (seq coll)] +; (reductions f (first s) (rest s)) +; (list (f))))) +; ([f init coll] +; (if (reduced? init) +; (list (deref init)) +; (cons init +; (lazy-seq +; (when-let [s (seq coll)] +; (reductions f (f init (first s)) (rest s)))))))) +; +;(defn into +; "Returns a new coll consisting of to-coll with all of the items of +; from-coll conjoined. A transducer may be supplied." +; ([] []) +; ([to] to) +; ([to from] +; (if (transientable? to) +; (with-meta (persistent! (reduce conj! (transient to) from)) (meta to)) +; (reduce conj to from))) +; ([to xform from] +; (if (transientable? to) +; (with-meta (persistent! (transduce xform conj! (transient to) from)) (meta to)) +; (transduce xform conj to from)))) +; +;; Redefine let and loop with destructuring. +;(defn destructure +; [bindings] +; (let [bents (partition 2 bindings) +; pb (fn pb [bvec b v] +; (let [pvec +; (fn pvec [bvec b val] +; (let [gvec (gensym "vec") +; gseq (gensym "seq") +; gfirst (gensym "first") +; has-rest (some #{'&} b)] +; (loop [ret (let [ret (conj bvec gvec val)] +; (if has-rest +; (conj ret gseq (list `seq gvec)) +; ret)) +; n 0 +; bs b +; seen-rest? false] +; (if (seq bs) +; (let [firstb (first bs)] +; (cond +; (= firstb '&) (recur (pb ret (second bs) gseq) +; n +; (nnext bs) +; true) +; (= firstb :as) (pb ret (second bs) gvec) +; :else (if seen-rest? +; (throw "Unsupported binding form, only :as can follow & parameter") +; (recur (pb (if has-rest +; (conj ret +; gfirst `(first ~gseq) +; gseq `(next ~gseq)) +; ret) +; firstb +; (if has-rest +; gfirst +; (list `nth gvec n nil))) +; (inc n) +; (next bs) +; seen-rest?)))) +; ret)))) +; pmap +; (fn pmap [bvec b v] +; (let [gmap (gensym "map") +; defaults (:or b)] +; (loop [ret (-> bvec +; (conj gmap) (conj v) +; (conj gmap) (conj `(if (seq? ~gmap) +; (if (next ~gmap) +; (into {} ~gmap) +; (if (seq ~gmap) +; (first ~gmap) +; {})) +; ~gmap)) +; ((fn pmap#ret [ret] +; (if (:as b) +; (conj ret (:as b) gmap) +; ret)))) +; bes (let [transforms +; (reduce +; (fn pmap#transforms [transforms mk] +; (if (keyword? mk) +; (let [mkns (namespace mk) +; mkn (name mk)] +; (cond (= mkn "keys") (assoc transforms mk #(keyword (or mkns (namespace %)) (name %))) +; (= mkn "syms") (assoc transforms mk #(list `quote (symbol (or mkns (namespace %)) (name %)))) +; (= mkn "strs") (assoc transforms mk str) +; :else transforms)) +; transforms)) +; {} +; (keys b))] +; (reduce +; (fn pmap#bes [bes entry] +; (reduce #(assoc %1 %2 ((val entry) %2)) +; (dissoc bes (key entry)) +; ((key entry) bes))) +; (dissoc b :as :or) +; transforms))] +; (if (seq bes) +; (let [bb (key (first bes)) +; bk (val (first bes)) +; local (if (named? bb) +; (with-meta (symbol nil (name bb)) (meta bb)) +; bb) +; bv (if (contains? defaults local) +; (list `get gmap bk (defaults local)) +; (list `get gmap bk))] +; (recur (if (ident? bb) +; (-> ret (conj local bv)) +; (pb ret bb bv)) +; (next bes))) +; ret))))] +; (cond +; (symbol? b) (-> bvec (conj b) (conj v)) +; (vector? b) (pvec bvec b v) +; (map? b) (pmap bvec b v) +; :else (throw (str "Unsupported binding form: " b))))) +; process-entry (fn process-entry [bvec b] +; (pb bvec (first b) (second b)))] +; (if (every? symbol? (map first bents)) +; bindings +; (reduce process-entry [] bents)))) +; +;(defmacro let +; "binding => binding-form init-expr +; binding-form => name, or destructuring-form +; destructuring-form => map-destructure-form, or seq-destructure-form +; +; Evaluates the exprs in a lexical context in which the symbols in +; the binding-forms are bound to their respective init-exprs or parts +; therein. +; +; See https://clojure.org/reference/special_forms#binding-forms for +; more information about destructuring." +; [bindings & body] +; (assert-macro-args +; (vector? bindings) "a vector for its binding" +; (even? (count bindings)) "an even number of forms in binding vector") +; `(let* ~(destructure bindings) ~@body)) +; +;(defn maybe-destructured +; {:private true} +; [params body] +; (if (every? symbol? params) +; (cons params body) +; (loop [params params +; new-params (with-meta [] (meta params)) +; lets []] +; (if params +; (if (symbol? (first params)) +; (recur (next params) (conj new-params (first params)) lets) +; (let [gparam (gensym "p__")] +; (recur (next params) (conj new-params gparam) +; (-> lets (conj (first params)) (conj gparam))))) +; `(~new-params +; (let ~lets +; ~@body)))))) +; +;(defmacro fn +; "params => positional-params*, or positional-params* & rest-param +; positional-param => binding-form +; rest-param => binding-form +; binding-form => name, or destructuring-form +; +; Defines a function. +; +; See https://clojure.org/reference/special_forms#fn for more information" +; [& sigs] +; (let [name (if (symbol? (first sigs)) (first sigs) nil) +; sigs (if name (next sigs) sigs) +; sigs (if (vector? (first sigs)) +; (list sigs) +; (if (seq? (first sigs)) +; sigs +; ; Assume single arity syntax +; (throw (if (seq sigs) +; (str "Parameter declaration " +; (first sigs) +; " should be a vector") +; (str "Parameter declaration missing"))))) +; psig (fn* [sig] +; ; Ensure correct type before destructuring sig +; (when (not (seq? sig)) +; (throw (str "Invalid signature " sig +; " should be a list"))) +; (let [[params & body] sig +; _ (when (not (vector? params)) +; (throw (if (seq? (first sigs)) +; (str "Parameter declaration " params +; " should be a vector") +; (str "Invalid signature " sig +; " should be a list")))) +; conds (when (and (next body) (map? (first body))) +; (first body)) +; body (if conds (next body) body) +; conds (or conds (meta params)) +; pre (:pre conds) +; post (:post conds) +; body (if post +; `((let [~'% ~(if (< 1 (count body)) +; `(do ~@body) +; (first body))] +; ~@(map (fn* [c] +; `(assert ~c)) post) +; ~'%)) +; body) +; body (if pre +; (concat (map (fn* [c] +; `(assert ~c)) pre) +; body) +; body)] +; (maybe-destructured params body))) +; new-sigs (map psig sigs)] +; (with-meta +; (if name +; `(fn* ~name ~@new-sigs) +; `(fn* ~@new-sigs)) +; (meta &form)))) +; +;(defmacro loop +; "Evaluates the exprs in a lexical context in which the symbols in +; the binding-forms are bound to their respective init-exprs or parts +; therein. Acts as a recur target." +; [all-bindings & body] +; (assert-macro-args +; (vector? all-bindings) "a vector for its binding" +; (even? (count all-bindings)) "an even number of forms in binding vector") +; (let [db (destructure all-bindings)] +; (if (= db all-bindings) +; `(loop* ~all-bindings ~@body) +; (let [values (take-nth 2 (drop 1 all-bindings)) +; bindings (take-nth 2 all-bindings) +; syms (map (fn [b] +; (if (symbol? b) +; b +; (gensym))) +; bindings) +; final-bindings (reduce (fn [ret [b v g]] +; (if (symbol? b) +; (conj ret g v) +; (conj ret g v b g))) +; [] +; (map vector bindings values syms))] +; `(let ~final-bindings +; (loop* ~(vec (interleave syms syms)) +; (let ~(vec (interleave bindings syms)) +; ~@body))))))) +; +;(defmacro for +; "List comprehension. Takes a vector of one or more +; binding-form/collection-expr pairs, each followed by zero or more +; modifiers, and yields a lazy sequence of evaluations of expr. +; Collections are iterated in a nested fashion, rightmost fastest, +; and nested coll-exprs can refer to bindings created in prior +; binding-forms. Supported modifiers are: :let [binding-form expr ...], +; :while test, :when test. +; +; (take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))" +; [seq-exprs body-expr] +; (assert-macro-args +; (vector? seq-exprs) "a vector for its binding" +; (even? (count seq-exprs)) "an even number of forms in binding vector") +; (let [to-groups (fn [seq-exprs] +; (reduce (fn [groups [k v]] +; (if (keyword? k) +; (conj (pop groups) (conj (peek groups) [k v])) +; (conj groups [k v]))) +; [] (partition 2 seq-exprs))) +; err (fn [& msg] (throw (apply str msg))) +; emit-bind (fn emit-bind [[[bind expr & mod-pairs] +; & [[_ next-expr] :as next-groups]]] +; (let [giter (gensym "iter__") +; gxs (gensym "s__") +; do-mod (fn do-mod [[[k v :as pair] & etc]] +; (cond +; (= k :let) `(let ~v ~(do-mod etc)) +; (= k :while) `(when ~v ~(do-mod etc)) +; (= k :when) `(if ~v +; ~(do-mod etc) +; (recur (rest ~gxs))) +; (keyword? k) (err "Invalid 'for' keyword " k) +; next-groups +; `(let [iterys# ~(emit-bind next-groups) +; fs# (seq (iterys# ~next-expr))] +; (if fs# +; (concat fs# (~giter (rest ~gxs))) +; (recur (rest ~gxs)))) +; :else (do +; `(cons ~body-expr +; (~giter (rest ~gxs))))))] +; (if next-groups +; ; not the inner-most loop +; `(fn ~giter [~gxs] +; (lazy-seq +; (loop [~gxs ~gxs] +; (when-first [~bind ~gxs] +; ~(do-mod mod-pairs))))) +; ; inner-most loop +; (let [gi (gensym "i__") +; gb (gensym "b__") +; do-cmod (fn do-cmod [[[k v :as pair] & etc]] +; (cond +; (= k :let) `(let ~v ~(do-cmod etc)) +; (= k :while) `(when ~v ~(do-cmod etc)) +; (= k :when) `(if ~v +; ~(do-cmod etc) +; (recur +; ; TODO: unchecked-inc +; (inc ~gi))) +; (keyword? k) +; (err "Invalid 'for' keyword " k) +; :else +; `(do (chunk-append ~gb ~body-expr) +; ; TODO: unchecked-inc +; (recur (inc ~gi)))))] +; `(fn ~giter [~gxs] +; (lazy-seq +; (loop [~gxs ~gxs] +; (when-let [~gxs (seq ~gxs)] +; (if (chunked-seq? ~gxs) +; (let [c# (chunk-first ~gxs) +; size# (int (count c#)) +; ~gb (chunk-buffer size#)] +; (if (loop [~gi (int 0)] +; (if (< ~gi size#) +; (let [~bind (nth c# ~gi)] +; ~(do-cmod mod-pairs)) +; true)) +; (chunk-cons +; (chunk ~gb) +; (~giter (chunk-rest ~gxs))) +; (chunk-cons (chunk ~gb) nil))) +; (let [~bind (first ~gxs)] +; ~(do-mod mod-pairs)))))))))))] +; `(let [iter# ~(emit-bind (to-groups seq-exprs))] +; (iter# ~(second seq-exprs))))) +; +;(defn not-empty +; "If coll is empty, returns nil, else coll" +; [coll] +; (when (seq coll) +; coll)) +; +;(defn get-in +; "Returns the value in a nested associative structure, +; where ks is a sequence of keys. Returns nil if the key +; is not present, or the not-found value if supplied." +; ([m ks] +; (reduce get m ks)) +; ([m ks not-found] +; (loop [m m +; ks (seq ks)] +; (if ks +; (let [m (get m (first ks) ::none)] +; (if (identical? ::none m) +; not-found +; (recur m (next ks)))) +; m)))) +; +;(defn assoc-in +; "Associates a value in a nested associative structure, where ks is a +; sequence of keys and v is the new value and returns a new nested structure. +; If any levels do not exist, hash-maps will be created." +; [m [k & ks] v] +; (if ks +; (assoc m k (assoc-in (get m k) ks v)) +; (assoc m k v))) +; +;(defn update-in +; "'Updates' a value in a nested associative structure, where ks is a +; sequence of keys and f is a function that will take the old value +; and any supplied args and return the new value, and returns a new +; nested structure. If any levels do not exist, hash-maps will be +; created." +; [m ks f & args] +; (let [up (fn up [m ks f args] +; (let [[k & ks] ks] +; (if ks +; (assoc m k (up (get m k) ks f args)) +; (assoc m k (apply f (get m k) args)))))] +; (up m ks f args))) +; +;(defn update +; "'Updates' a value in an associative structure, where k is a +; key and f is a function that will take the old value +; and any supplied args and return the new value, and returns a new +; structure. If the key does not exist, nil is passed as the old value." +; ([m k f] +; (assoc m k (f (get m k)))) +; ([m k f x] +; (assoc m k (f (get m k) x))) +; ([m k f x y] +; (assoc m k (f (get m k) x y))) +; ([m k f x y z] +; (assoc m k (f (get m k) x y z))) +; ([m k f x y z & more] +; (assoc m k (apply f (get m k) x y z more)))) +; +;(defmacro when-first +; "bindings => x xs +; +; Roughly the same as (when (seq xs) (let [x (first xs)] body)) but xs is evaluated only once" +; [bindings & body] +; (assert-macro-args +; (vector? bindings) "a vector for its binding" +; (= 2 (count bindings)) "exactly 2 forms in binding vector") +; (let [[x xs] bindings] +; `(when-let [xs# (seq ~xs)] +; (let [~x (first xs#)] +; ~@body)))) +; +;(defn take-last +; "Returns a seq of the last n items in coll. Depending on the type +; of coll may be no better than linear time. For vectors, see also subvec." +; [n coll] +; (loop [s (seq coll) +; lead (seq (drop n coll))] +; (if lead +; (recur (next s) (next lead)) +; s))) +; +;(defn mapv +; "Returns a vector consisting of the result of applying f to the +; set of first items of each coll, followed by applying f to the set +; of second items in each coll, until any one of the colls is +; exhausted. Any remaining items in other colls are ignored. Function +; f should accept number-of-colls arguments." +; ([f coll] +; (-> (reduce (fn [v o] +; (conj! v (f o))) +; (transient []) +; coll) +; persistent!)) +; ([f c1 c2] +; (into [] (map f c1 c2))) +; ([f c1 c2 c3] +; (into [] (map f c1 c2 c3))) +; ([f c1 c2 c3 & colls] +; (into [] (apply map f c1 c2 c3 colls)))) +; +;(defn filterv +; "Returns a vector of the items in coll for which +; (pred item) returns logical true. pred must be free of side-effects." +; [pred coll] +; (-> (reduce (fn [v o] +; (if (pred o) +; (conj! v o) +; v)) +; (transient []) +; coll) +; persistent!)) +; +;(defn mapcat +; "Returns the result of applying concat to the result of applying map +; to f and colls. Thus function f should return a collection. Returns +; a transducer when no collections are provided" +; ([f] (comp (map f) cat)) +; ; TODO: Variadic. +; ([f coll] +; (apply concat (map f coll)))) +; +;(defn tree-seq +; "Returns a lazy sequence of the nodes in a tree, via a depth-first walk. +; branch? must be a fn of one arg that returns true if passed a node +; that can have children (but may not). children must be a fn of one +; arg that returns a sequence of the children. Will only be called on +; nodes for which branch? returns true. Root is the root node of the +; tree." +; [branch? children root] +; (let [walk (fn walk [node] +; (lazy-seq +; (cons node +; (when (branch? node) +; (mapcat walk (children node))))))] +; (walk root))) +; +;(defn distinct +; "Returns a lazy sequence of the elements of coll with duplicates removed. +; Returns a stateful transducer when no collection is provided." +; ([] +; (fn [rf] +; (let [seen (volatile! #{})] +; (fn +; ([] (rf)) +; ([result] (rf result)) +; ([result input] +; (if (contains? (deref seen) input) +; result +; (do (vswap! seen conj input) +; (rf result input)))))))) +; ([coll] +; (let [step (fn step [xs seen] +; (lazy-seq +; ((fn [[f :as xs] seen] +; (when-let [s (seq xs)] +; (if (contains? seen f) +; (recur (rest s) seen) +; (cons f (step (rest s) (conj seen f)))))) +; xs seen)))] +; (step coll #{})))) +; +;(defn distinct? +; "Returns true if no two of the arguments are =" +; ([x] true) +; ([x y] (not (= x y))) +; ([x y & more] +; (if (not= x y) +; (loop [s #{x y} +; [x & etc :as xs] more] +; (if xs +; (if (contains? s x) +; false +; (recur (conj s x) etc)) +; true)) +; false))) +; +;(defn filter +; "Returns a lazy sequence of the items in coll for which +; (pred item) returns logical true. pred must be free of side-effects. +; Returns a transducer when no collection is provided." +; ([pred] +; (fn [rf] +; (fn +; ([] (rf)) +; ([result] (rf result)) +; ([result input] +; (if (pred input) +; (rf result input) +; result))))) +; ([pred coll] +; (lazy-seq +; (when-let [s (seq coll)] +; (if (chunked-seq? s) +; (let [c (chunk-first s) +; size (count c) +; b (chunk-buffer size)] +; (dotimes [i size] +; (let [v (nth c i)] +; (when (pred v) +; (chunk-append b v)))) +; (chunk-cons (chunk b) (filter pred (chunk-rest s)))) +; (let [f (first s) r (rest s)] +; (if (pred f) +; (cons f (filter pred r)) +; (filter pred r)))))))) +; +;(defn flatten +; "Takes any nested combination of sequential things (lists, vectors, +; etc.) and returns their contents as a single, flat lazy sequence. +; (flatten nil) returns an empty sequence." +; [x] +; (filter (complement sequential?) +; (rest (tree-seq sequential? seq x)))) +; +;(defn remove +; "Returns a lazy sequence of the items in coll for which +; (pred item) returns logical false. pred must be free of side-effects. +; Returns a transducer when no collection is provided." +; ([pred] +; (filter (complement pred))) +; ([pred coll] +; (filter (complement pred) coll))) +; +;(defn dedupe +; "Returns a lazy sequence removing consecutive duplicates in coll. +; Returns a transducer when no collection is provided." +; ([] +; (fn [rf] +; (let [pv (volatile! ::none)] +; (fn +; ([] (rf)) +; ([result] (rf result)) +; ([result input] +; (let [prior (deref pv)] +; (vreset! pv input) +; (if (= prior input) +; result +; (rf result input)))))))) +; ([coll] +; (let [step (fn step [prior xs] +; (lazy-seq +; (when-some [[x & more] (seq xs)] +; (if (= x prior) +; (step prior more) +; (cons x (step x more))))))] +; (step ::none coll)))) +; +;(defmacro condp +; "Takes a binary predicate, an expression, and a set of clauses. +; Each clause can take the form of either: +; +; test-expr result-expr +; +; test-expr :>> result-fn +; +; Note :>> is an ordinary keyword. +; +; For each clause, (pred test-expr expr) is evaluated. If it returns +; logical true, the clause is a match. If a binary clause matches, the +; result-expr is returned, if a ternary clause matches, its result-fn, +; which must be a unary function, is called with the result of the +; predicate as its argument, the result of that call being the return +; value of condp. A single default expression can follow the clauses, +; and its value will be returned if no clause matches. If no default +; expression is provided and no clause matches, an +; IllegalArgumentException is thrown." +; [pred expr & clauses] +; (let [gpred (gensym "pred__") +; gexpr (gensym "expr__") +; emit (fn emit [pred expr args] +; (let [[[a b c :as clause] more] +; (split-at (if (= :>> (second args)) 3 2) args) +; n (count clause)] +; (cond +; (= 0 n) `(throw (str "No matching clause: " ~expr)) +; (= 1 n) a +; (= 2 n) `(if (~pred ~a ~expr) +; ~b +; ~(emit pred expr more)) +; :else `(if-let [p# (~pred ~a ~expr)] +; (~c p#) +; ~(emit pred expr more)))))] +; `(let [~gpred ~pred +; ~gexpr ~expr] +; ~(emit gpred gexpr clauses)))) +; +;(defmacro cond-> +; "Takes an expression and a set of test/form pairs. Threads expr (via ->) +; through each form for which the corresponding test +; expression is true. Note that, unlike cond branching, cond-> threading does +; not short circuit after the first true test expression." +; [expr & clauses] +; (assert (even? (count clauses))) +; (let [g (gensym) +; steps (map (fn [test+step] +; (let [test (first test+step) +; step (second test+step)] +; `(if ~test +; (-> ~g ~step) +; ~g))) +; (partition 2 clauses))] +; `(let [~g ~expr +; ~@(interleave (repeat g) (butlast steps))] +; ~(if (empty? steps) +; g +; (last steps))))) +; +;(defmacro cond->> +; "Takes an expression and a set of test/form pairs. Threads expr (via ->>) +; through each form for which the corresponding test expression +; is true. Note that, unlike cond branching, cond->> threading does not short circuit +; after the first true test expression." +; [expr & clauses] +; (assert (even? (count clauses))) +; (let [g (gensym) +; steps (map (fn [[test step]] `(if ~test (->> ~g ~step) ~g)) +; (partition 2 clauses))] +; `(let [~g ~expr +; ~@(interleave (repeat g) (butlast steps))] +; ~(if (empty? steps) +; g +; (last steps))))) +; +;(defmacro as-> +; "Binds name to expr, evaluates the first form in the lexical context +; of that binding, then binds name to that result, repeating for each +; successive form, returning the result of the last form." +; [expr name & forms] +; `(let [~name ~expr +; ~@(interleave (repeat name) (butlast forms))] +; ~(if (empty? forms) +; name +; (last forms)))) +; +;(defmacro some-> +; "When expr is not nil, threads it into the first form (via ->), +; and when that result is not nil, through the next etc" +; [expr & forms] +; (let [g (gensym) +; steps (map (fn [step] `(if (nil? ~g) nil (-> ~g ~step))) +; forms)] +; `(let [~g ~expr +; ~@(interleave (repeat g) (butlast steps))] +; ~(if (empty? steps) +; g +; (last steps))))) +; +;(defmacro some->> +; "When expr is not nil, threads it into the first form (via ->>), +; and when that result is not nil, through the next etc" +; [expr & forms] +; (let [g (gensym) +; steps (map (fn [step] `(if (nil? ~g) nil (->> ~g ~step))) +; forms)] +; `(let [~g ~expr +; ~@(interleave (repeat g) (butlast steps))] +; ~(if (empty? steps) +; g +; (last steps))))) +; +;;; Functions. +;(defn ifn? +; "Returns true if x implements IFn. Note that many data structures +; (e.g. sets and maps) implement IFn" +; [x] +; (cpp/jank.runtime.is_callable x)) +;(defn fn? +; "Returns true if x implements Fn, i.e. is an object created via fn." +; [x] +; (cpp/clojure.core_native.is_fn x)) +; +;;; Multimethods. +;(defn- check-valid-options +; "Throws an exception if the given option map contains keys not listed +; as valid, else returns nil." +; [options & valid-keys] +; (when (seq (apply disj (apply hash-set (keys options)) valid-keys)) +; (throw (apply str "Only these options are valid: " +; (first valid-keys) +; (map #(str ", " %) (rest valid-keys)))))) +; +;(defn- multi-fn? +; [x] +; (cpp/clojure.core_native.is_multi_fn x)) +; +;(defn- multi-fn* +; [name dispatch_fn default hierarchy] +; (cpp/clojure.core_native.multi_fn name dispatch_fn default hierarchy)) +; +;(def global-hierarchy) +; +;(defmacro defmulti +; "Creates a new multimethod with the associated dispatch function. +; The docstring and attr-map are optional. +; +; Options are key-value pairs and may be one of: +; +; :default +; +; The default dispatch value, defaults to :default +; +; :hierarchy +; +; The value used for hierarchical dispatch (e.g. ::square is-a ::shape) +; +; Hierarchies are type-like relationships that do not depend upon type +; inheritance. By default Clojure's multimethods dispatch off of a +; global hierarchy map. However, a hierarchy relationship can be +; created with the derive function used to augment the root ancestor +; created with make-hierarchy. +; +; Multimethods expect the value of the hierarchy option to be supplied as +; a reference type e.g. a var (i.e. via the Var-quote dispatch macro #' +; or the var special form)." +; [mm-name & options] +; (let [docstring (if (string? (first options)) +; (first options) +; nil) +; options (if (string? (first options)) +; (next options) +; options) +; m (if (map? (first options)) +; (first options) +; {}) +; options (if (map? (first options)) +; (next options) +; options) +; dispatch-fn (first options) +; options (next options) +; m (if docstring +; (assoc m :doc docstring) +; m) +; m (if (meta mm-name) +; (conj (meta mm-name) m) +; m) +; mm-name (with-meta mm-name m)] +; (let [options (apply hash-map options) +; default (get options :default :default) +; hierarchy (get options :hierarchy #'global-hierarchy)] +; (check-valid-options options :default :hierarchy) +; ; TODO: This returns nil, due to an issue with let*. Why? +; `(let [v# (def ~mm-name)] +; (when-not (multi-fn? (deref v#)) +; (def ~mm-name (multi-fn* '~(symbol *ns* mm-name) ~dispatch-fn ~default ~hierarchy))))))) +; +;(defn- defmethod* +; [multifn dispatch-val f] +; (cpp/clojure.core_native.defmethod multifn dispatch-val f)) +; +;(defmacro defmethod +; "Creates and installs a new method of multimethod associated with dispatch-value. " +; [multifn dispatch-val & fn-tail] +; `(defmethod* ~multifn ~dispatch-val (fn ~@fn-tail))) +; +;(defn remove-all-methods +; "Removes all of the methods of multimethod." +; [multifn] +; (cpp/clojure.core_native.remove_all_methods multifn)) +; +;(defn remove-method +; "Removes the method of multimethod associated with dispatch-value." +; [multifn dispatch-val] +; (cpp/clojure.core_native.remove_method multifn dispatch-val)) +; +;(defn prefer-method +; "Causes the multimethod to prefer matches of dispatch-val-x over dispatch-val-y +; when there is a conflict" +; [multifn dispatch-val-x dispatch-val-y] +; (cpp/clojure.core_native.prefer_method multifn dispatch-val-x dispatch-val-y)) +; +;(defn methods +; "Given a multimethod, returns a map of dispatch values -> dispatch fns" +; [multifn] +; (cpp/clojure.core_native.methods multifn)) +; +;(defn get-method +; "Given a multimethod and a dispatch value, returns the dispatch fn +; that would apply to that value, or nil if none apply and no default" +; [multifn dispatch-val] +; (cpp/clojure.core_native.get_method multifn dispatch-val)) +; +;(defn prefers +; "Given a multimethod, returns a map of preferred value -> set of other values" +; [multifn] +; (cpp/clojure.core_native.prefers multifn)) +; +;;; Hierarchies. +;(defn make-hierarchy +; "Creates a hierarchy object for use with derive, isa? etc." +; [] +; {:parents {} +; :descendants {} +; :ancestors {}}) +; +;(def ^:private global-hierarchy (make-hierarchy)) +; +;(defn isa? +; "Returns true if (= child parent), or child is directly or indirectly derived from +; parent, either via a Java type inheritance relationship or a +; relationship established via derive. h must be a hierarchy obtained +; from make-hierarchy, if not supplied defaults to the global +; hierarchy" +; ([child parent] +; (isa? global-hierarchy child parent)) +; ([h child parent] +; (or (= child parent) +; (contains? (get (:ancestors h) child) parent) +; (and (vector? parent) (vector? child) +; (= (count parent) (count child)) +; (loop [ret true +; i 0] +; (if (or (not ret) (= i (count parent))) +; ret +; (recur (isa? h (get child i) (get parent i)) (inc i)))))))) +; +;(defn parents +; "Returns the immediate parents of tag, either via a Java type +; inheritance relationship or a relationship established via derive. h +; must be a hierarchy obtained from make-hierarchy, if not supplied +; defaults to the global hierarchy" +; ([tag] +; (parents global-hierarchy tag)) +; ([h tag] +; (not-empty (get (:parents h) tag)))) +; +;(defn ancestors +; "Returns the immediate and indirect parents of tag, either via a Java type +; inheritance relationship or a relationship established via derive. h +; must be a hierarchy obtained from make-hierarchy, if not supplied +; defaults to the global hierarchy" +; ([tag] +; (ancestors global-hierarchy tag)) +; ([h tag] +; (not-empty (get (:ancestors h) tag)))) +; +;(defn descendants +; "Returns the immediate and indirect children of tag, through a +; relationship established via derive. h must be a hierarchy obtained +; from make-hierarchy, if not supplied defaults to the global +; hierarchy. Note: does not work on Java type inheritance +; relationships." +; ([tag] +; (descendants global-hierarchy tag)) +; ([h tag] +; (not-empty (get (:descendants h) tag)))) +; +;(defn derive +; "Establishes a parent/child relationship between parent and +; tag. Parent must be a namespace-qualified symbol or keyword and +; child can be either a namespace-qualified symbol or keyword or a +; class. h must be a hierarchy obtained from make-hierarchy, if not +; supplied defaults to, and modifies, the global hierarchy." +; ([tag parent] +; (assert (namespace parent)) +; (assert (and (named? tag) (namespace tag))) +; (alter-var-root #'global-hierarchy derive tag parent) +; nil) +; ([h tag parent] +; (assert (not= tag parent)) +; (assert (named? tag)) +; (assert (named? parent)) +; (let [tp (:parents h) +; td (:descendants h) +; ta (:ancestors h) +; tf (fn [m source sources target targets] +; (reduce (fn [ret k] +; (assoc ret +; k +; (reduce conj +; (get targets k #{}) +; (cons target (targets target))))) +; m +; (cons source (sources source))))] +; (or +; (when-not (contains? (tp tag) parent) +; (when (contains? (ta tag) parent) +; (throw (str tag " already has " parent " as ancestor"))) +; (when (contains? (ta parent) tag) +; (throw (str "Cyclic derivation: " parent " has " tag " as ancestor"))) +; {:parents (assoc (:parents h) tag (conj (get tp tag #{}) parent)) +; :ancestors (tf (:ancestors h) tag td parent ta) +; :descendants (tf (:descendants h) parent ta tag td)}) +; h)))) +; +;(defn underive +; "Removes a parent/child relationship between parent and +; tag. h must be a hierarchy obtained from make-hierarchy, if not +; supplied defaults to, and modifies, the global hierarchy." +; ([tag parent] +; (alter-var-root #'global-hierarchy underive tag parent) nil) +; ([h tag parent] +; (let [parent-map (:parents h) +; child-parents (if (parent-map tag) +; (disj (parent-map tag) parent) +; #{}) +; new-parents (if (not-empty child-parents) +; (assoc parent-map tag child-parents) +; (dissoc parent-map tag)) +; deriv-seq (flatten (map #(cons (key %) (interpose (key %) (val %))) +; (seq new-parents)))] +; (if (contains? (parent-map tag) parent) +; (reduce #(apply derive %1 %2) +; (make-hierarchy) +; (partition 2 deriv-seq)) +; h)))) +; +;(defmacro defonce +; "defs name to have the root value of the expr iff the named var has no root value, +; else expr is unevaluated" +; [name expr] +; `(let [v# (def ~name)] +; (when-not (bound? v#) +; (def ~name ~expr)))) +; +;;; Case. +;(def ^:private max-mask-bits 13) +;(def ^:private max-switch-table-size (bit-shift-left 1 max-mask-bits)) +; +;(defn- i64? [n] +; (and (integer? n) +; (>= n (cpp/value "std::numeric_limits::min()")) +; (<= n (cpp/value "std::numeric_limits::max()")))) +; +;(defn- i32? [n] +; (and (integer? n) +; (>= n (cpp/value "std::numeric_limits::min()")) +; (<= n (cpp/value "std::numeric_limits::max()")))) +; +;(defn- shift-mask [shift mask x] +; (-> x (bit-shift-right shift) (bit-and mask))) +; +;(defn- case-hash +; "Returns the input if it is within the range of a 32-bit signed integer, otherwise returns the hash of the +; input. The native hash returns a int32 int so this is to make sure that (case-hash (case-hash x)) == (case-hash x). +; A key may be hashed more than once and we need to make sure its value does not change in later hashing." +; [input] +; (if (i32? input) +; input +; (hash input))) +; +;(defn- maybe-min-hash +; "Takes a collection of hashes and returns [shift mask] or nil if none found" +; [hashes] +; (first +; (filter +; (fn [[s m]] +; (apply distinct? (map #(shift-mask s m %) hashes))) +; (for [mask +; (map #(dec (bit-shift-left 1 %)) (range 1 (inc max-mask-bits))) +; shift +; (range 0 31)] +; [shift mask])))) +; +;(defn- case-map-with-check +; "Transforms a sequence of test constants and their corresponding branch expressions +; into a sorted map for consumption by `case*`. This version is used when no hash collisions +; are detected (i.e. the skip-check set is empty). +; +; Returns a sorted map where each key is the transformed test constant and each value is a `condp` form +; that checks the original expression against the test constant before selecting the branch." +; [expr-sym default case-f test-f tests thens] +; (into (sorted-map) +; (zipmap (map case-f tests) +; (map +; (fn [key then] +; (let [key +; (if (symbol? key) +; (list 'quote key) +; key)] +; `(condp = ~expr-sym ~key ~then +; ~default))) +; (map test-f tests) +; thens)))) +; +;(defn- case-map-collison-merged +; "Transforms a sequence of test constants and their corresponding branch expressions +; into a sorted map for consumption by `case*`. +; +; This version is selected when hash collisions have been detected (i.e. the skip-check set is nonempty) +; and resolved (typically via merging in `merge-hash-collisions`). In these cases, the branch expressions +; have already been pre-wrapped in `condp` forms to handle multiple colliding constants. Therefore, no additional +; wrapping is needed here-the transformed test constants are mapped directly to their corresponding branch expressions. +; +; Returns a sorted map mapping each transformed test constant directly to its branch expression." +; [case-f test-f tests thens] +; (into (sorted-map) +; (zipmap (map case-f tests) thens))) +; +;(defn- case-map +; [expr-sym default case-f test-f tests thens skip-check] +; (if (empty? skip-check) +; (case-map-with-check expr-sym default case-f test-f tests thens) +; (case-map-collison-merged case-f test-f tests thens))) +; +;(defn- fits-table? +; "Returns true if the collection of ints can fit within the +; max-table-switch-size, false otherwise." +; [ints] +; (< (- (apply max (seq ints)) (apply min (seq ints))) max-switch-table-size)) +; +;(defn- prep-ints +; "Takes a sequence of int-sized test constants and a corresponding sequence of +; then expressions. Returns a tuple of [shift mask case-map] where +; case-map is a map of int case values to [test then] tuples" +; [expr-sym default tests thens] +; (if (fits-table? tests) +; ; compact case ints, no shift-mask +; [0 0 (case-map expr-sym default int int tests thens #{})] +; (let [[shift mask] (or (maybe-min-hash (map int tests)) [0 0])] +; (if (zero? mask) +; ; sparse case ints, no shift-mask +; [0 0 (case-map expr-sym default int int tests thens #{})] +; ; compact case ints, with shift-mask +; [shift +; mask +; (case-map expr-sym default #(shift-mask shift mask (int %)) int tests thens #{})])))) +; +;(defn- merge-hash-collisions +; "Takes a case expression, default expression, and a sequence of test constants +; and a corresponding sequence of then expressions. Returns a tuple of +; [tests thens skip-check-set] where no tests have the same hash. Each set of +; input test constants with the same hash is replaced with a single test +; constant (the case int), and their respective thens are combined into: +; (condp = expr +; test-1 then-1 +; ... +; test-n then-n +; default). +; The skip-check is a set of case ints for which post-switch equivalence +; checking must not be done (the cases holding the above condp thens)." +; [expr-sym default tests thens] +; (let [buckets +; (loop [m {} +; ks tests +; vs thens] +; (if (and ks vs) +; (recur +; (update m (case-hash (first ks)) (fnil conj []) [(first ks) (first vs)]) +; (next ks) (next vs)) +; m)) +; assoc-multi +; (fn [m h bucket] +; (let [testexprs +; (mapcat (fn [kv] [(list 'quote (first kv)) (second kv)]) bucket) +; expr +; `(condp = ~expr-sym ~@testexprs ~default)] +; (assoc m h expr))) +; hmap +; (reduce +; (fn [m [h bucket]] +; (if (== 1 (count bucket)) +; (assoc m (ffirst bucket) (second (first bucket))) +; (assoc-multi m h bucket))) +; {} buckets) +; skip-check +; (->> buckets +; (filter #(< 1 (count (second %)))) +; (map first) +; (into #{}))] +; [(keys hmap) (vals hmap) skip-check])) +; +;(defn- prep-hashes +; "Takes a sequence of test constants and a corresponding sequence of then +; expressions. Returns a tuple of [shift mask case-map] +; where case-map is a map of int case values to [test then] tuples." +; [expr-sym default tests thens skip-check] +; (let [hashes (into #{} (map case-hash tests))] +; (if (== (count tests) (count hashes)) +; (if (fits-table? hashes) +; ; compact case ints, no shift-mask +; [0 0 +; (case-map expr-sym default case-hash identity tests thens skip-check)] +; (let [[shift mask] (or (maybe-min-hash hashes) [0 0])] +; (if (zero? mask) +; ; sparse case ints, no shift-mask +; [0 0 +; (case-map expr-sym default case-hash identity tests thens skip-check)] +; ; compact case ints, with shift-mask +; [shift mask +; (case-map expr-sym default #(shift-mask shift mask (case-hash %)) identity tests thens skip-check)]))) +; ; resolve hash collisions and try again +; (let [[tests thens skip-check] +; (merge-hash-collisions expr-sym default tests thens) +; [shift mask case-map] +; (prep-hashes expr-sym default tests thens skip-check) +; skip-check +; (if (zero? mask) +; skip-check +; (into #{} (map #(shift-mask shift mask %) skip-check)))] +; [shift mask case-map])))) +; +;(defmacro case +; "Takes an expression, and a set of clauses. +; +; Each clause can take the form of either: +; +; test-constant result-expr +; +; (test-constant1 ... test-constantN) result-expr +; +; The test-constants are not evaluated. They must be compile-time +; literals, and need not be quoted. If the expression is equal to a +; test-constant, the corresponding result-expr is returned. A single +; default expression can follow the clauses, and its value will be +; returned if no clause matches. If no default expression is provided +; and no clause matches, an IllegalArgumentException is thrown. +; +; Unlike cond and condp, case does a constant-time dispatch, the +; clauses are not considered sequentially. All manner of constant +; expressions are acceptable in case, including numbers, strings, +; symbols, keywords, and (Clojure) composites thereof. Note that since +; lists are used to group multiple constants that map to the same +; expression, a vector can be used to match a list if needed. The +; test-constants need not be all of the same type." +; {:added "1.2"} +; +; [e & clauses] +; (let [ge +; (gensym) +; default +; (if (odd? (count clauses)) +; (last clauses) +; `(throw (str "No matching clause: " ~ge)))] +; (if (> 2 (count clauses)) +; `(let [~ge ~e] ~default) +; (let [pairs +; (partition 2 clauses) +; assoc-test +; (fn assoc-test [m test expr] +; (if (contains? m test) +; (throw (str "Duplicate case test constant: " test)) +; (assoc m test expr))) +; pairs +; (reduce +; (fn [m [test expr]] +; (if (seq? test) +; (reduce #(assoc-test %1 %2 expr) m test) +; (assoc-test m test expr))) +; {} pairs) +; tests +; (keys pairs) +; thens +; (vals pairs) +; mode +; (cond +; (every? i64? tests) +; :ints +; +; (every? keyword? tests) +; :identity +; +; :else +; :hashes)] +; (condp = mode +; :ints +; (let [[shift mask imap] (prep-ints ge default tests thens)] +; `(let [~ge ~e] (case* ~ge ~shift ~mask ~default ~imap))) +; :hashes +; (let [[shift mask imap] +; (prep-hashes ge default tests thens #{})] +; `(let [~ge ~e] +; (case* ~ge ~shift ~mask ~default ~imap))) +; :identity +; (let [[shift mask imap] +; (prep-hashes ge default tests thens #{})] +; `(let [~ge ~e] +; (case* ~ge ~shift ~mask ~default ~imap)))))))) +; +;;; Miscellaneous. +;; TODO: jank.core +;(defn- sleep [ms] +; (cpp/clojure.core_native.sleep ms)) +;(defn- current-time [] +; (cpp/clojure.core_native.current_time)) +; +;(defmacro time +; "Evaluates expr and prints the time it took. Returns the value of expr." +; [expr] +; `(let [start# (current-time) +; ret# ~expr +; end# (current-time)] +; (println (str "Elapsed time: " (/ (- end# start#) 1000000.0) " ms")) +; ret#)) +; +;(defn with-redefs-fn +; "Temporarily redefines Vars during a call to func. Each val of +; binding-map will replace the root value of its key which must be +; a Var. After func is called with no args, the root values of all +; the Vars will be set back to their old values. These temporary +; changes will be visible in all threads. Useful for mocking out +; functions during testing." +; [binding-map fun] +; (let [root-bind (fn root-bind [m] +; (doseq [kv m] +; (cpp/clojure.core_native.var_bind_root (first kv) (second kv)))) +; old-vals (zipmap (keys binding-map) +; (map #(cpp/clojure.core_native.var_get_root %) (keys binding-map)))] +; (try +; (root-bind binding-map) +; (fun) +; (finally +; (root-bind old-vals))))) +; +;(defmacro with-redefs +; "binding => var-symbol temp-value-expr +; +; Temporarily redefines Vars while executing the body. The +; temp-value-exprs will be evaluated and each resulting value will +; replace in parallel the root value of its Var. After the body is +; executed, the root values of all the Vars will be set back to their +; old values. These temporary changes will be visible in all threads. +; Useful for mocking out functions during testing." +; [bindings & body] +; (list `with-redefs-fn +; (zipmap (map (fn [v] +; (list 'var v)) +; (take-nth 2 bindings)) +; (take-nth 2 (next bindings))) +; (list* `fn [] +; body))) +; +;;; Namespaces. +;(defn in-ns +; "Sets *ns* to the namespace named by the symbol, creating it if needed." +; [name] +; (cpp/clojure.core_native.in_ns name)) +; +;(defn create-ns +; "Create a new namespace named by the symbol if one doesn't already +; exist, returns it or the already-existing namespace of the same +; name." +; [sym] +; (cpp/clojure.core_native.intern_ns sym)) +; +; +;(defn find-ns +; "Returns the namespace named by the symbol or nil if it doesn't exist." +; [sym] +; (cpp/clojure.core_native.find_ns sym)) +; +;(defn find-var +; "Returns the global var named by the namespace-qualified symbol, or +; nil if no var with that name." +; [sym] +; (cpp/clojure.core_native.find_var sym)) +; +;(defn remove-ns +; "Removes the namespace named by the symbol. Use with caution. +; Cannot be used to remove the clojure namespace." +; [sym] +; (cpp/clojure.core_native.remove_ns sym)) +; +;(defn the-ns +; "If passed a namespace, returns it. Else, when passed a symbol, +; returns the namespace named by it, throwing an exception if not +; found." +; [ns-or-sym] +; (if (cpp/clojure.core_native.is_ns ns-or-sym) +; ns-or-sym +; (let [found (find-ns ns-or-sym)] +; (if (nil? found) +; (throw (ex-info :not-an-ns-or-sym {:value ns-or-sym})) +; found)))) +; +;(defn ns-name +; "Returns the name of the namespace, a symbol." +; [ns-sym] +; (let [ns (the-ns ns-sym)] +; (cpp/clojure.core_native.ns_name ns))) +; +;(defn ns-map +; "Returns a map of all the mappings for the namespace." +; [ns-sym] +; (let [ns (the-ns ns-sym)] +; (cpp/clojure.core_native.ns_map ns))) +; +;(defn ns-publics +; "Returns a map of the public intern mappings for the namespace." +; [ns-sym] +; (let [ns (the-ns ns-sym)] +; ; TODO: It may be faster to start with the whole map and dissoc. +; ; TODO: Good use case for transients. +; (reduce (fn [acc kv] +; (let [k (first kv) +; v (second kv)] +; ; TODO: Check for visibility. +; (if (var? v) +; (if (= ns (cpp/clojure.core_native.var_ns v)) +; (assoc acc k v) +; acc) +; acc))) +; {} +; (ns-map ns)))) +; +;(defn ns-resolve +; "Returns the var to which a symbol will be resolved in the +; namespace (unless found in the environment), else nil. Note that +; if the symbol is fully qualified, the var to which it resolves +; need not be present in the namespace." +; ([ns sym] +; (ns-resolve ns nil sym)) +; ([ns env sym] +; (when-not (contains? env sym) +; (cpp/clojure.core_native.ns_resolve (the-ns ns) sym)))) +; +;(defn resolve +; "Same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)" +; ([sym] +; (ns-resolve *ns* sym)) +; ([env sym] +; (ns-resolve *ns* env sym))) +; +;(defn- libspec? [x] +; (or (symbol? x) +; (and (vector? x) +; (or (nil? (second x)) +; (keyword? (second x)))))) +; +;(defn- prependss [x coll] +; (if (symbol? x) +; (cons x coll) +; (concat x coll))) +; +;(defn- root-resource [lib] +; (str "/" (name lib))) +; +;(defn- throw-if [pred msg] +; (when pred +; (throw (ex-info :assertion-failure {:msg msg})))) +; +;(defn alias +; "Add an alias in the current namespace to another +; namespace. Arguments are two symbols: the alias to be used, and +; the symbolic name of the target namespace. Use :as in the ns macro in preference +; to calling this directly." +; [alias ns-sym] +; (let [ns-obj (the-ns ns-sym)] +; (cpp/clojure.core_native.alias *ns* ns-obj alias))) +; +;(defn refer +; "refers to all public vars of ns, subject to filters. +; filters can include at most one each of: +; +; :exclude list-of-symbols +; :only list-of-symbols +; :rename map-of-fromsymbol-tosymbol +; +; For each public interned var in the namespace named by the symbol, +; adds a mapping from the name of the var to the var to the current +; namespace. Throws an exception if name is already mapped to +; something else in the current namespace. Filters can be used to +; select a subset, via inclusion or exclusion, or to provide a mapping +; to a symbol different from the var's name, in order to prevent +; clashes. Use :use in the ns macro in preference to calling this directly." +; [ns-sym & filters] +; (let [ns (find-ns ns-sym) +; _ (when (nil? ns) +; (throw (ex-info :unknown-namespace {:value ns-sym}))) +; filters (apply hash-map filters) +; rename (or (:rename filters) {}) +; exclude? (set (:exclude filters)) +; sym->var (ns-publics ns) +; to-refer (if (= :all (get filters :refer)) +; (keys sym->var) +; (or (get filters :refer) (get filters :only) (keys sym->var)))] +; ; TODO: Loop +; (reduce (fn [acc sym] +; (when (not (exclude? sym)) +; (let [v (get sym->var sym) +; sym (rename sym sym)] +; (when (nil? v) +; (throw (ex-info :var-does-not-exist {:value sym}))) +; (cpp/clojure.core_native.refer *ns* sym v)))) +; nil +; to-refer))) +; +;;; TODO: Should be a ref instead of atom +;(defonce +; ^{:private true +; :dynamic true +; :doc "An atom holding a sorted set of symbols representing loaded libs"} +; *loaded-libs* (atom (sorted-set))) +; +;(defonce +; ^{:private true +; :dynamic true +; :doc "A stack of paths currently being loaded by this thread"} +; *pending-paths* ()) +; +;(defn- check-cyclic-dependency +; "Detects and rejects non-trivial cyclic load dependencies. The +; exception message shows the dependency chain with the cycle +; highlighted. Ignores the trivial case of a file attempting to load +; itself because that can occur when a gen-class'd class loads its +; implementation." +; [path] +; (when (some #{path} (rest *pending-paths*)) +; (let [pending (map #(if (= % path) (str "[ " % " ]") %) +; (cons path *pending-paths*)) +; chain (apply str (interpose "->" pending))] +; (throw-if true (str "Cyclic load dependency: " chain))))) +; +;(defn load +; "Loads Clojure code from resources in the module path. A path is interpreted as +; module-path-relative if it begins with a slash or relative to the root +; directory for the current namespace otherwise." +; [& paths] +; (doseq [path paths] +; (check-cyclic-dependency path) +; (when-not (= path (first *pending-paths*)) +; (binding [*pending-paths* (conj *pending-paths* path)] +; (clojure.core-native/load-module path))))) +; +;(defn- load-one +; "Loads a lib given its name. If `need-ns?`, ensures that the associated +; namespace exists after loading. If `require?`, records the load so any +; duplicate loads can be skipped." +; [lib need-ns? require?] +; (load (root-resource lib)) +; (throw-if (and need-ns? (not (find-ns lib))) +; (str "namespace " lib " not found after loading " (root-resource lib))) +; (when require? +; (swap! *loaded-libs* conj lib))) +; +;(defn- load-all +; "Loads a lib given its name and forces a load of any libs it directly or +; indirectly loads. If need-ns?, ensures that the associated namespace +; exists after loading. If require?, records the load so any duplicate loads +; can be skipped." +; [lib need-ns? require?] +; (swap! *loaded-libs* #(reduce conj %1 %2) +; (binding [*loaded-libs* (atom (sorted-set))] +; (load-one lib need-ns? require?) +; @*loaded-libs*))) +; +;(defn- load-lib +; "Loads a lib with options" +; [lib & options] +; (let [opts (apply hash-map options) +; ; TODO: Map destructuring. +; as (:as opts) +; reload (:reload opts) +; reload-all (:reload-all opts) +; require (:require opts) +; use (:use opts) +; verbose (:verbose opts) +; as-alias (:as-alias opts) +; loaded? (contains? @*loaded-libs* lib) +; need-ns? (or as use) +; load (cond reload-all load-all +; reload load-one +; (not loaded?) (cond need-ns? load-one +; as-alias (fn [lib _need _require] +; (create-ns lib)) +; :else load-one)) +; +; filter-opts (select-keys opts [:exclude :only :rename :refer]) +; undefined-on-entry? (not (find-ns lib))] +; (if load +; (try +; (load lib need-ns? require) +; (catch e +; (when undefined-on-entry? +; (remove-ns lib)) +; (throw e))) +; (throw-if (and need-ns? (not (find-ns lib))) +; (str "namespace " lib " not found"))) +; (when as +; (alias as lib)) +; (when as-alias +; (alias as-alias lib)) +; (when (or use (:refer filter-opts)) +; (apply refer lib (mapcat seq filter-opts))))) +; +;(defn- load-libs +; "Loads libs, interpreting libspecs, prefix lists, and flags for +; forwarding to load-lib" +; [& args] +; (let [flags (filter keyword? args) +; opts (interleave flags (repeat true)) +; args (remove keyword? args)] +; (let [supported #{:as :reload :reload-all :require :use :verbose :refer :as-alias} +; unsupported (seq (remove supported flags))] +; (throw-if unsupported +; (str "Unsupported option(s) supplied: " unsupported))) +; (throw-if (not (seq args)) "Nothing specified to load") +; (doseq [arg args] +; (throw-if (not (libspec? arg)) (str "not a libspec: " arg)) +; (apply load-lib (prependss arg opts))))) +; +;(defn compile +; "Compiles the namespace named by the symbol lib into a set of +; classfiles. The source for the lib must be in a proper +; module-path-relative directory. The output files will go into the +; directory specified by *compile-path*, and that directory too must +; be in the module path." +; [path] +; (cpp/clojure.core_native.compile path)) +; +;(defn require +; "Loads libs, skipping any that are already loaded. Each argument is +; either a libspec that identifies a lib, a prefix list that identifies +; multiple libs whose names share a common prefix, or a flag that modifies +; how all the identified libs are loaded. Use :require in the ns macro +; in preference to calling this directly. +; +; Libs +; +; A 'lib' is a named set of resources in module path whose contents define a +; library of Clojure code. Lib names are symbols and each lib is associated +; with a Clojure namespace and a Java package that share its name. A lib's +; name also locates its root directory within module path using Java's +; package name to module path-relative path mapping. All resources in a lib +; should be contained in the directory structure under its root directory. +; All definitions a lib makes should be in its associated namespace. +; +; 'require loads a lib by loading its root resource. The root resource path +; is derived from the lib name in the following manner: +; Consider a lib named by the symbol 'x.y.z; it has the root directory +; /x/y/, and its root resource is /x/y/z.clj, or +; /x/y/z.cljc if /x/y/z.clj does not exist. The +; root resource should contain code to create the lib's +; namespace (usually by using the ns macro) and load any additional +; lib resources. +; +; Libspecs +; +; A libspec is a lib name or a vector containing a lib name followed by +; options expressed as sequential keywords and arguments. +; +; Recognized options: +; :as takes a symbol as its argument and makes that symbol an alias to the +; lib's namespace in the current namespace. +; :as-alias takes a symbol as its argument and aliases like :as, however +; the lib will not be loaded. If the lib has not been loaded, a new +; empty namespace will be created (as with create-ns). +; :refer takes a list of symbols to refer from the namespace or the :all +; keyword to bring in all public vars. +; +; Prefix Lists +; +; It's common for Clojure code to depend on several libs whose names have +; the same prefix. When specifying libs, prefix lists can be used to reduce +; repetition. A prefix list contains the shared prefix followed by libspecs +; with the shared prefix removed from the lib names. After removing the +; prefix, the names that remain must not contain any periods. +; +; Flags +; +; A flag is a keyword. +; Recognized flags: :reload, :reload-all, :verbose +; :reload forces loading of all the identified libs even if they are +; already loaded (has no effect on libspecs using :as-alias) +; :reload-all implies :reload and also forces loading of all libs that the +; identified libs directly or indirectly load via require or use +; (has no effect on libspecs using :as-alias) +; :verbose triggers printing information about each load, alias, and refer +; +; Example: +; +; The following would load the libraries clojure.zip and clojure.set +; abbreviated as 's'. +; +; (require '(clojure zip [set :as s]))" +; [& args] +; (apply load-libs :require args)) +; +;(defn use +; "Like 'require, but also refers to each lib's namespace using +; clojure.core/refer. Use :use in the ns macro in preference to calling +; this directly. +; +; 'use accepts additional options in libspecs: :exclude, :only, :rename. +; The arguments and semantics for :exclude, :only, and :rename are the same +; as those documented for clojure.core/refer." +; [& args] +; (apply load-libs :require :use args)) +; +;(defmacro ns +; "Sets *ns* to the namespace named by name (unevaluated), creating it +; if needed. References can be zero or more of: (:refer-clojure ...) +; (:require ...) (:use ...) (:load ...) +; with the syntax of refer-clojure/require/use/load respectively." +; [name & references] +; (let [process-reference (fn [reference] +; (let [kname (first reference) +; args (rest reference)] +; (cons (symbol "clojure.core" (clojure.core/name kname)) +; (map (fn [a] +; (list 'quote a)) +; args)))) +; refer-full-clojure? (not-any? (fn [ref] +; (= :refer-clojure (first ref))) +; references)] +; `(do +; (clojure.core/in-ns '~name) +; ; TODO: with-loading-context +; (do ; with-loading-context +; ~@(when (and (not= name 'clojure.core) refer-full-clojure?) +; `((clojure.core/refer '~'clojure.core))) +; ~@(map process-reference references)) +; (if (= '~name '~'clojure.core) +; nil +; (do (swap! @#'*loaded-libs* conj '~name) nil))))) +; +;(defmacro refer-clojure +; "Same as (refer 'clojure.core )" +; [& filters] +; `(clojure.core/refer '~'clojure.core ~@filters)) +; +;(defn intern +; "Finds or creates a var named by the symbol name in the namespace +; ns (which can be a symbol or a namespace), setting its root binding +; to val if supplied. The namespace must exist. The var will adopt any +; metadata from the name symbol. Returns the var." +; ([ns name] +; (let [v (cpp/clojure.core_native.intern_var +; (cpp/jank.runtime.to_qualified_symbol +; (the-ns ns) name))] +; (when (meta name) (cpp/jank.runtime.reset_meta v (meta name))) +; v)) +; ([ns name val] +; (let [v (cpp/clojure.core_native.intern_var +; (cpp/jank.runtime.to_qualified_symbol +; (the-ns ns) name))] +; (cpp/clojure.core_native.var_bind_root v val) +; (when (meta name) (cpp/jank.runtime.reset_meta v (meta name))) +; v))) +; +;(defn nfirst +; "Same as (next (first x))" +; [x] +; (next (first x))) +; +;(defn fnext +; "Same as (first (next x))" +; [x] +; (first (next x))) +; +;(defn instance? +; "Evaluates x and tests if it is an instance of the class +; c. Returns true or false" +; [c x] +; ;; (. c (isInstance x)) +; (throw "TODO: port instance?")) +; +;(def ^{:private true :dynamic true} +; assert-valid-fdecl (fn [fdecl])) +; +;(defn to-array +; "Returns an array of Objects containing the contents of coll, which +; can be any Collection. Maps to java.util.Collection.toArray()." +; [coll] +; ;; (. clojure.lang.RT (toArray coll)) +; (throw "TODO: port to-array")) +; +;(defn cast +; "Throws a ClassCastException if x is not a c, else returns x." +; [c x] +; ;; (. c (cast x)) +; (throw "TODO: port cast")) +; +;(defn sorted-map-by +; "keyval => key val +; Returns a new sorted map with supplied mappings, using the supplied +; comparator. If any keys are equal, they are handled as if by +; repeated uses of assoc." +; ([comparator & keyvals] +; ;; (clojure.lang.PersistentTreeMap/create comparator keyvals) +; (throw "TODO: port sorted-map-by"))) +; +;(defn any? +; "Returns true given any argument." +; [x] true) +; +;(defn find-keyword +; "Returns a Keyword with the given namespace and name if one already +; exists. This function will not intern a new keyword. If the keyword +; has not already been interned, it will return nil. Do not use : +; in the keyword strings, it will be added automatically." +; ([name] +; ;; (cond (keyword? name) name +; ;; (symbol? name) (clojure.lang.Keyword/find ^clojure.lang.Symbol name) +; ;; (string? name) (clojure.lang.Keyword/find ^String name)) +; (throw "TODO: port find-keyword")) +; ([ns name] +; ;; (clojure.lang.Keyword/find ns name) +; (throw "TODO: port find-keyword"))) +; +;(defn delay? +; "returns true if x is a Delay created with delay" +; [x] +; ;; (instance? clojure.lang.Delay x) +; (throw "TODO: port delay?")) +; +;(defmacro if-not +; "Evaluates test. If logical false, evaluates and returns then expr, +; otherwise else expr, if supplied, else nil." +; ([test then] `(if-not ~test ~then nil)) +; ([test then else] +; `(if (not ~test) ~then ~else))) +; +;(defn compare +; "Comparator. Returns a negative number, zero, or a positive number +; when x is logically 'less than', 'equal to', or 'greater than' +; y. Same as Java x.compareTo(y) except it also works for nil, and +; compares numbers and collections in a type-independent manner. x +; must implement Comparable" +; [x y] +; (cpp/jank.runtime.compare x y)) +; +;(defn inc' +; "Returns a number one greater than num. Supports arbitrary precision. +; See also: inc" +; [x] +; ;; (. clojure.lang.Numbers (incP x)) +; (throw "TODO: port inc'")) +; +;;; ;;math stuff +;;; (defn ^:private nary-inline +;;; ([op] (nary-inline op op)) +;;; ([op unchecked-op] +;;; (fn +;;; ([x] (let [op (if *unchecked-math* unchecked-op op)] +;;; `(. clojure.lang.Numbers (~op ~x)))) +;;; ([x y] (let [op (if *unchecked-math* unchecked-op op)] +;;; `(. clojure.lang.Numbers (~op ~x ~y)))) +;;; ([x y & more] +;;; (let [op (if *unchecked-math* unchecked-op op)] +;;; (reduce1 +;;; (fn [a b] `(. clojure.lang.Numbers (~op ~a ~b))) +;;; `(. clojure.lang.Numbers (~op ~x ~y)) more)))))) +; +;;; (defn ^:private >1? [n] (clojure.lang.Numbers/gt n 1)) +; +;;; (defn ^:private >0? [n] (clojure.lang.Numbers/gt n 0)) +; +;(defn +' +; "Returns the sum of nums. (+') returns 0. Supports arbitrary precision. +; See also: +" +; ([] 0) +; ([x] +; ;; (cast Number x) +; (throw "TODO: port +'")) +; ([x y] +; ;; (. clojure.lang.Numbers (addP x y)) +; (throw "TODO: port +'")) +; ([x y & more] +; (reduce +' (+' x y) more))) +; +;(defn *' +; "Returns the product of nums. (*') returns 1. Supports arbitrary precision. +; See also: *" +; ([] 1) +; ([x] +; ;; (cast Number x) +; (throw "TODO: port *'")) +; ([x y] +; ;; (. clojure.lang.Numbers (multiplyP x y)) +; (throw "TODO: port *'")) +; ([x y & more] +; (reduce *' (*' x y) more))) +; +;(defn -' +; "If no ys are supplied, returns the negation of x, else subtracts +; the ys from x and returns the result. Supports arbitrary precision. +; See also: -" +; ([x] +; ;; (. clojure.lang.Numbers (minusP x)) +; (throw "TODO: port -'")) +; ([x y] +; ;; (. clojure.lang.Numbers (minusP x y)) +; (throw "TODO: port -'")) +; ([x y & more] +; (reduce -' (-' x y) more))) +; +;(defn abs +; "Returns the absolute value of a. +; If a is Long/MIN_VALUE => Long/MIN_VALUE +; If a is a double and zero => +0.0 +; If a is a double and ##Inf or ##-Inf => ##Inf +; If a is a double and ##NaN => ##NaN" +; [a] +; (cpp/jank.runtime.abs a)) +; +;(defn dec' +; "Returns a number one less than num. Supports arbitrary precision. +; See also: dec" +; [x] +; ;; (. clojure.lang.Numbers (decP x)) +; (throw "TODO: port dec'")) +; +;(defn unchecked-inc-int +; "Returns a number one greater than x, an int. +; Note - uses a primitive operator subject to overflow." +; [x] +; ;; (. clojure.lang.Numbers (unchecked_int_inc x)) +; (throw "TODO: port unchecked-inc-int")) +; +;(defn unchecked-inc +; "Returns a number one greater than x, a long. +; Note - uses a primitive operator subject to overflow." +; [x] +; ;; (. clojure.lang.Numbers (unchecked_inc x)) +; (throw "TODO: port unchecked-inc")) +; +;(defn unchecked-dec-int +; "Returns a number one less than x, an int. +; Note - uses a primitive operator subject to overflow." +; [x] +; ;; (. clojure.lang.Numbers (unchecked_int_dec x)) +; (throw "TODO: port unchecked-dec-int")) +; +;(defn unchecked-dec +; "Returns a number one less than x, a long. +; Note - uses a primitive operator subject to overflow." +; [x] +; ;; (. clojure.lang.Numbers (unchecked_dec x)) +; (throw "TODO: port unchecked-dec")) +; +;(defn unchecked-negate-int +; "Returns the negation of x, an int. +; Note - uses a primitive operator subject to overflow." +; [x] +; ;; (. clojure.lang.Numbers (unchecked_int_negate x)) +; (throw "TODO: port unchecked-negate-int")) +; +;(defn unchecked-negate +; "Returns the negation of x, a long. +; Note - uses a primitive operator subject to overflow." +; [x] +; ;; (. clojure.lang.Numbers (unchecked_minus x)) +; (throw "TODO: port unchecked-negate")) +; +;(defn unchecked-add-int +; "Returns the sum of x and y, both int. +; Note - uses a primitive operator subject to overflow." +; [x y] +; ;; (. clojure.lang.Numbers (unchecked_int_add x y)) +; (throw "TODO: port unchecked-add-int")) +; +;(defn unchecked-add +; "Returns the sum of x and y, both long. +; Note - uses a primitive operator subject to overflow." +; [x y] +; ;; (. clojure.lang.Numbers (unchecked_add x y)) +; (throw "TODO: port unchecked-add")) +; +;(defn unchecked-subtract-int +; "Returns the difference of x and y, both int. +; Note - uses a primitive operator subject to overflow." +; [x y] +; ;; (. clojure.lang.Numbers (unchecked_int_subtract x y)) +; (throw "TODO: port unchecked-subtract-int")) +; +;(defn unchecked-subtract +; "Returns the difference of x and y, both long. +; Note - uses a primitive operator subject to overflow." +; [x y] +; ;; (. clojure.lang.Numbers (unchecked_minus x y)) +; (throw "TODO: port unchecked-subtract")) +; +;(defn unchecked-multiply-int +; "Returns the product of x and y, both int. +; Note - uses a primitive operator subject to overflow." +; [x y] +; ;; (. clojure.lang.Numbers (unchecked_int_multiply x y)) +; (throw "TODO: port unchecked-multiply-int")) +; +;(defn unchecked-multiply +; "Returns the product of x and y, both long. +; Note - uses a primitive operator subject to overflow." +; [x y] +; ;; (. clojure.lang.Numbers (unchecked_multiply x y)) +; (throw "TODO: port unchecked-multiply")) +; +;(defn unchecked-divide-int +; "Returns the division of x by y, both int. +; Note - uses a primitive operator subject to truncation." +; [x y] +; ;; (. clojure.lang.Numbers (unchecked_int_divide x y)) +; (throw "TODO: port unchecked-divide-int")) +; +;(defn unchecked-remainder-int +; "Returns the remainder of division of x by y, both int. +; Note - uses a primitive operator subject to truncation." +; [x y] +; ;; (. clojure.lang.Numbers (unchecked_int_remainder x y)) +; (throw "TODO: port unchecked-remainder-int")) +; +;(defn rationalize +; "returns the rational value of num" +; [num] +; ;; (. clojure.lang.Numbers (rationalize num)) +; (throw "TODO: port rationalize")) +; +;(defn int? +; "Return true if x is a fixed precision integer" +; [x] +; (integer? x)) +; +;(defn pos-int? +; "Return true if x is a positive fixed precision integer" +; [x] (and (int? x) +; (pos? x))) +; +;(defn neg-int? +; "Return true if x is a negative fixed precision integer" +; [x] (and (int? x) +; (neg? x))) +; +;(defn nat-int? +; "Return true if x is a non-negative fixed precision integer" +; [x] (and (int? x) +; (not (neg? x)))) +; +;(defn double? +; "Return true if x is a Double" +; [x] +; (float? x)) +; +;;;map stuff +; +;(defn map-entry? +; "Return true if x is a map entry" +; [x] +; (and (vector? x) +; (== 2 (count x)))) +; +;(defn rseq +; "Returns, in constant time, a seq of the items in rev (which +; can be a vector or sorted-map), in reverse order. If rev is empty returns nil" +; [#_clojure.lang.Reversible rev] +; ;; (. rev (rseq)) +; (throw "TODO: port rseq")) +; +;(defmacro locking +; "Executes exprs in an implicit do, while holding the monitor of x. +; Will release the monitor of x in all circumstances." +; [x & body] +; `(let [lockee# ~x] +; (try +; (let [locklocal# lockee#] +; (monitor-enter locklocal#) +; (try +; (do ~@body) +; (finally +; (monitor-exit locklocal#))))))) +; +;;; (defmacro .. +;;; "form => fieldName-symbol or (instanceMethodName-symbol args*) +; +;;; Expands into a member access (.) of the first member on the first +;;; argument, followed by the next member on the result, etc. For +;;; instance: +; +;;; (.. System (getProperties) (get \"os.name\")) +; +;;; expands to: +; +;;; (. (. System (getProperties)) (get \"os.name\")) +; +;;; but is easier to write, read, and understand." +;;; ([x form] +;;; ;; `(. ~x ~form) +;;; (throw "TODO: port")) +;;; ([x form & more] +;;; ;; `(.. (. ~x ~form) ~@more)) +;;; (throw "TODO: port")) +; +; +;;;;;;;;;; var stuff +; +;(defn with-bindings* +; "Takes a map of Var/value pairs. Installs for the given Vars the associated +; values as thread-local bindings. Then calls f with the supplied arguments. +; Pops the installed bindings after f returned. Returns whatever f returns." +; [binding-map f & args] +; (push-thread-bindings (if (= "persistent_array_map" (type binding-map)) +; (into (hash-map) binding-map) +; binding-map)) +; (try +; (apply f args) +; (finally +; (pop-thread-bindings)))) +; +;(defmacro with-bindings +; "Takes a map of Var/value pairs. Installs for the given Vars the associated +; values as thread-local bindings. Then executes body. Pops the installed +; bindings after body was evaluated. Returns the value of body." +; [binding-map & body] +; `(with-bindings* ~binding-map (fn [] ~@body))) +; +;(defn bound-fn* +; "Returns a function, which will install the same bindings in effect as in +; the thread at the time bound-fn* was called and then call f with any given +; arguments. This may be used to define a helper function which runs on a +; different thread, but needs the same bindings in place." +; [f] +; (let [bindings (get-thread-bindings)] +; (fn [& args] +; (apply with-bindings* bindings f args)))) +; +;(defmacro bound-fn +; "Returns a function defined by the given fntail, which will install the +; same bindings in effect as in the thread at the time bound-fn was called. +; This may be used to define a helper function which runs on a different +; thread, but needs the same bindings in place." +; [& fntail] +; `(bound-fn* (fn ~@fntail))) +; +;(defn- binding-conveyor-fn +; [f] +; ;; (let [frame (clojure.lang.Var/cloneThreadBindingFrame)] +; ;; (fn +; ;; ([] +; ;; (clojure.lang.Var/resetThreadBindingFrame frame) +; ;; (f)) +; ;; ([x] +; ;; (clojure.lang.Var/resetThreadBindingFrame frame) +; ;; (f x)) +; ;; ([x y] +; ;; (clojure.lang.Var/resetThreadBindingFrame frame) +; ;; (f x y)) +; ;; ([x y z] +; ;; (clojure.lang.Var/resetThreadBindingFrame frame) +; ;; (f x y z)) +; ;; ([x y z & args] +; ;; (clojure.lang.Var/resetThreadBindingFrame frame) +; ;; (apply f x y z args)))) +; (throw "TODO: port binding-conveyor-fn")) +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Refs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;(defn- +; setup-reference [#_clojure.lang.ARef r options] +; ;; (let [opts (apply hash-map options)] +; ;; (when (:meta opts) +; ;; (.resetMeta r (:meta opts))) +; ;; (when (:validator opts) +; ;; (.setValidator r (:validator opts))) +; ;; r) +; (throw "TODO: port setup-reference")) +; +;(defn agent +; "Creates and returns an agent with an initial value of state and +; zero or more options (in any order): +; +; :meta metadata-map +; +; :validator validate-fn +; +; :error-handler handler-fn +; +; :error-mode mode-keyword +; +; If metadata-map is supplied, it will become the metadata on the +; agent. validate-fn must be nil or a side-effect-free fn of one +; argument, which will be passed the intended new state on any state +; change. If the new state is unacceptable, the validate-fn should +; return false or throw an exception. handler-fn is called if an +; action throws an exception or if validate-fn rejects a new state -- +; see set-error-handler! for details. The mode-keyword may be either +; :continue (the default if an error-handler is given) or :fail (the +; default if no error-handler is given) -- see set-error-mode! for +; details." +; ([state & options] +; ;; (let [a (new clojure.lang.Agent state) +; ;; opts (apply hash-map options)] +; ;; (setup-reference a options) +; ;; (when (:error-handler opts) +; ;; (.setErrorHandler a (:error-handler opts))) +; ;; (.setErrorMode a (or (:error-mode opts) +; ;; (if (:error-handler opts) :continue :fail))) +; ;; a) +; (throw "TODO: port agent"))) +; +;(defn set-agent-send-executor! +; "Sets the ExecutorService to be used by send" +; [executor] +; ;; (set! clojure.lang.Agent/pooledExecutor executor) +; (throw "TODO: port set-agent-send-executor!")) +; +;(defn set-agent-send-off-executor! +; "Sets the ExecutorService to be used by send-off" +; [executor] +; ;; (set! clojure.lang.Agent/soloExecutor executor) +; (throw "TODO: port set-agent-send-off-executor!")) +; +;(defn send-via +; "Dispatch an action to an agent. Returns the agent immediately. +; Subsequently, in a thread supplied by executor, the state of the agent +; will be set to the value of: +; +; (apply action-fn state-of-agent args)" +; [executor #_clojure.lang.Agent a f & args] +; ;; (.dispatch a (binding [*agent* a] (binding-conveyor-fn f)) args executor) +; (throw "TODO: port send-via")) +; +;(defn send +; "Dispatch an action to an agent. Returns the agent immediately. +; Subsequently, in a thread from a thread pool, the state of the agent +; will be set to the value of: +; +; (apply action-fn state-of-agent args)" +; [#_clojure.lang.Agent a f & args] +; ;; (apply send-via clojure.lang.Agent/pooledExecutor a f args) +; (throw "TODO: port send")) +; +;(defn send-off +; "Dispatch a potentially blocking action to an agent. Returns the +; agent immediately. Subsequently, in a separate thread, the state of +; the agent will be set to the value of: +; +; (apply action-fn state-of-agent args)" +; [#_clojure.lang.Agent a f & args] +; ;; (apply send-via clojure.lang.Agent/soloExecutor a f args) +; (throw "TODO: port send-off")) +; +;(defn release-pending-sends +; "Normally, actions sent directly or indirectly during another action +; are held until the action completes (changes the agent's +; state). This function can be used to dispatch any pending sent +; actions immediately. This has no impact on actions sent during a +; transaction, which are still held until commit. If no action is +; occurring, does nothing. Returns the number of actions dispatched." +; [] +; ;; (clojure.lang.Agent/releasePendingSends) +; (throw "TODO: port release-pending-sends")) +; +;(defn add-watch +; "Adds a watch function to an agent/atom/var/ref reference. The watch +; fn must be a fn of 4 args: a key, the reference, its old-state, its +; new-state. Whenever the reference's state might have been changed, +; any registered watches will have their functions called. The watch fn +; will be called synchronously, on the agent's thread if an agent, +; before any pending sends if agent or ref. Note that an atom's or +; ref's state may have changed again prior to the fn call, so use +; old/new-state rather than derefing the reference. Note also that watch +; fns may be called from multiple threads simultaneously. Var watchers +; are triggered only by root binding changes, not thread-local +; set!s. Keys must be unique per reference, and can be used to remove +; the watch with remove-watch, but are otherwise considered opaque by +; the watch mechanism." +; [reference key f] +; (cpp/jank.runtime.add_watch reference key f)) +; +;(defn remove-watch +; "Removes a watch (set by add-watch) from a reference" +; [reference key] +; (cpp/jank.runtime.remove_watch reference key)) +; +;(defn agent-error +; "Returns the exception thrown during an asynchronous action of the +; agent if the agent is failed. Returns nil if the agent is not +; failed." +; [#_clojure.lang.Agent a] +; ;; (.getError a) +; (throw "TODO: port agent-error")) +; +;(defn restart-agent +; "When an agent is failed, changes the agent state to new-state and +; then un-fails the agent so that sends are allowed again. If +; a :clear-actions true option is given, any actions queued on the +; agent that were being held while it was failed will be discarded, +; otherwise those held actions will proceed. The new-state must pass +; the validator if any, or restart will throw an exception and the +; agent will remain failed with its old state and error. Watchers, if +; any, will NOT be notified of the new state. Throws an exception if +; the agent is not failed." +; [#_clojure.lang.Agent a, new-state & options] +; ;; (let [opts (apply hash-map options)] +; ;; (.restart a new-state (if (:clear-actions opts) true false))) +; (throw "TODO: port restart-agent")) +; +;(defn set-error-handler! +; "Sets the error-handler of agent a to handler-fn. If an action +; being run by the agent throws an exception or doesn't pass the +; validator fn, handler-fn will be called with two arguments: the +; agent and the exception." +; [#_clojure.lang.Agent a, handler-fn] +; ;; (.setErrorHandler a handler-fn) +; (throw "TODO: port set-error-handler!")) +; +;(defn error-handler +; "Returns the error-handler of agent a, or nil if there is none. +; See set-error-handler!" +; [#_clojure.lang.Agent a] +; ;; (.getErrorHandler a) +; (throw "TODO: port error-handler")) +; +;(defn set-error-mode! +; "Sets the error-mode of agent a to mode-keyword, which must be +; either :fail or :continue. If an action being run by the agent +; throws an exception or doesn't pass the validator fn, an +; error-handler may be called (see set-error-handler!), after which, +; if the mode is :continue, the agent will continue as if neither the +; action that caused the error nor the error itself ever happened. +; +; If the mode is :fail, the agent will become failed and will stop +; accepting new 'send' and 'send-off' actions, and any previously +; queued actions will be held until a 'restart-agent'. Deref will +; still work, returning the state of the agent before the error." +; [#_clojure.lang.Agent a, mode-keyword] +; ;; (.setErrorMode a mode-keyword) +; (throw "TODO: port set-error-mode!")) +; +;(defn error-mode +; "Returns the error-mode of agent a. See set-error-mode!" +; [#_clojure.lang.Agent a] +; ;; (.getErrorMode a) +; (throw "TODO: port error-mode")) +; +;(defn agent-errors +; "DEPRECATED: Use 'agent-error' instead. +; Returns a sequence of the exceptions thrown during asynchronous +; actions of the agent." +; [a] +; (when-let [e (agent-error a)] +; (list e))) +; +;(defn clear-agent-errors +; "DEPRECATED: Use 'restart-agent' instead. +; Clears any exceptions thrown during asynchronous actions of the +; agent, allowing subsequent actions to occur." +; [#_clojure.lang.Agent a] +; ;; (restart-agent a (.deref a)) +; (throw "TODO: port clear-agent-errors")) +; +;(defn shutdown-agents +; "Initiates a shutdown of the thread pools that back the agent +; system. Running actions will complete, but no new actions will be +; accepted" +; [] +; ;; (. clojure.lang.Agent shutdown) +; (throw "TODO: port shutdown-agents")) +; +;(defn ref +; "Creates and returns a Ref with an initial value of x and zero or +; more options (in any order): +; +; :meta metadata-map +; +; :validator validate-fn +; +; :min-history (default 0) +; :max-history (default 10) +; +; If metadata-map is supplied, it will become the metadata on the +; ref. validate-fn must be nil or a side-effect-free fn of one +; argument, which will be passed the intended new state on any state +; change. If the new state is unacceptable, the validate-fn should +; return false or throw an exception. validate-fn will be called on +; transaction commit, when all refs have their final values. +; +; Normally refs accumulate history dynamically as needed to deal with +; read demands. If you know in advance you will need history you can +; set :min-history to ensure it will be available when first needed (instead +; of after a read fault). History is limited, and the limit can be set +; with :max-history." +; ([x] +; ;; (new clojure.lang.Ref x) +; (throw "TODO: port ref")) +; ([x & options] +; ;; (let [r ^clojure.lang.Ref (setup-reference (ref x) options) +; ;; opts (apply hash-map options)] +; ;; (when (:max-history opts) +; ;; (.setMaxHistory r (:max-history opts))) +; ;; (when (:min-history opts) +; ;; (.setMinHistory r (:min-history opts))) +; ;; r) +; (throw "TODO: port ref"))) +; +;(defn- deref-future +; ([#_java.util.concurrent.Future fut] +; ;; (.get fut) +; (throw "TODO: port deref-future")) +; ([#_java.util.concurrent.Future fut timeout-ms timeout-val] +; ;; (try (.get fut timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS) +; ;; (catch java.util.concurrent.TimeoutException e +; ;; timeout-val)) +; (throw "TODO: port deref-future"))) +; +;(defn set-validator! +; "Sets the validator-fn for a var/ref/agent/atom. validator-fn must be nil or a +; side-effect-free fn of one argument, which will be passed the intended +; new state on any state change. If the new state is unacceptable, the +; validator-fn should return false or throw an exception. If the current state (root +; value if var) is not acceptable to the new validator, an exception +; will be thrown and the validator will not be changed." +; [#_clojure.lang.IRef iref validator-fn] +; ;; (. iref (setValidator validator-fn)) +; (throw "TODO: port set-validator!")) +; +;(defn get-validator +; "Gets the validator-fn for a var/ref/agent/atom." +; [#_clojure.lang.IRef iref] +; ;; (. iref (getValidator)) +; (throw "TODO: port get-validator")) +; +;(defn commute +; "Must be called in a transaction. Sets the in-transaction-value of +; ref to: +; +; (apply fun in-transaction-value-of-ref args) +; +; and returns the in-transaction-value of ref. +; +; At the commit point of the transaction, sets the value of ref to be: +; +; (apply fun most-recently-committed-value-of-ref args) +; +; Thus fun should be commutative, or, failing that, you must accept +; last-one-in-wins behavior. commute allows for more concurrency than +; ref-set." +; [#_clojure.lang.Ref ref fun & args] +; ;; (. ref (commute fun args)) +; (throw "TODO: port commute")) +; +;(defn alter +; "Must be called in a transaction. Sets the in-transaction-value of +; ref to: +; +; (apply fun in-transaction-value-of-ref args) +; +; and returns the in-transaction-value of ref." +; [#_clojure.lang.Ref ref fun & args] +; ;; (. ref (alter fun args)) +; (throw "TODO: port alter")) +; +;(defn ref-set +; "Must be called in a transaction. Sets the value of ref. +; Returns val." +; [#_clojure.lang.Ref ref val] +; ;; (. ref (set val)) +; (throw "TODO: port ref-set")) +; +;(defn ref-history-count +; "Returns the history count of a ref" +; [#_clojure.lang.Ref ref] +; ;; (.getHistoryCount ref) +; (throw "TODO: port ref-history-count")) +; +;(defn ref-min-history +; "Gets the min-history of a ref, or sets it and returns the ref" +; ([#_clojure.lang.Ref ref] +; ;; (.getMinHistory ref) +; (throw "TODO: port ref-min-history")) +; ([#_clojure.lang.Ref ref n] +; ;; (.setMinHistory ref n) +; (throw "TODO: port ref-min-history"))) +; +;(defn ref-max-history +; "Gets the max-history of a ref, or sets it and returns the ref" +; ([#_clojure.lang.Ref ref] +; ;; (.getMaxHistory ref) +; (throw "TODO: port ref-max-history")) +; ([#_clojure.lang.Ref ref n] +; ;; (.setMaxHistory ref n) +; (throw "TODO: port ref-max-history"))) +; +;(defn ensure +; "Must be called in a transaction. Protects the ref from modification +; by other transactions. Returns the in-transaction-value of +; ref. Allows for more concurrency than (ref-set ref @ref)" +; [#_clojure.lang.Ref ref] +; ;; (. ref (touch)) +; ;; (. ref (deref)) +; (throw "TODO: port ensure")) +; +;(defmacro sync +; "transaction-flags => TBD, pass nil for now +; +; Runs the exprs (in an implicit do) in a transaction that encompasses +; exprs and any nested calls. Starts a transaction if none is already +; running on this thread. Any uncaught exception will abort the +; transaction and flow out of sync. The exprs may be run more than +; once, but any effects on Refs will be atomic." +; [flags-ignored-for-now & body] +; ;; `(. clojure.lang.LockingTransaction +; ;; (runInTransaction (fn [] ~@body))) +; (throw "TODO: port sync")) +; +;(defmacro io! +; "If an io! block occurs in a transaction, throws an +; IllegalStateException, else runs body in an implicit do. If the +; first expression in body is a literal string, will use that as the +; exception message." +; [& body] +; ;; (let [message (when (string? (first body)) (first body)) +; ;; body (if message (next body) body)] +; ;; `(if (clojure.lang.LockingTransaction/isRunning) +; ;; (throw (new IllegalStateException ~(or message "I/O in transaction"))) +; ;; (do ~@body))) +; (throw "TODO: port io!")) +; +;;;;;;;;;;;;;;;;;;;; sequence fns ;;;;;;;;;;;;;;;;;;;;;;; +; +;(defn sequence +; "Coerces coll to a (possibly empty) sequence, if it is not already +; one. Will not force a lazy seq. (sequence nil) yields (), When a +; transducer is supplied, returns a lazy sequence of applications of +; the transform to the items in coll(s), i.e. to the set of first +; items of each coll, followed by the set of second +; items in each coll, until any one of the colls is exhausted. Any +; remaining items in other colls are ignored. The transform should accept +; number-of-colls arguments" +; ([coll] +; (if (seq? coll) coll +; (or (seq coll) ()))) +; ([xform coll] +; ;; (or (clojure.lang.RT/chunkIteratorSeq +; ;; (clojure.lang.TransformerIterator/create xform (clojure.lang.RT/iter coll))) +; ;; ()) +; (throw "TODO: port sequence")) +; ([xform coll & colls] +; ;; (or (clojure.lang.RT/chunkIteratorSeq +; ;; (clojure.lang.TransformerIterator/createMulti +; ;; xform +; ;; (map #(clojure.lang.RT/iter %) (cons coll colls)))) +; ;; ()) +; (throw "TODO: port sequence"))) +; +;(defn not-every? +; "Returns false if (pred x) is logical true for every x in +; coll, else true." +; [pred coll] +; (not (every? pred coll))) +; +;(defmacro declare +; "defs the supplied var names with no bindings, useful for making forward declarations." +; [& names] `(do ~@(map #(list 'def (vary-meta % assoc :declared true)) names))) +; +;(defn replicate +; "DEPRECATED: Use 'repeat' instead. +; Returns a lazy seq of n xs." +; [n x] (take n (repeat x))) +; +;(defn merge +; "Returns a map that consists of the rest of the maps conj-ed onto +; the first. If a key occurs in more than one map, the mapping from +; the latter (left-to-right) will be the mapping in the result." +; [& maps] +; (when (some identity maps) +; (reduce #(conj (or %1 {}) %2) maps))) +; +;(defn merge-with +; "Returns a map that consists of the rest of the maps conj-ed onto +; the first. If a key occurs in more than one map, the mapping(s) +; from the latter (left-to-right) will be combined with the mapping in +; the result by calling (f val-in-result val-in-latter)." +; [f & maps] +; (when (some identity maps) +; (let [merge-entry (fn [m e] +; (let [k (key e) v (val e)] +; (if (contains? m k) +; (assoc m k (f (get m k) v)) +; (assoc m k v)))) +; merge2 (fn [m1 m2] +; (reduce merge-entry (or m1 {}) (seq m2)))] +; (reduce merge2 maps)))) +; +;(defn line-seq +; "Returns the lines of text from rdr as a lazy sequence of strings. +; rdr must implement java.io.BufferedReader." +; [#_java.io.BufferedReader rdr] +; ;; (when-let [line (.readLine rdr)] +; ;; (cons line (lazy-seq (line-seq rdr)))) +; (throw "TODO: port line-seq")) +; +;(defn comparator +; "Returns an implementation of java.util.Comparator based upon pred." +; [pred] +; (fn [x y] +; (cond (pred x y) -1 (pred y x) 1 :else 0))) +; +;(defn sort +; "Returns a sorted sequence of the items in coll. If no comparator is +; supplied, uses compare. comparator must implement +; java.util.Comparator. Guaranteed to be stable: equal elements will +; not be reordered. If coll is a Java array, it will be modified. To +; avoid this, sort a copy of the array." +; [coll] +; (cpp/jank.runtime.sort coll)) +; +;(defn sort-by +; "Returns a sorted sequence of the items in coll, where the sort +; order is determined by comparing (keyfn item). If no comparator is +; supplied, uses compare. comparator must implement +; java.util.Comparator. Guaranteed to be stable: equal elements will +; not be reordered. If coll is a Java array, it will be modified. To +; avoid this, sort a copy of the array." +; ([keyfn coll] +; (sort-by keyfn compare coll)) +; ([keyfn #_java.util.Comparator comp coll] +; ;; (sort (fn [x y] (. comp (compare (keyfn x) (keyfn y)))) coll) +; (throw "TODO: port sort-by"))) +; +;;; evaluation +; +;(defn eval +; "Evaluates the form data structure (not text!) and returns the result." +; [form] +; (cpp/clojure.core_native.eval form)) +; +;(defn await +; "Blocks the current thread (indefinitely!) until all actions +; dispatched thus far, from this thread or agent, to the agent(s) have +; occurred. Will block on failed agents. Will never return if +; a failed agent is restarted with :clear-actions true or shutdown-agents was called." +; [& agents] +; ;; (io! "await in transaction" +; ;; (when *agent* +; ;; (throw (new Exception "Can't await in agent action"))) +; ;; (let [latch (new java.util.concurrent.CountDownLatch (count agents)) +; ;; count-down (fn [agent] (. latch (countDown)) agent)] +; ;; (doseq [agent agents] +; ;; (send agent count-down)) +; ;; (. latch (await)))) +; (throw "TODO: port await")) +; +;(defn await1 [#_clojure.lang.Agent a] +; ;; (when (pos? (.getQueueCount a)) +; ;; (await a)) +; ;; a +; (throw "TODO: port await1")) +; +;(defn await-for +; "Blocks the current thread until all actions dispatched thus +; far (from this thread or agent) to the agents have occurred, or the +; timeout (in milliseconds) has elapsed. Returns logical false if +; returning due to timeout, logical true otherwise." +; [timeout-ms & agents] +; ;; (io! "await-for in transaction" +; ;; (when *agent* +; ;; (throw (new Exception "Can't await in agent action"))) +; ;; (let [latch (new java.util.concurrent.CountDownLatch (count agents)) +; ;; count-down (fn [agent] (. latch (countDown)) agent)] +; ;; (doseq [agent agents] +; ;; (send agent count-down)) +; ;; (. latch (await timeout-ms (. java.util.concurrent.TimeUnit MILLISECONDS))))) +; (throw "TODO: port await-for")) +; +;(defn import +; "import is not implemented for jank, but a var is still bound to its symbol for portability. import always throws an exception" +; [& _] +; (throw "import is not supported in jank, for C/C++ dependency interoperability use cpp/raw with #include, e.g. (cpp/raw \"#include \"dependency.h\")\")")) +; +;(defn into-array +; "Returns an array with components set to the values in aseq. The array's +; component type is type if provided, or the type of the first value in +; aseq if present, or Object. All values in aseq must be compatible with +; the component type. Class objects for the primitive types can be obtained +; using, e.g., Integer/TYPE." +; ([aseq] +; ;; (clojure.lang.RT/seqToTypedArray (seq aseq)) +; (throw "TODO: port into-array")) +; ([type aseq] +; ;; (clojure.lang.RT/seqToTypedArray type (seq aseq)) +; (throw "TODO: port into-array"))) +; +;(defn- +; array [& items] +; (into-array items)) +; +;(defn class +; "Returns the Class of x" +; #_Class [#_Object x] +; ;; (if (nil? x) x (. x (getClass))) +; (throw "TODO: port class")) +; +;(defn num +; "Coerce to Number" +; [x] +; ;; (. clojure.lang.Numbers (num x)) +; (throw "TODO: port num")) +; +;(defn long +; "Coerce to long" +; [#_Number x] +; ;; (clojure.lang.RT/longCast x) +; (throw "TODO: port long")) +; +;(defn double +; "Coerce to double" +; [#_Number x] +; ;; (clojure.lang.RT/doubleCast x) +; (throw "TODO: port double")) +; +;(defn short +; "Coerce to short" +; [#_Number x] +; ;; (clojure.lang.RT/shortCast x) +; (throw "TODO: port short")) +; +;(defn byte +; "Coerce to byte" +; [#_Number x] +; ;; (clojure.lang.RT/byteCast x) +; (throw "TODO: port byte")) +; +;(defn char +; "Coerce to char" +; [x] +; ;; (. clojure.lang.RT (charCast x)) +; (throw "TODO: port char")) +; +;(defn unchecked-byte +; "Coerce to byte. Subject to rounding or truncation." +; [#_Number x] +; ;; (clojure.lang.RT/uncheckedByteCast x) +; (throw "TODO: port unchecked-byte")) +; +;(defn unchecked-short +; "Coerce to short. Subject to rounding or truncation." +; [#_Number x] +; ;; (clojure.lang.RT/uncheckedShortCast x) +; (throw "TODO: port unchecked-short")) +; +;(defn unchecked-char +; "Coerce to char. Subject to rounding or truncation." +; [x] +; ;; (. clojure.lang.RT (uncheckedCharCast x)) +; (throw "TODO: port unchecked-char")) +; +;(defn unchecked-int +; "Coerce to int. Subject to rounding or truncation." +; [#_Number x] +; ;; (clojure.lang.RT/uncheckedIntCast x) +; (throw "TODO: port unchecked-int")) +; +;(defn unchecked-long +; "Coerce to long. Subject to rounding or truncation." +; [#_Number x] +; ;; (clojure.lang.RT/uncheckedLongCast x) +; (throw "TODO: port unchecked-long")) +; +;(defn unchecked-float +; "Coerce to float. Subject to rounding." +; [#_Number x] +; ;; (clojure.lang.RT/uncheckedFloatCast x) +; (throw "TODO: port unchecked-float")) +; +;(defn unchecked-double +; "Coerce to double. Subject to rounding." +; [#_Number x] +; ;; (clojure.lang.RT/uncheckedDoubleCast x) +; (throw "TODO: port unchecked-double")) +; +;(defn ratio? +; "Returns true if n is a Ratio" +; [r] +; (cpp/jank.runtime.is_ratio r)) +; +;(defn numerator +; "Returns the numerator part of a Ratio." +; [r] +; (cpp/jank.runtime.numerator r)) +; +;(defn denominator +; "Returns the denominator part of a Ratio." +; [r] +; (cpp/jank.runtime.denominator r)) +; +;(defn decimal? +; "Returns true if n is a BigDecimal" +; [n] +; ;; (instance? BigDecimal n) +; (cpp/jank.runtime.is_big_decimal n)) +; +;(defn rational? +; "Returns true if n is a rational number" +; [n] +; (or (integer? n) (ratio? n) (decimal? n))) +; +;(defn bigint +; "Coerce to BigInt" +; [x] +; ;; (cond +; ;; (instance? clojure.lang.BigInt x) x +; ;; (instance? BigInteger x) (clojure.lang.BigInt/fromBigInteger x) +; ;; (decimal? x) (bigint (.toBigInteger ^BigDecimal x)) +; ;; (float? x) (bigint (. BigDecimal valueOf (double x))) +; ;; (ratio? x) (bigint (.bigIntegerValue ^clojure.lang.Ratio x)) +; ;; (number? x) (clojure.lang.BigInt/valueOf (long x)) +; ;; :else (bigint (BigInteger. x))) +; (throw "TODO: port bigint")) +; +;(defn biginteger +; "Coerce to BigInteger" +; [x] +; ;; (cond +; ;; (instance? BigInteger x) x +; ;; (instance? clojure.lang.BigInt x) (.toBigInteger ^clojure.lang.BigInt x) +; ;; (decimal? x) (.toBigInteger ^BigDecimal x) +; ;; (float? x) (.toBigInteger (. BigDecimal valueOf (double x))) +; ;; (ratio? x) (.bigIntegerValue ^clojure.lang.Ratio x) +; ;; (number? x) (BigInteger/valueOf (long x)) +; ;; :else (BigInteger. x)) +; (throw "TODO: port biginteger")) +; +;(defn bigdec +; "Coerce to BigDecimal" +; [x] +; (cpp/jank.runtime.to_big_decimal x)) +; +;(def ^:dynamic ^:private print-initialized false) +; +;(defmulti print-method (fn [x writer] +; (let [t (get (meta x) :type)] +; (if (keyword? t) t (class x))))) +; +;(defmulti print-dup (fn [x writer] (class x))) +; +;(def ^:private #_String system-newline +; ;; (System/getProperty "line.separator") +; "\n") +; +;(defn newline +; "Writes a platform-specific newline to *out*" +; [] +; ;; (. *out* (append system-newline)) +; ;; nil +; (throw "TODO: port newline")) +; +;(defn flush +; "Flushes the output stream that is the current value of +; *out*" +; [] +; ;; (. *out* (flush)) +; ;; nil +; (throw "TODO: port flesh")) +; +;(defn read +; "Reads the next object from stream, which must be an instance of +; java.io.PushbackReader or some derivee. stream defaults to the +; current value of *in*. +; +; Opts is a persistent map with valid keys: +; :read-cond - :allow to process reader conditionals, or +; :preserve to keep all branches +; :features - persistent set of feature keywords for reader conditionals +; :eof - on eof, return value unless :eofthrow, then throw. +; if not specified, will throw +; +; Note that read can execute code (controlled by *read-eval*), +; and as such should be used only with trusted sources. +; +; For data structure interop use clojure.edn/read" +; ([] +; (read *in*)) +; ([stream] +; (read stream true nil)) +; ([stream eof-error? eof-value] +; (read stream eof-error? eof-value false)) +; ([stream eof-error? eof-value recursive?] +; ;; (. clojure.lang.LispReader (read stream (boolean eof-error?) eof-value recursive?)) +; (throw "TODO: port read")) +; ([opts stream] +; ;; (. clojure.lang.LispReader (read stream opts)) +; (throw "TODO: port read"))) +; +;(defn read+string +; "Like read, and taking the same args. stream must be a LineNumberingPushbackReader. +; Returns a vector containing the object read and the (whitespace-trimmed) string read." +; ([] (read+string *in*)) +; ([stream] (read+string stream true nil)) +; ([stream eof-error? eof-value] (read+string stream eof-error? eof-value false)) +; ([#_clojure.lang.LineNumberingPushbackReader stream eof-error? eof-value recursive?] +; ;; (try +; ;; (.captureString stream) +; ;; (let [o (read stream eof-error? eof-value recursive?) +; ;; s (.trim (.getString stream))] +; ;; [o s]) +; ;; (catch Throwable ex +; ;; (.getString stream) +; ;; (throw ex))) +; (throw "TODO: port read+string")) +; ([opts #_clojure.lang.LineNumberingPushbackReader stream] +; ;; (try +; ;; (.captureString stream) +; ;; (let [o (read opts stream) +; ;; s (.trim (.getString stream))] +; ;; [o s]) +; ;; (catch Throwable ex +; ;; (.getString stream) +; ;; (throw ex))) +; (throw "TODO: port read+string"))) +; +;(defn read-line +; "Reads the next line from stream that is the current value of *in* ." +; [] +; ;; (if (instance? clojure.lang.LineNumberingPushbackReader *in*) +; ;; (.readLine ^clojure.lang.LineNumberingPushbackReader *in*) +; ;; (.readLine ^java.io.BufferedReader *in*)) +; (throw "TODO: port read-line")) +; +;(defn read-string +; "Reads one object from the string s. Optionally include reader +; options, as specified in read. +; +; Note that read-string can execute code (controlled by *read-eval*), +; and as such should be used only with trusted sources. +; +; For data structure interop use clojure.edn/read-string" +; ([s] +; (read-string {} s)) +; ([opts s] +; (cpp/clojure.core_native.read_string opts s))) +; +;(defmacro with-open +; "bindings => [name init ...] +; +; Evaluates body in a try expression with names bound to the values +; of the inits, and a finally clause that calls (.close name) on each +; name in reverse order." +; [bindings & body] +; (assert-macro-args +; (vector? bindings) "a vector for its binding" +; (even? (count bindings)) "an even number of forms in binding vector") +; ;; (cond +; ;; (= (count bindings) 0) `(do ~@body) +; ;; (symbol? (bindings 0)) `(let ~(subvec bindings 0 2) +; ;; (try +; ;; (with-open ~(subvec bindings 2) ~@body) +; ;; (finally +; ;; (. ~(bindings 0) ~'close)))) +; ;; :else (throw (IllegalArgumentException. +; ;; "with-open only allows Symbols in bindings"))) +; (throw "TODO: port with-open")) +; +;(defmacro memfn +; "Expands into code that creates a fn that expects to be passed an +; object and any args and calls the named instance method on the +; object passing the args. Use when you want to treat a Java method as +; a first-class fn. name may be type-hinted with the method receiver's +; type in order to avoid reflective calls." +; [name & args] +; ;; (let [t (with-meta (gensym "target") +; ;; (meta name))] +; ;; `(fn [~t ~@args] +; ;; (. ~t (~name ~@args)))) +; (throw "TODO: port memfn")) +; +;(defn alength +; "Returns the length of the Java array. Works on arrays of all +; types." +; [array] +; ;; (. clojure.lang.RT (alength array)) +; (throw "TODO: port alength")) +; +;(defn aclone +; "Returns a clone of the Java array. Works on arrays of known +; types." +; [array] +; ;; (. clojure.lang.RT (aclone array)) +; (throw "TODO: port aclone")) +; +;(defn aget +; "Returns the value at the index/indices. Works on Java arrays of all +; types." +; ([array idx] +; ;; (clojure.lang.Reflector/prepRet (.getComponentType (class array)) (. Array (get array idx))) +; (throw "TODO: port aget")) +; ([array idx & idxs] +; (apply aget (aget array idx) idxs))) +; +;(defmacro aset +; "Sets the value at the index/indices. Returns val." +; [array idx & more] +; (if (= 1 (count more)) +; ;; Simple case: (aset array index value) +; (let [val (first more)] +; `(do +; (cpp/= (cpp/aget ~array ~idx) ~val) +; ~val)) +; ;; Nested case: (aset array idx1 idx2 & idxv) - not yet implemented +; `(throw "TODO: Nested array indexing not yet implemented"))) +; +;(defmacro +; ^{:private true} +; def-aset [name method coerce] +; `(defn ~name +; {:arglists '([~'array ~'idx ~'val] [~'array ~'idx ~'idx2 & ~'idxv])} +; ([array# idx# val#] +; ;; (. Array (~method array# idx# (~coerce val#))) +; ;; val# +; (throw ~(str "TODO: port " name))) +; ([array# idx# idx2# & idxv#] +; (apply ~name (aget array# idx#) idx2# idxv#)))) +; +;(def-aset +; ^{:doc "Sets the value at the index/indices. Works on arrays of int. Returns val."} +; aset-int setInt int) +; +;(def-aset +; ^{:doc "Sets the value at the index/indices. Works on arrays of long. Returns val."} +; aset-long setLong long) +; +;(def-aset +; ^{:doc "Sets the value at the index/indices. Works on arrays of boolean. Returns val."} +; aset-boolean setBoolean boolean) +; +;(def-aset +; ^{:doc "Sets the value at the index/indices. Works on arrays of float. Returns val."} +; aset-float setFloat float) +; +;(def-aset +; ^{:doc "Sets the value at the index/indices. Works on arrays of double. Returns val."} +; aset-double setDouble double) +; +;(def-aset +; ^{:doc "Sets the value at the index/indices. Works on arrays of short. Returns val."} +; aset-short setShort short) +; +;(def-aset +; ^{:doc "Sets the value at the index/indices. Works on arrays of byte. Returns val."} +; aset-byte setByte byte) +; +;(def-aset +; ^{:doc "Sets the value at the index/indices. Works on arrays of char. Returns val."} +; aset-char setChar char) +; +;(defn make-array +; "Creates and returns an array of instances of the specified class of +; the specified dimension(s). Note that a class object is required. +; Class objects can be obtained by using their name. +; Class objects for the primitive types can be obtained using, e.g., Integer/TYPE." +; ([#_Class type len] +; ;; (. Array (newInstance type (int len))) +; (throw "TODO: port make-array")) +; ([#_Class type dim & more-dims] +; ;; (let [dims (cons dim more-dims) +; ;; ^"[I" dimarray (make-array (. Integer TYPE) (count dims))] +; ;; (dotimes [i (alength dimarray)] +; ;; (aset-int dimarray i (nth dims i))) +; ;; (. Array (newInstance type dimarray)))) +; (throw "TODO: port make-array"))) +; +;(defn to-array-2d +; "Returns a (potentially-ragged) 2-dimensional array of Objects +; containing the contents of coll, which can be any Collection of any +; Collection." +; [#_java.util.Collection coll] +; ;; (let [ret (make-array (. Class (forName "[Ljava.lang.Object;")) (. coll (size)))] +; ;; (loop [i 0 xs (seq coll)] +; ;; (when xs +; ;; (aset ret i (to-array (first xs))) +; ;; (recur (inc i) (next xs)))) +; ;; ret) +; (throw "TODO: port to-array-2d")) +; +;(defn create-struct +; "Returns a structure basis object." +; [& keys] +; ;; (. clojure.lang.PersistentStructMap (createSlotMap keys)) +; (throw "TODO: port create-struct")) +; +;(defmacro defstruct +; "Same as (def name (create-struct keys...))" +; [name & keys] +; `(def ~name (create-struct ~@keys))) +; +;(defn struct-map +; "Returns a new structmap instance with the keys of the +; structure-basis. keyvals may contain all, some or none of the basis +; keys - where values are not supplied they will default to nil. +; keyvals can also contain keys not in the basis." +; [s & inits] +; ;; (. clojure.lang.PersistentStructMap (create s inits)) +; (throw "TODO: port struct-map")) +; +;(defn struct +; "Returns a new structmap instance with the keys of the +; structure-basis. vals must be supplied for basis keys in order - +; where values are not supplied they will default to nil." +; [s & vals] +; ;; (. clojure.lang.PersistentStructMap (construct s vals)) +; (throw "TODO: port struct")) +; +;(defn accessor +; "Returns a fn that, given an instance of a structmap with the basis, +; returns the value at the key. The key must be in the basis. The +; returned function should be (slightly) more efficient than using +; get, but such use of accessors should be limited to known +; performance-critical areas." +; [s key] +; ;; (. clojure.lang.PersistentStructMap (getAccessor s key)) +; (throw "TODO: port accessor")) +; +;(defn load-reader +; "Sequentially read and evaluate the set of forms contained in the +; stream/file" +; [rdr] +; ;; (. clojure.lang.Compiler (load rdr)) +; (throw "TODO: port load-reader")) +; +;(defn load-string +; "Sequentially read and evaluate the set of forms contained in the +; string" +; [s] +; ;; (let [rdr (-> (java.io.StringReader. s) +; ;; (clojure.lang.LineNumberingPushbackReader.))] +; ;; (load-reader rdr)) +; (throw "TODO: port load-string")) +; +;(defn- +; filter-key [keyfn pred amap] +; (loop [ret {} es (seq amap)] +; (if es +; (if (pred (keyfn (first es))) +; (recur (assoc ret (key (first es)) (val (first es))) (next es)) +; (recur ret (next es))) +; ret))) +; +;(defn all-ns +; "Returns a sequence of all namespaces." +; [] +; ;; (clojure.lang.Namespace/all) +; (throw "TODO: port all-ns")) +; +;(defn ns-unmap +; "Removes the mappings for the symbol from the namespace." +; [ns sym] +; (cpp/clojure.core_native.ns_unmap (the-ns ns) sym)) +; +;(defn ns-imports +; "Returns a map of the import mappings for the namespace." +; [ns] +; ;; (filter-key val (partial instance? Class) (ns-map ns)) +; (throw "TODO: port ns-imports")) +; +;(defn ns-interns +; "Returns a map of the intern mappings for the namespace." +; [ns] +; (let [ns (the-ns ns)] +; (filter-key val (fn [v] (and (var? v) +; (= (ns-name ns) (-> v symbol namespace symbol)))) +; (ns-map ns)))) +; +;(defn ns-refers +; "Returns a map of the refer mappings for the namespace." +; [ns] +; ;; (let [ns (the-ns ns)] +; ;; (filter-key val (fn [^clojure.lang.Var v] (and (instance? clojure.lang.Var v) +; ;; (not= ns (.ns v)))) +; ;; (ns-map ns))) +; (throw "TODO: port ns-refers")) +; +;(defn ns-aliases +; "Returns a map of the aliases for the namespace." +; [ns] +; ;; (.getAliases (the-ns ns)) +; (throw "TODO: port ns-aliases")) +; +;(defn ns-unalias +; "Removes the alias for the symbol from the namespace." +; [ns sym] +; (cpp/clojure.core_native.ns_unalias (the-ns ns) sym)) +; +;(defn var-set +; "Sets the value in the var object to val. The var must be +; thread-locally bound." +; [#_clojure.lang.Var x val] +; ;; (. x (set val)) +; (throw "TODO: port var-set")) +; +;(defmacro with-local-vars +; "varbinding=> symbol init-expr +; +; Executes the exprs in a context in which the symbols are bound to +; vars with per-thread bindings to the init-exprs. The symbols refer +; to the var objects themselves, and must be accessed with var-get and +; var-set" +; [name-vals-vec & body] +; (assert-macro-args +; (vector? name-vals-vec) "a vector for its binding" +; (even? (count name-vals-vec)) "an even number of forms in binding vector") +; ;; `(let [~@(interleave (take-nth 2 name-vals-vec) +; ;; (repeat '(.. clojure.lang.Var create setDynamic)))] +; ;; (. clojure.lang.Var (pushThreadBindings (hash-map ~@name-vals-vec))) +; ;; (try +; ;; (do ~@body) +; ;; (finally (. clojure.lang.Var (popThreadBindings))))) +; (throw "TODO: port with-local-vars")) +; +;(defn array-map +; "Constructs an array-map. If any keys are equal, they are handled as +; if by repeated uses of assoc." +; ([] +; ;; (. clojure.lang.PersistentArrayMap EMPTY) +; (throw "TODO: port array-map")) +; ([& keyvals] +; ;; (let [ary (to-array keyvals)] +; ;; (if (odd? (alength ary)) +; ;; (throw (IllegalArgumentException. (str "No value supplied for key: " (last keyvals)))) +; ;; (clojure.lang.PersistentArrayMap/createAsIfByAssoc ary))) +; (throw "TODO: port array-map"))) +; +;(defn seq-to-map-for-destructuring +; "Builds a map from a seq as described in +; https://clojure.org/reference/special_forms#keyword-arguments" +; [s] +; ;; (if (next s) +; ;; (clojure.lang.PersistentArrayMap/createAsIfByAssoc (to-array s)) +; ;; (if (seq s) (first s) clojure.lang.PersistentArrayMap/EMPTY)) +; (throw "TODO: port seq-to-map-for-destructuring")) +; +;(defmacro lazy-cat +; "Expands to code which yields a lazy sequence of the concatenation +; of the supplied colls. Each coll expr is not evaluated until it is +; needed. +; +; (lazy-cat xs ys zs) === (concat (lazy-seq xs) (lazy-seq ys) (lazy-seq zs))" +; [& colls] +; `(concat ~@(map #(list `lazy-seq %) colls))) +; +;(defmacro with-out-str +; "Evaluates exprs in a context in which *out* is bound to a fresh +; StringWriter. Returns the string created by any nested printing +; calls." +; [& body] +; ;; `(let [s# (new java.io.StringWriter)] +; ;; (binding [*out* s#] +; ;; ~@body +; ;; (str s#))) +; (throw "TODO: port with-out-str")) +; +;(defmacro with-in-str +; "Evaluates body in a context in which *in* is bound to a fresh +; StringReader initialized with the string s." +; [s & body] +; `(with-open [s# (-> (java.io.StringReader. ~s) clojure.lang.LineNumberingPushbackReader.)] +; (binding [*in* s#] +; ~@body))) +; +;(defn prn-str +; "prn to a string, returning it" +; [& xs] +; ;; (with-out-str +; ;; (apply prn xs)) +; (throw "TODO: port prn-str")) +; +; +;(defn print-str +; "print to a string, returning it" +; [& xs] +; ;; (with-out-str +; ;; (apply print xs)) +; (throw "TODO: port print-str")) +; +;(defn println-str +; "println to a string, returning it" +; [& xs] +; ;; (with-out-str +; ;; (apply println xs)) +; (throw "TODO: port println-str")) +; +;(defn ^:private elide-top-frames +; [#_Throwable ex class-name] +; ;; (let [tr (.getStackTrace ex)] +; ;; (doto ex +; ;; (.setStackTrace +; ;; (when tr +; ;; (into-array StackTraceElement +; ;; (drop-while #(= class-name (.getClassName ^StackTraceElement %1)) tr)))))) +; (throw "TODO: port elide-top-frames")) +; +;(defn test +; "test [v] finds fn at key :test in var metadata and calls it, +; presuming failure will throw exception" +; [v] +; (let [f (:test (meta v))] +; (if f +; (do (f) :ok) +; :no-test))) +; +;(defn re-pattern +; "Returns an instance of java.util.regex.Pattern, for use, e.g. in +; re-matcher." +; [s] +; (cpp/jank.runtime.re_pattern s)) +; +;(defn re-matcher +; "Returns an instance of java.util.regex.Matcher, for use, e.g. in +; re-find." +; [re s] +; (cpp/jank.runtime.re_matcher re s)) +; +;(defn re-groups +; "Returns the groups from the most recent match/find. If there are no +; nested groups, returns a string of the entire match. If there are +; nested groups, returns a vector of the groups, the first element +; being the entire match." +; [m] +; (cpp/jank.runtime.re_groups m)) +; +;(defn re-matches +; "Returns the match, if any, of string to pattern, using +; java.util.regex.Matcher.matches(). Uses re-groups to return the +; groups." +; [re s] +; (cpp/jank.runtime.re_matches re s)) +; +;(defn re-find +; "Returns the next regex match, if any, of string to pattern, using +; java.util.regex.Matcher.find(). Uses re-groups to return the +; groups." +; ([m] +; (cpp/jank.runtime.re_find m)) +; ([re s] +; (let [m (re-matcher re s)] +; (re-find m)))) +; +;(defn re-seq +; "Returns a lazy sequence of successive matches of pattern in string, +; using java.util.regex.Matcher.find(), each such match processed with +; re-groups." +; [re s] +; (let [m (cpp/jank.runtime.re_matcher re s)] +; ((fn step [] +; (when (re-find m) +; (cons (re-groups m) (lazy-seq (step)))))))) +; +;(defn rand-int +; "Returns a random integer between 0 (inclusive) and n (exclusive)." +; [n] (int (rand n))) +; +;(defn file-seq +; "A tree seq on java.io.Files" +; [dir] +; ;; (tree-seq +; ;; (fn [^java.io.File f] (. f (isDirectory))) +; ;; (fn [^java.io.File d] (seq (. d (listFiles)))) +; ;; dir) +; (throw "TODO: port file-seq")) +; +;(defn xml-seq +; "A tree seq on the xml elements as per xml/parse" +; [root] +; (tree-seq +; (complement string?) +; (comp seq :content) +; root)) +; +;(defn special-symbol? +; "Returns true if s names a special form" +; [s] +; ;; (contains? (. clojure.lang.Compiler specials) s) +; (throw "TODO: port special-symbol?")) +; +;(defn max-key +; "Returns the x for which (k x), a number, is greatest. +; +; If there are multiple such xs, the last one is returned." +; ([k x] x) +; ([k x y] (if (> (k x) (k y)) x y)) +; ([k x y & more] +; (let [kx (k x) ky (k y) +; [v kv] (if (> kx ky) [x kx] [y ky])] +; (loop [v v kv kv more more] +; (if more +; (let [w (first more) +; kw (k w)] +; (if (>= kw kv) +; (recur w kw (next more)) +; (recur v kv (next more)))) +; v))))) +; +;(defn min-key +; "Returns the x for which (k x), a number, is least. +; +; If there are multiple such xs, the last one is returned." +; ([k x] x) +; ([k x y] (if (< (k x) (k y)) x y)) +; ([k x y & more] +; (let [kx (k x) ky (k y) +; [v kv] (if (< kx ky) [x kx] [y ky])] +; (loop [v v kv kv more more] +; (if more +; (let [w (first more) +; kw (k w)] +; (if (<= kw kv) +; (recur w kw (next more)) +; (recur v kv (next more)))) +; v))))) +; +;(defn replace +; "Given a map of replacement pairs and a vector/collection, returns a +; vector/seq with any elements = a key in smap replaced with the +; corresponding val in smap. Returns a transducer when no collection +; is provided." +; ([smap] +; (map #(if-let [e (find smap %)] (val e) %))) +; ([smap coll] +; (if (vector? coll) +; (reduce (fn [v i] +; (if-let [e (find smap (nth v i))] +; (assoc v i (val e)) +; v)) +; coll (range (count coll))) +; (map #(if-let [e (find smap %)] (val e) %) coll)))) +; +;(defmacro dosync +; "Runs the exprs (in an implicit do) in a transaction that encompasses +; exprs and any nested calls. Starts a transaction if none is already +; running on this thread. Any uncaught exception will abort the +; transaction and flow out of dosync. The exprs may be run more than +; once, but any effects on Refs will be atomic." +; [& exprs] +; `(sync nil ~@exprs)) +; +;(defmacro with-precision +; "Sets the precision and rounding mode to be used for BigDecimal operations. +; +; Usage: (with-precision 10 (/ 1M 3)) +; or: (with-precision 10 :rounding HALF_DOWN (/ 1M 3)) +; +; The rounding mode is one of CEILING, FLOOR, HALF_UP, HALF_DOWN, +; HALF_EVEN, UP, DOWN and UNNECESSARY; it defaults to HALF_UP." +; [precision & exprs] +; ;; (let [[body rm] (if (= (first exprs) :rounding) +; ;; [(next (next exprs)) +; ;; `((. java.math.RoundingMode ~(second exprs)))] +; ;; [exprs nil])] +; ;; `(binding [*math-context* (java.math.MathContext. ~precision ~@rm)] +; ;; ~@body)) +; (throw "TODO: port with-precision")) +; +;(defn- mk-bound-fn +; [#_clojure.lang.Sorted sc test key] +; ;; (fn [e] +; ;; (test (.. sc comparator (compare (. sc entryKey e) key)) 0)) +; (throw "TODO: port mk-bound-fn")) +; +;(defn subseq +; "sc must be a sorted collection, test(s) one of <, <=, > or +; >=. Returns a seq of those entries with keys ek for +; which (test (.. sc comparator (compare ek key)) 0) is true" +; ([#_clojure.lang.Sorted sc test key] +; ;; (let [include (mk-bound-fn sc test key)] +; ;; (if (#{> >=} test) +; ;; (when-let [[e :as s] (. sc seqFrom key true)] +; ;; (if (include e) s (next s))) +; ;; (take-while include (. sc seq true)))) +; (throw "TODO: port subseq")) +; ([#_clojure.lang.Sorted sc start-test start-key end-test end-key] +; ;; (when-let [[e :as s] (. sc seqFrom start-key true)] +; ;; (take-while (mk-bound-fn sc end-test end-key) +; ;; (if ((mk-bound-fn sc start-test start-key) e) s (next s)))) +; (throw "TODO: port subseq"))) +; +;(defn rsubseq +; "sc must be a sorted collection, test(s) one of <, <=, > or +; >=. Returns a reverse seq of those entries with keys ek for +; which (test (.. sc comparator (compare ek key)) 0) is true" +; ([#_clojure.lang.Sorted sc test key] +; ;; (let [include (mk-bound-fn sc test key)] +; ;; (if (#{< <=} test) +; ;; (when-let [[e :as s] (. sc seqFrom key false)] +; ;; (if (include e) s (next s))) +; ;; (take-while include (. sc seq false)))) +; (throw "TODO: port rsubseq")) +; ([#_clojure.lang.Sorted sc start-test start-key end-test end-key] +; ;; (when-let [[e :as s] (. sc seqFrom end-key false)] +; ;; (take-while (mk-bound-fn sc start-test start-key) +; ;; (if ((mk-bound-fn sc end-test end-key) e) s (next s)))) +; (throw "TODO: port rsubseq"))) +; +;(defn add-classpath +; "DEPRECATED +; +; Adds the url (String or URL object) to the classpath per +; URLClassLoader.addURL" +; [url] +; (println "WARNING: add-classpath is deprecated") +; ;; (clojure.lang.RT/addURL url) +; (throw "TODO: port add-classpath")) +; +;(defn mix-collection-hash +; "Mix final collection hash for ordered or unordered collections. +; hash-basis is the combined collection hash, count is the number +; of elements included in the basis. Note this is the hash code +; consistent with =, different from .hashCode. +; See http://clojure.org/data_structures#hash for full algorithms." +; #_long +; [#_long hash-basis #_long count] +; ;; (clojure.lang.Murmur3/mixCollHash hash-basis count) +; (throw "TODO: port mix-collection-hash")) +; +;(defn hash-ordered-coll +; "Returns the hash code, consistent with =, for an external ordered +; collection implementing Iterable. +; See http://clojure.org/data_structures#hash for full algorithms." +; #_long +; [coll] +; ;; (clojure.lang.Murmur3/hashOrdered coll) +; (throw "TODO: port hash-ordered-coll")) +; +;(defn hash-unordered-coll +; "Returns the hash code, consistent with =, for an external unordered +; collection implementing Iterable. For maps, the iterator should +; return map entries whose hash is computed as +; (hash-ordered-coll [k v]). +; See http://clojure.org/data_structures#hash for full algorithms." +; [coll] +; (cpp/clojure.core_native.hash_unordered coll)) +; +;(defmacro definline +; "Experimental - like defmacro, except defines a named function whose +; body is the expansion, calls to which may be expanded inline as if +; it were a macro. Cannot be used with variadic (&) args." +; [name & decl] +; (let [[pre-args [args expr]] (split-with (comp not vector?) decl)] +; `(do +; (defn ~name ~@pre-args ~args ~(apply (eval (list `fn args expr)) args)) +; (alter-meta! (var ~name) assoc :inline (fn ~name ~args ~expr)) +; (var ~name)))) +; +;(defmacro amap +; "Maps an expression across an array a, using an index named idx, and +; return value named ret, initialized to a clone of a, then setting +; each element of ret to the evaluation of expr, returning the new +; array ret." +; [a idx ret expr] +; `(let [a# ~a l# (alength a#) +; ~ret (aclone a#)] +; (loop [~idx 0] +; (if (< ~idx l#) +; (do +; (aset ~ret ~idx ~expr) +; (recur (unchecked-inc ~idx))) +; ~ret)))) +; +;(defmacro areduce +; "Reduces an expression across an array a, using an index named idx, +; and return value named ret, initialized to init, setting ret to the +; evaluation of expr at each step, returning ret." +; [a idx ret init expr] +; `(let [a# ~a l# (alength a#)] +; (loop [~idx 0 ~ret ~init] +; (if (< ~idx l#) +; (recur (unchecked-inc-int ~idx) ~expr) +; ~ret)))) +; +;(defn float-array +; "Creates an array of floats" +; ([size-or-seq] +; ;; (. clojure.lang.Numbers float_array size-or-seq) +; (throw "TODO: port float-array")) +; ([size init-val-or-seq] +; ;; (. clojure.lang.Numbers float_array size init-val-or-seq) +; (throw "TODO: port float-array") )) +; +;(defn boolean-array +; "Creates an array of booleans" +; ([size-or-seq] +; ;; (. clojure.lang.Numbers boolean_array size-or-seq) +; (throw "TODO: port boolean-array")) +; ([size init-val-or-seq] +; ;; (. clojure.lang.Numbers boolean_array size init-val-or-seq) +; (throw "TODO: port boolean-array"))) +; +;(defn byte-array +; "Creates an array of bytes" +; ([size-or-seq] +; ;; (. clojure.lang.Numbers byte_array size-or-seq) +; (throw "TODO: port byte-array")) +; ([size init-val-or-seq] +; ;; (. clojure.lang.Numbers byte_array size init-val-or-seq) +; (throw "TODO: port byte-array"))) +; +;(defn char-array +; "Creates an array of chars" +; ([size-or-seq] +; ;; (. clojure.lang.Numbers char_array size-or-seq) +; (throw "TODO: port char-array")) +; ([size init-val-or-seq] +; ;; (. clojure.lang.Numbers char_array size init-val-or-seq) +; (throw "TODO: port char-array"))) +; +;(defn short-array +; "Creates an array of shorts" +; ([size-or-seq] +; ;; (. clojure.lang.Numbers short_array size-or-seq) +; (throw "TODO: port short-array")) +; ([size init-val-or-seq] +; ;; (. clojure.lang.Numbers short_array size init-val-or-seq) +; (throw "TODO: port short-array"))) +; +;(defn double-array +; "Creates an array of doubles" +; ([size-or-seq] +; ;; (. clojure.lang.Numbers double_array size-or-seq) +; (throw "TODO: port double-array")) +; ([size init-val-or-seq] +; ;; (. clojure.lang.Numbers double_array size init-val-or-seq) +; (throw "TODO: port double-array"))) +; +;(defn object-array +; "Creates an array of objects" +; ([size-or-seq] +; ;; (. clojure.lang.RT object_array size-or-seq) +; (throw "TODO: port object-array"))) +; +;(defn int-array +; "Creates an array of ints" +; ([size-or-seq] +; ;; (. clojure.lang.Numbers int_array size-or-seq) +; (throw "TODO: port int-array")) +; ([size init-val-or-seq] +; ;; (. clojure.lang.Numbers int_array size init-val-or-seq) +; (throw "TODO: port int-array"))) +; +;(defn long-array +; "Creates an array of longs" +; ([size-or-seq] +; ;; (. clojure.lang.Numbers long_array size-or-seq) +; (throw "TODO: port long-array")) +; ([size init-val-or-seq] +; ;; (. clojure.lang.Numbers long_array size init-val-or-seq) +; (throw "TODO: port long-array"))) +; +;;; definline doesn't work without eval +; +;;; (definline booleans +;;; "Casts to boolean[]" +;;; [xs] +;;; ;; `(. clojure.lang.Numbers booleans ~xs) +;;; (throw "TODO: port")) +; +;;; (definline bytes +;;; "Casts to bytes[]" +;;; [xs] +;;; ;; `(. clojure.lang.Numbers bytes ~xs) +;;; (throw "TODO: port")) +; +;;; (definline chars +;;; "Casts to chars[]" +;;; [xs] +;;; ;; `(. clojure.lang.Numbers chars ~xs) +;;; (throw "TODO: port")) +; +;;; (definline shorts +;;; "Casts to shorts[]" +;;; [xs] +;;; ;; `(. clojure.lang.Numbers shorts ~xs) +;;; (throw "TODO: port")) +; +;;; (definline floats +;;; "Casts to float[]" +;;; [xs] +;;; ;; `(. clojure.lang.Numbers floats ~xs) +;;; (throw "TODO: port")) +; +;;; (definline ints +;;; "Casts to int[]" +;;; [xs] +;;; ;; `(. clojure.lang.Numbers ints ~xs) +;;; (throw "TODO: port")) +; +;;; (definline doubles +;;; "Casts to double[]" +;;; [xs] +;;; ;; `(. clojure.lang.Numbers doubles ~xs) +;;; (throw "TODO: port")) +; +;;; (definline longs +;;; "Casts to long[]" +;;; [xs] +;;; ;; `(. clojure.lang.Numbers longs ~xs) +;;; (throw "TODO: port")) +; +;(defn bytes? +; "Return true if x is a byte array" +; [x] +; ;; (if (nil? x) +; ;; false +; ;; (-> x class .getComponentType (= Byte/TYPE))) +; (throw "TODO: port bytes?")) +; +;(defn seque +; "Creates a queued seq on another (presumably lazy) seq s. The queued +; seq will produce a concrete seq in the background, and can get up to +; n items ahead of the consumer. n-or-q can be an integer n buffer +; size, or an instance of java.util.concurrent BlockingQueue. Note +; that reading from a seque can block if the reader gets ahead of the +; producer." +; ([s] (seque 100 s)) +; ([n-or-q s] +; ;; (let [^BlockingQueue q (if (instance? BlockingQueue n-or-q) +; ;; n-or-q +; ;; (LinkedBlockingQueue. (int n-or-q))) +; ;; NIL (Object.) ;nil sentinel since LBQ doesn't support nils +; ;; agt (agent (lazy-seq s)) ; never start with nil; that signifies we've already put eos +; ;; log-error (fn [q e] +; ;; (if (.offer q q) +; ;; (throw e) +; ;; e)) +; ;; fill (fn [s] +; ;; (when s +; ;; (if (instance? Exception s) ; we failed to .offer an error earlier +; ;; (log-error q s) +; ;; (try +; ;; (loop [[x & xs :as s] (seq s)] +; ;; (if s +; ;; (if (.offer q (if (nil? x) NIL x)) +; ;; (recur xs) +; ;; s) +; ;; (when-not (.offer q q) ; q itself is eos sentinel +; ;; ()))) ; empty seq, not nil, so we know to put eos next time +; ;; (catch Exception e +; ;; (log-error q e)))))) +; ;; drain (fn drain [] +; ;; (lazy-seq +; ;; (let [x (.take q)] +; ;; (if (identical? x q) ;q itself is eos sentinel +; ;; (do @agt nil) ;touch agent just to propagate errors +; ;; (do +; ;; (send-off agt fill) +; ;; (release-pending-sends) +; ;; (cons (if (identical? x NIL) nil x) (drain)))))))] +; ;; (send-off agt fill) +; ;; (drain)) +; (throw "TODO: port seque"))) +; +;(defn class? +; "Returns true if x is an instance of Class" +; [x] +; ;; (instance? Class x) +; (throw "TODO: port class?")) +; +;(defn- is-annotation? [c] +; ;; (and (class? c) +; ;; (.isAssignableFrom java.lang.annotation.Annotation c)) +; (throw "TODO: port is-annotation?")) +; +;(defn- is-runtime-annotation? [#_Class c] +; ;; (boolean +; ;; (and (is-annotation? c) +; ;; (when-let [^java.lang.annotation.Retention r +; ;; (.getAnnotation c java.lang.annotation.Retention)] +; ;; (= (.value r) java.lang.annotation.RetentionPolicy/RUNTIME)))) +; (throw "TODO: port is-runtime-annotation?")) +; +;(defn- descriptor [#_Class c] +; ;; (clojure.asm.Type/getDescriptor c) +; (throw "TODO: port descriptor")) +; +;(declare process-annotation) +; +;(defn- add-annotation [#_clojure.asm.AnnotationVisitor av name v] +; ;; (cond +; ;; (vector? v) (let [avec (.visitArray av name)] +; ;; (doseq [vval v] +; ;; (add-annotation avec "value" vval)) +; ;; (.visitEnd avec)) +; ;; (symbol? v) (let [ev (eval v)] +; ;; (cond +; ;; (instance? java.lang.Enum ev) +; ;; (.visitEnum av name (descriptor (class ev)) (str ev)) +; ;; (class? ev) (.visit av name (clojure.asm.Type/getType ev)) +; ;; :else (throw (IllegalArgumentException. +; ;; (str "Unsupported annotation value: " v " of class " (class ev)))))) +; ;; (seq? v) (let [[nested nv] v +; ;; c (resolve nested) +; ;; nav (.visitAnnotation av name (descriptor c))] +; ;; (process-annotation nav nv) +; ;; (.visitEnd nav)) +; ;; :else (.visit av name v)) +; (throw "TODO: port add-annotation")) +; +;(defn- process-annotation [av v] +; (if (map? v) +; (doseq [[k v] v] +; (add-annotation av (name k) v)) +; (add-annotation av "value" v))) +; +;(defn- add-annotations +; ([visitor m] (add-annotations visitor m nil)) +; ([visitor m i] +; ;; (doseq [[k v] m] +; ;; (when (symbol? k) +; ;; (when-let [c (resolve k)] +; ;; (when (is-annotation? c) +; ;; ;this is known duck/reflective as no common base of ASM Visitors +; ;; (let [av (if i +; ;; (.visitParameterAnnotation visitor i (descriptor c) +; ;; (is-runtime-annotation? c)) +; ;; (.visitAnnotation visitor (descriptor c) +; ;; (is-runtime-annotation? c)))] +; ;; (process-annotation av v) +; ;; (.visitEnd av)))))) +; (throw "TODO: port add-annotations"))) +; +;(defn bases +; "Returns the immediate superclass and direct interfaces of c, if any" +; [#_Class c] +; ;; (when c +; ;; (let [i (seq (.getInterfaces c)) +; ;; s (.getSuperclass c)] +; ;; (if s (cons s i) i))) +; (throw "TODO: port bases")) +; +;(defn supers +; "Returns the immediate and indirect superclasses and interfaces of c, if any" +; [#_Class class] +; (loop [ret (set (bases class)) cs ret] +; (if (seq cs) +; (let [c (first cs) bs (bases c)] +; (recur (into ret bs) (into (disj cs c) bs))) +; (not-empty ret)))) +; +; +;(defn resultset-seq +; "Creates and returns a lazy sequence of structmaps corresponding to +; the rows in the java.sql.ResultSet rs" +; [#_java.sql.ResultSet rs] +; ;; (let [rsmeta (. rs (getMetaData)) +; ;; idxs (range 1 (inc (. rsmeta (getColumnCount)))) +; ;; keys (map (comp keyword #(.toLowerCase ^String %)) +; ;; (map (fn [i] (. rsmeta (getColumnLabel i))) idxs)) +; ;; check-keys +; ;; (or (apply distinct? keys) +; ;; (throw (Exception. "ResultSet must have unique column labels"))) +; ;; row-struct (apply create-struct keys) +; ;; row-values (fn [] (map (fn [^Integer i] (. rs (getObject i))) idxs)) +; ;; rows (fn thisfn [] +; ;; (when (. rs (next)) +; ;; (cons (apply struct row-struct (row-values)) (lazy-seq (thisfn)))))] +; ;; (rows)) +; (throw "TODO: port resultset-seq")) +; +;(defn iterator-seq +; "Returns a seq on a java.util.Iterator. Note that most collections +; providing iterators implement Iterable and thus support seq directly. +; Seqs cache values, thus iterator-seq should not be used on any +; iterator that repeatedly returns the same mutable object." +; [iter] +; ;; (clojure.lang.RT/chunkIteratorSeq iter) +; (throw "TODO: port iterator-seq")) +; +;(defn enumeration-seq +; "Returns a seq on a java.util.Enumeration" +; [e] +; ;; (clojure.lang.EnumerationSeq/create e) +; (throw "TODO: port enumeration-seq")) +; +;(defn format +; "Formats a string using java.lang.String.format, see java.util.Formatter for format +; string syntax" +; #_String [fmt & args] +; ;; (String/format fmt (to-array args)) +; (throw "TODO: port format")) +; +;(defn printf +; "Prints formatted output, as per format" +; [fmt & args] +; (print (apply format fmt args))) +; +;(declare gen-class) +; +;(defmacro with-loading-context [& body] +; ;; `((fn loading# [] +; ;; (. clojure.lang.Var (pushThreadBindings {clojure.lang.Compiler/LOADER +; ;; (.getClassLoader (.getClass ^Object loading#))})) +; ;; (try +; ;; (do ~@body) +; ;; (finally +; ;; (. clojure.lang.Var (popThreadBindings)))))) +; (throw "TODO: port with-loading-context")) +; +;(defonce +; ^{:private true +; :dynamic true +; :doc "True while a verbose load is pending"} +; *loading-verbosely* false) +; +;(defn- root-directory +; "Returns the root resource path for a lib" +; [lib] +; ;; (let [d (root-resource lib)] +; ;; (subs d 0 (.lastIndexOf d "/"))) +; (throw "TODO: port root-resource")) +; +;(defn- serialized-require +; "Like 'require', but serializes loading. +; Interim function preferred over 'require' for known asynchronous loads. +; Future changes may make these equivalent." +; [& args] +; ;; (locking clojure.lang.RT/REQUIRE_LOCK +; ;; (apply require args)) +; (throw "TODO: port serialized-require")) +; +;(defn requiring-resolve +; "Resolves namespace-qualified sym per 'resolve'. If initial resolve +;fails, attempts to require sym's namespace and retries." +; [sym] +; ;; (if (qualified-symbol? sym) +; ;; (or (resolve sym) +; ;; (do (-> sym namespace symbol serialized-require) +; ;; (resolve sym))) +; ;; (throw (IllegalArgumentException. (str "Not a qualified symbol: " sym)))) +; (throw "TODO: port requiring-resolve")) +; +;(defn loaded-libs +; "Returns a sorted set of symbols naming the currently loaded libs" +; [] @*loaded-libs*) +; +;(defn sorted? +; "Returns true if coll implements Sorted" +; [coll] +; (cpp/jank.runtime.is_sorted coll)) +; +;(defn counted? +; "Returns true if coll implements count in constant time" +; [coll] +; (cpp/jank.runtime.is_counted coll)) +; +;(defn reversible? +; "Returns true if coll implements Reversible" +; [coll] +; ;; (instance? clojure.lang.Reversible coll) +; (throw "TODO: port reversible?")) +; +;(defn indexed? +; "Return true if coll implements Indexed, indicating efficient lookup by index" +; [coll] +; ;; (instance? clojure.lang.Indexed coll) +; (throw "TODO: port indexed?")) +; +;(def ^:dynamic +; ^{:doc "bound in a repl thread to the most recent value printed"} +; *1) +; +;(def ^:dynamic +; ^{:doc "bound in a repl thread to the second most recent value printed"} +; *2) +; +;(def ^:dynamic +; ^{:doc "bound in a repl thread to the third most recent value printed"} +; *3) +; +;(def ^:dynamic +; ^{:doc "bound in a repl thread to the most recent exception caught by the repl"} +; *e) +; +;(def ^:dynamic +; ^{:doc "Bound to true in a repl thread"} +; *repl* false) +; +;(defn trampoline +; "trampoline can be used to convert algorithms requiring mutual +; recursion without stack consumption. Calls f with supplied args, if +; any. If f returns a fn, calls that fn with no arguments, and +; continues to repeat, until the return value is not a fn, then +; returns that non-fn value. Note that if you want to return a fn as a +; final value, you must wrap it in some data structure and unpack it +; after trampoline returns." +; ([f] +; (let [ret (f)] +; (if (fn? ret) +; (recur ret) +; ret))) +; ([f & args] +; (trampoline #(apply f args)))) +; +;(defmacro while +; "Repeatedly executes body while test expression is true. Presumes +; some side-effect will cause test to become false/nil. Returns nil" +; [test & body] +; `(loop [] +; (when ~test +; ~@body +; (recur)))) +; +;(defn memoize +; "Returns a memoized version of a referentially transparent function. The +; memoized version of the function keeps a cache of the mapping from arguments +; to results and, when calls with the same arguments are repeated often, has +; higher performance at the expense of higher memory use." +; [f] +; (let [mem (atom {})] +; (fn [& args] +; (if-let [e (find @mem args)] +; (val e) +; (let [ret (apply f args)] +; (swap! mem assoc args ret) +; ret))))) +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; var documentation ;;;;;;;;;;;;;;;;;;;;;;;;;; +; +;(defmacro add-doc-and-meta {:private true} [name docstring meta] +; `(alter-meta! (var ~name) merge (assoc ~meta :doc ~docstring))) +; +;;; (add-doc-and-meta *file* +;;; "The path of the file being evaluated, as a String. +; +;;; When there is no file, e.g. in the REPL, the value is not defined." +;;; {}) +; +;;; (add-doc-and-meta *command-line-args* +;;; "A sequence of the supplied command line arguments, or nil if +;;; none were supplied" +;;; {}) +; +;;; (add-doc-and-meta *warn-on-reflection* +;;; "When set to true, the compiler will emit warnings when reflection is +;;; needed to resolve Java method calls or field accesses. +; +;;; Defaults to false." +;;; {}) +; +;;; (add-doc-and-meta *compile-path* +;;; "Specifies the directory where 'compile' will write out .class +;;; files. This directory must be in the classpath for 'compile' to +;;; work. +; +;;; Defaults to \"classes\"" +;;; {}) +; +;;; (add-doc-and-meta *compile-files* +;;; "Set to true when compiling files, false otherwise." +;;; {}) +; +;;; (add-doc-and-meta *unchecked-math* +;;; "While bound to true, compilations of +, -, *, inc, dec and the +;;; coercions will be done without overflow checks. While bound +;;; to :warn-on-boxed, same behavior as true, and a warning is emitted +;;; when compilation uses boxed math. Default: false." +;;; {}) +; +;;; (add-doc-and-meta *compiler-options* +;;; "A map of keys to options. +;;; Note, when binding dynamically make sure to merge with previous value. +;;; Supported options: +;;; :elide-meta - a collection of metadata keys to elide during compilation. +;;; :disable-locals-clearing - set to true to disable clearing, useful for using a debugger +;;; :direct-linking - set to true to use direct static invocation of functions, rather than vars +;;; Note that call sites compiled with direct linking will not be affected by var redefinition. +;;; Use ^:redef (or ^:dynamic) on a var to prevent direct linking and allow redefinition. +;;; See https://clojure.org/reference/compilation for more information." +;;; {}) +; +;;; (add-doc-and-meta *in* +;;; "A java.io.Reader object representing standard input for read operations. +; +;;; Defaults to System/in, wrapped in a LineNumberingPushbackReader" +;;; {}) +; +;;; (add-doc-and-meta *err* +;;; "A java.io.Writer object representing standard error for print operations. +; +;;; Defaults to System/err, wrapped in a PrintWriter" +;;; {}) +; +;;; (add-doc-and-meta *flush-on-newline* +;;; "When set to true, output will be flushed whenever a newline is printed. +; +;;; Defaults to true." +;;; {}) +; +;;; (add-doc-and-meta *print-meta* +;;; "If set to logical true, when printing an object, its metadata will also +;;; be printed in a form that can be read back by the reader. +; +;;; Defaults to false." +;;; {}) +; +;;; (add-doc-and-meta *print-dup* +;;; "When set to logical true, objects will be printed in a way that preserves +;;; their type when read in later. +; +;;; Defaults to false." +;;; {}) +; +;;; (add-doc-and-meta *print-readably* +;;; "When set to logical false, strings and characters will be printed with +;;; non-alphanumeric characters converted to the appropriate escape sequences. +; +;;; Defaults to true" +;;; {}) +; +;;; (add-doc-and-meta *read-eval* +;;; "Defaults to true (or value specified by system property, see below) +;;; ***This setting implies that the full power of the reader is in play, +;;; including syntax that can cause code to execute. It should never be +;;; used with untrusted sources. See also: clojure.edn/read.*** +; +;;; When set to logical false in the thread-local binding, +;;; the eval reader (#=) and record/type literal syntax are disabled in read/load. +;;; Example (will fail): (binding [*read-eval* false] (read-string \"#=(* 2 21)\")) +; +;;; The default binding can be controlled by the system property +;;; 'clojure.read.eval' System properties can be set on the command line +;;; like this: +; +;;; java -Dclojure.read.eval=false ... +; +;;; The system property can also be set to 'unknown' via +;;; -Dclojure.read.eval=unknown, in which case the default binding +;;; is :unknown and all reads will fail in contexts where *read-eval* +;;; has not been explicitly bound to either true or false. This setting +;;; can be a useful diagnostic tool to ensure that all of your reads +;;; occur in considered contexts. You can also accomplish this in a +;;; particular scope by binding *read-eval* to :unknown +;;; " +;;; {}) +; +;;; (add-doc-and-meta *assert* +;;; "When set to logical false, 'assert' will omit assertion checks in +;;; compiled code. Defaults to true." +;;; {}) +; +;(defn future? +; "Returns true if x is a future" +; [x] +; ;; (instance? java.util.concurrent.Future x) +; (throw "TODO: port future?")) +; +;(defn future-done? +; "Returns true if future f is done" +; [#_java.util.concurrent.Future f] +; ;; (.isDone f) +; (throw "TODO: port future-done?")) +; +;(defmacro letfn +; "fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+) +; +; Takes a vector of function specs and a body, and generates a set of +; bindings of functions to their names. All of the names are available +; in all of the definitions of the functions, as well as the body." +; {:forms '[(letfn [fnspecs*] exprs*)], +; :special-form true} +; [fnspecs & body] +; `(letfn* ~(vec (interleave (map first fnspecs) +; (map #(cons `fn %) fnspecs))) +; ~@body)) +; +;(defn stream-reduce! +; "Works like reduce but takes a java.util.stream.BaseStream as its source. +; Honors 'reduced', is a terminal operation on the stream" +; ([f #_java.util.stream.BaseStream s] +; ;; (clojure.core.protocols/iterator-reduce! (.iterator s) f) +; (throw "TODO: port stream-reduce!")) +; ([f init #_java.util.stream.BaseStream s] +; ;; (clojure.core.protocols/iterator-reduce! (.iterator s) f init) +; (throw "TODO: port stream-reduce!"))) +; +;(defn stream-seq! +; "Takes a java.util.stream.BaseStream instance s and returns a seq of its +; contents. This is a terminal operation on the stream." +; [#_java.util.stream.BaseStream stream] +; ;; (iterator-seq (.iterator stream)) +; (throw "TODO: port stream-seq!")) +; +;(defn stream-transduce! +; "Works like transduce but takes a java.util.stream.BaseStream as its source. +; This is a terminal operation on the stream." +; ([xform f #_java.util.stream.BaseStream stream] +; (stream-transduce! xform f (f) stream)) +; ([xform f init #_java.util.stream.BaseStream stream] +; (let [f (xform f) +; ret (stream-reduce! f init stream)] +; (f ret)))) +; +;(defn stream-into! +; "Returns a new coll consisting of coll with all of the items of the +; stream conjoined. This is a terminal operation on the stream." +; ([to #_java.util.stream.BaseStream stream] +; ;; (if (instance? clojure.lang.IEditableCollection to) +; ;; (with-meta (persistent! (stream-reduce! conj! (transient to) stream)) (meta to)) +; ;; (stream-reduce! conj to stream)) +; (throw "TODO: port stream-into!")) +; ([to xform #_java.util.stream.BaseStream stream] +; ;; (if (instance? clojure.lang.IEditableCollection to) +; ;; (with-meta (persistent! (stream-transduce! xform conj! (transient to) stream)) (meta to)) +; ;; (stream-transduce! xform conj to stream)) +; (throw "TODO: port stream-into!"))) +; +; +;(defmacro ^:private when-class [class-name & body] +; ;; `(try +; ;; (Class/forName ^String ~class-name) +; ;; ~@body +; ;; (catch ClassNotFoundException _#)) +; (throw "TODO: port when-class")) +; +;;; (defprotocol Inst +;;; (inst-ms* [inst])) +; +;;; (extend-protocol Inst +;;; java.util.Date +;;; (inst-ms* [inst] (.getTime ^java.util.Date inst))) +; +;(defn inst-ms +; "Return the number of milliseconds since January 1, 1970, 00:00:00 GMT" +; [inst] +; (cpp/jank.runtime.inst_ms inst)) +; +;(defn inst? +; "Return true if x satisfies Inst" +; [x] +; (cpp/jank.runtime.is_inst x)) +; +;;; (extend-protocol clojure.core/Inst +;;; java.time.Instant +;;; (inst-ms* [inst] (.toEpochMilli ^java.time.Instant inst))) +; +;(defn uuid? +; "Return true if x is a java.util.UUID" +; [x] +; (cpp/jank.runtime.is_uuid x)) +; +;(defn random-uuid +; "Returns a pseudo-randomly generated java.util.UUID instance (i.e. type 4). +; +; See: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID--" +; [] +; (cpp/jank.runtime.random_uuid)) +; +;;; (extend-protocol clojure.core.protocols/IKVReduce +;;; nil +;;; (kv-reduce +;;; [_ f init] +;;; init) +; +;;; ;;slow path default +;;; java.lang.Object +;;; (kv-reduce +;;; [amap f init] +;;; (reduce (fn [ret ^java.util.Map$Entry me] +;;; (f ret +;;; (.getKey me) +;;; (.getValue me))) +;;; init +;;; amap)) +; +;;; clojure.lang.IKVReduce +;;; (kv-reduce +;;; [amap f init] +;;; (.kvreduce amap f init))) +; +;(defn reduce-kv +; "Reduces an associative collection. f should be a function of 3 +; arguments. Returns the result of applying f to init, the first key +; and the first value in coll, then applying f to that result and the +; 2nd key and value, etc. If coll contains no entries, returns init +; and f is not called. Note that reduce-kv is supported on vectors, +; where the keys will be the ordinals." +; ([f init coll] +; ;; (clojure.core.protocols/kv-reduce coll f init) +; (reduce (fn [s [k v]] (f s k v)) init coll))) +; +;(defn- normalize-slurp-opts +; [opts] +; (if (string? (first opts)) +; (do +; (println "WARNING: (slurp f enc) is deprecated, use (slurp f :encoding enc).") +; [:encoding (first opts)]) +; opts)) +; +;(defn slurp +; "Opens a reader on f and reads all its contents, returning a string. +; See clojure.java.io/reader for a complete list of supported arguments." +; ([f & opts] +; (let [opts (normalize-slurp-opts opts) +; fname (cpp/cast (cpp/type "char const*") f) +; file (cpp/std.ifstream. fname)] +; (if-not (cpp/.is_open file) +; (throw (str f " (No such file or directory)")) +; (let [size (cpp/std.filesystem.file_size fname) +; out (cpp/std.string. size (cpp/char 0))] +; (cpp/.read file (cpp/& (cpp/.front out)) size) +; out))))) +; +;(defn spit +; "Opposite of slurp. Opens f with writer, writes content, then +; closes f. Options passed to clojure.java.io/writer." +; [f content & options] +; (let [file (cpp/std.ofstream.)] +; (cpp/.open file (cpp/cast (cpp/type "char const*") f)) +; (cpp/<< file (cpp/cast (cpp/type "char const*") content)) +; (cpp/.close file) +; nil)) +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; futures (needs proxy);;;;;;;;;;;;;;;;;; +;(defn future-call +; "Takes a function of no args and yields a future object that will +; invoke the function in another thread, and will cache the result and +; return it on all subsequent calls to deref/@. If the computation has +; not yet finished, calls to deref/@ will block, unless the variant +; of deref with timeout is used. See also - realized?." +; [f] +; ;; (let [f (binding-conveyor-fn f) +; ;; fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)] +; ;; (reify +; ;; clojure.lang.IDeref +; ;; (deref [_] (deref-future fut)) +; ;; clojure.lang.IBlockingDeref +; ;; (deref +; ;; [_ timeout-ms timeout-val] +; ;; (deref-future fut timeout-ms timeout-val)) +; ;; clojure.lang.IPending +; ;; (isRealized [_] (.isDone fut)) +; ;; java.util.concurrent.Future +; ;; (get [_] (.get fut)) +; ;; (get [_ timeout unit] (.get fut timeout unit)) +; ;; (isCancelled [_] (.isCancelled fut)) +; ;; (isDone [_] (.isDone fut)) +; ;; (cancel [_ interrupt?] (.cancel fut interrupt?)))) +; (throw "TODO: port future-call")) +; +;(defmacro future +; "Takes a body of expressions and yields a future object that will +; invoke the body in another thread, and will cache the result and +; return it on all subsequent calls to deref/@. If the computation has +; not yet finished, calls to deref/@ will block, unless the variant of +; deref with timeout is used. See also - realized?." +; [& body] +; ;; `(future-call (^{:once true} fn* [] ~@body)) +; (throw "TODO: port future")) +; +;(defn future-cancel +; "Cancels the future, if possible." +; [#_java.util.concurrent.Future f] +; ;; (.cancel f true) +; (throw "TODO: port future-cancel")) +; +;(defn future-cancelled? +; "Returns true if future f is cancelled" +; [#_java.util.concurrent.Future f] +; ;; (.isCancelled f) +; (throw "TODO: port future-cancelled?")) +; +;(defn pmap +; "Like map, except f is applied in parallel. Semi-lazy in that the +; parallel computation stays ahead of the consumption, but doesn't +; realize the entire result unless required. Only useful for +; computationally intensive functions where the time of f dominates +; the coordination overhead." +; ([f coll] +; ;; (let [n (+ 2 (.. Runtime getRuntime availableProcessors)) +; ;; rets (map #(future (f %)) coll) +; ;; step (fn step [[x & xs :as vs] fs] +; ;; (lazy-seq +; ;; (if-let [s (seq fs)] +; ;; (cons (deref x) (step xs (rest s))) +; ;; (map deref vs))))] +; ;; (step rets (drop n rets))) +; (throw "TODO: port pmap")) +; ([f coll & colls] +; ;; (let [step (fn step [cs] +; ;; (lazy-seq +; ;; (let [ss (map seq cs)] +; ;; (when (every? identity ss) +; ;; (cons (map first ss) (step (map rest ss)))))))] +; ;; (pmap #(apply f %) (step (cons coll colls)))) +; (throw "TODO: port pmap"))) +; +; +;(defn pcalls +; "Executes the no-arg fns in parallel, returning a lazy sequence of +; their values" +; [& fns] (pmap #(%) fns)) +; +;(defmacro pvalues +; "Returns a lazy sequence of the values of the exprs, which are +; evaluated in parallel" +; [& exprs] +; `(pcalls ~@(map #(list `fn [] %) exprs))) +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; clojure version number ;;;;;;;;;;;;;;;;;;;;;; +; +;;; (let [^java.util.Properties +;;; properties (with-open [version-stream (.getResourceAsStream +;;; (clojure.lang.RT/baseLoader) +;;; "clojure/version.properties")] +;;; (doto (new java.util.Properties) +;;; (.load version-stream))) +;;; version-string (.getProperty properties "version") +;;; [_ major minor incremental qualifier snapshot] +;;; (re-matches +;;; #"(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9_]+))?(?:-(SNAPSHOT))?" +;;; version-string) +;;; clojure-version {:major (Integer/valueOf ^String major) +;;; :minor (Integer/valueOf ^String minor) +;;; :incremental (Integer/valueOf ^String incremental) +;;; :qualifier (if (= qualifier "SNAPSHOT") nil qualifier)}] +;;; (def ^:dynamic *clojure-version* +;;; (if (.contains version-string "SNAPSHOT") +;;; (clojure.lang.RT/assoc clojure-version :interim true) +;;; clojure-version))) +; +;;; (add-doc-and-meta *clojure-version* +;;; "The version info for Clojure core, as a map containing :major :minor +;;; :incremental and :qualifier keys. Feature releases may increment +;;; :minor and/or :major, bugfix releases will increment :incremental. +;;; Possible values of :qualifier include \"GA\", \"SNAPSHOT\", \"RC-x\" \"BETA-x\"" +;;; {:added "1.0"}) +; +;(defn clojure-version +; "Returns clojure version as a printable string." +; [] +; (cpp/clojure.core_native.jank_version)) +; +;(defn promise +; "Returns a promise object that can be read with deref/@, and set, +; once only, with deliver. Calls to deref/@ prior to delivery will +; block, unless the variant of deref with timeout is used. All +; subsequent derefs will return the same delivered value without +; blocking. See also - realized?." +; [] +; ;; (let [d (java.util.concurrent.CountDownLatch. 1) +; ;; v (atom d)] +; ;; (reify +; ;; clojure.lang.IDeref +; ;; (deref [_] (.await d) @v) +; ;; clojure.lang.IBlockingDeref +; ;; (deref +; ;; [_ timeout-ms timeout-val] +; ;; (if (.await d timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS) +; ;; @v +; ;; timeout-val)) +; ;; clojure.lang.IPending +; ;; (isRealized [this] +; ;; (zero? (.getCount d))) +; ;; clojure.lang.IFn +; ;; (invoke +; ;; [this x] +; ;; (when (and (pos? (.getCount d)) +; ;; (compare-and-set! v d x)) +; ;; (.countDown d) +; ;; this)))) +; (throw "TODO: port promise")) +; +;(defn deliver +; "Delivers the supplied value to the promise, releasing any pending +; derefs. A subsequent call to deliver on a promise will have no effect." +; [promise val] (promise val)) +; +;(defn rand-nth +; "Return a random element of the (sequential) collection. Will have +; the same performance characteristics as nth for the given +; collection." +; [coll] +; (nth coll (rand-int (count coll)))) +; +;(defn splitv-at +; "Returns a vector of [(into [] (take n) coll) (drop n coll)]" +; [n coll] +; [(into [] (take n) coll) (drop n coll)]) +; +;(defn partitionv +; "Returns a lazy sequence of vectors of n items each, at offsets step +; apart. If step is not supplied, defaults to n, i.e. the partitions +; do not overlap. If a pad collection is supplied, use its elements as +; necessary to complete last partition upto n items. In case there are +; not enough padding elements, return a partition with less than n items." +; ([n coll] +; (partitionv n n coll)) +; ([n step coll] +; (lazy-seq +; (when-let [s (seq coll)] +; (let [p (into [] (take n) s)] +; (when (= n (count p)) +; (cons p (partitionv n step (nthrest s step)))))))) +; ([n step pad coll] +; (lazy-seq +; (when-let [s (seq coll)] +; (let [p (into [] (take n) s)] +; (if (= n (count p)) +; (cons p (partitionv n step pad (nthrest s step))) +; (list (into [] (take n) (concat p pad))))))))) +; +;(defn partitionv-all +; "Returns a lazy sequence of vector partitions, but may include +; partitions with fewer than n items at the end. +; Returns a stateful transducer when no collection is provided." +; ([n] +; (partition-all n)) +; ([n coll] +; (partitionv-all n n coll)) +; ([n step coll] +; (lazy-seq +; (when-let [s (seq coll)] +; (let [seg (into [] (take n) coll)] +; (cons seg (partitionv-all n step (drop step s)))))))) +; +;(defn shuffle +; "Return a random permutation of coll" +; [coll] +; (cpp/jank.runtime.shuffle coll)) +; +;(defn bounded-count +; "If coll is counted? returns its count, else will count at most the first n +; elements of coll using its seq" +; [n coll] +; (if (counted? coll) +; (count coll) +; (loop [i 0 s (seq coll)] +; (if (and s (< i n)) +; (recur (inc i) (next s)) +; i)))) +; +;(defn bounded-count +; "If coll is counted? returns its count, else will count at most the first n +; elements of coll using its seq" +; [n coll] +; (if (counted? coll) +; (count coll) +; (loop [i 0 s (seq coll)] +; (if (and s (< i n)) +; (recur (inc i) (next s)) +; i)))) +; +;(defn- ^{:dynamic true} assert-valid-fdecl +; "A good fdecl looks like (([a] ...) ([a b] ...)) near the end of defn." +; [fdecl] +; (when (empty? fdecl) (throw "Parameter declaration missing")) +; (let [argdecls (map +; #(if (seq? %) +; (first %) +; (throw (if (seq? (first fdecl)) +; (str "Invalid signature \"" +; % +; "\" should be a list") +; (str "Parameter declaration \"" +; % +; "\" should be a vector")))) +; fdecl) +; bad-args (seq (remove #(vector? %) argdecls))] +; (when bad-args +; (throw (str "Parameter declaration \"" (first bad-args) +; "\" should be a vector"))))) +; +;(defn realized? +; "Returns true if a value has been produced for a promise, delay, future or lazy sequence." +; [#_clojure.lang.IPending x] +; ;; (.isRealized x) +; (throw "TODO: port realized?")) +; +;(defn random-sample +; "Returns items from coll with random probability of prob (0.0 - +; 1.0). Returns a transducer when no collection is provided." +; ([prob] +; (filter (fn [_] (< (rand) prob)))) +; ([prob coll] +; (filter (fn [_] (< (rand) prob)) coll))) +; +;;; (deftype Eduction [xform coll] +;;; Iterable +;;; (iterator [_] +;;; (clojure.lang.TransformerIterator/create xform (clojure.lang.RT/iter coll))) +; +;;; clojure.lang.IReduceInit +;;; (reduce [_ f init] +;;; ;; NB (completing f) isolates completion of inner rf from outer rf +;;; (transduce xform (completing f) init coll)) +; +;;; clojure.lang.Sequential) +; +;;; (defn eduction +;;; "Returns a reducible/iterable application of the transducers +;;; to the items in coll. Transducers are applied in order as if +;;; combined with comp. Note that these applications will be +;;; performed every time reduce/iterator is called." +;;; [& xforms] +;;; (Eduction. (apply comp (butlast xforms)) (last xforms))) +; +;;; (defmethod print-method Eduction [c, ^Writer w] +;;; (if *print-readably* +;;; (do +;;; (print-sequential "(" pr-on " " ")" c w)) +;;; (print-object c w))) +; +;(defn iteration +; "Creates a seqable/reducible via repeated calls to step, +; a function of some (continuation token) 'k'. The first call to step +; will be passed initk, returning 'ret'. Iff (somef ret) is true, +; (vf ret) will be included in the iteration, else iteration will +; terminate and vf/kf will not be called. If (kf ret) is non-nil it +; will be passed to the next step call, else iteration will terminate. +; +; This can be used e.g. to consume APIs that return paginated or batched data. +; +; step - (possibly impure) fn of 'k' -> 'ret' +; +; :somef - fn of 'ret' -> logical true/false, default 'some?' +; :vf - fn of 'ret' -> 'v', a value produced by the iteration, default 'identity' +; :kf - fn of 'ret' -> 'next-k' or nil (signaling 'do not continue'), default 'identity' +; :initk - the first value passed to step, default 'nil' +; +; It is presumed that step with non-initk is unreproducible/non-idempotent. +; If step with initk is unreproducible it is on the consumer to not consume twice." +; [step & {:keys [somef vf kf initk] +; :or {vf identity +; kf identity +; somef some? +; initk nil}}] +; ;; (reify +; ;; clojure.lang.Seqable +; ;; (seq [_] +; ;; ((fn next [ret] +; ;; (when (somef ret) +; ;; (cons (vf ret) +; ;; (when-some [k (kf ret)] +; ;; (lazy-seq (next (step k))))))) +; ;; (step initk))) +; ;; clojure.lang.IReduceInit +; ;; (reduce [_ rf init] +; ;; (loop [acc init +; ;; ret (step initk)] +; ;; (if (somef ret) +; ;; (let [acc (rf acc (vf ret))] +; ;; (if (reduced? acc) +; ;; @acc +; ;; (if-some [k (kf ret)] +; ;; (recur acc (step k)) +; ;; acc))) +; ;; acc)))) +; (throw "TODO: port iteration")) +; +;(defn tagged-literal? +; "Return true if the value is the data representation of a tagged literal" +; [value] +; (cpp/jank.runtime.is_tagged_literal value)) +; +;(defn tagged-literal +; "Construct a data representation of a tagged literal from a +; tag symbol and a form." +; [tag form] +; (cpp/jank.runtime.tagged_literal tag form)) +; +;(defn reader-conditional? +; "Return true if the value is the data representation of a reader conditional" +; [value] +; ;; (instance? clojure.lang.ReaderConditional value) +; (throw "TODO: port reader-conditional?")) +; +;(defn reader-conditional +; "Construct a data representation of a reader conditional. +; If true, splicing? indicates read-cond-splicing." +; [form #_Boolean splicing?] +; ;; (clojure.lang.ReaderConditional/create form splicing?) +; (throw "TODO: port reader-conditional")) +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; data readers ;;;;;;;;;;;;;;;;;; +; +;(def default-data-readers +; "Default map of data reader functions provided by Clojure. May be +; overridden by binding *data-readers*." +; (merge +; ;; {'uuid #'clojure.uuid/default-uuid-reader} +; ;; (when-class "java.sql.Timestamp" +; ;; {'inst #'clojure.instant/read-instant-date}) +; )) +; +;(def ^:dynamic *data-readers* +; "Map from reader tag symbols to data reader Vars. +; +; When Clojure starts, it searches for files named 'data_readers.clj' +; and 'data_readers.cljc' at the root of the classpath. Each such file +; must contain a literal map of symbols, like this: +; +; {foo/bar my.project.foo/bar +; foo/baz my.project/baz} +; +; The first symbol in each pair is a tag that will be recognized by +; the Clojure reader. The second symbol in the pair is the +; fully-qualified name of a Var which will be invoked by the reader to +; parse the form following the tag. For example, given the +; data_readers.clj file above, the Clojure reader would parse this +; form: +; +; #foo/bar [1 2 3] +; +; by invoking the Var #'my.project.foo/bar on the vector [1 2 3]. The +; data reader function is invoked on the form AFTER it has been read +; as a normal Clojure data structure by the reader. +; +; Reader tags without namespace qualifiers are reserved for +; Clojure. Default reader tags are defined in +; clojure.core/default-data-readers but may be overridden in +; data_readers.clj, data_readers.cljc, or by rebinding this Var." +; {}) +; +;(def ^:dynamic *default-data-reader-fn* +; "When no data reader is found for a tag and *default-data-reader-fn* +; is non-nil, it will be called with two arguments, +; the tag and the value. If *default-data-reader-fn* is nil (the +; default), an exception will be thrown for the unknown tag." +; nil) +; +;(defn- data-reader-urls [] +; ;; (let [cl (.. Thread currentThread getContextClassLoader)] +; ;; (concat +; ;; (enumeration-seq (.getResources cl "data_readers.clj")) +; ;; (enumeration-seq (.getResources cl "data_readers.cljc")))) +; (throw "TODO: port data-reader-urls")) +; +;(defn- data-reader-var [sym] +; (intern (create-ns (symbol (namespace sym))) +; (symbol (name sym)))) +; +;(defn- load-data-reader-file [mappings #_java.net.URL url] +; ;; (with-open [rdr (clojure.lang.LineNumberingPushbackReader. +; ;; (java.io.InputStreamReader. +; ;; (.openStream url) "UTF-8"))] +; ;; (binding [*file* (.getFile url)] +; ;; (let [read-opts (if (.endsWith (.getPath url) "cljc") +; ;; {:eof nil :read-cond :allow} +; ;; {:eof nil}) +; ;; new-mappings (read read-opts rdr)] +; ;; (when (not (map? new-mappings)) +; ;; (throw (ex-info (str "Not a valid data-reader map") +; ;; {:url url}))) +; ;; (reduce +; ;; (fn [m [k v]] +; ;; (when (not (symbol? k)) +; ;; (throw (ex-info (str "Invalid form in data-reader file") +; ;; {:url url +; ;; :form k}))) +; ;; (let [v-var (data-reader-var v)] +; ;; (when (and (contains? mappings k) +; ;; (not= (mappings k) v-var)) +; ;; (throw (ex-info "Conflicting data-reader mapping" +; ;; {:url url +; ;; :conflict k +; ;; :mappings m}))) +; ;; (assoc m k v-var))) +; ;; mappings +; ;; new-mappings)))) +; (throw "TODO: port load-data-reader-file")) +; +;(defn- load-data-readers [] +; ;; (alter-var-root #'*data-readers* +; ;; (fn [mappings] +; ;; (reduce load-data-reader-file +; ;; mappings (data-reader-urls)))) +; (throw "TODO: port load-data-readers")) +; +;;; (try +;;; (load-data-readers) +;;; (catch #_Throwable t +;;; (.printStackTrace t) +;;; (throw t))) +; +;(defonce ^:private tapset (atom #{})) +; +;;; (defonce ^:private ^java.util.concurrent.ArrayBlockingQueue tapq (java.util.concurrent.ArrayBlockingQueue. 1024)) +; +;(defonce ^:private tap-loop +; ;; (delay +; ;; (doto (Thread. +; ;; #(let [t (.take tapq) +; ;; x (if (identical? ::tap-nil t) nil t) +; ;; taps @tapset] +; ;; (doseq [tap taps] +; ;; (try +; ;; (tap x) +; ;; (catch Throwable ex))) +; ;; (recur)) +; ;; "clojure.core/tap-loop") +; ;; (.setDaemon true) +; ;; (.start))) +; nil) +; +;(defn add-tap +; "adds f, a fn of one argument, to the tap set. This function will be called with anything sent via tap>. +; This function may (briefly) block (e.g. for streams), and will never impede calls to tap>, +; but blocking indefinitely may cause tap values to be dropped. +; Remember f in order to remove-tap" +; [f] +; (force tap-loop) +; (swap! tapset conj f) +; nil) +; +;(defn remove-tap +; "Remove f from the tap set." +; [f] +; (swap! tapset disj f) +; nil) +; +;(defn tap> +; "sends x to any taps. Will not block. Returns true if there was room in the queue, +; false if not (dropped)." +; [x] +; (force tap-loop) +; ;; (.offer tapq (if (nil? x) ::tap-nil x)) +; (throw "TODO: port tap>")) +; +;(defn update-vals +; "m f => {k (f v) ...} +; +; Given a map m and a function f of 1-argument, returns a new map where the keys of m +; are mapped to result of applying f to the corresponding values of m." +; [m f] +; (with-meta +; (persistent! +; (reduce-kv (fn [acc k v] (assoc! acc k (f v))) +; (if (transientable? m) +; (transient m) +; (transient {})) +; m)) +; (meta m))) +; +;(defn update-keys +; "m f => {(f k) v ...} +; +; Given a map m and a function f of 1-argument, returns a new map whose +; keys are the result of applying f to the keys of m, mapped to the +; corresponding values of m. +; f must return a unique key for each key of m, else the behavior is undefined." +; [m f] +; (let [ret (persistent! +; (reduce-kv (fn [acc k v] (assoc! acc (f k) v)) +; (transient {}) +; m))] +; (with-meta ret (meta m)))) +; +;(defn- parsing-err +; "Construct message for parsing for non-string parsing error" +; [val] +; (str "Expected string, got " (if (nil? val) "nil" (type val)))) +; +;(defn parse-long +; "Parse string of decimal digits with optional leading -/+ and return a +; Long value, or nil if parse fails" +; [s] +; (cpp/jank.runtime.parse_long s)) +; +;(defn parse-double +; "Parse string with floating point components and return a Double value, +; or nil if parse fails. +; +; Grammar: https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#valueOf-java.lang.String-" +; [s] +; (cpp/jank.runtime.parse_double s)) +; +;(defn parse-uuid +; "Parse a string representing a UUID and return a java.util.UUID instance, +; or nil if parse fails. +; +; Grammar: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#toString--" +; [s] +; (cpp/jank.runtime.parse_uuid s)) +; +;(defn parse-boolean +; "Parse strings \"true\" or \"false\" and return a boolean, or nil if invalid" +; [s] +; (if (string? s) +; (case s +; "true" true +; "false" false +; nil) +; (throw (parsing-err s)))) +; +;(defn NaN? +; "Returns true if num is NaN, else false" +; [num] +; (cpp/jank.runtime.is_nan num)) +; +;(defn infinite? +; "Returns true if num is negative or positive infinity, else false" +; [num] +; (cpp/jank.runtime.is_infinite num)) diff --git a/compiler+runtime/test/cpp/main.cpp b/compiler+runtime/test/cpp/main.cpp index 3808ddf00..38b52523b 100644 --- a/compiler+runtime/test/cpp/main.cpp +++ b/compiler+runtime/test/cpp/main.cpp @@ -1,9 +1,6 @@ #define DOCTEST_CONFIG_IMPLEMENT #include -#include -#include - #include #include #include From 09904b089cb7223092ccc4a580204a702fcd971b Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 6 Dec 2025 19:39:25 -0800 Subject: [PATCH 067/122] Try fixing more arc issues --- .../include/cpp/jank/runtime/oref.hpp | 8 +- .../include/cpp/jank/runtime/rtti.hpp | 13 + .../cpp/jank/runtime/sequence_range.hpp | 2 +- .../include/cpp/jank/runtime/weak_oref.hpp | 17 +- .../src/cpp/jank/analyze/processor.cpp | 9 +- compiler+runtime/src/cpp/jank/evaluate.cpp | 6 +- .../src/cpp/jank/runtime/context.cpp | 11 +- .../src/cpp/jank/runtime/object.cpp | 6 +- compiler+runtime/src/cpp/main.cpp | 2 +- compiler+runtime/src/jank/clojure/core.jank | 6986 ++++++++--------- 10 files changed, 3544 insertions(+), 3516 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/runtime/oref.hpp b/compiler+runtime/include/cpp/jank/runtime/oref.hpp index d3753a3f5..ec026432b 100644 --- a/compiler+runtime/include/cpp/jank/runtime/oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/oref.hpp @@ -107,12 +107,13 @@ namespace jank::runtime release(); } - constexpr void retain() + constexpr oref &retain() { if(is_some()) { data->retain(); } + return *this; } constexpr void release() @@ -120,7 +121,6 @@ namespace jank::runtime if(is_some()) { data->release(); - reset(); } } @@ -295,12 +295,13 @@ namespace jank::runtime release(); } - constexpr void retain() + constexpr oref &retain() { if(is_some()) { (*this)->base.retain(); } + return *this; } constexpr void release() @@ -308,7 +309,6 @@ namespace jank::runtime if(is_some()) { (*this)->base.release(); - reset(); } } diff --git a/compiler+runtime/include/cpp/jank/runtime/rtti.hpp b/compiler+runtime/include/cpp/jank/runtime/rtti.hpp index 2c355f730..207422e82 100644 --- a/compiler+runtime/include/cpp/jank/runtime/rtti.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/rtti.hpp @@ -59,6 +59,19 @@ namespace jank::runtime return reinterpret_cast(reinterpret_cast(o.data) - offsetof(T, base)); } + template + requires behavior::object_like + [[gnu::always_inline, gnu::flatten, gnu::hot]] + constexpr weak_oref expect_object(weak_object_ref const &o) + { + if constexpr(T::obj_type != object_type::nil) + { + jank_debug_assert(o.is_some()); + } + jank_debug_assert(o->type == T::obj_type); + return reinterpret_cast(reinterpret_cast(o.data) - offsetof(T, base)); + } + template requires behavior::object_like [[gnu::always_inline, gnu::flatten, gnu::hot]] diff --git a/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp b/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp index 416b01f99..38962ede5 100644 --- a/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp @@ -185,7 +185,7 @@ namespace jank::runtime if constexpr(jtl::is_same) { - return s; + return sequence_range{ s }; } else if constexpr(behavior::sequenceable_in_place) { diff --git a/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp b/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp index 8399638d9..ef190e2fc 100644 --- a/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp @@ -126,7 +126,12 @@ namespace jank::runtime constexpr operator oref() const noexcept { - return { data }; + return data; + } + + constexpr oref strong() const noexcept + { + return data; } constexpr value_type *get() const noexcept @@ -287,6 +292,11 @@ namespace jank::runtime return erase(); } + constexpr oref strong() const noexcept + { + return static_cast>(*this); + } + constexpr object *get() const noexcept { return erase(); @@ -409,6 +419,11 @@ namespace jank::runtime return {}; } + constexpr oref strong() const noexcept + { + return {}; + } + constexpr object *get() const noexcept { return erase(); diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index 84d6b2d39..4ca2dc765 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -1831,7 +1831,7 @@ namespace jank::analyze if constexpr(runtime::behavior::sequenceable) { - auto arity_list(runtime::obj::persistent_list::create(typed_arity_list)); + auto arity_list(runtime::obj::persistent_list::create(typed_arity_list.strong())); auto result(analyze_fn_arity(arity_list, name, current_frame)); if(result.is_err()) @@ -2629,7 +2629,8 @@ namespace jank::analyze finally_ }; - static runtime::obj::symbol catch_{ "catch" }, finally_{ "finally" }; + static runtime::obj::symbol_ref catch_{ make_box("catch") }, + finally_{ make_box("finally") }; bool has_catch{}, has_finally{}; for(auto it(list->fresh_seq()->next_in_place()); it.is_some(); it = it->next_in_place()) @@ -2646,11 +2647,11 @@ namespace jank::analyze else { auto const first(runtime::first(typed_item->seq())); - if(runtime::equal(first, &catch_)) + if(runtime::equal(first, catch_)) { return try_expression_type::catch_; } - else if(runtime::equal(first, &finally_)) + else if(runtime::equal(first, finally_)) { return try_expression_type::finally_; } diff --git a/compiler+runtime/src/cpp/jank/evaluate.cpp b/compiler+runtime/src/cpp/jank/evaluate.cpp index fc276ced7..b94925aa7 100644 --- a/compiler+runtime/src/cpp/jank/evaluate.cpp +++ b/compiler+runtime/src/cpp/jank/evaluate.cpp @@ -604,10 +604,12 @@ namespace jank::evaluate } __rt_ctx->jit_prc.eval_string(cg_prc.declaration_str()); - auto const expr_str{ cg_prc.expression_str() + ".erase()" }; + auto const expr_str{ cg_prc.expression_str() + ".retain().erase()" }; clang::Value v; __rt_ctx->jit_prc.eval_string({ expr_str.data(), expr_str.size() }, &v); - return try_object(v.convertTo()); + auto ret{ try_object(v.convertTo()) }; + ret->base.release(); + return ret; } } diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index f8afe5c52..db46be2e6 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -206,7 +206,7 @@ namespace jank::runtime { profile::timer const timer{ "rt compile-module parse + write" }; codegen::processor cg_prc{ fn, module, codegen::compilation_target::module }; - //util::println("{}\n", util::format_cpp_source(cg_prc.declaration_str()).expect_ok()); + util::println("{}\n", util::format_cpp_source(cg_prc.declaration_str()).expect_ok()); auto const code{ cg_prc.declaration_str() }; auto parse_res{ jit_prc.interpreter->Parse({ code.data(), code.size() }) }; if(!parse_res) @@ -539,9 +539,8 @@ namespace jank::runtime } auto locked_namespaces(namespaces.wlock()); - obj::symbol ns_sym{ qualified_sym->ns }; - ns_sym.base.retain(); - auto const found_ns(locked_namespaces->find(&ns_sym)); + obj::symbol_ref ns_sym{ make_box(qualified_sym->ns) }; + auto const found_ns(locked_namespaces->find(ns_sym)); if(found_ns == locked_namespaces->end()) { return err(util::format("Can't intern var. Namespace doesn't exist: {}", qualified_sym->ns)); @@ -574,8 +573,8 @@ namespace jank::runtime } auto locked_namespaces(namespaces.wlock()); - obj::symbol const ns_sym{ qualified_sym->ns }; - auto const found_ns(locked_namespaces->find(&ns_sym)); + obj::symbol_ref const ns_sym{ make_box(qualified_sym->ns) }; + auto const found_ns(locked_namespaces->find(ns_sym)); if(found_ns == locked_namespaces->end()) { return err(util::format("Can't intern var. Namespace doesn't exist: {}", qualified_sym->ns)); diff --git a/compiler+runtime/src/cpp/jank/runtime/object.cpp b/compiler+runtime/src/cpp/jank/runtime/object.cpp index 32a7bb795..e2596e24a 100644 --- a/compiler+runtime/src/cpp/jank/runtime/object.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/object.cpp @@ -10,14 +10,14 @@ namespace jank::runtime { ++ref_count; jank_debug_assert(ref_count > 0); - util::println("retain {} type {} count {}", this, object_type_str(type), ref_count); + //util::println("retain {} type {} count {}", this, object_type_str(type), ref_count); } void object::release() { jank_debug_assert(ref_count > 0); --ref_count; - util::println("release {} type {} count {}", this, object_type_str(type), ref_count); + //util::println("release {} type {} count {}", this, object_type_str(type), ref_count); if(ref_count == 0) { visit_object( @@ -25,8 +25,6 @@ namespace jank::runtime using T = typename jtl::decay_t::value_type; delete static_cast(typed_this.data); - - typed_this.reset(); }, this); } diff --git a/compiler+runtime/src/cpp/main.cpp b/compiler+runtime/src/cpp/main.cpp index e1add713c..5236985fa 100644 --- a/compiler+runtime/src/cpp/main.cpp +++ b/compiler+runtime/src/cpp/main.cpp @@ -46,7 +46,7 @@ namespace jank { profile::timer const timer{ "load clojure.core" }; - //__rt_ctx->load_module("/clojure.core", module::origin::latest).expect_ok(); + __rt_ctx->load_module("/clojure.core", module::origin::latest).expect_ok(); } { diff --git a/compiler+runtime/src/jank/clojure/core.jank b/compiler+runtime/src/jank/clojure/core.jank index 700ae8b40..21cf54045 100644 --- a/compiler+runtime/src/jank/clojure/core.jank +++ b/compiler+runtime/src/jank/clojure/core.jank @@ -20,706 +20,706 @@ ; Defined in runtime::context ctor. (def ^:dynamic *ns*) -(def ^:dynamic *assert*) -(def ^:dynamic *compile-files*) -(def ^:dynamic *file*) - -(def ^:dynamic *in* nil) -(def ^:dynamic *out* nil) -(def ^:dynamic *command-line-args* nil) -(def ^:dynamic *warn-on-reflection* nil) -(def ^:dynamic *compile-path* nil) -(def ^:dynamic *unchecked-math* nil) -(def ^:dynamic *compiler-options* nil) -(def ^:dynamic *err* nil) -(def ^:dynamic *flush-on-newline* nil) -(def ^:dynamic *print-meta* nil) -(def ^:dynamic *print-dup* nil) -(def ^:dynamic *print-readably* nil) -(def ^:dynamic *read-eval* nil) - -(cpp/raw "#include ") -(cpp/raw "#include ") -(cpp/raw "#include ") - -(cpp/raw "#include ") -(cpp/raw "#include ") -(cpp/raw "#include ") -(cpp/raw "#include ") - -; Syntax quoting. -(def unquote - (fn* unquote [_] - (throw "~ cannot be used outside of syntax quote"))) -(def unquote-splicing - (fn* unquote-splicing [_] - (throw "~@ cannot be used outside of syntax quote"))) - -(def type (fn* type [o] - (cpp/jank.runtime.object_type_str (cpp/.-type o)))) - -; Exceptions -(def ex-info - "Create an instance of ExceptionInfo, a RuntimeException subclass - that carries a map of additional data." - (fn* ex-info - ([msg map] - {:error msg - :data map}) - ([msg map cause] - {:error msg - :data map - :cause cause}))) - -(def ex-message - "Returns the message attached to ex if ex is a Throwable. - Otherwise returns nil." - :error) - -(def ex-data - "Returns exception data (a map) if ex is an IExceptionInfo. - Otherwise returns nil." - :data) - -(def ex-cause - "Returns the cause of ex if ex is a Throwable. - Otherwise returns nil." - :cause) - -; Relations. -;; Miscellaneous. -(def nil? - "Returns true if x is nil, false otherwise." - (fn* nil? [o] - (cpp/== (cpp/.-type o) cpp/jank.runtime.object_type.nil))) - -(def identical? - "Tests if 2 arguments are the same object, meaning the same pointer address." - (fn* identical? [lhs rhs] - (cpp/== lhs rhs))) - -; Collections. -(def empty? - "Returns true if coll has no items - same as (not (seq coll))." - (fn* empty? [o] - (cpp/jank.runtime.is_empty o))) -(def empty - "Returns an empty collection of the same category as coll, or nil" - (fn* empty [o] - (cpp/jank.runtime.empty o))) -(def count - "Returns the number of items in the collection. (count nil) returns - 0. Also works on strings, arrays, and Java Collections and Maps" - (fn* [coll] - (cpp/jank.runtime.sequence_length coll))) - -; Numbers. -(def boolean - "Coerce to boolean" - (fn* boolean [o] - (cpp/jank.runtime.truthy o))) -(def int - "Coerce to int" - (fn* int [o] - (cpp/jank.runtime.to_int o))) -(def float - "Coerce to float" - (fn* real [o] - (cpp/jank.runtime.to_real o))) - -;; Sequences. -(def seq - "Returns a seq on the collection. If the collection is - empty, returns nil. (seq nil) returns nil. seq also works on - Strings, native Java arrays (of reference types) and any objects - that implement Iterable. Note that seqs cache values, thus seq - should not be used on any Iterable whose iterator repeatedly - returns the same mutable object." - (fn* seq [o] - (cpp/jank.runtime.seq o))) -(def fresh-seq - (fn* fresh-seq [o] - (cpp/jank.runtime.fresh_seq o))) -(def first - "Returns the first item in the collection. Calls seq on its - argument. If coll is nil, returns nil." - (fn* first [o] - (cpp/jank.runtime.first o))) -(def ffirst - "Same as (first (first x))" - (fn* ffirst [o] - (first (first o)))) -(def next - "Returns a seq of the items after the first. Calls seq on its - argument. If there are no more items, returns nil." - (fn* next [o] - (cpp/jank.runtime.next o))) -(def next-in-place - (fn* next-in-place [o] - (cpp/jank.runtime.next_in_place o))) -(def nnext - "Same as (next (next x))" - (fn* nnext [o] - (next (next o)))) -(def second - "Same as (first (next x))" - (fn* second [o] - (cpp/jank.runtime.second o))) -(def rest - "Returns a possibly empty seq of the items after the first. Calls seq on its - argument." - (fn* rest [o] - (cpp/jank.runtime.rest o))) -(def cons - "Returns a new seq where x is the first element and seq is - the rest." - (fn* cons [head tail] - (cpp/jank.runtime.cons head tail))) -(def coll? - "Returns true if x implements IPersistentCollection" - (fn* coll? [o] - (cpp/jank.runtime.is_collection o))) -(def seq? - "Return true if x implements ISeq" - (fn* seq? [o] - (cpp/jank.runtime.is_seq o))) -(def seqable? - "Return true if the seq function is supported for x" - (fn* seqable? [o] - (cpp/jank.runtime.is_seqable o))) - -(def ^:private reverse* - (fn* reverse* [coll] - (loop* [acc '() - coll (seq coll)] - (if (empty? coll) - acc - (recur (cons (first coll) acc) - (rest coll)))))) - -; XXX: The real concat will be defined later on, to be lazy. -(def ^:private concat* - (fn* concat* - ([] - '()) - ([x] - (seq x)) - ([x y] - (loop* [acc y - x (reverse* x)] - (if (empty? x) - acc - (recur (cons (first x) acc) - (rest x))))) - ([x y & zs] - (let* [r (concat* x y)] - (if (empty? zs) - r - (recur r (first zs) (rest zs))))))) - -; Lists. -(def list? - "Returns true if x implements IPersistentList" - (fn* list? [o] - (cpp/jank.runtime.is_list o))) -(def list - "Creates a new list containing the items." - (fn* list [& args] - (cpp/jank.runtime.list args))) - -;; Vectors. -(def vector? - "Return true if x implements IPersistentVector" - (fn* vector? [o] - (cpp/jank.runtime.is_vector o))) -(def vec - "Creates a new vector containing the contents of coll. Java arrays - will be aliased and should not be modified." - (fn* vec [o] - (cpp/jank.runtime.vec o))) - -(def subvec - "Returns a persistent vector of the items in vector from - start (inclusive) to end (exclusive). If end is not supplied, - defaults to (count vector). This operation is O(1) and very fast, as - the resulting vector shares structure with the original and no - trimming is done." - (fn* subvec - ([v start] - (subvec v start (count v))) - ([v start end] - (cpp/jank.runtime.subvec v start end)))) - -(def conj - "conj[oin]. Returns a new collection with the xs - 'added'. (conj nil item) returns (item). - (conj coll) returns coll. (conj) returns []. - The 'addition' may happen at different 'places' depending - on the concrete type." - (fn* conj - ([] - []) - ([coll] - coll) - ([coll x] - (cpp/jank.runtime.conj coll x)) - ([coll x & args] - (let* [res (conj coll x)] - (if (empty? args) - res - (recur res (first args) (next args))))))) - -(def last - "Return the last item in coll, in linear time." - (fn* last [s] - (if (next s) - (recur (next s)) - (first s)))) - -(def butlast - "Return a seq of all but the last item in coll, in linear time." - (fn* butlast [s] - (loop* [ret [] - s s] - (if (next s) - (recur (conj ret (first s)) (next s)) - (seq ret))))) - -;; Maps. -(def hash-map - "keyval => key val - Returns a new hash map with supplied mappings. If any keys are - equal, they are handled as if by repeated uses of assoc." - (fn* hash-map - ([] (cpp/jank.runtime.obj.persistent_hash_map.empty)) - ([& keyvals] - (cpp/jank.runtime.obj.persistent_hash_map.create_from_seq keyvals)))) - -(def sorted-map - "keyval => key val - Returns a new sorted map with supplied mappings. If any keys are - equal, they are handled as if by repeated uses of assoc." - (fn* sorted-map - ([] (cpp/jank.runtime.obj.persistent_sorted_map.empty)) - ([& keyvals] - (cpp/jank.runtime.obj.persistent_sorted_map.create_from_seq keyvals)))) - -(def map? - "Return true if x implements IPersistentMap" - (fn* map? [o] - (cpp/jank.runtime.is_map o))) - -(def associative? - "Returns true if coll implements Associative" - (fn* associative? [o] - (cpp/jank.runtime.is_associative o))) - -(def assoc - "assoc[iate]. When applied to a map, returns a new map of the - same (hashed/sorted) type, that contains the mapping of key(s) to - val(s). When applied to a vector, returns a new vector that - contains val at index. Note - index must be <= (count vector)." - (fn* assoc - ([map key val] - (cpp/jank.runtime.assoc map key val)) - ([map key val & kvs] - (let* [res (assoc map key val)] - (if kvs - (if (next kvs) - (recur res (first kvs) (second kvs) (nnext kvs)) - (throw "assoc expects even number of args after the first")) - res))))) - -;; Strings. -(def string? - "Return true if x is a String" - (fn* string? [o] - (cpp/jank.runtime.is_string o))) - -(def char? - "Return true if x is a Character" - (fn* char? [o] - (cpp/jank.runtime.is_char o))) - -(def str - "With no args, returns the empty string. With one arg x, returns - x.toString(). (str nil) returns the empty string. With more than - one arg, returns the concatenation of the str values of the args." - (fn* str - ([] - "") - ([o] - (if (nil? o) - "" - (cpp/jank.runtime.to_string o))) - ([o & args] - (cpp/jank.runtime.str o args)))) - -;; Symbols. -(def symbol? - "Return true if x is a Symbol" - (fn* symbol? [o] - (cpp/jank.runtime.is_symbol o))) -(def - symbol - "Returns a Symbol with the given namespace and name. Arity-1 works - on strings, keywords, and vars." - (fn* symbol - ([o] - (cpp/jank.runtime.to_unqualified_symbol o)) - ([ns o] - (if (nil? ns) - (symbol o) - (cpp/jank.runtime.to_qualified_symbol ns o))))) -(def simple-symbol? - "Return true if x is a symbol without a namespace" - (fn* simple-symbol? [x] - (cpp/jank.runtime.is_simple_symbol x))) -(def qualified-symbol? - "Return true if x is a symbol with a namespace" - (fn* qualified-symbol? [x] - (cpp/jank.runtime.is_qualified_symbol x))) - -; Relations. -;; Miscellaneous. -(def true? - "Returns true if x is the value true, false otherwise." - (fn* true? [x] - (cpp/jank.runtime.is_true x))) -(def false? - "Returns true if x is the value false, false otherwise." - (fn* false? [x] - (cpp/jank.runtime.is_false x))) -(def not - "Returns true if x is logical false, false otherwise." - (fn* not [x] - (cpp/clojure.core_native.not_ x))) -(def some? - "Returns true if x is not nil, false otherwise." - (fn* some? [x] - (cpp/jank.runtime.is_some x))) - -;; Metadata. -(def meta - "Returns the metadata of obj, returns nil if there is no metadata." - (fn* meta [obj] - (cpp/jank.runtime.meta obj))) -(def with-meta - "Returns an object of the same type and value as obj, with - map m as its metadata." - (fn* with-meta [obj m] - (cpp/jank.runtime.with_meta obj m))) -(def reset-meta! - "Atomically resets the metadata for a namespace/var/ref/agent/atom" - (fn* [iref metadata-map] - (cpp/jank.runtime.reset_meta iref metadata-map))) - -;; Input/output. -(def print - "Prints the object(s) to the output stream that is the current value - of *out*. print and println produce output for human consumption." - (fn* print [& more] - (cpp/jank.runtime.print more))) -(def println - "Same as print followed by (newline)" - (fn* println [& more] - (cpp/jank.runtime.println more))) -(def pr - "Prints the object(s) to the output stream that is the current value - of *out*. Prints the object(s), separated by spaces if there is - more than one. By default, pr and prn print in a way that objects - can be read by the reader" - (fn* pr [& more] - (cpp/jank.runtime.pr more))) -(def prn - "Same as pr followed by (newline). Observes *flush-on-newline*" - (fn* prn [& more] - (cpp/jank.runtime.prn more))) -(def pr-str - "pr to a string, returning it" - ;; TODO: support multiple parameters, preserving current behavior - (fn* pr-str [x] - (cpp/jank.runtime.to_code_string x))) - -;; Utils. -; The full `apply` will be defined below, but it requires more helpers to support -; all of its arities. This version of apply* is used by the parser for syntax quoting. -; This allows us to use syntax quoting sooner and also have more easily inlinable -; syntax quoting code, since this version of apply is lighter than the full version. -(def ^:private apply* - (fn* apply* [source args] - (cpp/jank.runtime.apply_to source args))) - -(def ^{:macro true} let - (fn* let [&form &env & decl] - `(let* ~@decl))) - -(def ^{:macro true} loop - (fn* loop [&form &env & decl] - `(loop* ~@decl))) - -(def ^{:macro true} fn - (fn* fn [&form &env & decl] - (with-meta `(fn* ~@decl) (meta &form)))) - -(def = - "Equality. Returns true if x equals y, false if not. It also works - for nil and compares numbers and collections in a type-independent - manner. Clojure's immutable data structures define equals() (and - thus =) as a value, not an identity, comparison." - (fn* = - ([x] true) - ([x y] - (cpp/jank.runtime.equal x y)) - ([x y & more] - (if (cpp/jank.runtime.equal x y) - (if (next more) - (recur y (first more) (next more)) - (cpp/jank.runtime.equal y (first more))) - false)))) - -(def == - "Returns non-nil if nums all have the equivalent - value (type-independent), otherwise false" - (fn* == - ([x] true) - ([x y] - (cpp/jank.runtime.is_equiv x y)) - ([x y & more] - (if (cpp/jank.runtime.is_equiv x y) - (if (next more) - (recur y (first more) (next more)) - (cpp/jank.runtime.is_equiv y (first more))) - false)))) - -(def ^:private sigs - (fn* [fdecl] - (let* [asig (fn* asig [fdecl] - (let* [arglist (first fdecl) - ;elide implicit macro args - arglist (if (= '&form (first arglist)) - (subvec arglist 2 (count arglist)) - arglist) - body (next fdecl)] - (if (map? (first body)) - (if (next body) - (with-meta arglist (conj (if (meta arglist) - (meta arglist) - {}) - (first body))) - arglist) - arglist)))] - (if (seq? (first fdecl)) - (loop* [ret [] - fdecls fdecl] - (if fdecls - (recur (conj ret (asig (first fdecls))) (next fdecls)) - (seq ret))) - (list (asig fdecl)))))) - -; Macros. -(def ^{:macro true - :doc "Same as (def name (fn [params* ] exprs*)) or (def - name (fn ([params* ] exprs*)+)) with any doc-string or attrs added - to the var metadata. prepost-map defines a map with optional keys - :pre and :post that contain collections of pre or post conditions."} - defn - (fn* defn [&form &env name & fdecl] - ;; Note: Cannot delegate this check to def because of the call to (with-meta name ..) - (if (not (symbol? name)) - (throw "First argument to defn must be a symbol")) - (let* [m (if (string? (first fdecl)) - {:doc (first fdecl)} - {}) - fdecl (if (string? (first fdecl)) - (next fdecl) - fdecl) - m (if (map? (first fdecl)) - (conj m (first fdecl)) - m) - fdecl (if (map? (first fdecl)) - (next fdecl) - fdecl) - fdecl (if (vector? (first fdecl)) - (list fdecl) - fdecl) - m (if (map? (last fdecl)) - (conj m (last fdecl)) - m) - fdecl (if (map? (last fdecl)) - (butlast fdecl) - fdecl) - m (conj {:arglists (list 'quote (sigs fdecl))} m) - m (let* [inline (:inline m) - ifn (first inline) - iname (second inline)] - ;; same as: (if (and (= 'fn ifn) (not (symbol? iname))) ...) - (if (if (= 'fn ifn) - (if (symbol? iname) - false - true)) - ;; inserts the same fn name to the inline fn if it does not have one - (assoc m :inline (cons ifn (cons (symbol (str iname "__inliner")) - (next inline)))) - m)) - m (conj (if (meta name) (meta name) {}) m)] - `(def ~(with-meta name m) - ~(with-meta `(fn ~name ~@fdecl) {:rettag (:tag m)}))))) - -(defn macroexpand-1 - "If form represents a macro form, returns its expansion, - else returns form." - [form] - (cpp/jank.runtime.macroexpand1 form)) -(defn macroexpand - "Repeatedly calls macroexpand-1 on form until it no longer - represents a macro form, then returns it. Note neither - macroexpand-1 nor macroexpand expand macros in subforms." - [form] - (cpp/jank.runtime.macroexpand form)) - -(defn gensym - "Returns a new symbol with a unique name. If a prefix string is - supplied, the name is prefix# where # is some unique number. If - prefix is not supplied, the prefix is 'G__'." - ([] - (cpp/jank.runtime.gensym "G__")) - ([prefix-string] - (cpp/jank.runtime.gensym prefix-string))) - -(defn - ^{:macro true - :doc "Like defn, but the resulting function name is declared as a - macro and will be used as a macro by the compiler when it is - called."} - defmacro - [&form &env name & args] - (let [prefix (loop [p (list name) args args] - (let [f (first args)] - (if (string? f) - (recur (cons f p) (next args)) - (if (map? f) - (recur (cons f p) (next args)) - p)))) - fdecl (loop [fd args] - (if (string? (first fd)) - (recur (next fd)) - (if (map? (first fd)) - (recur (next fd)) - fd))) - fdecl (if (vector? (first fdecl)) - (list fdecl) - fdecl) - add-implicit-args (fn [fd] - (let [args (first fd)] - (cons (vec (cons '&form (cons '&env args))) (next fd)))) - add-args (fn [acc ds] - (if (nil? ds) - acc - (let [d (first ds)] - (if (map? d) - (conj acc d) - (recur (conj acc (add-implicit-args d)) (next ds)))))) - fdecl (seq (add-args [] fdecl)) - decl (loop [p prefix d fdecl] - (if p - (recur (next p) (cons (first p) d)) - d))] - (list 'do - (cons `defn decl) - (list `reset-meta! (list 'var name) (list 'assoc - (list 'meta (list 'var name)) - :macro - true)) - (list 'var name)))) - -(defmacro defn- - "Same as defn, yielding non-public def." - {:added "1.0"} - [name & decls] - (cons `defn (cons (with-meta name (assoc (meta name) :private true)) decls))) - -(defmacro when - "Evaluates test. If logical true, evaluates body in an implicit do." - [condition & body] - (list 'if condition - (cons 'do body) - nil)) - -(defmacro when-not - "Evaluates test. If logical false, evaluates body in an implicit do." - [condition & body] - (list 'if (list 'clojure.core/not condition) - (cons 'do body) - nil)) - -(defmacro cond - "Takes a set of test/expr pairs. It evaluates each test one at a - time. If a test returns logical true, cond evaluates and returns - the value of the corresponding expr and doesn't evaluate any of the - other tests or exprs. (cond) returns nil." - [& clauses] - (when clauses - (list 'if (first clauses) - (if (next clauses) - (second clauses) - (let [err "cond requires an even number of forms"] - (list 'throw (list 'clojure.core/ex-info "invalid cond" {:err err})))) - (cons 'clojure.core/cond (next (next clauses)))))) - -(defmacro or - "Evaluates exprs one at a time, from left to right. If a form - returns a logical true value, or returns that value and doesn't - evaluate any of the other expressions, otherwise it returns the - value of the last expression. (or) returns nil." - ([] - nil) - ([x] - x) - ([x & more] - (let [x-res (gensym)] - (list `let [x-res x] - (list 'if x-res - x-res - (cons `or more)))))) - -(defmacro and - "Evaluates exprs one at a time, from left to right. If a form - returns logical false (nil or false), and returns that value and - doesn't evaluate any of the other expressions, otherwise it returns - the value of the last expr. (and) returns true." - ([] - true) - ([x] - x) - ([x & more] - (let [x-res (gensym)] - (list `let [x-res x] - (list 'if x-res - (cons `and more) - x-res))))) - -(defmacro assert - "Evaluates expr and throws an exception if it does not evaluate to - logical true." - ([x] - (when *assert* - (list `when-not x - (list 'throw (list `ex-info - "assertion failed" - {:assertion (pr-str x)}))))) - ([x message] - (when *assert* - (list `when-not x - (list 'throw (list `ex-info - "assertion failed" - {:assertion (pr-str x) - :message message})))))) - -(defmacro comment - "Ignores body, yields nil" - [& body]) - +;(def ^:dynamic *assert*) +;(def ^:dynamic *compile-files*) +;(def ^:dynamic *file*) +; +;(def ^:dynamic *in* nil) +;(def ^:dynamic *out* nil) +;(def ^:dynamic *command-line-args* nil) +;(def ^:dynamic *warn-on-reflection* nil) +;(def ^:dynamic *compile-path* nil) +;(def ^:dynamic *unchecked-math* nil) +;(def ^:dynamic *compiler-options* nil) +;(def ^:dynamic *err* nil) +;(def ^:dynamic *flush-on-newline* nil) +;(def ^:dynamic *print-meta* nil) +;(def ^:dynamic *print-dup* nil) +;(def ^:dynamic *print-readably* nil) +;(def ^:dynamic *read-eval* nil) +; +;(cpp/raw "#include ") +;(cpp/raw "#include ") +;(cpp/raw "#include ") +; +;(cpp/raw "#include ") +;(cpp/raw "#include ") +;(cpp/raw "#include ") +;(cpp/raw "#include ") +; +;; Syntax quoting. +;(def unquote +; (fn* unquote [_] +; (throw "~ cannot be used outside of syntax quote"))) +;(def unquote-splicing +; (fn* unquote-splicing [_] +; (throw "~@ cannot be used outside of syntax quote"))) +; +;(def type (fn* type [o] +; (cpp/jank.runtime.object_type_str (cpp/.-type o)))) +; +;; Exceptions +;(def ex-info +; "Create an instance of ExceptionInfo, a RuntimeException subclass +; that carries a map of additional data." +; (fn* ex-info +; ([msg map] +; {:error msg +; :data map}) +; ([msg map cause] +; {:error msg +; :data map +; :cause cause}))) +; +;(def ex-message +; "Returns the message attached to ex if ex is a Throwable. +; Otherwise returns nil." +; :error) +; +;(def ex-data +; "Returns exception data (a map) if ex is an IExceptionInfo. +; Otherwise returns nil." +; :data) +; +;(def ex-cause +; "Returns the cause of ex if ex is a Throwable. +; Otherwise returns nil." +; :cause) +; +;; Relations. +;;; Miscellaneous. +;(def nil? +; "Returns true if x is nil, false otherwise." +; (fn* nil? [o] +; (cpp/== (cpp/.-type o) cpp/jank.runtime.object_type.nil))) +; +;(def identical? +; "Tests if 2 arguments are the same object, meaning the same pointer address." +; (fn* identical? [lhs rhs] +; (cpp/== lhs rhs))) +; +;; Collections. +;(def empty? +; "Returns true if coll has no items - same as (not (seq coll))." +; (fn* empty? [o] +; (cpp/jank.runtime.is_empty o))) +;(def empty +; "Returns an empty collection of the same category as coll, or nil" +; (fn* empty [o] +; (cpp/jank.runtime.empty o))) +;(def count +; "Returns the number of items in the collection. (count nil) returns +; 0. Also works on strings, arrays, and Java Collections and Maps" +; (fn* [coll] +; (cpp/jank.runtime.sequence_length coll))) +; +;; Numbers. +;(def boolean +; "Coerce to boolean" +; (fn* boolean [o] +; (cpp/jank.runtime.truthy o))) +;(def int +; "Coerce to int" +; (fn* int [o] +; (cpp/jank.runtime.to_int o))) +;(def float +; "Coerce to float" +; (fn* real [o] +; (cpp/jank.runtime.to_real o))) +; +;;; Sequences. +;(def seq +; "Returns a seq on the collection. If the collection is +; empty, returns nil. (seq nil) returns nil. seq also works on +; Strings, native Java arrays (of reference types) and any objects +; that implement Iterable. Note that seqs cache values, thus seq +; should not be used on any Iterable whose iterator repeatedly +; returns the same mutable object." +; (fn* seq [o] +; (cpp/jank.runtime.seq o))) +;(def fresh-seq +; (fn* fresh-seq [o] +; (cpp/jank.runtime.fresh_seq o))) +;(def first +; "Returns the first item in the collection. Calls seq on its +; argument. If coll is nil, returns nil." +; (fn* first [o] +; (cpp/jank.runtime.first o))) +;(def ffirst +; "Same as (first (first x))" +; (fn* ffirst [o] +; (first (first o)))) +;(def next +; "Returns a seq of the items after the first. Calls seq on its +; argument. If there are no more items, returns nil." +; (fn* next [o] +; (cpp/jank.runtime.next o))) +;(def next-in-place +; (fn* next-in-place [o] +; (cpp/jank.runtime.next_in_place o))) +;(def nnext +; "Same as (next (next x))" +; (fn* nnext [o] +; (next (next o)))) +;(def second +; "Same as (first (next x))" +; (fn* second [o] +; (cpp/jank.runtime.second o))) +;(def rest +; "Returns a possibly empty seq of the items after the first. Calls seq on its +; argument." +; (fn* rest [o] +; (cpp/jank.runtime.rest o))) +;(def cons +; "Returns a new seq where x is the first element and seq is +; the rest." +; (fn* cons [head tail] +; (cpp/jank.runtime.cons head tail))) +;(def coll? +; "Returns true if x implements IPersistentCollection" +; (fn* coll? [o] +; (cpp/jank.runtime.is_collection o))) +;(def seq? +; "Return true if x implements ISeq" +; (fn* seq? [o] +; (cpp/jank.runtime.is_seq o))) +;(def seqable? +; "Return true if the seq function is supported for x" +; (fn* seqable? [o] +; (cpp/jank.runtime.is_seqable o))) +; +;(def ^:private reverse* +; (fn* reverse* [coll] +; (loop* [acc '() +; coll (seq coll)] +; (if (empty? coll) +; acc +; (recur (cons (first coll) acc) +; (rest coll)))))) +; +;; XXX: The real concat will be defined later on, to be lazy. +;(def ^:private concat* +; (fn* concat* +; ([] +; '()) +; ([x] +; (seq x)) +; ([x y] +; (loop* [acc y +; x (reverse* x)] +; (if (empty? x) +; acc +; (recur (cons (first x) acc) +; (rest x))))) +; ([x y & zs] +; (let* [r (concat* x y)] +; (if (empty? zs) +; r +; (recur r (first zs) (rest zs))))))) +; +;; Lists. +;(def list? +; "Returns true if x implements IPersistentList" +; (fn* list? [o] +; (cpp/jank.runtime.is_list o))) +;(def list +; "Creates a new list containing the items." +; (fn* list [& args] +; (cpp/jank.runtime.list args))) +; +;;; Vectors. +;(def vector? +; "Return true if x implements IPersistentVector" +; (fn* vector? [o] +; (cpp/jank.runtime.is_vector o))) +;(def vec +; "Creates a new vector containing the contents of coll. Java arrays +; will be aliased and should not be modified." +; (fn* vec [o] +; (cpp/jank.runtime.vec o))) +; +;(def subvec +; "Returns a persistent vector of the items in vector from +; start (inclusive) to end (exclusive). If end is not supplied, +; defaults to (count vector). This operation is O(1) and very fast, as +; the resulting vector shares structure with the original and no +; trimming is done." +; (fn* subvec +; ([v start] +; (subvec v start (count v))) +; ([v start end] +; (cpp/jank.runtime.subvec v start end)))) +; +;(def conj +; "conj[oin]. Returns a new collection with the xs +; 'added'. (conj nil item) returns (item). +; (conj coll) returns coll. (conj) returns []. +; The 'addition' may happen at different 'places' depending +; on the concrete type." +; (fn* conj +; ([] +; []) +; ([coll] +; coll) +; ([coll x] +; (cpp/jank.runtime.conj coll x)) +; ([coll x & args] +; (let* [res (conj coll x)] +; (if (empty? args) +; res +; (recur res (first args) (next args))))))) +; +;(def last +; "Return the last item in coll, in linear time." +; (fn* last [s] +; (if (next s) +; (recur (next s)) +; (first s)))) +; +;(def butlast +; "Return a seq of all but the last item in coll, in linear time." +; (fn* butlast [s] +; (loop* [ret [] +; s s] +; (if (next s) +; (recur (conj ret (first s)) (next s)) +; (seq ret))))) +; +;;; Maps. +;(def hash-map +; "keyval => key val +; Returns a new hash map with supplied mappings. If any keys are +; equal, they are handled as if by repeated uses of assoc." +; (fn* hash-map +; ([] (cpp/jank.runtime.obj.persistent_hash_map.empty)) +; ([& keyvals] +; (cpp/jank.runtime.obj.persistent_hash_map.create_from_seq keyvals)))) +; +;(def sorted-map +; "keyval => key val +; Returns a new sorted map with supplied mappings. If any keys are +; equal, they are handled as if by repeated uses of assoc." +; (fn* sorted-map +; ([] (cpp/jank.runtime.obj.persistent_sorted_map.empty)) +; ([& keyvals] +; (cpp/jank.runtime.obj.persistent_sorted_map.create_from_seq keyvals)))) +; +;(def map? +; "Return true if x implements IPersistentMap" +; (fn* map? [o] +; (cpp/jank.runtime.is_map o))) +; +;(def associative? +; "Returns true if coll implements Associative" +; (fn* associative? [o] +; (cpp/jank.runtime.is_associative o))) +; +;(def assoc +; "assoc[iate]. When applied to a map, returns a new map of the +; same (hashed/sorted) type, that contains the mapping of key(s) to +; val(s). When applied to a vector, returns a new vector that +; contains val at index. Note - index must be <= (count vector)." +; (fn* assoc +; ([map key val] +; (cpp/jank.runtime.assoc map key val)) +; ([map key val & kvs] +; (let* [res (assoc map key val)] +; (if kvs +; (if (next kvs) +; (recur res (first kvs) (second kvs) (nnext kvs)) +; (throw "assoc expects even number of args after the first")) +; res))))) +; +;;; Strings. +;(def string? +; "Return true if x is a String" +; (fn* string? [o] +; (cpp/jank.runtime.is_string o))) +; +;(def char? +; "Return true if x is a Character" +; (fn* char? [o] +; (cpp/jank.runtime.is_char o))) +; +;(def str +; "With no args, returns the empty string. With one arg x, returns +; x.toString(). (str nil) returns the empty string. With more than +; one arg, returns the concatenation of the str values of the args." +; (fn* str +; ([] +; "") +; ([o] +; (if (nil? o) +; "" +; (cpp/jank.runtime.to_string o))) +; ([o & args] +; (cpp/jank.runtime.str o args)))) +; +;;; Symbols. +;(def symbol? +; "Return true if x is a Symbol" +; (fn* symbol? [o] +; (cpp/jank.runtime.is_symbol o))) +;(def +; symbol +; "Returns a Symbol with the given namespace and name. Arity-1 works +; on strings, keywords, and vars." +; (fn* symbol +; ([o] +; (cpp/jank.runtime.to_unqualified_symbol o)) +; ([ns o] +; (if (nil? ns) +; (symbol o) +; (cpp/jank.runtime.to_qualified_symbol ns o))))) +;(def simple-symbol? +; "Return true if x is a symbol without a namespace" +; (fn* simple-symbol? [x] +; (cpp/jank.runtime.is_simple_symbol x))) +;(def qualified-symbol? +; "Return true if x is a symbol with a namespace" +; (fn* qualified-symbol? [x] +; (cpp/jank.runtime.is_qualified_symbol x))) +; +;; Relations. +;;; Miscellaneous. +;(def true? +; "Returns true if x is the value true, false otherwise." +; (fn* true? [x] +; (cpp/jank.runtime.is_true x))) +;(def false? +; "Returns true if x is the value false, false otherwise." +; (fn* false? [x] +; (cpp/jank.runtime.is_false x))) +;(def not +; "Returns true if x is logical false, false otherwise." +; (fn* not [x] +; (cpp/clojure.core_native.not_ x))) +;(def some? +; "Returns true if x is not nil, false otherwise." +; (fn* some? [x] +; (cpp/jank.runtime.is_some x))) +; +;;; Metadata. +;(def meta +; "Returns the metadata of obj, returns nil if there is no metadata." +; (fn* meta [obj] +; (cpp/jank.runtime.meta obj))) +;(def with-meta +; "Returns an object of the same type and value as obj, with +; map m as its metadata." +; (fn* with-meta [obj m] +; (cpp/jank.runtime.with_meta obj m))) +;(def reset-meta! +; "Atomically resets the metadata for a namespace/var/ref/agent/atom" +; (fn* [iref metadata-map] +; (cpp/jank.runtime.reset_meta iref metadata-map))) +; +;;; Input/output. +;(def print +; "Prints the object(s) to the output stream that is the current value +; of *out*. print and println produce output for human consumption." +; (fn* print [& more] +; (cpp/jank.runtime.print more))) +;(def println +; "Same as print followed by (newline)" +; (fn* println [& more] +; (cpp/jank.runtime.println more))) +;(def pr +; "Prints the object(s) to the output stream that is the current value +; of *out*. Prints the object(s), separated by spaces if there is +; more than one. By default, pr and prn print in a way that objects +; can be read by the reader" +; (fn* pr [& more] +; (cpp/jank.runtime.pr more))) +;(def prn +; "Same as pr followed by (newline). Observes *flush-on-newline*" +; (fn* prn [& more] +; (cpp/jank.runtime.prn more))) +;(def pr-str +; "pr to a string, returning it" +; ;; TODO: support multiple parameters, preserving current behavior +; (fn* pr-str [x] +; (cpp/jank.runtime.to_code_string x))) +; +;;; Utils. +;; The full `apply` will be defined below, but it requires more helpers to support +;; all of its arities. This version of apply* is used by the parser for syntax quoting. +;; This allows us to use syntax quoting sooner and also have more easily inlinable +;; syntax quoting code, since this version of apply is lighter than the full version. +;(def ^:private apply* +; (fn* apply* [source args] +; (cpp/jank.runtime.apply_to source args))) +; +;(def ^{:macro true} let +; (fn* let [&form &env & decl] +; `(let* ~@decl))) +; +;(def ^{:macro true} loop +; (fn* loop [&form &env & decl] +; `(loop* ~@decl))) +; +;(def ^{:macro true} fn +; (fn* fn [&form &env & decl] +; (with-meta `(fn* ~@decl) (meta &form)))) +; +;(def = +; "Equality. Returns true if x equals y, false if not. It also works +; for nil and compares numbers and collections in a type-independent +; manner. Clojure's immutable data structures define equals() (and +; thus =) as a value, not an identity, comparison." +; (fn* = +; ([x] true) +; ([x y] +; (cpp/jank.runtime.equal x y)) +; ([x y & more] +; (if (cpp/jank.runtime.equal x y) +; (if (next more) +; (recur y (first more) (next more)) +; (cpp/jank.runtime.equal y (first more))) +; false)))) +; +;(def == +; "Returns non-nil if nums all have the equivalent +; value (type-independent), otherwise false" +; (fn* == +; ([x] true) +; ([x y] +; (cpp/jank.runtime.is_equiv x y)) +; ([x y & more] +; (if (cpp/jank.runtime.is_equiv x y) +; (if (next more) +; (recur y (first more) (next more)) +; (cpp/jank.runtime.is_equiv y (first more))) +; false)))) +; +;(def ^:private sigs +; (fn* [fdecl] +; (let* [asig (fn* asig [fdecl] +; (let* [arglist (first fdecl) +; ;elide implicit macro args +; arglist (if (= '&form (first arglist)) +; (subvec arglist 2 (count arglist)) +; arglist) +; body (next fdecl)] +; (if (map? (first body)) +; (if (next body) +; (with-meta arglist (conj (if (meta arglist) +; (meta arglist) +; {}) +; (first body))) +; arglist) +; arglist)))] +; (if (seq? (first fdecl)) +; (loop* [ret [] +; fdecls fdecl] +; (if fdecls +; (recur (conj ret (asig (first fdecls))) (next fdecls)) +; (seq ret))) +; (list (asig fdecl)))))) +; +;; Macros. +;(def ^{:macro true +; :doc "Same as (def name (fn [params* ] exprs*)) or (def +; name (fn ([params* ] exprs*)+)) with any doc-string or attrs added +; to the var metadata. prepost-map defines a map with optional keys +; :pre and :post that contain collections of pre or post conditions."} +; defn +; (fn* defn [&form &env name & fdecl] +; ;; Note: Cannot delegate this check to def because of the call to (with-meta name ..) +; (if (not (symbol? name)) +; (throw "First argument to defn must be a symbol")) +; (let* [m (if (string? (first fdecl)) +; {:doc (first fdecl)} +; {}) +; fdecl (if (string? (first fdecl)) +; (next fdecl) +; fdecl) +; m (if (map? (first fdecl)) +; (conj m (first fdecl)) +; m) +; fdecl (if (map? (first fdecl)) +; (next fdecl) +; fdecl) +; fdecl (if (vector? (first fdecl)) +; (list fdecl) +; fdecl) +; m (if (map? (last fdecl)) +; (conj m (last fdecl)) +; m) +; fdecl (if (map? (last fdecl)) +; (butlast fdecl) +; fdecl) +; m (conj {:arglists (list 'quote (sigs fdecl))} m) +; m (let* [inline (:inline m) +; ifn (first inline) +; iname (second inline)] +; ;; same as: (if (and (= 'fn ifn) (not (symbol? iname))) ...) +; (if (if (= 'fn ifn) +; (if (symbol? iname) +; false +; true)) +; ;; inserts the same fn name to the inline fn if it does not have one +; (assoc m :inline (cons ifn (cons (symbol (str iname "__inliner")) +; (next inline)))) +; m)) +; m (conj (if (meta name) (meta name) {}) m)] +; `(def ~(with-meta name m) +; ~(with-meta `(fn ~name ~@fdecl) {:rettag (:tag m)}))))) +; +;(defn macroexpand-1 +; "If form represents a macro form, returns its expansion, +; else returns form." +; [form] +; (cpp/jank.runtime.macroexpand1 form)) +;(defn macroexpand +; "Repeatedly calls macroexpand-1 on form until it no longer +; represents a macro form, then returns it. Note neither +; macroexpand-1 nor macroexpand expand macros in subforms." +; [form] +; (cpp/jank.runtime.macroexpand form)) +; +;(defn gensym +; "Returns a new symbol with a unique name. If a prefix string is +; supplied, the name is prefix# where # is some unique number. If +; prefix is not supplied, the prefix is 'G__'." +; ([] +; (cpp/jank.runtime.gensym "G__")) +; ([prefix-string] +; (cpp/jank.runtime.gensym prefix-string))) +; +;(defn +; ^{:macro true +; :doc "Like defn, but the resulting function name is declared as a +; macro and will be used as a macro by the compiler when it is +; called."} +; defmacro +; [&form &env name & args] +; (let [prefix (loop [p (list name) args args] +; (let [f (first args)] +; (if (string? f) +; (recur (cons f p) (next args)) +; (if (map? f) +; (recur (cons f p) (next args)) +; p)))) +; fdecl (loop [fd args] +; (if (string? (first fd)) +; (recur (next fd)) +; (if (map? (first fd)) +; (recur (next fd)) +; fd))) +; fdecl (if (vector? (first fdecl)) +; (list fdecl) +; fdecl) +; add-implicit-args (fn [fd] +; (let [args (first fd)] +; (cons (vec (cons '&form (cons '&env args))) (next fd)))) +; add-args (fn [acc ds] +; (if (nil? ds) +; acc +; (let [d (first ds)] +; (if (map? d) +; (conj acc d) +; (recur (conj acc (add-implicit-args d)) (next ds)))))) +; fdecl (seq (add-args [] fdecl)) +; decl (loop [p prefix d fdecl] +; (if p +; (recur (next p) (cons (first p) d)) +; d))] +; (list 'do +; (cons `defn decl) +; (list `reset-meta! (list 'var name) (list 'assoc +; (list 'meta (list 'var name)) +; :macro +; true)) +; (list 'var name)))) +; +;(defmacro defn- +; "Same as defn, yielding non-public def." +; {:added "1.0"} +; [name & decls] +; (cons `defn (cons (with-meta name (assoc (meta name) :private true)) decls))) +; +;(defmacro when +; "Evaluates test. If logical true, evaluates body in an implicit do." +; [condition & body] +; (list 'if condition +; (cons 'do body) +; nil)) +; +;(defmacro when-not +; "Evaluates test. If logical false, evaluates body in an implicit do." +; [condition & body] +; (list 'if (list 'clojure.core/not condition) +; (cons 'do body) +; nil)) +; +;(defmacro cond +; "Takes a set of test/expr pairs. It evaluates each test one at a +; time. If a test returns logical true, cond evaluates and returns +; the value of the corresponding expr and doesn't evaluate any of the +; other tests or exprs. (cond) returns nil." +; [& clauses] +; (when clauses +; (list 'if (first clauses) +; (if (next clauses) +; (second clauses) +; (let [err "cond requires an even number of forms"] +; (list 'throw (list 'clojure.core/ex-info "invalid cond" {:err err})))) +; (cons 'clojure.core/cond (next (next clauses)))))) +; +;(defmacro or +; "Evaluates exprs one at a time, from left to right. If a form +; returns a logical true value, or returns that value and doesn't +; evaluate any of the other expressions, otherwise it returns the +; value of the last expression. (or) returns nil." +; ([] +; nil) +; ([x] +; x) +; ([x & more] +; (let [x-res (gensym)] +; (list `let [x-res x] +; (list 'if x-res +; x-res +; (cons `or more)))))) +; +;(defmacro and +; "Evaluates exprs one at a time, from left to right. If a form +; returns logical false (nil or false), and returns that value and +; doesn't evaluate any of the other expressions, otherwise it returns +; the value of the last expr. (and) returns true." +; ([] +; true) +; ([x] +; x) +; ([x & more] +; (let [x-res (gensym)] +; (list `let [x-res x] +; (list 'if x-res +; (cons `and more) +; x-res))))) +; +;(defmacro assert +; "Evaluates expr and throws an exception if it does not evaluate to +; logical true." +; ([x] +; (when *assert* +; (list `when-not x +; (list 'throw (list `ex-info +; "assertion failed" +; {:assertion (pr-str x)}))))) +; ([x message] +; (when *assert* +; (list `when-not x +; (list 'throw (list `ex-info +; "assertion failed" +; {:assertion (pr-str x) +; :message message})))))) +; +;(defmacro comment +; "Ignores body, yields nil" +; [& body]) +; ;;; Transients. ;(defn- transientable? ; "Returns a whether the collection can be made transient." @@ -4740,2796 +4740,2796 @@ ; ;;;;;;;;;; var stuff ; -;(defn with-bindings* -; "Takes a map of Var/value pairs. Installs for the given Vars the associated -; values as thread-local bindings. Then calls f with the supplied arguments. -; Pops the installed bindings after f returned. Returns whatever f returns." -; [binding-map f & args] -; (push-thread-bindings (if (= "persistent_array_map" (type binding-map)) -; (into (hash-map) binding-map) -; binding-map)) -; (try -; (apply f args) -; (finally -; (pop-thread-bindings)))) -; -;(defmacro with-bindings -; "Takes a map of Var/value pairs. Installs for the given Vars the associated -; values as thread-local bindings. Then executes body. Pops the installed -; bindings after body was evaluated. Returns the value of body." -; [binding-map & body] -; `(with-bindings* ~binding-map (fn [] ~@body))) -; -;(defn bound-fn* -; "Returns a function, which will install the same bindings in effect as in -; the thread at the time bound-fn* was called and then call f with any given -; arguments. This may be used to define a helper function which runs on a -; different thread, but needs the same bindings in place." -; [f] -; (let [bindings (get-thread-bindings)] -; (fn [& args] -; (apply with-bindings* bindings f args)))) -; -;(defmacro bound-fn -; "Returns a function defined by the given fntail, which will install the -; same bindings in effect as in the thread at the time bound-fn was called. -; This may be used to define a helper function which runs on a different -; thread, but needs the same bindings in place." -; [& fntail] -; `(bound-fn* (fn ~@fntail))) -; -;(defn- binding-conveyor-fn -; [f] -; ;; (let [frame (clojure.lang.Var/cloneThreadBindingFrame)] -; ;; (fn -; ;; ([] -; ;; (clojure.lang.Var/resetThreadBindingFrame frame) -; ;; (f)) -; ;; ([x] -; ;; (clojure.lang.Var/resetThreadBindingFrame frame) -; ;; (f x)) -; ;; ([x y] -; ;; (clojure.lang.Var/resetThreadBindingFrame frame) -; ;; (f x y)) -; ;; ([x y z] -; ;; (clojure.lang.Var/resetThreadBindingFrame frame) -; ;; (f x y z)) -; ;; ([x y z & args] -; ;; (clojure.lang.Var/resetThreadBindingFrame frame) -; ;; (apply f x y z args)))) -; (throw "TODO: port binding-conveyor-fn")) -; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Refs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;(defn- -; setup-reference [#_clojure.lang.ARef r options] -; ;; (let [opts (apply hash-map options)] -; ;; (when (:meta opts) -; ;; (.resetMeta r (:meta opts))) -; ;; (when (:validator opts) -; ;; (.setValidator r (:validator opts))) -; ;; r) -; (throw "TODO: port setup-reference")) -; -;(defn agent -; "Creates and returns an agent with an initial value of state and -; zero or more options (in any order): -; -; :meta metadata-map -; -; :validator validate-fn -; -; :error-handler handler-fn -; -; :error-mode mode-keyword -; -; If metadata-map is supplied, it will become the metadata on the -; agent. validate-fn must be nil or a side-effect-free fn of one -; argument, which will be passed the intended new state on any state -; change. If the new state is unacceptable, the validate-fn should -; return false or throw an exception. handler-fn is called if an -; action throws an exception or if validate-fn rejects a new state -- -; see set-error-handler! for details. The mode-keyword may be either -; :continue (the default if an error-handler is given) or :fail (the -; default if no error-handler is given) -- see set-error-mode! for -; details." -; ([state & options] -; ;; (let [a (new clojure.lang.Agent state) -; ;; opts (apply hash-map options)] -; ;; (setup-reference a options) -; ;; (when (:error-handler opts) -; ;; (.setErrorHandler a (:error-handler opts))) -; ;; (.setErrorMode a (or (:error-mode opts) -; ;; (if (:error-handler opts) :continue :fail))) -; ;; a) -; (throw "TODO: port agent"))) -; -;(defn set-agent-send-executor! -; "Sets the ExecutorService to be used by send" -; [executor] -; ;; (set! clojure.lang.Agent/pooledExecutor executor) -; (throw "TODO: port set-agent-send-executor!")) -; -;(defn set-agent-send-off-executor! -; "Sets the ExecutorService to be used by send-off" -; [executor] -; ;; (set! clojure.lang.Agent/soloExecutor executor) -; (throw "TODO: port set-agent-send-off-executor!")) -; -;(defn send-via -; "Dispatch an action to an agent. Returns the agent immediately. -; Subsequently, in a thread supplied by executor, the state of the agent -; will be set to the value of: -; -; (apply action-fn state-of-agent args)" -; [executor #_clojure.lang.Agent a f & args] -; ;; (.dispatch a (binding [*agent* a] (binding-conveyor-fn f)) args executor) -; (throw "TODO: port send-via")) -; -;(defn send -; "Dispatch an action to an agent. Returns the agent immediately. -; Subsequently, in a thread from a thread pool, the state of the agent -; will be set to the value of: -; -; (apply action-fn state-of-agent args)" -; [#_clojure.lang.Agent a f & args] -; ;; (apply send-via clojure.lang.Agent/pooledExecutor a f args) -; (throw "TODO: port send")) -; -;(defn send-off -; "Dispatch a potentially blocking action to an agent. Returns the -; agent immediately. Subsequently, in a separate thread, the state of -; the agent will be set to the value of: -; -; (apply action-fn state-of-agent args)" -; [#_clojure.lang.Agent a f & args] -; ;; (apply send-via clojure.lang.Agent/soloExecutor a f args) -; (throw "TODO: port send-off")) -; -;(defn release-pending-sends -; "Normally, actions sent directly or indirectly during another action -; are held until the action completes (changes the agent's -; state). This function can be used to dispatch any pending sent -; actions immediately. This has no impact on actions sent during a -; transaction, which are still held until commit. If no action is -; occurring, does nothing. Returns the number of actions dispatched." -; [] -; ;; (clojure.lang.Agent/releasePendingSends) -; (throw "TODO: port release-pending-sends")) -; -;(defn add-watch -; "Adds a watch function to an agent/atom/var/ref reference. The watch -; fn must be a fn of 4 args: a key, the reference, its old-state, its -; new-state. Whenever the reference's state might have been changed, -; any registered watches will have their functions called. The watch fn -; will be called synchronously, on the agent's thread if an agent, -; before any pending sends if agent or ref. Note that an atom's or -; ref's state may have changed again prior to the fn call, so use -; old/new-state rather than derefing the reference. Note also that watch -; fns may be called from multiple threads simultaneously. Var watchers -; are triggered only by root binding changes, not thread-local -; set!s. Keys must be unique per reference, and can be used to remove -; the watch with remove-watch, but are otherwise considered opaque by -; the watch mechanism." -; [reference key f] -; (cpp/jank.runtime.add_watch reference key f)) -; -;(defn remove-watch -; "Removes a watch (set by add-watch) from a reference" -; [reference key] -; (cpp/jank.runtime.remove_watch reference key)) -; -;(defn agent-error -; "Returns the exception thrown during an asynchronous action of the -; agent if the agent is failed. Returns nil if the agent is not -; failed." -; [#_clojure.lang.Agent a] -; ;; (.getError a) -; (throw "TODO: port agent-error")) -; -;(defn restart-agent -; "When an agent is failed, changes the agent state to new-state and -; then un-fails the agent so that sends are allowed again. If -; a :clear-actions true option is given, any actions queued on the -; agent that were being held while it was failed will be discarded, -; otherwise those held actions will proceed. The new-state must pass -; the validator if any, or restart will throw an exception and the -; agent will remain failed with its old state and error. Watchers, if -; any, will NOT be notified of the new state. Throws an exception if -; the agent is not failed." -; [#_clojure.lang.Agent a, new-state & options] -; ;; (let [opts (apply hash-map options)] -; ;; (.restart a new-state (if (:clear-actions opts) true false))) -; (throw "TODO: port restart-agent")) -; -;(defn set-error-handler! -; "Sets the error-handler of agent a to handler-fn. If an action -; being run by the agent throws an exception or doesn't pass the -; validator fn, handler-fn will be called with two arguments: the -; agent and the exception." -; [#_clojure.lang.Agent a, handler-fn] -; ;; (.setErrorHandler a handler-fn) -; (throw "TODO: port set-error-handler!")) -; -;(defn error-handler -; "Returns the error-handler of agent a, or nil if there is none. -; See set-error-handler!" -; [#_clojure.lang.Agent a] -; ;; (.getErrorHandler a) -; (throw "TODO: port error-handler")) -; -;(defn set-error-mode! -; "Sets the error-mode of agent a to mode-keyword, which must be -; either :fail or :continue. If an action being run by the agent -; throws an exception or doesn't pass the validator fn, an -; error-handler may be called (see set-error-handler!), after which, -; if the mode is :continue, the agent will continue as if neither the -; action that caused the error nor the error itself ever happened. -; -; If the mode is :fail, the agent will become failed and will stop -; accepting new 'send' and 'send-off' actions, and any previously -; queued actions will be held until a 'restart-agent'. Deref will -; still work, returning the state of the agent before the error." -; [#_clojure.lang.Agent a, mode-keyword] -; ;; (.setErrorMode a mode-keyword) -; (throw "TODO: port set-error-mode!")) -; -;(defn error-mode -; "Returns the error-mode of agent a. See set-error-mode!" -; [#_clojure.lang.Agent a] -; ;; (.getErrorMode a) -; (throw "TODO: port error-mode")) -; -;(defn agent-errors -; "DEPRECATED: Use 'agent-error' instead. -; Returns a sequence of the exceptions thrown during asynchronous -; actions of the agent." -; [a] -; (when-let [e (agent-error a)] -; (list e))) -; -;(defn clear-agent-errors -; "DEPRECATED: Use 'restart-agent' instead. -; Clears any exceptions thrown during asynchronous actions of the -; agent, allowing subsequent actions to occur." -; [#_clojure.lang.Agent a] -; ;; (restart-agent a (.deref a)) -; (throw "TODO: port clear-agent-errors")) -; -;(defn shutdown-agents -; "Initiates a shutdown of the thread pools that back the agent -; system. Running actions will complete, but no new actions will be -; accepted" -; [] -; ;; (. clojure.lang.Agent shutdown) -; (throw "TODO: port shutdown-agents")) -; -;(defn ref -; "Creates and returns a Ref with an initial value of x and zero or -; more options (in any order): -; -; :meta metadata-map -; -; :validator validate-fn -; -; :min-history (default 0) -; :max-history (default 10) -; -; If metadata-map is supplied, it will become the metadata on the -; ref. validate-fn must be nil or a side-effect-free fn of one -; argument, which will be passed the intended new state on any state -; change. If the new state is unacceptable, the validate-fn should -; return false or throw an exception. validate-fn will be called on -; transaction commit, when all refs have their final values. -; -; Normally refs accumulate history dynamically as needed to deal with -; read demands. If you know in advance you will need history you can -; set :min-history to ensure it will be available when first needed (instead -; of after a read fault). History is limited, and the limit can be set -; with :max-history." -; ([x] -; ;; (new clojure.lang.Ref x) -; (throw "TODO: port ref")) -; ([x & options] -; ;; (let [r ^clojure.lang.Ref (setup-reference (ref x) options) -; ;; opts (apply hash-map options)] -; ;; (when (:max-history opts) -; ;; (.setMaxHistory r (:max-history opts))) -; ;; (when (:min-history opts) -; ;; (.setMinHistory r (:min-history opts))) -; ;; r) -; (throw "TODO: port ref"))) -; -;(defn- deref-future -; ([#_java.util.concurrent.Future fut] -; ;; (.get fut) -; (throw "TODO: port deref-future")) -; ([#_java.util.concurrent.Future fut timeout-ms timeout-val] -; ;; (try (.get fut timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS) -; ;; (catch java.util.concurrent.TimeoutException e -; ;; timeout-val)) -; (throw "TODO: port deref-future"))) -; -;(defn set-validator! -; "Sets the validator-fn for a var/ref/agent/atom. validator-fn must be nil or a -; side-effect-free fn of one argument, which will be passed the intended -; new state on any state change. If the new state is unacceptable, the -; validator-fn should return false or throw an exception. If the current state (root -; value if var) is not acceptable to the new validator, an exception -; will be thrown and the validator will not be changed." -; [#_clojure.lang.IRef iref validator-fn] -; ;; (. iref (setValidator validator-fn)) -; (throw "TODO: port set-validator!")) -; -;(defn get-validator -; "Gets the validator-fn for a var/ref/agent/atom." -; [#_clojure.lang.IRef iref] -; ;; (. iref (getValidator)) -; (throw "TODO: port get-validator")) -; -;(defn commute -; "Must be called in a transaction. Sets the in-transaction-value of -; ref to: -; -; (apply fun in-transaction-value-of-ref args) -; -; and returns the in-transaction-value of ref. -; -; At the commit point of the transaction, sets the value of ref to be: -; -; (apply fun most-recently-committed-value-of-ref args) -; -; Thus fun should be commutative, or, failing that, you must accept -; last-one-in-wins behavior. commute allows for more concurrency than -; ref-set." -; [#_clojure.lang.Ref ref fun & args] -; ;; (. ref (commute fun args)) -; (throw "TODO: port commute")) -; -;(defn alter -; "Must be called in a transaction. Sets the in-transaction-value of -; ref to: -; -; (apply fun in-transaction-value-of-ref args) -; -; and returns the in-transaction-value of ref." -; [#_clojure.lang.Ref ref fun & args] -; ;; (. ref (alter fun args)) -; (throw "TODO: port alter")) -; -;(defn ref-set -; "Must be called in a transaction. Sets the value of ref. -; Returns val." -; [#_clojure.lang.Ref ref val] -; ;; (. ref (set val)) -; (throw "TODO: port ref-set")) -; -;(defn ref-history-count -; "Returns the history count of a ref" -; [#_clojure.lang.Ref ref] -; ;; (.getHistoryCount ref) -; (throw "TODO: port ref-history-count")) -; -;(defn ref-min-history -; "Gets the min-history of a ref, or sets it and returns the ref" -; ([#_clojure.lang.Ref ref] -; ;; (.getMinHistory ref) -; (throw "TODO: port ref-min-history")) -; ([#_clojure.lang.Ref ref n] -; ;; (.setMinHistory ref n) -; (throw "TODO: port ref-min-history"))) -; -;(defn ref-max-history -; "Gets the max-history of a ref, or sets it and returns the ref" -; ([#_clojure.lang.Ref ref] -; ;; (.getMaxHistory ref) -; (throw "TODO: port ref-max-history")) -; ([#_clojure.lang.Ref ref n] -; ;; (.setMaxHistory ref n) -; (throw "TODO: port ref-max-history"))) -; -;(defn ensure -; "Must be called in a transaction. Protects the ref from modification -; by other transactions. Returns the in-transaction-value of -; ref. Allows for more concurrency than (ref-set ref @ref)" -; [#_clojure.lang.Ref ref] -; ;; (. ref (touch)) -; ;; (. ref (deref)) -; (throw "TODO: port ensure")) -; -;(defmacro sync -; "transaction-flags => TBD, pass nil for now -; -; Runs the exprs (in an implicit do) in a transaction that encompasses -; exprs and any nested calls. Starts a transaction if none is already -; running on this thread. Any uncaught exception will abort the -; transaction and flow out of sync. The exprs may be run more than -; once, but any effects on Refs will be atomic." -; [flags-ignored-for-now & body] -; ;; `(. clojure.lang.LockingTransaction -; ;; (runInTransaction (fn [] ~@body))) -; (throw "TODO: port sync")) -; -;(defmacro io! -; "If an io! block occurs in a transaction, throws an -; IllegalStateException, else runs body in an implicit do. If the -; first expression in body is a literal string, will use that as the -; exception message." -; [& body] -; ;; (let [message (when (string? (first body)) (first body)) -; ;; body (if message (next body) body)] -; ;; `(if (clojure.lang.LockingTransaction/isRunning) -; ;; (throw (new IllegalStateException ~(or message "I/O in transaction"))) -; ;; (do ~@body))) -; (throw "TODO: port io!")) -; -;;;;;;;;;;;;;;;;;;;; sequence fns ;;;;;;;;;;;;;;;;;;;;;;; -; -;(defn sequence -; "Coerces coll to a (possibly empty) sequence, if it is not already -; one. Will not force a lazy seq. (sequence nil) yields (), When a -; transducer is supplied, returns a lazy sequence of applications of -; the transform to the items in coll(s), i.e. to the set of first -; items of each coll, followed by the set of second -; items in each coll, until any one of the colls is exhausted. Any -; remaining items in other colls are ignored. The transform should accept -; number-of-colls arguments" -; ([coll] -; (if (seq? coll) coll -; (or (seq coll) ()))) -; ([xform coll] -; ;; (or (clojure.lang.RT/chunkIteratorSeq -; ;; (clojure.lang.TransformerIterator/create xform (clojure.lang.RT/iter coll))) -; ;; ()) -; (throw "TODO: port sequence")) -; ([xform coll & colls] -; ;; (or (clojure.lang.RT/chunkIteratorSeq -; ;; (clojure.lang.TransformerIterator/createMulti -; ;; xform -; ;; (map #(clojure.lang.RT/iter %) (cons coll colls)))) -; ;; ()) -; (throw "TODO: port sequence"))) -; -;(defn not-every? -; "Returns false if (pred x) is logical true for every x in -; coll, else true." -; [pred coll] -; (not (every? pred coll))) -; -;(defmacro declare -; "defs the supplied var names with no bindings, useful for making forward declarations." -; [& names] `(do ~@(map #(list 'def (vary-meta % assoc :declared true)) names))) -; -;(defn replicate -; "DEPRECATED: Use 'repeat' instead. -; Returns a lazy seq of n xs." -; [n x] (take n (repeat x))) -; -;(defn merge -; "Returns a map that consists of the rest of the maps conj-ed onto -; the first. If a key occurs in more than one map, the mapping from -; the latter (left-to-right) will be the mapping in the result." -; [& maps] -; (when (some identity maps) -; (reduce #(conj (or %1 {}) %2) maps))) -; -;(defn merge-with -; "Returns a map that consists of the rest of the maps conj-ed onto -; the first. If a key occurs in more than one map, the mapping(s) -; from the latter (left-to-right) will be combined with the mapping in -; the result by calling (f val-in-result val-in-latter)." -; [f & maps] -; (when (some identity maps) -; (let [merge-entry (fn [m e] -; (let [k (key e) v (val e)] -; (if (contains? m k) -; (assoc m k (f (get m k) v)) -; (assoc m k v)))) -; merge2 (fn [m1 m2] -; (reduce merge-entry (or m1 {}) (seq m2)))] -; (reduce merge2 maps)))) -; -;(defn line-seq -; "Returns the lines of text from rdr as a lazy sequence of strings. -; rdr must implement java.io.BufferedReader." -; [#_java.io.BufferedReader rdr] -; ;; (when-let [line (.readLine rdr)] -; ;; (cons line (lazy-seq (line-seq rdr)))) -; (throw "TODO: port line-seq")) -; -;(defn comparator -; "Returns an implementation of java.util.Comparator based upon pred." -; [pred] -; (fn [x y] -; (cond (pred x y) -1 (pred y x) 1 :else 0))) -; -;(defn sort -; "Returns a sorted sequence of the items in coll. If no comparator is -; supplied, uses compare. comparator must implement -; java.util.Comparator. Guaranteed to be stable: equal elements will -; not be reordered. If coll is a Java array, it will be modified. To -; avoid this, sort a copy of the array." -; [coll] -; (cpp/jank.runtime.sort coll)) -; -;(defn sort-by -; "Returns a sorted sequence of the items in coll, where the sort -; order is determined by comparing (keyfn item). If no comparator is -; supplied, uses compare. comparator must implement -; java.util.Comparator. Guaranteed to be stable: equal elements will -; not be reordered. If coll is a Java array, it will be modified. To -; avoid this, sort a copy of the array." -; ([keyfn coll] -; (sort-by keyfn compare coll)) -; ([keyfn #_java.util.Comparator comp coll] -; ;; (sort (fn [x y] (. comp (compare (keyfn x) (keyfn y)))) coll) -; (throw "TODO: port sort-by"))) -; -;;; evaluation -; -;(defn eval -; "Evaluates the form data structure (not text!) and returns the result." -; [form] -; (cpp/clojure.core_native.eval form)) -; -;(defn await -; "Blocks the current thread (indefinitely!) until all actions -; dispatched thus far, from this thread or agent, to the agent(s) have -; occurred. Will block on failed agents. Will never return if -; a failed agent is restarted with :clear-actions true or shutdown-agents was called." -; [& agents] -; ;; (io! "await in transaction" -; ;; (when *agent* -; ;; (throw (new Exception "Can't await in agent action"))) -; ;; (let [latch (new java.util.concurrent.CountDownLatch (count agents)) -; ;; count-down (fn [agent] (. latch (countDown)) agent)] -; ;; (doseq [agent agents] -; ;; (send agent count-down)) -; ;; (. latch (await)))) -; (throw "TODO: port await")) -; -;(defn await1 [#_clojure.lang.Agent a] -; ;; (when (pos? (.getQueueCount a)) -; ;; (await a)) -; ;; a -; (throw "TODO: port await1")) -; -;(defn await-for -; "Blocks the current thread until all actions dispatched thus -; far (from this thread or agent) to the agents have occurred, or the -; timeout (in milliseconds) has elapsed. Returns logical false if -; returning due to timeout, logical true otherwise." -; [timeout-ms & agents] -; ;; (io! "await-for in transaction" -; ;; (when *agent* -; ;; (throw (new Exception "Can't await in agent action"))) -; ;; (let [latch (new java.util.concurrent.CountDownLatch (count agents)) -; ;; count-down (fn [agent] (. latch (countDown)) agent)] -; ;; (doseq [agent agents] -; ;; (send agent count-down)) -; ;; (. latch (await timeout-ms (. java.util.concurrent.TimeUnit MILLISECONDS))))) -; (throw "TODO: port await-for")) -; -;(defn import -; "import is not implemented for jank, but a var is still bound to its symbol for portability. import always throws an exception" -; [& _] -; (throw "import is not supported in jank, for C/C++ dependency interoperability use cpp/raw with #include, e.g. (cpp/raw \"#include \"dependency.h\")\")")) -; -;(defn into-array -; "Returns an array with components set to the values in aseq. The array's -; component type is type if provided, or the type of the first value in -; aseq if present, or Object. All values in aseq must be compatible with -; the component type. Class objects for the primitive types can be obtained -; using, e.g., Integer/TYPE." -; ([aseq] -; ;; (clojure.lang.RT/seqToTypedArray (seq aseq)) -; (throw "TODO: port into-array")) -; ([type aseq] -; ;; (clojure.lang.RT/seqToTypedArray type (seq aseq)) -; (throw "TODO: port into-array"))) -; -;(defn- -; array [& items] -; (into-array items)) -; -;(defn class -; "Returns the Class of x" -; #_Class [#_Object x] -; ;; (if (nil? x) x (. x (getClass))) -; (throw "TODO: port class")) -; -;(defn num -; "Coerce to Number" -; [x] -; ;; (. clojure.lang.Numbers (num x)) -; (throw "TODO: port num")) -; -;(defn long -; "Coerce to long" -; [#_Number x] -; ;; (clojure.lang.RT/longCast x) -; (throw "TODO: port long")) -; -;(defn double -; "Coerce to double" -; [#_Number x] -; ;; (clojure.lang.RT/doubleCast x) -; (throw "TODO: port double")) -; -;(defn short -; "Coerce to short" -; [#_Number x] -; ;; (clojure.lang.RT/shortCast x) -; (throw "TODO: port short")) -; -;(defn byte -; "Coerce to byte" -; [#_Number x] -; ;; (clojure.lang.RT/byteCast x) -; (throw "TODO: port byte")) -; -;(defn char -; "Coerce to char" -; [x] -; ;; (. clojure.lang.RT (charCast x)) -; (throw "TODO: port char")) -; -;(defn unchecked-byte -; "Coerce to byte. Subject to rounding or truncation." -; [#_Number x] -; ;; (clojure.lang.RT/uncheckedByteCast x) -; (throw "TODO: port unchecked-byte")) -; -;(defn unchecked-short -; "Coerce to short. Subject to rounding or truncation." -; [#_Number x] -; ;; (clojure.lang.RT/uncheckedShortCast x) -; (throw "TODO: port unchecked-short")) -; -;(defn unchecked-char -; "Coerce to char. Subject to rounding or truncation." -; [x] -; ;; (. clojure.lang.RT (uncheckedCharCast x)) -; (throw "TODO: port unchecked-char")) -; -;(defn unchecked-int -; "Coerce to int. Subject to rounding or truncation." -; [#_Number x] -; ;; (clojure.lang.RT/uncheckedIntCast x) -; (throw "TODO: port unchecked-int")) -; -;(defn unchecked-long -; "Coerce to long. Subject to rounding or truncation." -; [#_Number x] -; ;; (clojure.lang.RT/uncheckedLongCast x) -; (throw "TODO: port unchecked-long")) -; -;(defn unchecked-float -; "Coerce to float. Subject to rounding." -; [#_Number x] -; ;; (clojure.lang.RT/uncheckedFloatCast x) -; (throw "TODO: port unchecked-float")) -; -;(defn unchecked-double -; "Coerce to double. Subject to rounding." -; [#_Number x] -; ;; (clojure.lang.RT/uncheckedDoubleCast x) -; (throw "TODO: port unchecked-double")) -; -;(defn ratio? -; "Returns true if n is a Ratio" -; [r] -; (cpp/jank.runtime.is_ratio r)) -; -;(defn numerator -; "Returns the numerator part of a Ratio." -; [r] -; (cpp/jank.runtime.numerator r)) -; -;(defn denominator -; "Returns the denominator part of a Ratio." -; [r] -; (cpp/jank.runtime.denominator r)) -; -;(defn decimal? -; "Returns true if n is a BigDecimal" -; [n] -; ;; (instance? BigDecimal n) -; (cpp/jank.runtime.is_big_decimal n)) -; -;(defn rational? -; "Returns true if n is a rational number" -; [n] -; (or (integer? n) (ratio? n) (decimal? n))) -; -;(defn bigint -; "Coerce to BigInt" -; [x] -; ;; (cond -; ;; (instance? clojure.lang.BigInt x) x -; ;; (instance? BigInteger x) (clojure.lang.BigInt/fromBigInteger x) -; ;; (decimal? x) (bigint (.toBigInteger ^BigDecimal x)) -; ;; (float? x) (bigint (. BigDecimal valueOf (double x))) -; ;; (ratio? x) (bigint (.bigIntegerValue ^clojure.lang.Ratio x)) -; ;; (number? x) (clojure.lang.BigInt/valueOf (long x)) -; ;; :else (bigint (BigInteger. x))) -; (throw "TODO: port bigint")) -; -;(defn biginteger -; "Coerce to BigInteger" -; [x] -; ;; (cond -; ;; (instance? BigInteger x) x -; ;; (instance? clojure.lang.BigInt x) (.toBigInteger ^clojure.lang.BigInt x) -; ;; (decimal? x) (.toBigInteger ^BigDecimal x) -; ;; (float? x) (.toBigInteger (. BigDecimal valueOf (double x))) -; ;; (ratio? x) (.bigIntegerValue ^clojure.lang.Ratio x) -; ;; (number? x) (BigInteger/valueOf (long x)) -; ;; :else (BigInteger. x)) -; (throw "TODO: port biginteger")) -; -;(defn bigdec -; "Coerce to BigDecimal" -; [x] -; (cpp/jank.runtime.to_big_decimal x)) -; -;(def ^:dynamic ^:private print-initialized false) -; -;(defmulti print-method (fn [x writer] -; (let [t (get (meta x) :type)] -; (if (keyword? t) t (class x))))) -; -;(defmulti print-dup (fn [x writer] (class x))) -; -;(def ^:private #_String system-newline -; ;; (System/getProperty "line.separator") -; "\n") -; -;(defn newline -; "Writes a platform-specific newline to *out*" -; [] -; ;; (. *out* (append system-newline)) -; ;; nil -; (throw "TODO: port newline")) -; -;(defn flush -; "Flushes the output stream that is the current value of -; *out*" -; [] -; ;; (. *out* (flush)) -; ;; nil -; (throw "TODO: port flesh")) -; -;(defn read -; "Reads the next object from stream, which must be an instance of -; java.io.PushbackReader or some derivee. stream defaults to the -; current value of *in*. -; -; Opts is a persistent map with valid keys: -; :read-cond - :allow to process reader conditionals, or -; :preserve to keep all branches -; :features - persistent set of feature keywords for reader conditionals -; :eof - on eof, return value unless :eofthrow, then throw. -; if not specified, will throw -; -; Note that read can execute code (controlled by *read-eval*), -; and as such should be used only with trusted sources. -; -; For data structure interop use clojure.edn/read" -; ([] -; (read *in*)) -; ([stream] -; (read stream true nil)) -; ([stream eof-error? eof-value] -; (read stream eof-error? eof-value false)) -; ([stream eof-error? eof-value recursive?] -; ;; (. clojure.lang.LispReader (read stream (boolean eof-error?) eof-value recursive?)) -; (throw "TODO: port read")) -; ([opts stream] -; ;; (. clojure.lang.LispReader (read stream opts)) -; (throw "TODO: port read"))) -; -;(defn read+string -; "Like read, and taking the same args. stream must be a LineNumberingPushbackReader. -; Returns a vector containing the object read and the (whitespace-trimmed) string read." -; ([] (read+string *in*)) -; ([stream] (read+string stream true nil)) -; ([stream eof-error? eof-value] (read+string stream eof-error? eof-value false)) -; ([#_clojure.lang.LineNumberingPushbackReader stream eof-error? eof-value recursive?] -; ;; (try -; ;; (.captureString stream) -; ;; (let [o (read stream eof-error? eof-value recursive?) -; ;; s (.trim (.getString stream))] -; ;; [o s]) -; ;; (catch Throwable ex -; ;; (.getString stream) -; ;; (throw ex))) -; (throw "TODO: port read+string")) -; ([opts #_clojure.lang.LineNumberingPushbackReader stream] -; ;; (try -; ;; (.captureString stream) -; ;; (let [o (read opts stream) -; ;; s (.trim (.getString stream))] -; ;; [o s]) -; ;; (catch Throwable ex -; ;; (.getString stream) -; ;; (throw ex))) -; (throw "TODO: port read+string"))) -; -;(defn read-line -; "Reads the next line from stream that is the current value of *in* ." -; [] -; ;; (if (instance? clojure.lang.LineNumberingPushbackReader *in*) -; ;; (.readLine ^clojure.lang.LineNumberingPushbackReader *in*) -; ;; (.readLine ^java.io.BufferedReader *in*)) -; (throw "TODO: port read-line")) -; -;(defn read-string -; "Reads one object from the string s. Optionally include reader -; options, as specified in read. -; -; Note that read-string can execute code (controlled by *read-eval*), -; and as such should be used only with trusted sources. -; -; For data structure interop use clojure.edn/read-string" -; ([s] -; (read-string {} s)) -; ([opts s] -; (cpp/clojure.core_native.read_string opts s))) -; -;(defmacro with-open -; "bindings => [name init ...] -; -; Evaluates body in a try expression with names bound to the values -; of the inits, and a finally clause that calls (.close name) on each -; name in reverse order." -; [bindings & body] -; (assert-macro-args -; (vector? bindings) "a vector for its binding" -; (even? (count bindings)) "an even number of forms in binding vector") -; ;; (cond -; ;; (= (count bindings) 0) `(do ~@body) -; ;; (symbol? (bindings 0)) `(let ~(subvec bindings 0 2) -; ;; (try -; ;; (with-open ~(subvec bindings 2) ~@body) -; ;; (finally -; ;; (. ~(bindings 0) ~'close)))) -; ;; :else (throw (IllegalArgumentException. -; ;; "with-open only allows Symbols in bindings"))) -; (throw "TODO: port with-open")) -; -;(defmacro memfn -; "Expands into code that creates a fn that expects to be passed an -; object and any args and calls the named instance method on the -; object passing the args. Use when you want to treat a Java method as -; a first-class fn. name may be type-hinted with the method receiver's -; type in order to avoid reflective calls." -; [name & args] -; ;; (let [t (with-meta (gensym "target") -; ;; (meta name))] -; ;; `(fn [~t ~@args] -; ;; (. ~t (~name ~@args)))) -; (throw "TODO: port memfn")) -; -;(defn alength -; "Returns the length of the Java array. Works on arrays of all -; types." -; [array] -; ;; (. clojure.lang.RT (alength array)) -; (throw "TODO: port alength")) -; -;(defn aclone -; "Returns a clone of the Java array. Works on arrays of known -; types." -; [array] -; ;; (. clojure.lang.RT (aclone array)) -; (throw "TODO: port aclone")) -; -;(defn aget -; "Returns the value at the index/indices. Works on Java arrays of all -; types." -; ([array idx] -; ;; (clojure.lang.Reflector/prepRet (.getComponentType (class array)) (. Array (get array idx))) -; (throw "TODO: port aget")) -; ([array idx & idxs] -; (apply aget (aget array idx) idxs))) -; -;(defmacro aset -; "Sets the value at the index/indices. Returns val." -; [array idx & more] -; (if (= 1 (count more)) -; ;; Simple case: (aset array index value) -; (let [val (first more)] -; `(do -; (cpp/= (cpp/aget ~array ~idx) ~val) -; ~val)) -; ;; Nested case: (aset array idx1 idx2 & idxv) - not yet implemented -; `(throw "TODO: Nested array indexing not yet implemented"))) -; -;(defmacro -; ^{:private true} -; def-aset [name method coerce] -; `(defn ~name -; {:arglists '([~'array ~'idx ~'val] [~'array ~'idx ~'idx2 & ~'idxv])} -; ([array# idx# val#] -; ;; (. Array (~method array# idx# (~coerce val#))) -; ;; val# -; (throw ~(str "TODO: port " name))) -; ([array# idx# idx2# & idxv#] -; (apply ~name (aget array# idx#) idx2# idxv#)))) -; -;(def-aset -; ^{:doc "Sets the value at the index/indices. Works on arrays of int. Returns val."} -; aset-int setInt int) -; -;(def-aset -; ^{:doc "Sets the value at the index/indices. Works on arrays of long. Returns val."} -; aset-long setLong long) -; -;(def-aset -; ^{:doc "Sets the value at the index/indices. Works on arrays of boolean. Returns val."} -; aset-boolean setBoolean boolean) -; -;(def-aset -; ^{:doc "Sets the value at the index/indices. Works on arrays of float. Returns val."} -; aset-float setFloat float) -; -;(def-aset -; ^{:doc "Sets the value at the index/indices. Works on arrays of double. Returns val."} -; aset-double setDouble double) -; -;(def-aset -; ^{:doc "Sets the value at the index/indices. Works on arrays of short. Returns val."} -; aset-short setShort short) -; -;(def-aset -; ^{:doc "Sets the value at the index/indices. Works on arrays of byte. Returns val."} -; aset-byte setByte byte) -; -;(def-aset -; ^{:doc "Sets the value at the index/indices. Works on arrays of char. Returns val."} -; aset-char setChar char) -; -;(defn make-array -; "Creates and returns an array of instances of the specified class of -; the specified dimension(s). Note that a class object is required. -; Class objects can be obtained by using their name. -; Class objects for the primitive types can be obtained using, e.g., Integer/TYPE." -; ([#_Class type len] -; ;; (. Array (newInstance type (int len))) -; (throw "TODO: port make-array")) -; ([#_Class type dim & more-dims] -; ;; (let [dims (cons dim more-dims) -; ;; ^"[I" dimarray (make-array (. Integer TYPE) (count dims))] -; ;; (dotimes [i (alength dimarray)] -; ;; (aset-int dimarray i (nth dims i))) -; ;; (. Array (newInstance type dimarray)))) -; (throw "TODO: port make-array"))) -; -;(defn to-array-2d -; "Returns a (potentially-ragged) 2-dimensional array of Objects -; containing the contents of coll, which can be any Collection of any -; Collection." -; [#_java.util.Collection coll] -; ;; (let [ret (make-array (. Class (forName "[Ljava.lang.Object;")) (. coll (size)))] -; ;; (loop [i 0 xs (seq coll)] -; ;; (when xs -; ;; (aset ret i (to-array (first xs))) -; ;; (recur (inc i) (next xs)))) -; ;; ret) -; (throw "TODO: port to-array-2d")) -; -;(defn create-struct -; "Returns a structure basis object." -; [& keys] -; ;; (. clojure.lang.PersistentStructMap (createSlotMap keys)) -; (throw "TODO: port create-struct")) -; -;(defmacro defstruct -; "Same as (def name (create-struct keys...))" -; [name & keys] -; `(def ~name (create-struct ~@keys))) -; -;(defn struct-map -; "Returns a new structmap instance with the keys of the -; structure-basis. keyvals may contain all, some or none of the basis -; keys - where values are not supplied they will default to nil. -; keyvals can also contain keys not in the basis." -; [s & inits] -; ;; (. clojure.lang.PersistentStructMap (create s inits)) -; (throw "TODO: port struct-map")) -; -;(defn struct -; "Returns a new structmap instance with the keys of the -; structure-basis. vals must be supplied for basis keys in order - -; where values are not supplied they will default to nil." -; [s & vals] -; ;; (. clojure.lang.PersistentStructMap (construct s vals)) -; (throw "TODO: port struct")) -; -;(defn accessor -; "Returns a fn that, given an instance of a structmap with the basis, -; returns the value at the key. The key must be in the basis. The -; returned function should be (slightly) more efficient than using -; get, but such use of accessors should be limited to known -; performance-critical areas." -; [s key] -; ;; (. clojure.lang.PersistentStructMap (getAccessor s key)) -; (throw "TODO: port accessor")) -; -;(defn load-reader -; "Sequentially read and evaluate the set of forms contained in the -; stream/file" -; [rdr] -; ;; (. clojure.lang.Compiler (load rdr)) -; (throw "TODO: port load-reader")) -; -;(defn load-string -; "Sequentially read and evaluate the set of forms contained in the -; string" -; [s] -; ;; (let [rdr (-> (java.io.StringReader. s) -; ;; (clojure.lang.LineNumberingPushbackReader.))] -; ;; (load-reader rdr)) -; (throw "TODO: port load-string")) -; -;(defn- -; filter-key [keyfn pred amap] -; (loop [ret {} es (seq amap)] -; (if es -; (if (pred (keyfn (first es))) -; (recur (assoc ret (key (first es)) (val (first es))) (next es)) -; (recur ret (next es))) -; ret))) -; -;(defn all-ns -; "Returns a sequence of all namespaces." -; [] -; ;; (clojure.lang.Namespace/all) -; (throw "TODO: port all-ns")) -; -;(defn ns-unmap -; "Removes the mappings for the symbol from the namespace." -; [ns sym] -; (cpp/clojure.core_native.ns_unmap (the-ns ns) sym)) -; -;(defn ns-imports -; "Returns a map of the import mappings for the namespace." -; [ns] -; ;; (filter-key val (partial instance? Class) (ns-map ns)) -; (throw "TODO: port ns-imports")) -; -;(defn ns-interns -; "Returns a map of the intern mappings for the namespace." -; [ns] -; (let [ns (the-ns ns)] -; (filter-key val (fn [v] (and (var? v) -; (= (ns-name ns) (-> v symbol namespace symbol)))) -; (ns-map ns)))) -; -;(defn ns-refers -; "Returns a map of the refer mappings for the namespace." -; [ns] -; ;; (let [ns (the-ns ns)] -; ;; (filter-key val (fn [^clojure.lang.Var v] (and (instance? clojure.lang.Var v) -; ;; (not= ns (.ns v)))) -; ;; (ns-map ns))) -; (throw "TODO: port ns-refers")) -; -;(defn ns-aliases -; "Returns a map of the aliases for the namespace." -; [ns] -; ;; (.getAliases (the-ns ns)) -; (throw "TODO: port ns-aliases")) -; -;(defn ns-unalias -; "Removes the alias for the symbol from the namespace." -; [ns sym] -; (cpp/clojure.core_native.ns_unalias (the-ns ns) sym)) -; -;(defn var-set -; "Sets the value in the var object to val. The var must be -; thread-locally bound." -; [#_clojure.lang.Var x val] -; ;; (. x (set val)) -; (throw "TODO: port var-set")) -; -;(defmacro with-local-vars -; "varbinding=> symbol init-expr -; -; Executes the exprs in a context in which the symbols are bound to -; vars with per-thread bindings to the init-exprs. The symbols refer -; to the var objects themselves, and must be accessed with var-get and -; var-set" -; [name-vals-vec & body] -; (assert-macro-args -; (vector? name-vals-vec) "a vector for its binding" -; (even? (count name-vals-vec)) "an even number of forms in binding vector") -; ;; `(let [~@(interleave (take-nth 2 name-vals-vec) -; ;; (repeat '(.. clojure.lang.Var create setDynamic)))] -; ;; (. clojure.lang.Var (pushThreadBindings (hash-map ~@name-vals-vec))) -; ;; (try -; ;; (do ~@body) -; ;; (finally (. clojure.lang.Var (popThreadBindings))))) -; (throw "TODO: port with-local-vars")) -; -;(defn array-map -; "Constructs an array-map. If any keys are equal, they are handled as -; if by repeated uses of assoc." -; ([] -; ;; (. clojure.lang.PersistentArrayMap EMPTY) -; (throw "TODO: port array-map")) -; ([& keyvals] -; ;; (let [ary (to-array keyvals)] -; ;; (if (odd? (alength ary)) -; ;; (throw (IllegalArgumentException. (str "No value supplied for key: " (last keyvals)))) -; ;; (clojure.lang.PersistentArrayMap/createAsIfByAssoc ary))) -; (throw "TODO: port array-map"))) -; -;(defn seq-to-map-for-destructuring -; "Builds a map from a seq as described in -; https://clojure.org/reference/special_forms#keyword-arguments" -; [s] -; ;; (if (next s) -; ;; (clojure.lang.PersistentArrayMap/createAsIfByAssoc (to-array s)) -; ;; (if (seq s) (first s) clojure.lang.PersistentArrayMap/EMPTY)) -; (throw "TODO: port seq-to-map-for-destructuring")) -; -;(defmacro lazy-cat -; "Expands to code which yields a lazy sequence of the concatenation -; of the supplied colls. Each coll expr is not evaluated until it is -; needed. -; -; (lazy-cat xs ys zs) === (concat (lazy-seq xs) (lazy-seq ys) (lazy-seq zs))" -; [& colls] -; `(concat ~@(map #(list `lazy-seq %) colls))) -; -;(defmacro with-out-str -; "Evaluates exprs in a context in which *out* is bound to a fresh -; StringWriter. Returns the string created by any nested printing -; calls." -; [& body] -; ;; `(let [s# (new java.io.StringWriter)] -; ;; (binding [*out* s#] -; ;; ~@body -; ;; (str s#))) -; (throw "TODO: port with-out-str")) -; -;(defmacro with-in-str -; "Evaluates body in a context in which *in* is bound to a fresh -; StringReader initialized with the string s." -; [s & body] -; `(with-open [s# (-> (java.io.StringReader. ~s) clojure.lang.LineNumberingPushbackReader.)] -; (binding [*in* s#] -; ~@body))) -; -;(defn prn-str -; "prn to a string, returning it" -; [& xs] -; ;; (with-out-str -; ;; (apply prn xs)) -; (throw "TODO: port prn-str")) -; -; -;(defn print-str -; "print to a string, returning it" -; [& xs] -; ;; (with-out-str -; ;; (apply print xs)) -; (throw "TODO: port print-str")) -; -;(defn println-str -; "println to a string, returning it" -; [& xs] -; ;; (with-out-str -; ;; (apply println xs)) -; (throw "TODO: port println-str")) -; -;(defn ^:private elide-top-frames -; [#_Throwable ex class-name] -; ;; (let [tr (.getStackTrace ex)] -; ;; (doto ex -; ;; (.setStackTrace -; ;; (when tr -; ;; (into-array StackTraceElement -; ;; (drop-while #(= class-name (.getClassName ^StackTraceElement %1)) tr)))))) -; (throw "TODO: port elide-top-frames")) -; -;(defn test -; "test [v] finds fn at key :test in var metadata and calls it, -; presuming failure will throw exception" -; [v] -; (let [f (:test (meta v))] -; (if f -; (do (f) :ok) -; :no-test))) -; -;(defn re-pattern -; "Returns an instance of java.util.regex.Pattern, for use, e.g. in -; re-matcher." -; [s] -; (cpp/jank.runtime.re_pattern s)) -; -;(defn re-matcher -; "Returns an instance of java.util.regex.Matcher, for use, e.g. in -; re-find." -; [re s] -; (cpp/jank.runtime.re_matcher re s)) -; -;(defn re-groups -; "Returns the groups from the most recent match/find. If there are no -; nested groups, returns a string of the entire match. If there are -; nested groups, returns a vector of the groups, the first element -; being the entire match." -; [m] -; (cpp/jank.runtime.re_groups m)) -; -;(defn re-matches -; "Returns the match, if any, of string to pattern, using -; java.util.regex.Matcher.matches(). Uses re-groups to return the -; groups." -; [re s] -; (cpp/jank.runtime.re_matches re s)) -; -;(defn re-find -; "Returns the next regex match, if any, of string to pattern, using -; java.util.regex.Matcher.find(). Uses re-groups to return the -; groups." -; ([m] -; (cpp/jank.runtime.re_find m)) -; ([re s] -; (let [m (re-matcher re s)] -; (re-find m)))) -; -;(defn re-seq -; "Returns a lazy sequence of successive matches of pattern in string, -; using java.util.regex.Matcher.find(), each such match processed with -; re-groups." -; [re s] -; (let [m (cpp/jank.runtime.re_matcher re s)] -; ((fn step [] -; (when (re-find m) -; (cons (re-groups m) (lazy-seq (step)))))))) -; -;(defn rand-int -; "Returns a random integer between 0 (inclusive) and n (exclusive)." -; [n] (int (rand n))) -; -;(defn file-seq -; "A tree seq on java.io.Files" -; [dir] -; ;; (tree-seq -; ;; (fn [^java.io.File f] (. f (isDirectory))) -; ;; (fn [^java.io.File d] (seq (. d (listFiles)))) -; ;; dir) -; (throw "TODO: port file-seq")) -; -;(defn xml-seq -; "A tree seq on the xml elements as per xml/parse" -; [root] -; (tree-seq -; (complement string?) -; (comp seq :content) -; root)) -; -;(defn special-symbol? -; "Returns true if s names a special form" -; [s] -; ;; (contains? (. clojure.lang.Compiler specials) s) -; (throw "TODO: port special-symbol?")) -; -;(defn max-key -; "Returns the x for which (k x), a number, is greatest. -; -; If there are multiple such xs, the last one is returned." -; ([k x] x) -; ([k x y] (if (> (k x) (k y)) x y)) -; ([k x y & more] -; (let [kx (k x) ky (k y) -; [v kv] (if (> kx ky) [x kx] [y ky])] -; (loop [v v kv kv more more] -; (if more -; (let [w (first more) -; kw (k w)] -; (if (>= kw kv) -; (recur w kw (next more)) -; (recur v kv (next more)))) -; v))))) -; -;(defn min-key -; "Returns the x for which (k x), a number, is least. -; -; If there are multiple such xs, the last one is returned." -; ([k x] x) -; ([k x y] (if (< (k x) (k y)) x y)) -; ([k x y & more] -; (let [kx (k x) ky (k y) -; [v kv] (if (< kx ky) [x kx] [y ky])] -; (loop [v v kv kv more more] -; (if more -; (let [w (first more) -; kw (k w)] -; (if (<= kw kv) -; (recur w kw (next more)) -; (recur v kv (next more)))) -; v))))) -; -;(defn replace -; "Given a map of replacement pairs and a vector/collection, returns a -; vector/seq with any elements = a key in smap replaced with the -; corresponding val in smap. Returns a transducer when no collection -; is provided." -; ([smap] -; (map #(if-let [e (find smap %)] (val e) %))) -; ([smap coll] -; (if (vector? coll) -; (reduce (fn [v i] -; (if-let [e (find smap (nth v i))] -; (assoc v i (val e)) -; v)) -; coll (range (count coll))) -; (map #(if-let [e (find smap %)] (val e) %) coll)))) -; -;(defmacro dosync -; "Runs the exprs (in an implicit do) in a transaction that encompasses -; exprs and any nested calls. Starts a transaction if none is already -; running on this thread. Any uncaught exception will abort the -; transaction and flow out of dosync. The exprs may be run more than -; once, but any effects on Refs will be atomic." -; [& exprs] -; `(sync nil ~@exprs)) -; -;(defmacro with-precision -; "Sets the precision and rounding mode to be used for BigDecimal operations. -; -; Usage: (with-precision 10 (/ 1M 3)) -; or: (with-precision 10 :rounding HALF_DOWN (/ 1M 3)) -; -; The rounding mode is one of CEILING, FLOOR, HALF_UP, HALF_DOWN, -; HALF_EVEN, UP, DOWN and UNNECESSARY; it defaults to HALF_UP." -; [precision & exprs] -; ;; (let [[body rm] (if (= (first exprs) :rounding) -; ;; [(next (next exprs)) -; ;; `((. java.math.RoundingMode ~(second exprs)))] -; ;; [exprs nil])] -; ;; `(binding [*math-context* (java.math.MathContext. ~precision ~@rm)] -; ;; ~@body)) -; (throw "TODO: port with-precision")) -; -;(defn- mk-bound-fn -; [#_clojure.lang.Sorted sc test key] -; ;; (fn [e] -; ;; (test (.. sc comparator (compare (. sc entryKey e) key)) 0)) -; (throw "TODO: port mk-bound-fn")) -; -;(defn subseq -; "sc must be a sorted collection, test(s) one of <, <=, > or -; >=. Returns a seq of those entries with keys ek for -; which (test (.. sc comparator (compare ek key)) 0) is true" -; ([#_clojure.lang.Sorted sc test key] -; ;; (let [include (mk-bound-fn sc test key)] -; ;; (if (#{> >=} test) -; ;; (when-let [[e :as s] (. sc seqFrom key true)] -; ;; (if (include e) s (next s))) -; ;; (take-while include (. sc seq true)))) -; (throw "TODO: port subseq")) -; ([#_clojure.lang.Sorted sc start-test start-key end-test end-key] -; ;; (when-let [[e :as s] (. sc seqFrom start-key true)] -; ;; (take-while (mk-bound-fn sc end-test end-key) -; ;; (if ((mk-bound-fn sc start-test start-key) e) s (next s)))) -; (throw "TODO: port subseq"))) -; -;(defn rsubseq -; "sc must be a sorted collection, test(s) one of <, <=, > or -; >=. Returns a reverse seq of those entries with keys ek for -; which (test (.. sc comparator (compare ek key)) 0) is true" -; ([#_clojure.lang.Sorted sc test key] -; ;; (let [include (mk-bound-fn sc test key)] -; ;; (if (#{< <=} test) -; ;; (when-let [[e :as s] (. sc seqFrom key false)] -; ;; (if (include e) s (next s))) -; ;; (take-while include (. sc seq false)))) -; (throw "TODO: port rsubseq")) -; ([#_clojure.lang.Sorted sc start-test start-key end-test end-key] -; ;; (when-let [[e :as s] (. sc seqFrom end-key false)] -; ;; (take-while (mk-bound-fn sc start-test start-key) -; ;; (if ((mk-bound-fn sc end-test end-key) e) s (next s)))) -; (throw "TODO: port rsubseq"))) -; -;(defn add-classpath -; "DEPRECATED -; -; Adds the url (String or URL object) to the classpath per -; URLClassLoader.addURL" -; [url] -; (println "WARNING: add-classpath is deprecated") -; ;; (clojure.lang.RT/addURL url) -; (throw "TODO: port add-classpath")) -; -;(defn mix-collection-hash -; "Mix final collection hash for ordered or unordered collections. -; hash-basis is the combined collection hash, count is the number -; of elements included in the basis. Note this is the hash code -; consistent with =, different from .hashCode. -; See http://clojure.org/data_structures#hash for full algorithms." -; #_long -; [#_long hash-basis #_long count] -; ;; (clojure.lang.Murmur3/mixCollHash hash-basis count) -; (throw "TODO: port mix-collection-hash")) -; -;(defn hash-ordered-coll -; "Returns the hash code, consistent with =, for an external ordered -; collection implementing Iterable. -; See http://clojure.org/data_structures#hash for full algorithms." -; #_long -; [coll] -; ;; (clojure.lang.Murmur3/hashOrdered coll) -; (throw "TODO: port hash-ordered-coll")) -; -;(defn hash-unordered-coll -; "Returns the hash code, consistent with =, for an external unordered -; collection implementing Iterable. For maps, the iterator should -; return map entries whose hash is computed as -; (hash-ordered-coll [k v]). -; See http://clojure.org/data_structures#hash for full algorithms." -; [coll] -; (cpp/clojure.core_native.hash_unordered coll)) -; -;(defmacro definline -; "Experimental - like defmacro, except defines a named function whose -; body is the expansion, calls to which may be expanded inline as if -; it were a macro. Cannot be used with variadic (&) args." -; [name & decl] -; (let [[pre-args [args expr]] (split-with (comp not vector?) decl)] -; `(do -; (defn ~name ~@pre-args ~args ~(apply (eval (list `fn args expr)) args)) -; (alter-meta! (var ~name) assoc :inline (fn ~name ~args ~expr)) -; (var ~name)))) -; -;(defmacro amap -; "Maps an expression across an array a, using an index named idx, and -; return value named ret, initialized to a clone of a, then setting -; each element of ret to the evaluation of expr, returning the new -; array ret." -; [a idx ret expr] -; `(let [a# ~a l# (alength a#) -; ~ret (aclone a#)] -; (loop [~idx 0] -; (if (< ~idx l#) -; (do -; (aset ~ret ~idx ~expr) -; (recur (unchecked-inc ~idx))) -; ~ret)))) -; -;(defmacro areduce -; "Reduces an expression across an array a, using an index named idx, -; and return value named ret, initialized to init, setting ret to the -; evaluation of expr at each step, returning ret." -; [a idx ret init expr] -; `(let [a# ~a l# (alength a#)] -; (loop [~idx 0 ~ret ~init] -; (if (< ~idx l#) -; (recur (unchecked-inc-int ~idx) ~expr) -; ~ret)))) -; -;(defn float-array -; "Creates an array of floats" -; ([size-or-seq] -; ;; (. clojure.lang.Numbers float_array size-or-seq) -; (throw "TODO: port float-array")) -; ([size init-val-or-seq] -; ;; (. clojure.lang.Numbers float_array size init-val-or-seq) -; (throw "TODO: port float-array") )) -; -;(defn boolean-array -; "Creates an array of booleans" -; ([size-or-seq] -; ;; (. clojure.lang.Numbers boolean_array size-or-seq) -; (throw "TODO: port boolean-array")) -; ([size init-val-or-seq] -; ;; (. clojure.lang.Numbers boolean_array size init-val-or-seq) -; (throw "TODO: port boolean-array"))) -; -;(defn byte-array -; "Creates an array of bytes" -; ([size-or-seq] -; ;; (. clojure.lang.Numbers byte_array size-or-seq) -; (throw "TODO: port byte-array")) -; ([size init-val-or-seq] -; ;; (. clojure.lang.Numbers byte_array size init-val-or-seq) -; (throw "TODO: port byte-array"))) -; -;(defn char-array -; "Creates an array of chars" -; ([size-or-seq] -; ;; (. clojure.lang.Numbers char_array size-or-seq) -; (throw "TODO: port char-array")) -; ([size init-val-or-seq] -; ;; (. clojure.lang.Numbers char_array size init-val-or-seq) -; (throw "TODO: port char-array"))) -; -;(defn short-array -; "Creates an array of shorts" -; ([size-or-seq] -; ;; (. clojure.lang.Numbers short_array size-or-seq) -; (throw "TODO: port short-array")) -; ([size init-val-or-seq] -; ;; (. clojure.lang.Numbers short_array size init-val-or-seq) -; (throw "TODO: port short-array"))) -; -;(defn double-array -; "Creates an array of doubles" -; ([size-or-seq] -; ;; (. clojure.lang.Numbers double_array size-or-seq) -; (throw "TODO: port double-array")) -; ([size init-val-or-seq] -; ;; (. clojure.lang.Numbers double_array size init-val-or-seq) -; (throw "TODO: port double-array"))) -; -;(defn object-array -; "Creates an array of objects" -; ([size-or-seq] -; ;; (. clojure.lang.RT object_array size-or-seq) -; (throw "TODO: port object-array"))) -; -;(defn int-array -; "Creates an array of ints" -; ([size-or-seq] -; ;; (. clojure.lang.Numbers int_array size-or-seq) -; (throw "TODO: port int-array")) -; ([size init-val-or-seq] -; ;; (. clojure.lang.Numbers int_array size init-val-or-seq) -; (throw "TODO: port int-array"))) -; -;(defn long-array -; "Creates an array of longs" -; ([size-or-seq] -; ;; (. clojure.lang.Numbers long_array size-or-seq) -; (throw "TODO: port long-array")) -; ([size init-val-or-seq] -; ;; (. clojure.lang.Numbers long_array size init-val-or-seq) -; (throw "TODO: port long-array"))) -; -;;; definline doesn't work without eval -; -;;; (definline booleans -;;; "Casts to boolean[]" -;;; [xs] -;;; ;; `(. clojure.lang.Numbers booleans ~xs) -;;; (throw "TODO: port")) -; -;;; (definline bytes -;;; "Casts to bytes[]" -;;; [xs] -;;; ;; `(. clojure.lang.Numbers bytes ~xs) -;;; (throw "TODO: port")) -; -;;; (definline chars -;;; "Casts to chars[]" -;;; [xs] -;;; ;; `(. clojure.lang.Numbers chars ~xs) -;;; (throw "TODO: port")) -; -;;; (definline shorts -;;; "Casts to shorts[]" -;;; [xs] -;;; ;; `(. clojure.lang.Numbers shorts ~xs) -;;; (throw "TODO: port")) -; -;;; (definline floats -;;; "Casts to float[]" -;;; [xs] -;;; ;; `(. clojure.lang.Numbers floats ~xs) -;;; (throw "TODO: port")) -; -;;; (definline ints -;;; "Casts to int[]" -;;; [xs] -;;; ;; `(. clojure.lang.Numbers ints ~xs) -;;; (throw "TODO: port")) -; -;;; (definline doubles -;;; "Casts to double[]" -;;; [xs] -;;; ;; `(. clojure.lang.Numbers doubles ~xs) -;;; (throw "TODO: port")) -; -;;; (definline longs -;;; "Casts to long[]" -;;; [xs] -;;; ;; `(. clojure.lang.Numbers longs ~xs) -;;; (throw "TODO: port")) -; -;(defn bytes? -; "Return true if x is a byte array" -; [x] -; ;; (if (nil? x) -; ;; false -; ;; (-> x class .getComponentType (= Byte/TYPE))) -; (throw "TODO: port bytes?")) -; -;(defn seque -; "Creates a queued seq on another (presumably lazy) seq s. The queued -; seq will produce a concrete seq in the background, and can get up to -; n items ahead of the consumer. n-or-q can be an integer n buffer -; size, or an instance of java.util.concurrent BlockingQueue. Note -; that reading from a seque can block if the reader gets ahead of the -; producer." -; ([s] (seque 100 s)) -; ([n-or-q s] -; ;; (let [^BlockingQueue q (if (instance? BlockingQueue n-or-q) -; ;; n-or-q -; ;; (LinkedBlockingQueue. (int n-or-q))) -; ;; NIL (Object.) ;nil sentinel since LBQ doesn't support nils -; ;; agt (agent (lazy-seq s)) ; never start with nil; that signifies we've already put eos -; ;; log-error (fn [q e] -; ;; (if (.offer q q) -; ;; (throw e) -; ;; e)) -; ;; fill (fn [s] -; ;; (when s -; ;; (if (instance? Exception s) ; we failed to .offer an error earlier -; ;; (log-error q s) -; ;; (try -; ;; (loop [[x & xs :as s] (seq s)] -; ;; (if s -; ;; (if (.offer q (if (nil? x) NIL x)) -; ;; (recur xs) -; ;; s) -; ;; (when-not (.offer q q) ; q itself is eos sentinel -; ;; ()))) ; empty seq, not nil, so we know to put eos next time -; ;; (catch Exception e -; ;; (log-error q e)))))) -; ;; drain (fn drain [] -; ;; (lazy-seq -; ;; (let [x (.take q)] -; ;; (if (identical? x q) ;q itself is eos sentinel -; ;; (do @agt nil) ;touch agent just to propagate errors -; ;; (do -; ;; (send-off agt fill) -; ;; (release-pending-sends) -; ;; (cons (if (identical? x NIL) nil x) (drain)))))))] -; ;; (send-off agt fill) -; ;; (drain)) -; (throw "TODO: port seque"))) -; -;(defn class? -; "Returns true if x is an instance of Class" -; [x] -; ;; (instance? Class x) -; (throw "TODO: port class?")) -; -;(defn- is-annotation? [c] -; ;; (and (class? c) -; ;; (.isAssignableFrom java.lang.annotation.Annotation c)) -; (throw "TODO: port is-annotation?")) -; -;(defn- is-runtime-annotation? [#_Class c] -; ;; (boolean -; ;; (and (is-annotation? c) -; ;; (when-let [^java.lang.annotation.Retention r -; ;; (.getAnnotation c java.lang.annotation.Retention)] -; ;; (= (.value r) java.lang.annotation.RetentionPolicy/RUNTIME)))) -; (throw "TODO: port is-runtime-annotation?")) -; -;(defn- descriptor [#_Class c] -; ;; (clojure.asm.Type/getDescriptor c) -; (throw "TODO: port descriptor")) -; -;(declare process-annotation) -; -;(defn- add-annotation [#_clojure.asm.AnnotationVisitor av name v] -; ;; (cond -; ;; (vector? v) (let [avec (.visitArray av name)] -; ;; (doseq [vval v] -; ;; (add-annotation avec "value" vval)) -; ;; (.visitEnd avec)) -; ;; (symbol? v) (let [ev (eval v)] -; ;; (cond -; ;; (instance? java.lang.Enum ev) -; ;; (.visitEnum av name (descriptor (class ev)) (str ev)) -; ;; (class? ev) (.visit av name (clojure.asm.Type/getType ev)) -; ;; :else (throw (IllegalArgumentException. -; ;; (str "Unsupported annotation value: " v " of class " (class ev)))))) -; ;; (seq? v) (let [[nested nv] v -; ;; c (resolve nested) -; ;; nav (.visitAnnotation av name (descriptor c))] -; ;; (process-annotation nav nv) -; ;; (.visitEnd nav)) -; ;; :else (.visit av name v)) -; (throw "TODO: port add-annotation")) -; -;(defn- process-annotation [av v] -; (if (map? v) -; (doseq [[k v] v] -; (add-annotation av (name k) v)) -; (add-annotation av "value" v))) -; -;(defn- add-annotations -; ([visitor m] (add-annotations visitor m nil)) -; ([visitor m i] -; ;; (doseq [[k v] m] -; ;; (when (symbol? k) -; ;; (when-let [c (resolve k)] -; ;; (when (is-annotation? c) -; ;; ;this is known duck/reflective as no common base of ASM Visitors -; ;; (let [av (if i -; ;; (.visitParameterAnnotation visitor i (descriptor c) -; ;; (is-runtime-annotation? c)) -; ;; (.visitAnnotation visitor (descriptor c) -; ;; (is-runtime-annotation? c)))] -; ;; (process-annotation av v) -; ;; (.visitEnd av)))))) -; (throw "TODO: port add-annotations"))) -; -;(defn bases -; "Returns the immediate superclass and direct interfaces of c, if any" -; [#_Class c] -; ;; (when c -; ;; (let [i (seq (.getInterfaces c)) -; ;; s (.getSuperclass c)] -; ;; (if s (cons s i) i))) -; (throw "TODO: port bases")) -; -;(defn supers -; "Returns the immediate and indirect superclasses and interfaces of c, if any" -; [#_Class class] -; (loop [ret (set (bases class)) cs ret] -; (if (seq cs) -; (let [c (first cs) bs (bases c)] -; (recur (into ret bs) (into (disj cs c) bs))) -; (not-empty ret)))) -; -; -;(defn resultset-seq -; "Creates and returns a lazy sequence of structmaps corresponding to -; the rows in the java.sql.ResultSet rs" -; [#_java.sql.ResultSet rs] -; ;; (let [rsmeta (. rs (getMetaData)) -; ;; idxs (range 1 (inc (. rsmeta (getColumnCount)))) -; ;; keys (map (comp keyword #(.toLowerCase ^String %)) -; ;; (map (fn [i] (. rsmeta (getColumnLabel i))) idxs)) -; ;; check-keys -; ;; (or (apply distinct? keys) -; ;; (throw (Exception. "ResultSet must have unique column labels"))) -; ;; row-struct (apply create-struct keys) -; ;; row-values (fn [] (map (fn [^Integer i] (. rs (getObject i))) idxs)) -; ;; rows (fn thisfn [] -; ;; (when (. rs (next)) -; ;; (cons (apply struct row-struct (row-values)) (lazy-seq (thisfn)))))] -; ;; (rows)) -; (throw "TODO: port resultset-seq")) -; -;(defn iterator-seq -; "Returns a seq on a java.util.Iterator. Note that most collections -; providing iterators implement Iterable and thus support seq directly. -; Seqs cache values, thus iterator-seq should not be used on any -; iterator that repeatedly returns the same mutable object." -; [iter] -; ;; (clojure.lang.RT/chunkIteratorSeq iter) -; (throw "TODO: port iterator-seq")) -; -;(defn enumeration-seq -; "Returns a seq on a java.util.Enumeration" -; [e] -; ;; (clojure.lang.EnumerationSeq/create e) -; (throw "TODO: port enumeration-seq")) -; -;(defn format -; "Formats a string using java.lang.String.format, see java.util.Formatter for format -; string syntax" -; #_String [fmt & args] -; ;; (String/format fmt (to-array args)) -; (throw "TODO: port format")) -; -;(defn printf -; "Prints formatted output, as per format" -; [fmt & args] -; (print (apply format fmt args))) -; -;(declare gen-class) -; -;(defmacro with-loading-context [& body] -; ;; `((fn loading# [] -; ;; (. clojure.lang.Var (pushThreadBindings {clojure.lang.Compiler/LOADER -; ;; (.getClassLoader (.getClass ^Object loading#))})) -; ;; (try -; ;; (do ~@body) -; ;; (finally -; ;; (. clojure.lang.Var (popThreadBindings)))))) -; (throw "TODO: port with-loading-context")) -; -;(defonce -; ^{:private true -; :dynamic true -; :doc "True while a verbose load is pending"} -; *loading-verbosely* false) -; -;(defn- root-directory -; "Returns the root resource path for a lib" -; [lib] -; ;; (let [d (root-resource lib)] -; ;; (subs d 0 (.lastIndexOf d "/"))) -; (throw "TODO: port root-resource")) -; -;(defn- serialized-require -; "Like 'require', but serializes loading. -; Interim function preferred over 'require' for known asynchronous loads. -; Future changes may make these equivalent." -; [& args] -; ;; (locking clojure.lang.RT/REQUIRE_LOCK -; ;; (apply require args)) -; (throw "TODO: port serialized-require")) -; -;(defn requiring-resolve -; "Resolves namespace-qualified sym per 'resolve'. If initial resolve -;fails, attempts to require sym's namespace and retries." -; [sym] -; ;; (if (qualified-symbol? sym) -; ;; (or (resolve sym) -; ;; (do (-> sym namespace symbol serialized-require) -; ;; (resolve sym))) -; ;; (throw (IllegalArgumentException. (str "Not a qualified symbol: " sym)))) -; (throw "TODO: port requiring-resolve")) -; -;(defn loaded-libs -; "Returns a sorted set of symbols naming the currently loaded libs" -; [] @*loaded-libs*) -; -;(defn sorted? -; "Returns true if coll implements Sorted" -; [coll] -; (cpp/jank.runtime.is_sorted coll)) -; -;(defn counted? -; "Returns true if coll implements count in constant time" -; [coll] -; (cpp/jank.runtime.is_counted coll)) -; -;(defn reversible? -; "Returns true if coll implements Reversible" -; [coll] -; ;; (instance? clojure.lang.Reversible coll) -; (throw "TODO: port reversible?")) -; -;(defn indexed? -; "Return true if coll implements Indexed, indicating efficient lookup by index" -; [coll] -; ;; (instance? clojure.lang.Indexed coll) -; (throw "TODO: port indexed?")) -; -;(def ^:dynamic -; ^{:doc "bound in a repl thread to the most recent value printed"} -; *1) -; -;(def ^:dynamic -; ^{:doc "bound in a repl thread to the second most recent value printed"} -; *2) -; -;(def ^:dynamic -; ^{:doc "bound in a repl thread to the third most recent value printed"} -; *3) -; -;(def ^:dynamic -; ^{:doc "bound in a repl thread to the most recent exception caught by the repl"} -; *e) -; -;(def ^:dynamic -; ^{:doc "Bound to true in a repl thread"} -; *repl* false) -; -;(defn trampoline -; "trampoline can be used to convert algorithms requiring mutual -; recursion without stack consumption. Calls f with supplied args, if -; any. If f returns a fn, calls that fn with no arguments, and -; continues to repeat, until the return value is not a fn, then -; returns that non-fn value. Note that if you want to return a fn as a -; final value, you must wrap it in some data structure and unpack it -; after trampoline returns." -; ([f] -; (let [ret (f)] -; (if (fn? ret) -; (recur ret) -; ret))) -; ([f & args] -; (trampoline #(apply f args)))) -; -;(defmacro while -; "Repeatedly executes body while test expression is true. Presumes -; some side-effect will cause test to become false/nil. Returns nil" -; [test & body] -; `(loop [] -; (when ~test -; ~@body -; (recur)))) -; -;(defn memoize -; "Returns a memoized version of a referentially transparent function. The -; memoized version of the function keeps a cache of the mapping from arguments -; to results and, when calls with the same arguments are repeated often, has -; higher performance at the expense of higher memory use." -; [f] -; (let [mem (atom {})] -; (fn [& args] -; (if-let [e (find @mem args)] -; (val e) -; (let [ret (apply f args)] -; (swap! mem assoc args ret) -; ret))))) -; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; var documentation ;;;;;;;;;;;;;;;;;;;;;;;;;; -; -;(defmacro add-doc-and-meta {:private true} [name docstring meta] -; `(alter-meta! (var ~name) merge (assoc ~meta :doc ~docstring))) -; -;;; (add-doc-and-meta *file* -;;; "The path of the file being evaluated, as a String. -; -;;; When there is no file, e.g. in the REPL, the value is not defined." -;;; {}) -; -;;; (add-doc-and-meta *command-line-args* -;;; "A sequence of the supplied command line arguments, or nil if -;;; none were supplied" -;;; {}) -; -;;; (add-doc-and-meta *warn-on-reflection* -;;; "When set to true, the compiler will emit warnings when reflection is -;;; needed to resolve Java method calls or field accesses. -; -;;; Defaults to false." -;;; {}) -; -;;; (add-doc-and-meta *compile-path* -;;; "Specifies the directory where 'compile' will write out .class -;;; files. This directory must be in the classpath for 'compile' to -;;; work. -; -;;; Defaults to \"classes\"" -;;; {}) -; -;;; (add-doc-and-meta *compile-files* -;;; "Set to true when compiling files, false otherwise." -;;; {}) -; -;;; (add-doc-and-meta *unchecked-math* -;;; "While bound to true, compilations of +, -, *, inc, dec and the -;;; coercions will be done without overflow checks. While bound -;;; to :warn-on-boxed, same behavior as true, and a warning is emitted -;;; when compilation uses boxed math. Default: false." -;;; {}) -; -;;; (add-doc-and-meta *compiler-options* -;;; "A map of keys to options. -;;; Note, when binding dynamically make sure to merge with previous value. -;;; Supported options: -;;; :elide-meta - a collection of metadata keys to elide during compilation. -;;; :disable-locals-clearing - set to true to disable clearing, useful for using a debugger -;;; :direct-linking - set to true to use direct static invocation of functions, rather than vars -;;; Note that call sites compiled with direct linking will not be affected by var redefinition. -;;; Use ^:redef (or ^:dynamic) on a var to prevent direct linking and allow redefinition. -;;; See https://clojure.org/reference/compilation for more information." -;;; {}) -; -;;; (add-doc-and-meta *in* -;;; "A java.io.Reader object representing standard input for read operations. -; -;;; Defaults to System/in, wrapped in a LineNumberingPushbackReader" -;;; {}) -; -;;; (add-doc-and-meta *err* -;;; "A java.io.Writer object representing standard error for print operations. -; -;;; Defaults to System/err, wrapped in a PrintWriter" -;;; {}) -; -;;; (add-doc-and-meta *flush-on-newline* -;;; "When set to true, output will be flushed whenever a newline is printed. -; -;;; Defaults to true." -;;; {}) -; -;;; (add-doc-and-meta *print-meta* -;;; "If set to logical true, when printing an object, its metadata will also -;;; be printed in a form that can be read back by the reader. -; -;;; Defaults to false." -;;; {}) -; -;;; (add-doc-and-meta *print-dup* -;;; "When set to logical true, objects will be printed in a way that preserves -;;; their type when read in later. -; -;;; Defaults to false." -;;; {}) -; -;;; (add-doc-and-meta *print-readably* -;;; "When set to logical false, strings and characters will be printed with -;;; non-alphanumeric characters converted to the appropriate escape sequences. -; -;;; Defaults to true" -;;; {}) -; -;;; (add-doc-and-meta *read-eval* -;;; "Defaults to true (or value specified by system property, see below) -;;; ***This setting implies that the full power of the reader is in play, -;;; including syntax that can cause code to execute. It should never be -;;; used with untrusted sources. See also: clojure.edn/read.*** -; -;;; When set to logical false in the thread-local binding, -;;; the eval reader (#=) and record/type literal syntax are disabled in read/load. -;;; Example (will fail): (binding [*read-eval* false] (read-string \"#=(* 2 21)\")) -; -;;; The default binding can be controlled by the system property -;;; 'clojure.read.eval' System properties can be set on the command line -;;; like this: -; -;;; java -Dclojure.read.eval=false ... -; -;;; The system property can also be set to 'unknown' via -;;; -Dclojure.read.eval=unknown, in which case the default binding -;;; is :unknown and all reads will fail in contexts where *read-eval* -;;; has not been explicitly bound to either true or false. This setting -;;; can be a useful diagnostic tool to ensure that all of your reads -;;; occur in considered contexts. You can also accomplish this in a -;;; particular scope by binding *read-eval* to :unknown -;;; " -;;; {}) -; -;;; (add-doc-and-meta *assert* -;;; "When set to logical false, 'assert' will omit assertion checks in -;;; compiled code. Defaults to true." -;;; {}) -; -;(defn future? -; "Returns true if x is a future" -; [x] -; ;; (instance? java.util.concurrent.Future x) -; (throw "TODO: port future?")) -; -;(defn future-done? -; "Returns true if future f is done" -; [#_java.util.concurrent.Future f] -; ;; (.isDone f) -; (throw "TODO: port future-done?")) -; -;(defmacro letfn -; "fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+) -; -; Takes a vector of function specs and a body, and generates a set of -; bindings of functions to their names. All of the names are available -; in all of the definitions of the functions, as well as the body." -; {:forms '[(letfn [fnspecs*] exprs*)], -; :special-form true} -; [fnspecs & body] -; `(letfn* ~(vec (interleave (map first fnspecs) -; (map #(cons `fn %) fnspecs))) -; ~@body)) -; -;(defn stream-reduce! -; "Works like reduce but takes a java.util.stream.BaseStream as its source. -; Honors 'reduced', is a terminal operation on the stream" -; ([f #_java.util.stream.BaseStream s] -; ;; (clojure.core.protocols/iterator-reduce! (.iterator s) f) -; (throw "TODO: port stream-reduce!")) -; ([f init #_java.util.stream.BaseStream s] -; ;; (clojure.core.protocols/iterator-reduce! (.iterator s) f init) -; (throw "TODO: port stream-reduce!"))) -; -;(defn stream-seq! -; "Takes a java.util.stream.BaseStream instance s and returns a seq of its -; contents. This is a terminal operation on the stream." -; [#_java.util.stream.BaseStream stream] -; ;; (iterator-seq (.iterator stream)) -; (throw "TODO: port stream-seq!")) -; -;(defn stream-transduce! -; "Works like transduce but takes a java.util.stream.BaseStream as its source. -; This is a terminal operation on the stream." -; ([xform f #_java.util.stream.BaseStream stream] -; (stream-transduce! xform f (f) stream)) -; ([xform f init #_java.util.stream.BaseStream stream] -; (let [f (xform f) -; ret (stream-reduce! f init stream)] -; (f ret)))) -; -;(defn stream-into! -; "Returns a new coll consisting of coll with all of the items of the -; stream conjoined. This is a terminal operation on the stream." -; ([to #_java.util.stream.BaseStream stream] -; ;; (if (instance? clojure.lang.IEditableCollection to) -; ;; (with-meta (persistent! (stream-reduce! conj! (transient to) stream)) (meta to)) -; ;; (stream-reduce! conj to stream)) -; (throw "TODO: port stream-into!")) -; ([to xform #_java.util.stream.BaseStream stream] -; ;; (if (instance? clojure.lang.IEditableCollection to) -; ;; (with-meta (persistent! (stream-transduce! xform conj! (transient to) stream)) (meta to)) -; ;; (stream-transduce! xform conj to stream)) -; (throw "TODO: port stream-into!"))) -; -; -;(defmacro ^:private when-class [class-name & body] -; ;; `(try -; ;; (Class/forName ^String ~class-name) -; ;; ~@body -; ;; (catch ClassNotFoundException _#)) -; (throw "TODO: port when-class")) -; -;;; (defprotocol Inst -;;; (inst-ms* [inst])) -; -;;; (extend-protocol Inst -;;; java.util.Date -;;; (inst-ms* [inst] (.getTime ^java.util.Date inst))) -; -;(defn inst-ms -; "Return the number of milliseconds since January 1, 1970, 00:00:00 GMT" -; [inst] -; (cpp/jank.runtime.inst_ms inst)) -; -;(defn inst? -; "Return true if x satisfies Inst" -; [x] -; (cpp/jank.runtime.is_inst x)) -; -;;; (extend-protocol clojure.core/Inst -;;; java.time.Instant -;;; (inst-ms* [inst] (.toEpochMilli ^java.time.Instant inst))) -; -;(defn uuid? -; "Return true if x is a java.util.UUID" -; [x] -; (cpp/jank.runtime.is_uuid x)) -; -;(defn random-uuid -; "Returns a pseudo-randomly generated java.util.UUID instance (i.e. type 4). -; -; See: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID--" -; [] -; (cpp/jank.runtime.random_uuid)) -; -;;; (extend-protocol clojure.core.protocols/IKVReduce -;;; nil -;;; (kv-reduce -;;; [_ f init] -;;; init) -; -;;; ;;slow path default -;;; java.lang.Object -;;; (kv-reduce -;;; [amap f init] -;;; (reduce (fn [ret ^java.util.Map$Entry me] -;;; (f ret -;;; (.getKey me) -;;; (.getValue me))) -;;; init -;;; amap)) -; -;;; clojure.lang.IKVReduce -;;; (kv-reduce -;;; [amap f init] -;;; (.kvreduce amap f init))) -; -;(defn reduce-kv -; "Reduces an associative collection. f should be a function of 3 -; arguments. Returns the result of applying f to init, the first key -; and the first value in coll, then applying f to that result and the -; 2nd key and value, etc. If coll contains no entries, returns init -; and f is not called. Note that reduce-kv is supported on vectors, -; where the keys will be the ordinals." -; ([f init coll] -; ;; (clojure.core.protocols/kv-reduce coll f init) -; (reduce (fn [s [k v]] (f s k v)) init coll))) -; -;(defn- normalize-slurp-opts -; [opts] -; (if (string? (first opts)) -; (do -; (println "WARNING: (slurp f enc) is deprecated, use (slurp f :encoding enc).") -; [:encoding (first opts)]) -; opts)) -; -;(defn slurp -; "Opens a reader on f and reads all its contents, returning a string. -; See clojure.java.io/reader for a complete list of supported arguments." -; ([f & opts] -; (let [opts (normalize-slurp-opts opts) -; fname (cpp/cast (cpp/type "char const*") f) -; file (cpp/std.ifstream. fname)] -; (if-not (cpp/.is_open file) -; (throw (str f " (No such file or directory)")) -; (let [size (cpp/std.filesystem.file_size fname) -; out (cpp/std.string. size (cpp/char 0))] -; (cpp/.read file (cpp/& (cpp/.front out)) size) -; out))))) -; -;(defn spit -; "Opposite of slurp. Opens f with writer, writes content, then -; closes f. Options passed to clojure.java.io/writer." -; [f content & options] -; (let [file (cpp/std.ofstream.)] -; (cpp/.open file (cpp/cast (cpp/type "char const*") f)) -; (cpp/<< file (cpp/cast (cpp/type "char const*") content)) -; (cpp/.close file) -; nil)) -; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; futures (needs proxy);;;;;;;;;;;;;;;;;; -;(defn future-call -; "Takes a function of no args and yields a future object that will -; invoke the function in another thread, and will cache the result and -; return it on all subsequent calls to deref/@. If the computation has -; not yet finished, calls to deref/@ will block, unless the variant -; of deref with timeout is used. See also - realized?." -; [f] -; ;; (let [f (binding-conveyor-fn f) -; ;; fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)] -; ;; (reify -; ;; clojure.lang.IDeref -; ;; (deref [_] (deref-future fut)) -; ;; clojure.lang.IBlockingDeref -; ;; (deref -; ;; [_ timeout-ms timeout-val] -; ;; (deref-future fut timeout-ms timeout-val)) -; ;; clojure.lang.IPending -; ;; (isRealized [_] (.isDone fut)) -; ;; java.util.concurrent.Future -; ;; (get [_] (.get fut)) -; ;; (get [_ timeout unit] (.get fut timeout unit)) -; ;; (isCancelled [_] (.isCancelled fut)) -; ;; (isDone [_] (.isDone fut)) -; ;; (cancel [_ interrupt?] (.cancel fut interrupt?)))) -; (throw "TODO: port future-call")) -; -;(defmacro future -; "Takes a body of expressions and yields a future object that will -; invoke the body in another thread, and will cache the result and -; return it on all subsequent calls to deref/@. If the computation has -; not yet finished, calls to deref/@ will block, unless the variant of -; deref with timeout is used. See also - realized?." -; [& body] -; ;; `(future-call (^{:once true} fn* [] ~@body)) -; (throw "TODO: port future")) -; -;(defn future-cancel -; "Cancels the future, if possible." -; [#_java.util.concurrent.Future f] -; ;; (.cancel f true) -; (throw "TODO: port future-cancel")) -; -;(defn future-cancelled? -; "Returns true if future f is cancelled" -; [#_java.util.concurrent.Future f] -; ;; (.isCancelled f) -; (throw "TODO: port future-cancelled?")) -; -;(defn pmap -; "Like map, except f is applied in parallel. Semi-lazy in that the -; parallel computation stays ahead of the consumption, but doesn't -; realize the entire result unless required. Only useful for -; computationally intensive functions where the time of f dominates -; the coordination overhead." -; ([f coll] -; ;; (let [n (+ 2 (.. Runtime getRuntime availableProcessors)) -; ;; rets (map #(future (f %)) coll) -; ;; step (fn step [[x & xs :as vs] fs] -; ;; (lazy-seq -; ;; (if-let [s (seq fs)] -; ;; (cons (deref x) (step xs (rest s))) -; ;; (map deref vs))))] -; ;; (step rets (drop n rets))) -; (throw "TODO: port pmap")) -; ([f coll & colls] -; ;; (let [step (fn step [cs] -; ;; (lazy-seq -; ;; (let [ss (map seq cs)] -; ;; (when (every? identity ss) -; ;; (cons (map first ss) (step (map rest ss)))))))] -; ;; (pmap #(apply f %) (step (cons coll colls)))) -; (throw "TODO: port pmap"))) -; -; -;(defn pcalls -; "Executes the no-arg fns in parallel, returning a lazy sequence of -; their values" -; [& fns] (pmap #(%) fns)) -; -;(defmacro pvalues -; "Returns a lazy sequence of the values of the exprs, which are -; evaluated in parallel" -; [& exprs] -; `(pcalls ~@(map #(list `fn [] %) exprs))) -; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; clojure version number ;;;;;;;;;;;;;;;;;;;;;; -; -;;; (let [^java.util.Properties -;;; properties (with-open [version-stream (.getResourceAsStream -;;; (clojure.lang.RT/baseLoader) -;;; "clojure/version.properties")] -;;; (doto (new java.util.Properties) -;;; (.load version-stream))) -;;; version-string (.getProperty properties "version") -;;; [_ major minor incremental qualifier snapshot] -;;; (re-matches -;;; #"(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9_]+))?(?:-(SNAPSHOT))?" -;;; version-string) -;;; clojure-version {:major (Integer/valueOf ^String major) -;;; :minor (Integer/valueOf ^String minor) -;;; :incremental (Integer/valueOf ^String incremental) -;;; :qualifier (if (= qualifier "SNAPSHOT") nil qualifier)}] -;;; (def ^:dynamic *clojure-version* -;;; (if (.contains version-string "SNAPSHOT") -;;; (clojure.lang.RT/assoc clojure-version :interim true) -;;; clojure-version))) -; -;;; (add-doc-and-meta *clojure-version* -;;; "The version info for Clojure core, as a map containing :major :minor -;;; :incremental and :qualifier keys. Feature releases may increment -;;; :minor and/or :major, bugfix releases will increment :incremental. -;;; Possible values of :qualifier include \"GA\", \"SNAPSHOT\", \"RC-x\" \"BETA-x\"" -;;; {:added "1.0"}) -; -;(defn clojure-version -; "Returns clojure version as a printable string." -; [] -; (cpp/clojure.core_native.jank_version)) -; -;(defn promise -; "Returns a promise object that can be read with deref/@, and set, -; once only, with deliver. Calls to deref/@ prior to delivery will -; block, unless the variant of deref with timeout is used. All -; subsequent derefs will return the same delivered value without -; blocking. See also - realized?." -; [] -; ;; (let [d (java.util.concurrent.CountDownLatch. 1) -; ;; v (atom d)] -; ;; (reify -; ;; clojure.lang.IDeref -; ;; (deref [_] (.await d) @v) -; ;; clojure.lang.IBlockingDeref -; ;; (deref -; ;; [_ timeout-ms timeout-val] -; ;; (if (.await d timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS) -; ;; @v -; ;; timeout-val)) -; ;; clojure.lang.IPending -; ;; (isRealized [this] -; ;; (zero? (.getCount d))) -; ;; clojure.lang.IFn -; ;; (invoke -; ;; [this x] -; ;; (when (and (pos? (.getCount d)) -; ;; (compare-and-set! v d x)) -; ;; (.countDown d) -; ;; this)))) -; (throw "TODO: port promise")) -; -;(defn deliver -; "Delivers the supplied value to the promise, releasing any pending -; derefs. A subsequent call to deliver on a promise will have no effect." -; [promise val] (promise val)) -; -;(defn rand-nth -; "Return a random element of the (sequential) collection. Will have -; the same performance characteristics as nth for the given -; collection." -; [coll] -; (nth coll (rand-int (count coll)))) -; -;(defn splitv-at -; "Returns a vector of [(into [] (take n) coll) (drop n coll)]" -; [n coll] -; [(into [] (take n) coll) (drop n coll)]) -; -;(defn partitionv -; "Returns a lazy sequence of vectors of n items each, at offsets step -; apart. If step is not supplied, defaults to n, i.e. the partitions -; do not overlap. If a pad collection is supplied, use its elements as -; necessary to complete last partition upto n items. In case there are -; not enough padding elements, return a partition with less than n items." -; ([n coll] -; (partitionv n n coll)) -; ([n step coll] -; (lazy-seq -; (when-let [s (seq coll)] -; (let [p (into [] (take n) s)] -; (when (= n (count p)) -; (cons p (partitionv n step (nthrest s step)))))))) -; ([n step pad coll] -; (lazy-seq -; (when-let [s (seq coll)] -; (let [p (into [] (take n) s)] -; (if (= n (count p)) -; (cons p (partitionv n step pad (nthrest s step))) -; (list (into [] (take n) (concat p pad))))))))) -; -;(defn partitionv-all -; "Returns a lazy sequence of vector partitions, but may include -; partitions with fewer than n items at the end. -; Returns a stateful transducer when no collection is provided." -; ([n] -; (partition-all n)) -; ([n coll] -; (partitionv-all n n coll)) -; ([n step coll] -; (lazy-seq -; (when-let [s (seq coll)] -; (let [seg (into [] (take n) coll)] -; (cons seg (partitionv-all n step (drop step s)))))))) -; -;(defn shuffle -; "Return a random permutation of coll" -; [coll] -; (cpp/jank.runtime.shuffle coll)) -; -;(defn bounded-count -; "If coll is counted? returns its count, else will count at most the first n -; elements of coll using its seq" -; [n coll] -; (if (counted? coll) -; (count coll) -; (loop [i 0 s (seq coll)] -; (if (and s (< i n)) -; (recur (inc i) (next s)) -; i)))) -; -;(defn bounded-count -; "If coll is counted? returns its count, else will count at most the first n -; elements of coll using its seq" -; [n coll] -; (if (counted? coll) -; (count coll) -; (loop [i 0 s (seq coll)] -; (if (and s (< i n)) -; (recur (inc i) (next s)) -; i)))) -; -;(defn- ^{:dynamic true} assert-valid-fdecl -; "A good fdecl looks like (([a] ...) ([a b] ...)) near the end of defn." -; [fdecl] -; (when (empty? fdecl) (throw "Parameter declaration missing")) -; (let [argdecls (map -; #(if (seq? %) -; (first %) -; (throw (if (seq? (first fdecl)) -; (str "Invalid signature \"" -; % -; "\" should be a list") -; (str "Parameter declaration \"" -; % -; "\" should be a vector")))) -; fdecl) -; bad-args (seq (remove #(vector? %) argdecls))] -; (when bad-args -; (throw (str "Parameter declaration \"" (first bad-args) -; "\" should be a vector"))))) -; -;(defn realized? -; "Returns true if a value has been produced for a promise, delay, future or lazy sequence." -; [#_clojure.lang.IPending x] -; ;; (.isRealized x) -; (throw "TODO: port realized?")) -; -;(defn random-sample -; "Returns items from coll with random probability of prob (0.0 - -; 1.0). Returns a transducer when no collection is provided." -; ([prob] -; (filter (fn [_] (< (rand) prob)))) -; ([prob coll] -; (filter (fn [_] (< (rand) prob)) coll))) -; -;;; (deftype Eduction [xform coll] -;;; Iterable -;;; (iterator [_] -;;; (clojure.lang.TransformerIterator/create xform (clojure.lang.RT/iter coll))) -; -;;; clojure.lang.IReduceInit -;;; (reduce [_ f init] -;;; ;; NB (completing f) isolates completion of inner rf from outer rf -;;; (transduce xform (completing f) init coll)) -; -;;; clojure.lang.Sequential) -; -;;; (defn eduction -;;; "Returns a reducible/iterable application of the transducers -;;; to the items in coll. Transducers are applied in order as if -;;; combined with comp. Note that these applications will be -;;; performed every time reduce/iterator is called." -;;; [& xforms] -;;; (Eduction. (apply comp (butlast xforms)) (last xforms))) -; -;;; (defmethod print-method Eduction [c, ^Writer w] -;;; (if *print-readably* -;;; (do -;;; (print-sequential "(" pr-on " " ")" c w)) -;;; (print-object c w))) -; -;(defn iteration -; "Creates a seqable/reducible via repeated calls to step, -; a function of some (continuation token) 'k'. The first call to step -; will be passed initk, returning 'ret'. Iff (somef ret) is true, -; (vf ret) will be included in the iteration, else iteration will -; terminate and vf/kf will not be called. If (kf ret) is non-nil it -; will be passed to the next step call, else iteration will terminate. -; -; This can be used e.g. to consume APIs that return paginated or batched data. -; -; step - (possibly impure) fn of 'k' -> 'ret' -; -; :somef - fn of 'ret' -> logical true/false, default 'some?' -; :vf - fn of 'ret' -> 'v', a value produced by the iteration, default 'identity' -; :kf - fn of 'ret' -> 'next-k' or nil (signaling 'do not continue'), default 'identity' -; :initk - the first value passed to step, default 'nil' -; -; It is presumed that step with non-initk is unreproducible/non-idempotent. -; If step with initk is unreproducible it is on the consumer to not consume twice." -; [step & {:keys [somef vf kf initk] -; :or {vf identity -; kf identity -; somef some? -; initk nil}}] -; ;; (reify -; ;; clojure.lang.Seqable -; ;; (seq [_] -; ;; ((fn next [ret] -; ;; (when (somef ret) -; ;; (cons (vf ret) -; ;; (when-some [k (kf ret)] -; ;; (lazy-seq (next (step k))))))) -; ;; (step initk))) -; ;; clojure.lang.IReduceInit -; ;; (reduce [_ rf init] -; ;; (loop [acc init -; ;; ret (step initk)] -; ;; (if (somef ret) -; ;; (let [acc (rf acc (vf ret))] -; ;; (if (reduced? acc) -; ;; @acc -; ;; (if-some [k (kf ret)] -; ;; (recur acc (step k)) -; ;; acc))) -; ;; acc)))) -; (throw "TODO: port iteration")) -; -;(defn tagged-literal? -; "Return true if the value is the data representation of a tagged literal" -; [value] -; (cpp/jank.runtime.is_tagged_literal value)) -; -;(defn tagged-literal -; "Construct a data representation of a tagged literal from a -; tag symbol and a form." -; [tag form] -; (cpp/jank.runtime.tagged_literal tag form)) -; -;(defn reader-conditional? -; "Return true if the value is the data representation of a reader conditional" -; [value] -; ;; (instance? clojure.lang.ReaderConditional value) -; (throw "TODO: port reader-conditional?")) -; -;(defn reader-conditional -; "Construct a data representation of a reader conditional. -; If true, splicing? indicates read-cond-splicing." -; [form #_Boolean splicing?] -; ;; (clojure.lang.ReaderConditional/create form splicing?) -; (throw "TODO: port reader-conditional")) -; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; data readers ;;;;;;;;;;;;;;;;;; -; -;(def default-data-readers -; "Default map of data reader functions provided by Clojure. May be -; overridden by binding *data-readers*." -; (merge -; ;; {'uuid #'clojure.uuid/default-uuid-reader} -; ;; (when-class "java.sql.Timestamp" -; ;; {'inst #'clojure.instant/read-instant-date}) -; )) -; -;(def ^:dynamic *data-readers* -; "Map from reader tag symbols to data reader Vars. -; -; When Clojure starts, it searches for files named 'data_readers.clj' -; and 'data_readers.cljc' at the root of the classpath. Each such file -; must contain a literal map of symbols, like this: -; -; {foo/bar my.project.foo/bar -; foo/baz my.project/baz} -; -; The first symbol in each pair is a tag that will be recognized by -; the Clojure reader. The second symbol in the pair is the -; fully-qualified name of a Var which will be invoked by the reader to -; parse the form following the tag. For example, given the -; data_readers.clj file above, the Clojure reader would parse this -; form: -; -; #foo/bar [1 2 3] -; -; by invoking the Var #'my.project.foo/bar on the vector [1 2 3]. The -; data reader function is invoked on the form AFTER it has been read -; as a normal Clojure data structure by the reader. -; -; Reader tags without namespace qualifiers are reserved for -; Clojure. Default reader tags are defined in -; clojure.core/default-data-readers but may be overridden in -; data_readers.clj, data_readers.cljc, or by rebinding this Var." -; {}) -; -;(def ^:dynamic *default-data-reader-fn* -; "When no data reader is found for a tag and *default-data-reader-fn* -; is non-nil, it will be called with two arguments, -; the tag and the value. If *default-data-reader-fn* is nil (the -; default), an exception will be thrown for the unknown tag." -; nil) -; -;(defn- data-reader-urls [] -; ;; (let [cl (.. Thread currentThread getContextClassLoader)] -; ;; (concat -; ;; (enumeration-seq (.getResources cl "data_readers.clj")) -; ;; (enumeration-seq (.getResources cl "data_readers.cljc")))) -; (throw "TODO: port data-reader-urls")) -; -;(defn- data-reader-var [sym] -; (intern (create-ns (symbol (namespace sym))) -; (symbol (name sym)))) -; -;(defn- load-data-reader-file [mappings #_java.net.URL url] -; ;; (with-open [rdr (clojure.lang.LineNumberingPushbackReader. -; ;; (java.io.InputStreamReader. -; ;; (.openStream url) "UTF-8"))] -; ;; (binding [*file* (.getFile url)] -; ;; (let [read-opts (if (.endsWith (.getPath url) "cljc") -; ;; {:eof nil :read-cond :allow} -; ;; {:eof nil}) -; ;; new-mappings (read read-opts rdr)] -; ;; (when (not (map? new-mappings)) -; ;; (throw (ex-info (str "Not a valid data-reader map") -; ;; {:url url}))) -; ;; (reduce -; ;; (fn [m [k v]] -; ;; (when (not (symbol? k)) -; ;; (throw (ex-info (str "Invalid form in data-reader file") -; ;; {:url url -; ;; :form k}))) -; ;; (let [v-var (data-reader-var v)] -; ;; (when (and (contains? mappings k) -; ;; (not= (mappings k) v-var)) -; ;; (throw (ex-info "Conflicting data-reader mapping" -; ;; {:url url -; ;; :conflict k -; ;; :mappings m}))) -; ;; (assoc m k v-var))) -; ;; mappings -; ;; new-mappings)))) -; (throw "TODO: port load-data-reader-file")) -; -;(defn- load-data-readers [] -; ;; (alter-var-root #'*data-readers* -; ;; (fn [mappings] -; ;; (reduce load-data-reader-file -; ;; mappings (data-reader-urls)))) -; (throw "TODO: port load-data-readers")) -; -;;; (try -;;; (load-data-readers) -;;; (catch #_Throwable t -;;; (.printStackTrace t) -;;; (throw t))) -; -;(defonce ^:private tapset (atom #{})) -; -;;; (defonce ^:private ^java.util.concurrent.ArrayBlockingQueue tapq (java.util.concurrent.ArrayBlockingQueue. 1024)) -; -;(defonce ^:private tap-loop -; ;; (delay -; ;; (doto (Thread. -; ;; #(let [t (.take tapq) -; ;; x (if (identical? ::tap-nil t) nil t) -; ;; taps @tapset] -; ;; (doseq [tap taps] -; ;; (try -; ;; (tap x) -; ;; (catch Throwable ex))) -; ;; (recur)) -; ;; "clojure.core/tap-loop") -; ;; (.setDaemon true) -; ;; (.start))) -; nil) -; -;(defn add-tap -; "adds f, a fn of one argument, to the tap set. This function will be called with anything sent via tap>. -; This function may (briefly) block (e.g. for streams), and will never impede calls to tap>, -; but blocking indefinitely may cause tap values to be dropped. -; Remember f in order to remove-tap" -; [f] -; (force tap-loop) -; (swap! tapset conj f) -; nil) -; -;(defn remove-tap -; "Remove f from the tap set." -; [f] -; (swap! tapset disj f) -; nil) -; -;(defn tap> -; "sends x to any taps. Will not block. Returns true if there was room in the queue, -; false if not (dropped)." -; [x] -; (force tap-loop) -; ;; (.offer tapq (if (nil? x) ::tap-nil x)) -; (throw "TODO: port tap>")) -; -;(defn update-vals -; "m f => {k (f v) ...} -; -; Given a map m and a function f of 1-argument, returns a new map where the keys of m -; are mapped to result of applying f to the corresponding values of m." -; [m f] -; (with-meta -; (persistent! -; (reduce-kv (fn [acc k v] (assoc! acc k (f v))) -; (if (transientable? m) -; (transient m) -; (transient {})) -; m)) -; (meta m))) -; -;(defn update-keys -; "m f => {(f k) v ...} -; -; Given a map m and a function f of 1-argument, returns a new map whose -; keys are the result of applying f to the keys of m, mapped to the -; corresponding values of m. -; f must return a unique key for each key of m, else the behavior is undefined." -; [m f] -; (let [ret (persistent! -; (reduce-kv (fn [acc k v] (assoc! acc (f k) v)) -; (transient {}) -; m))] -; (with-meta ret (meta m)))) -; -;(defn- parsing-err -; "Construct message for parsing for non-string parsing error" -; [val] -; (str "Expected string, got " (if (nil? val) "nil" (type val)))) -; -;(defn parse-long -; "Parse string of decimal digits with optional leading -/+ and return a -; Long value, or nil if parse fails" -; [s] -; (cpp/jank.runtime.parse_long s)) -; -;(defn parse-double -; "Parse string with floating point components and return a Double value, -; or nil if parse fails. -; -; Grammar: https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#valueOf-java.lang.String-" -; [s] -; (cpp/jank.runtime.parse_double s)) -; -;(defn parse-uuid -; "Parse a string representing a UUID and return a java.util.UUID instance, -; or nil if parse fails. -; -; Grammar: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#toString--" -; [s] -; (cpp/jank.runtime.parse_uuid s)) -; -;(defn parse-boolean -; "Parse strings \"true\" or \"false\" and return a boolean, or nil if invalid" -; [s] -; (if (string? s) -; (case s -; "true" true -; "false" false -; nil) -; (throw (parsing-err s)))) -; -;(defn NaN? -; "Returns true if num is NaN, else false" -; [num] -; (cpp/jank.runtime.is_nan num)) -; -;(defn infinite? -; "Returns true if num is negative or positive infinity, else false" -; [num] -; (cpp/jank.runtime.is_infinite num)) +;;(defn with-bindings* +;; "Takes a map of Var/value pairs. Installs for the given Vars the associated +;; values as thread-local bindings. Then calls f with the supplied arguments. +;; Pops the installed bindings after f returned. Returns whatever f returns." +;; [binding-map f & args] +;; (push-thread-bindings (if (= "persistent_array_map" (type binding-map)) +;; (into (hash-map) binding-map) +;; binding-map)) +;; (try +;; (apply f args) +;; (finally +;; (pop-thread-bindings)))) +;; +;;(defmacro with-bindings +;; "Takes a map of Var/value pairs. Installs for the given Vars the associated +;; values as thread-local bindings. Then executes body. Pops the installed +;; bindings after body was evaluated. Returns the value of body." +;; [binding-map & body] +;; `(with-bindings* ~binding-map (fn [] ~@body))) +;; +;;(defn bound-fn* +;; "Returns a function, which will install the same bindings in effect as in +;; the thread at the time bound-fn* was called and then call f with any given +;; arguments. This may be used to define a helper function which runs on a +;; different thread, but needs the same bindings in place." +;; [f] +;; (let [bindings (get-thread-bindings)] +;; (fn [& args] +;; (apply with-bindings* bindings f args)))) +;; +;;(defmacro bound-fn +;; "Returns a function defined by the given fntail, which will install the +;; same bindings in effect as in the thread at the time bound-fn was called. +;; This may be used to define a helper function which runs on a different +;; thread, but needs the same bindings in place." +;; [& fntail] +;; `(bound-fn* (fn ~@fntail))) +;; +;;(defn- binding-conveyor-fn +;; [f] +;; ;; (let [frame (clojure.lang.Var/cloneThreadBindingFrame)] +;; ;; (fn +;; ;; ([] +;; ;; (clojure.lang.Var/resetThreadBindingFrame frame) +;; ;; (f)) +;; ;; ([x] +;; ;; (clojure.lang.Var/resetThreadBindingFrame frame) +;; ;; (f x)) +;; ;; ([x y] +;; ;; (clojure.lang.Var/resetThreadBindingFrame frame) +;; ;; (f x y)) +;; ;; ([x y z] +;; ;; (clojure.lang.Var/resetThreadBindingFrame frame) +;; ;; (f x y z)) +;; ;; ([x y z & args] +;; ;; (clojure.lang.Var/resetThreadBindingFrame frame) +;; ;; (apply f x y z args)))) +;; (throw "TODO: port binding-conveyor-fn")) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Refs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;(defn- +;; setup-reference [#_clojure.lang.ARef r options] +;; ;; (let [opts (apply hash-map options)] +;; ;; (when (:meta opts) +;; ;; (.resetMeta r (:meta opts))) +;; ;; (when (:validator opts) +;; ;; (.setValidator r (:validator opts))) +;; ;; r) +;; (throw "TODO: port setup-reference")) +;; +;;(defn agent +;; "Creates and returns an agent with an initial value of state and +;; zero or more options (in any order): +;; +;; :meta metadata-map +;; +;; :validator validate-fn +;; +;; :error-handler handler-fn +;; +;; :error-mode mode-keyword +;; +;; If metadata-map is supplied, it will become the metadata on the +;; agent. validate-fn must be nil or a side-effect-free fn of one +;; argument, which will be passed the intended new state on any state +;; change. If the new state is unacceptable, the validate-fn should +;; return false or throw an exception. handler-fn is called if an +;; action throws an exception or if validate-fn rejects a new state -- +;; see set-error-handler! for details. The mode-keyword may be either +;; :continue (the default if an error-handler is given) or :fail (the +;; default if no error-handler is given) -- see set-error-mode! for +;; details." +;; ([state & options] +;; ;; (let [a (new clojure.lang.Agent state) +;; ;; opts (apply hash-map options)] +;; ;; (setup-reference a options) +;; ;; (when (:error-handler opts) +;; ;; (.setErrorHandler a (:error-handler opts))) +;; ;; (.setErrorMode a (or (:error-mode opts) +;; ;; (if (:error-handler opts) :continue :fail))) +;; ;; a) +;; (throw "TODO: port agent"))) +;; +;;(defn set-agent-send-executor! +;; "Sets the ExecutorService to be used by send" +;; [executor] +;; ;; (set! clojure.lang.Agent/pooledExecutor executor) +;; (throw "TODO: port set-agent-send-executor!")) +;; +;;(defn set-agent-send-off-executor! +;; "Sets the ExecutorService to be used by send-off" +;; [executor] +;; ;; (set! clojure.lang.Agent/soloExecutor executor) +;; (throw "TODO: port set-agent-send-off-executor!")) +;; +;;(defn send-via +;; "Dispatch an action to an agent. Returns the agent immediately. +;; Subsequently, in a thread supplied by executor, the state of the agent +;; will be set to the value of: +;; +;; (apply action-fn state-of-agent args)" +;; [executor #_clojure.lang.Agent a f & args] +;; ;; (.dispatch a (binding [*agent* a] (binding-conveyor-fn f)) args executor) +;; (throw "TODO: port send-via")) +;; +;;(defn send +;; "Dispatch an action to an agent. Returns the agent immediately. +;; Subsequently, in a thread from a thread pool, the state of the agent +;; will be set to the value of: +;; +;; (apply action-fn state-of-agent args)" +;; [#_clojure.lang.Agent a f & args] +;; ;; (apply send-via clojure.lang.Agent/pooledExecutor a f args) +;; (throw "TODO: port send")) +;; +;;(defn send-off +;; "Dispatch a potentially blocking action to an agent. Returns the +;; agent immediately. Subsequently, in a separate thread, the state of +;; the agent will be set to the value of: +;; +;; (apply action-fn state-of-agent args)" +;; [#_clojure.lang.Agent a f & args] +;; ;; (apply send-via clojure.lang.Agent/soloExecutor a f args) +;; (throw "TODO: port send-off")) +;; +;;(defn release-pending-sends +;; "Normally, actions sent directly or indirectly during another action +;; are held until the action completes (changes the agent's +;; state). This function can be used to dispatch any pending sent +;; actions immediately. This has no impact on actions sent during a +;; transaction, which are still held until commit. If no action is +;; occurring, does nothing. Returns the number of actions dispatched." +;; [] +;; ;; (clojure.lang.Agent/releasePendingSends) +;; (throw "TODO: port release-pending-sends")) +;; +;;(defn add-watch +;; "Adds a watch function to an agent/atom/var/ref reference. The watch +;; fn must be a fn of 4 args: a key, the reference, its old-state, its +;; new-state. Whenever the reference's state might have been changed, +;; any registered watches will have their functions called. The watch fn +;; will be called synchronously, on the agent's thread if an agent, +;; before any pending sends if agent or ref. Note that an atom's or +;; ref's state may have changed again prior to the fn call, so use +;; old/new-state rather than derefing the reference. Note also that watch +;; fns may be called from multiple threads simultaneously. Var watchers +;; are triggered only by root binding changes, not thread-local +;; set!s. Keys must be unique per reference, and can be used to remove +;; the watch with remove-watch, but are otherwise considered opaque by +;; the watch mechanism." +;; [reference key f] +;; (cpp/jank.runtime.add_watch reference key f)) +;; +;;(defn remove-watch +;; "Removes a watch (set by add-watch) from a reference" +;; [reference key] +;; (cpp/jank.runtime.remove_watch reference key)) +;; +;;(defn agent-error +;; "Returns the exception thrown during an asynchronous action of the +;; agent if the agent is failed. Returns nil if the agent is not +;; failed." +;; [#_clojure.lang.Agent a] +;; ;; (.getError a) +;; (throw "TODO: port agent-error")) +;; +;;(defn restart-agent +;; "When an agent is failed, changes the agent state to new-state and +;; then un-fails the agent so that sends are allowed again. If +;; a :clear-actions true option is given, any actions queued on the +;; agent that were being held while it was failed will be discarded, +;; otherwise those held actions will proceed. The new-state must pass +;; the validator if any, or restart will throw an exception and the +;; agent will remain failed with its old state and error. Watchers, if +;; any, will NOT be notified of the new state. Throws an exception if +;; the agent is not failed." +;; [#_clojure.lang.Agent a, new-state & options] +;; ;; (let [opts (apply hash-map options)] +;; ;; (.restart a new-state (if (:clear-actions opts) true false))) +;; (throw "TODO: port restart-agent")) +;; +;;(defn set-error-handler! +;; "Sets the error-handler of agent a to handler-fn. If an action +;; being run by the agent throws an exception or doesn't pass the +;; validator fn, handler-fn will be called with two arguments: the +;; agent and the exception." +;; [#_clojure.lang.Agent a, handler-fn] +;; ;; (.setErrorHandler a handler-fn) +;; (throw "TODO: port set-error-handler!")) +;; +;;(defn error-handler +;; "Returns the error-handler of agent a, or nil if there is none. +;; See set-error-handler!" +;; [#_clojure.lang.Agent a] +;; ;; (.getErrorHandler a) +;; (throw "TODO: port error-handler")) +;; +;;(defn set-error-mode! +;; "Sets the error-mode of agent a to mode-keyword, which must be +;; either :fail or :continue. If an action being run by the agent +;; throws an exception or doesn't pass the validator fn, an +;; error-handler may be called (see set-error-handler!), after which, +;; if the mode is :continue, the agent will continue as if neither the +;; action that caused the error nor the error itself ever happened. +;; +;; If the mode is :fail, the agent will become failed and will stop +;; accepting new 'send' and 'send-off' actions, and any previously +;; queued actions will be held until a 'restart-agent'. Deref will +;; still work, returning the state of the agent before the error." +;; [#_clojure.lang.Agent a, mode-keyword] +;; ;; (.setErrorMode a mode-keyword) +;; (throw "TODO: port set-error-mode!")) +;; +;;(defn error-mode +;; "Returns the error-mode of agent a. See set-error-mode!" +;; [#_clojure.lang.Agent a] +;; ;; (.getErrorMode a) +;; (throw "TODO: port error-mode")) +;; +;;(defn agent-errors +;; "DEPRECATED: Use 'agent-error' instead. +;; Returns a sequence of the exceptions thrown during asynchronous +;; actions of the agent." +;; [a] +;; (when-let [e (agent-error a)] +;; (list e))) +;; +;;(defn clear-agent-errors +;; "DEPRECATED: Use 'restart-agent' instead. +;; Clears any exceptions thrown during asynchronous actions of the +;; agent, allowing subsequent actions to occur." +;; [#_clojure.lang.Agent a] +;; ;; (restart-agent a (.deref a)) +;; (throw "TODO: port clear-agent-errors")) +;; +;;(defn shutdown-agents +;; "Initiates a shutdown of the thread pools that back the agent +;; system. Running actions will complete, but no new actions will be +;; accepted" +;; [] +;; ;; (. clojure.lang.Agent shutdown) +;; (throw "TODO: port shutdown-agents")) +;; +;;(defn ref +;; "Creates and returns a Ref with an initial value of x and zero or +;; more options (in any order): +;; +;; :meta metadata-map +;; +;; :validator validate-fn +;; +;; :min-history (default 0) +;; :max-history (default 10) +;; +;; If metadata-map is supplied, it will become the metadata on the +;; ref. validate-fn must be nil or a side-effect-free fn of one +;; argument, which will be passed the intended new state on any state +;; change. If the new state is unacceptable, the validate-fn should +;; return false or throw an exception. validate-fn will be called on +;; transaction commit, when all refs have their final values. +;; +;; Normally refs accumulate history dynamically as needed to deal with +;; read demands. If you know in advance you will need history you can +;; set :min-history to ensure it will be available when first needed (instead +;; of after a read fault). History is limited, and the limit can be set +;; with :max-history." +;; ([x] +;; ;; (new clojure.lang.Ref x) +;; (throw "TODO: port ref")) +;; ([x & options] +;; ;; (let [r ^clojure.lang.Ref (setup-reference (ref x) options) +;; ;; opts (apply hash-map options)] +;; ;; (when (:max-history opts) +;; ;; (.setMaxHistory r (:max-history opts))) +;; ;; (when (:min-history opts) +;; ;; (.setMinHistory r (:min-history opts))) +;; ;; r) +;; (throw "TODO: port ref"))) +;; +;;(defn- deref-future +;; ([#_java.util.concurrent.Future fut] +;; ;; (.get fut) +;; (throw "TODO: port deref-future")) +;; ([#_java.util.concurrent.Future fut timeout-ms timeout-val] +;; ;; (try (.get fut timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS) +;; ;; (catch java.util.concurrent.TimeoutException e +;; ;; timeout-val)) +;; (throw "TODO: port deref-future"))) +;; +;;(defn set-validator! +;; "Sets the validator-fn for a var/ref/agent/atom. validator-fn must be nil or a +;; side-effect-free fn of one argument, which will be passed the intended +;; new state on any state change. If the new state is unacceptable, the +;; validator-fn should return false or throw an exception. If the current state (root +;; value if var) is not acceptable to the new validator, an exception +;; will be thrown and the validator will not be changed." +;; [#_clojure.lang.IRef iref validator-fn] +;; ;; (. iref (setValidator validator-fn)) +;; (throw "TODO: port set-validator!")) +;; +;;(defn get-validator +;; "Gets the validator-fn for a var/ref/agent/atom." +;; [#_clojure.lang.IRef iref] +;; ;; (. iref (getValidator)) +;; (throw "TODO: port get-validator")) +;; +;;(defn commute +;; "Must be called in a transaction. Sets the in-transaction-value of +;; ref to: +;; +;; (apply fun in-transaction-value-of-ref args) +;; +;; and returns the in-transaction-value of ref. +;; +;; At the commit point of the transaction, sets the value of ref to be: +;; +;; (apply fun most-recently-committed-value-of-ref args) +;; +;; Thus fun should be commutative, or, failing that, you must accept +;; last-one-in-wins behavior. commute allows for more concurrency than +;; ref-set." +;; [#_clojure.lang.Ref ref fun & args] +;; ;; (. ref (commute fun args)) +;; (throw "TODO: port commute")) +;; +;;(defn alter +;; "Must be called in a transaction. Sets the in-transaction-value of +;; ref to: +;; +;; (apply fun in-transaction-value-of-ref args) +;; +;; and returns the in-transaction-value of ref." +;; [#_clojure.lang.Ref ref fun & args] +;; ;; (. ref (alter fun args)) +;; (throw "TODO: port alter")) +;; +;;(defn ref-set +;; "Must be called in a transaction. Sets the value of ref. +;; Returns val." +;; [#_clojure.lang.Ref ref val] +;; ;; (. ref (set val)) +;; (throw "TODO: port ref-set")) +;; +;;(defn ref-history-count +;; "Returns the history count of a ref" +;; [#_clojure.lang.Ref ref] +;; ;; (.getHistoryCount ref) +;; (throw "TODO: port ref-history-count")) +;; +;;(defn ref-min-history +;; "Gets the min-history of a ref, or sets it and returns the ref" +;; ([#_clojure.lang.Ref ref] +;; ;; (.getMinHistory ref) +;; (throw "TODO: port ref-min-history")) +;; ([#_clojure.lang.Ref ref n] +;; ;; (.setMinHistory ref n) +;; (throw "TODO: port ref-min-history"))) +;; +;;(defn ref-max-history +;; "Gets the max-history of a ref, or sets it and returns the ref" +;; ([#_clojure.lang.Ref ref] +;; ;; (.getMaxHistory ref) +;; (throw "TODO: port ref-max-history")) +;; ([#_clojure.lang.Ref ref n] +;; ;; (.setMaxHistory ref n) +;; (throw "TODO: port ref-max-history"))) +;; +;;(defn ensure +;; "Must be called in a transaction. Protects the ref from modification +;; by other transactions. Returns the in-transaction-value of +;; ref. Allows for more concurrency than (ref-set ref @ref)" +;; [#_clojure.lang.Ref ref] +;; ;; (. ref (touch)) +;; ;; (. ref (deref)) +;; (throw "TODO: port ensure")) +;; +;;(defmacro sync +;; "transaction-flags => TBD, pass nil for now +;; +;; Runs the exprs (in an implicit do) in a transaction that encompasses +;; exprs and any nested calls. Starts a transaction if none is already +;; running on this thread. Any uncaught exception will abort the +;; transaction and flow out of sync. The exprs may be run more than +;; once, but any effects on Refs will be atomic." +;; [flags-ignored-for-now & body] +;; ;; `(. clojure.lang.LockingTransaction +;; ;; (runInTransaction (fn [] ~@body))) +;; (throw "TODO: port sync")) +;; +;;(defmacro io! +;; "If an io! block occurs in a transaction, throws an +;; IllegalStateException, else runs body in an implicit do. If the +;; first expression in body is a literal string, will use that as the +;; exception message." +;; [& body] +;; ;; (let [message (when (string? (first body)) (first body)) +;; ;; body (if message (next body) body)] +;; ;; `(if (clojure.lang.LockingTransaction/isRunning) +;; ;; (throw (new IllegalStateException ~(or message "I/O in transaction"))) +;; ;; (do ~@body))) +;; (throw "TODO: port io!")) +;; +;;;;;;;;;;;;;;;;;;;;; sequence fns ;;;;;;;;;;;;;;;;;;;;;;; +;; +;;(defn sequence +;; "Coerces coll to a (possibly empty) sequence, if it is not already +;; one. Will not force a lazy seq. (sequence nil) yields (), When a +;; transducer is supplied, returns a lazy sequence of applications of +;; the transform to the items in coll(s), i.e. to the set of first +;; items of each coll, followed by the set of second +;; items in each coll, until any one of the colls is exhausted. Any +;; remaining items in other colls are ignored. The transform should accept +;; number-of-colls arguments" +;; ([coll] +;; (if (seq? coll) coll +;; (or (seq coll) ()))) +;; ([xform coll] +;; ;; (or (clojure.lang.RT/chunkIteratorSeq +;; ;; (clojure.lang.TransformerIterator/create xform (clojure.lang.RT/iter coll))) +;; ;; ()) +;; (throw "TODO: port sequence")) +;; ([xform coll & colls] +;; ;; (or (clojure.lang.RT/chunkIteratorSeq +;; ;; (clojure.lang.TransformerIterator/createMulti +;; ;; xform +;; ;; (map #(clojure.lang.RT/iter %) (cons coll colls)))) +;; ;; ()) +;; (throw "TODO: port sequence"))) +;; +;;(defn not-every? +;; "Returns false if (pred x) is logical true for every x in +;; coll, else true." +;; [pred coll] +;; (not (every? pred coll))) +;; +;;(defmacro declare +;; "defs the supplied var names with no bindings, useful for making forward declarations." +;; [& names] `(do ~@(map #(list 'def (vary-meta % assoc :declared true)) names))) +;; +;;(defn replicate +;; "DEPRECATED: Use 'repeat' instead. +;; Returns a lazy seq of n xs." +;; [n x] (take n (repeat x))) +;; +;;(defn merge +;; "Returns a map that consists of the rest of the maps conj-ed onto +;; the first. If a key occurs in more than one map, the mapping from +;; the latter (left-to-right) will be the mapping in the result." +;; [& maps] +;; (when (some identity maps) +;; (reduce #(conj (or %1 {}) %2) maps))) +;; +;;(defn merge-with +;; "Returns a map that consists of the rest of the maps conj-ed onto +;; the first. If a key occurs in more than one map, the mapping(s) +;; from the latter (left-to-right) will be combined with the mapping in +;; the result by calling (f val-in-result val-in-latter)." +;; [f & maps] +;; (when (some identity maps) +;; (let [merge-entry (fn [m e] +;; (let [k (key e) v (val e)] +;; (if (contains? m k) +;; (assoc m k (f (get m k) v)) +;; (assoc m k v)))) +;; merge2 (fn [m1 m2] +;; (reduce merge-entry (or m1 {}) (seq m2)))] +;; (reduce merge2 maps)))) +;; +;;(defn line-seq +;; "Returns the lines of text from rdr as a lazy sequence of strings. +;; rdr must implement java.io.BufferedReader." +;; [#_java.io.BufferedReader rdr] +;; ;; (when-let [line (.readLine rdr)] +;; ;; (cons line (lazy-seq (line-seq rdr)))) +;; (throw "TODO: port line-seq")) +;; +;;(defn comparator +;; "Returns an implementation of java.util.Comparator based upon pred." +;; [pred] +;; (fn [x y] +;; (cond (pred x y) -1 (pred y x) 1 :else 0))) +;; +;;(defn sort +;; "Returns a sorted sequence of the items in coll. If no comparator is +;; supplied, uses compare. comparator must implement +;; java.util.Comparator. Guaranteed to be stable: equal elements will +;; not be reordered. If coll is a Java array, it will be modified. To +;; avoid this, sort a copy of the array." +;; [coll] +;; (cpp/jank.runtime.sort coll)) +;; +;;(defn sort-by +;; "Returns a sorted sequence of the items in coll, where the sort +;; order is determined by comparing (keyfn item). If no comparator is +;; supplied, uses compare. comparator must implement +;; java.util.Comparator. Guaranteed to be stable: equal elements will +;; not be reordered. If coll is a Java array, it will be modified. To +;; avoid this, sort a copy of the array." +;; ([keyfn coll] +;; (sort-by keyfn compare coll)) +;; ([keyfn #_java.util.Comparator comp coll] +;; ;; (sort (fn [x y] (. comp (compare (keyfn x) (keyfn y)))) coll) +;; (throw "TODO: port sort-by"))) +;; +;;;; evaluation +;; +;;(defn eval +;; "Evaluates the form data structure (not text!) and returns the result." +;; [form] +;; (cpp/clojure.core_native.eval form)) +;; +;;(defn await +;; "Blocks the current thread (indefinitely!) until all actions +;; dispatched thus far, from this thread or agent, to the agent(s) have +;; occurred. Will block on failed agents. Will never return if +;; a failed agent is restarted with :clear-actions true or shutdown-agents was called." +;; [& agents] +;; ;; (io! "await in transaction" +;; ;; (when *agent* +;; ;; (throw (new Exception "Can't await in agent action"))) +;; ;; (let [latch (new java.util.concurrent.CountDownLatch (count agents)) +;; ;; count-down (fn [agent] (. latch (countDown)) agent)] +;; ;; (doseq [agent agents] +;; ;; (send agent count-down)) +;; ;; (. latch (await)))) +;; (throw "TODO: port await")) +;; +;;(defn await1 [#_clojure.lang.Agent a] +;; ;; (when (pos? (.getQueueCount a)) +;; ;; (await a)) +;; ;; a +;; (throw "TODO: port await1")) +;; +;;(defn await-for +;; "Blocks the current thread until all actions dispatched thus +;; far (from this thread or agent) to the agents have occurred, or the +;; timeout (in milliseconds) has elapsed. Returns logical false if +;; returning due to timeout, logical true otherwise." +;; [timeout-ms & agents] +;; ;; (io! "await-for in transaction" +;; ;; (when *agent* +;; ;; (throw (new Exception "Can't await in agent action"))) +;; ;; (let [latch (new java.util.concurrent.CountDownLatch (count agents)) +;; ;; count-down (fn [agent] (. latch (countDown)) agent)] +;; ;; (doseq [agent agents] +;; ;; (send agent count-down)) +;; ;; (. latch (await timeout-ms (. java.util.concurrent.TimeUnit MILLISECONDS))))) +;; (throw "TODO: port await-for")) +;; +;;(defn import +;; "import is not implemented for jank, but a var is still bound to its symbol for portability. import always throws an exception" +;; [& _] +;; (throw "import is not supported in jank, for C/C++ dependency interoperability use cpp/raw with #include, e.g. (cpp/raw \"#include \"dependency.h\")\")")) +;; +;;(defn into-array +;; "Returns an array with components set to the values in aseq. The array's +;; component type is type if provided, or the type of the first value in +;; aseq if present, or Object. All values in aseq must be compatible with +;; the component type. Class objects for the primitive types can be obtained +;; using, e.g., Integer/TYPE." +;; ([aseq] +;; ;; (clojure.lang.RT/seqToTypedArray (seq aseq)) +;; (throw "TODO: port into-array")) +;; ([type aseq] +;; ;; (clojure.lang.RT/seqToTypedArray type (seq aseq)) +;; (throw "TODO: port into-array"))) +;; +;;(defn- +;; array [& items] +;; (into-array items)) +;; +;;(defn class +;; "Returns the Class of x" +;; #_Class [#_Object x] +;; ;; (if (nil? x) x (. x (getClass))) +;; (throw "TODO: port class")) +;; +;;(defn num +;; "Coerce to Number" +;; [x] +;; ;; (. clojure.lang.Numbers (num x)) +;; (throw "TODO: port num")) +;; +;;(defn long +;; "Coerce to long" +;; [#_Number x] +;; ;; (clojure.lang.RT/longCast x) +;; (throw "TODO: port long")) +;; +;;(defn double +;; "Coerce to double" +;; [#_Number x] +;; ;; (clojure.lang.RT/doubleCast x) +;; (throw "TODO: port double")) +;; +;;(defn short +;; "Coerce to short" +;; [#_Number x] +;; ;; (clojure.lang.RT/shortCast x) +;; (throw "TODO: port short")) +;; +;;(defn byte +;; "Coerce to byte" +;; [#_Number x] +;; ;; (clojure.lang.RT/byteCast x) +;; (throw "TODO: port byte")) +;; +;;(defn char +;; "Coerce to char" +;; [x] +;; ;; (. clojure.lang.RT (charCast x)) +;; (throw "TODO: port char")) +;; +;;(defn unchecked-byte +;; "Coerce to byte. Subject to rounding or truncation." +;; [#_Number x] +;; ;; (clojure.lang.RT/uncheckedByteCast x) +;; (throw "TODO: port unchecked-byte")) +;; +;;(defn unchecked-short +;; "Coerce to short. Subject to rounding or truncation." +;; [#_Number x] +;; ;; (clojure.lang.RT/uncheckedShortCast x) +;; (throw "TODO: port unchecked-short")) +;; +;;(defn unchecked-char +;; "Coerce to char. Subject to rounding or truncation." +;; [x] +;; ;; (. clojure.lang.RT (uncheckedCharCast x)) +;; (throw "TODO: port unchecked-char")) +;; +;;(defn unchecked-int +;; "Coerce to int. Subject to rounding or truncation." +;; [#_Number x] +;; ;; (clojure.lang.RT/uncheckedIntCast x) +;; (throw "TODO: port unchecked-int")) +;; +;;(defn unchecked-long +;; "Coerce to long. Subject to rounding or truncation." +;; [#_Number x] +;; ;; (clojure.lang.RT/uncheckedLongCast x) +;; (throw "TODO: port unchecked-long")) +;; +;;(defn unchecked-float +;; "Coerce to float. Subject to rounding." +;; [#_Number x] +;; ;; (clojure.lang.RT/uncheckedFloatCast x) +;; (throw "TODO: port unchecked-float")) +;; +;;(defn unchecked-double +;; "Coerce to double. Subject to rounding." +;; [#_Number x] +;; ;; (clojure.lang.RT/uncheckedDoubleCast x) +;; (throw "TODO: port unchecked-double")) +;; +;;(defn ratio? +;; "Returns true if n is a Ratio" +;; [r] +;; (cpp/jank.runtime.is_ratio r)) +;; +;;(defn numerator +;; "Returns the numerator part of a Ratio." +;; [r] +;; (cpp/jank.runtime.numerator r)) +;; +;;(defn denominator +;; "Returns the denominator part of a Ratio." +;; [r] +;; (cpp/jank.runtime.denominator r)) +;; +;;(defn decimal? +;; "Returns true if n is a BigDecimal" +;; [n] +;; ;; (instance? BigDecimal n) +;; (cpp/jank.runtime.is_big_decimal n)) +;; +;;(defn rational? +;; "Returns true if n is a rational number" +;; [n] +;; (or (integer? n) (ratio? n) (decimal? n))) +;; +;;(defn bigint +;; "Coerce to BigInt" +;; [x] +;; ;; (cond +;; ;; (instance? clojure.lang.BigInt x) x +;; ;; (instance? BigInteger x) (clojure.lang.BigInt/fromBigInteger x) +;; ;; (decimal? x) (bigint (.toBigInteger ^BigDecimal x)) +;; ;; (float? x) (bigint (. BigDecimal valueOf (double x))) +;; ;; (ratio? x) (bigint (.bigIntegerValue ^clojure.lang.Ratio x)) +;; ;; (number? x) (clojure.lang.BigInt/valueOf (long x)) +;; ;; :else (bigint (BigInteger. x))) +;; (throw "TODO: port bigint")) +;; +;;(defn biginteger +;; "Coerce to BigInteger" +;; [x] +;; ;; (cond +;; ;; (instance? BigInteger x) x +;; ;; (instance? clojure.lang.BigInt x) (.toBigInteger ^clojure.lang.BigInt x) +;; ;; (decimal? x) (.toBigInteger ^BigDecimal x) +;; ;; (float? x) (.toBigInteger (. BigDecimal valueOf (double x))) +;; ;; (ratio? x) (.bigIntegerValue ^clojure.lang.Ratio x) +;; ;; (number? x) (BigInteger/valueOf (long x)) +;; ;; :else (BigInteger. x)) +;; (throw "TODO: port biginteger")) +;; +;;(defn bigdec +;; "Coerce to BigDecimal" +;; [x] +;; (cpp/jank.runtime.to_big_decimal x)) +;; +;;(def ^:dynamic ^:private print-initialized false) +;; +;;(defmulti print-method (fn [x writer] +;; (let [t (get (meta x) :type)] +;; (if (keyword? t) t (class x))))) +;; +;;(defmulti print-dup (fn [x writer] (class x))) +;; +;;(def ^:private #_String system-newline +;; ;; (System/getProperty "line.separator") +;; "\n") +;; +;;(defn newline +;; "Writes a platform-specific newline to *out*" +;; [] +;; ;; (. *out* (append system-newline)) +;; ;; nil +;; (throw "TODO: port newline")) +;; +;;(defn flush +;; "Flushes the output stream that is the current value of +;; *out*" +;; [] +;; ;; (. *out* (flush)) +;; ;; nil +;; (throw "TODO: port flesh")) +;; +;;(defn read +;; "Reads the next object from stream, which must be an instance of +;; java.io.PushbackReader or some derivee. stream defaults to the +;; current value of *in*. +;; +;; Opts is a persistent map with valid keys: +;; :read-cond - :allow to process reader conditionals, or +;; :preserve to keep all branches +;; :features - persistent set of feature keywords for reader conditionals +;; :eof - on eof, return value unless :eofthrow, then throw. +;; if not specified, will throw +;; +;; Note that read can execute code (controlled by *read-eval*), +;; and as such should be used only with trusted sources. +;; +;; For data structure interop use clojure.edn/read" +;; ([] +;; (read *in*)) +;; ([stream] +;; (read stream true nil)) +;; ([stream eof-error? eof-value] +;; (read stream eof-error? eof-value false)) +;; ([stream eof-error? eof-value recursive?] +;; ;; (. clojure.lang.LispReader (read stream (boolean eof-error?) eof-value recursive?)) +;; (throw "TODO: port read")) +;; ([opts stream] +;; ;; (. clojure.lang.LispReader (read stream opts)) +;; (throw "TODO: port read"))) +;; +;;(defn read+string +;; "Like read, and taking the same args. stream must be a LineNumberingPushbackReader. +;; Returns a vector containing the object read and the (whitespace-trimmed) string read." +;; ([] (read+string *in*)) +;; ([stream] (read+string stream true nil)) +;; ([stream eof-error? eof-value] (read+string stream eof-error? eof-value false)) +;; ([#_clojure.lang.LineNumberingPushbackReader stream eof-error? eof-value recursive?] +;; ;; (try +;; ;; (.captureString stream) +;; ;; (let [o (read stream eof-error? eof-value recursive?) +;; ;; s (.trim (.getString stream))] +;; ;; [o s]) +;; ;; (catch Throwable ex +;; ;; (.getString stream) +;; ;; (throw ex))) +;; (throw "TODO: port read+string")) +;; ([opts #_clojure.lang.LineNumberingPushbackReader stream] +;; ;; (try +;; ;; (.captureString stream) +;; ;; (let [o (read opts stream) +;; ;; s (.trim (.getString stream))] +;; ;; [o s]) +;; ;; (catch Throwable ex +;; ;; (.getString stream) +;; ;; (throw ex))) +;; (throw "TODO: port read+string"))) +;; +;;(defn read-line +;; "Reads the next line from stream that is the current value of *in* ." +;; [] +;; ;; (if (instance? clojure.lang.LineNumberingPushbackReader *in*) +;; ;; (.readLine ^clojure.lang.LineNumberingPushbackReader *in*) +;; ;; (.readLine ^java.io.BufferedReader *in*)) +;; (throw "TODO: port read-line")) +;; +;;(defn read-string +;; "Reads one object from the string s. Optionally include reader +;; options, as specified in read. +;; +;; Note that read-string can execute code (controlled by *read-eval*), +;; and as such should be used only with trusted sources. +;; +;; For data structure interop use clojure.edn/read-string" +;; ([s] +;; (read-string {} s)) +;; ([opts s] +;; (cpp/clojure.core_native.read_string opts s))) +;; +;;(defmacro with-open +;; "bindings => [name init ...] +;; +;; Evaluates body in a try expression with names bound to the values +;; of the inits, and a finally clause that calls (.close name) on each +;; name in reverse order." +;; [bindings & body] +;; (assert-macro-args +;; (vector? bindings) "a vector for its binding" +;; (even? (count bindings)) "an even number of forms in binding vector") +;; ;; (cond +;; ;; (= (count bindings) 0) `(do ~@body) +;; ;; (symbol? (bindings 0)) `(let ~(subvec bindings 0 2) +;; ;; (try +;; ;; (with-open ~(subvec bindings 2) ~@body) +;; ;; (finally +;; ;; (. ~(bindings 0) ~'close)))) +;; ;; :else (throw (IllegalArgumentException. +;; ;; "with-open only allows Symbols in bindings"))) +;; (throw "TODO: port with-open")) +;; +;;(defmacro memfn +;; "Expands into code that creates a fn that expects to be passed an +;; object and any args and calls the named instance method on the +;; object passing the args. Use when you want to treat a Java method as +;; a first-class fn. name may be type-hinted with the method receiver's +;; type in order to avoid reflective calls." +;; [name & args] +;; ;; (let [t (with-meta (gensym "target") +;; ;; (meta name))] +;; ;; `(fn [~t ~@args] +;; ;; (. ~t (~name ~@args)))) +;; (throw "TODO: port memfn")) +;; +;;(defn alength +;; "Returns the length of the Java array. Works on arrays of all +;; types." +;; [array] +;; ;; (. clojure.lang.RT (alength array)) +;; (throw "TODO: port alength")) +;; +;;(defn aclone +;; "Returns a clone of the Java array. Works on arrays of known +;; types." +;; [array] +;; ;; (. clojure.lang.RT (aclone array)) +;; (throw "TODO: port aclone")) +;; +;;(defn aget +;; "Returns the value at the index/indices. Works on Java arrays of all +;; types." +;; ([array idx] +;; ;; (clojure.lang.Reflector/prepRet (.getComponentType (class array)) (. Array (get array idx))) +;; (throw "TODO: port aget")) +;; ([array idx & idxs] +;; (apply aget (aget array idx) idxs))) +;; +;;(defmacro aset +;; "Sets the value at the index/indices. Returns val." +;; [array idx & more] +;; (if (= 1 (count more)) +;; ;; Simple case: (aset array index value) +;; (let [val (first more)] +;; `(do +;; (cpp/= (cpp/aget ~array ~idx) ~val) +;; ~val)) +;; ;; Nested case: (aset array idx1 idx2 & idxv) - not yet implemented +;; `(throw "TODO: Nested array indexing not yet implemented"))) +;; +;;(defmacro +;; ^{:private true} +;; def-aset [name method coerce] +;; `(defn ~name +;; {:arglists '([~'array ~'idx ~'val] [~'array ~'idx ~'idx2 & ~'idxv])} +;; ([array# idx# val#] +;; ;; (. Array (~method array# idx# (~coerce val#))) +;; ;; val# +;; (throw ~(str "TODO: port " name))) +;; ([array# idx# idx2# & idxv#] +;; (apply ~name (aget array# idx#) idx2# idxv#)))) +;; +;;(def-aset +;; ^{:doc "Sets the value at the index/indices. Works on arrays of int. Returns val."} +;; aset-int setInt int) +;; +;;(def-aset +;; ^{:doc "Sets the value at the index/indices. Works on arrays of long. Returns val."} +;; aset-long setLong long) +;; +;;(def-aset +;; ^{:doc "Sets the value at the index/indices. Works on arrays of boolean. Returns val."} +;; aset-boolean setBoolean boolean) +;; +;;(def-aset +;; ^{:doc "Sets the value at the index/indices. Works on arrays of float. Returns val."} +;; aset-float setFloat float) +;; +;;(def-aset +;; ^{:doc "Sets the value at the index/indices. Works on arrays of double. Returns val."} +;; aset-double setDouble double) +;; +;;(def-aset +;; ^{:doc "Sets the value at the index/indices. Works on arrays of short. Returns val."} +;; aset-short setShort short) +;; +;;(def-aset +;; ^{:doc "Sets the value at the index/indices. Works on arrays of byte. Returns val."} +;; aset-byte setByte byte) +;; +;;(def-aset +;; ^{:doc "Sets the value at the index/indices. Works on arrays of char. Returns val."} +;; aset-char setChar char) +;; +;;(defn make-array +;; "Creates and returns an array of instances of the specified class of +;; the specified dimension(s). Note that a class object is required. +;; Class objects can be obtained by using their name. +;; Class objects for the primitive types can be obtained using, e.g., Integer/TYPE." +;; ([#_Class type len] +;; ;; (. Array (newInstance type (int len))) +;; (throw "TODO: port make-array")) +;; ([#_Class type dim & more-dims] +;; ;; (let [dims (cons dim more-dims) +;; ;; ^"[I" dimarray (make-array (. Integer TYPE) (count dims))] +;; ;; (dotimes [i (alength dimarray)] +;; ;; (aset-int dimarray i (nth dims i))) +;; ;; (. Array (newInstance type dimarray)))) +;; (throw "TODO: port make-array"))) +;; +;;(defn to-array-2d +;; "Returns a (potentially-ragged) 2-dimensional array of Objects +;; containing the contents of coll, which can be any Collection of any +;; Collection." +;; [#_java.util.Collection coll] +;; ;; (let [ret (make-array (. Class (forName "[Ljava.lang.Object;")) (. coll (size)))] +;; ;; (loop [i 0 xs (seq coll)] +;; ;; (when xs +;; ;; (aset ret i (to-array (first xs))) +;; ;; (recur (inc i) (next xs)))) +;; ;; ret) +;; (throw "TODO: port to-array-2d")) +;; +;;(defn create-struct +;; "Returns a structure basis object." +;; [& keys] +;; ;; (. clojure.lang.PersistentStructMap (createSlotMap keys)) +;; (throw "TODO: port create-struct")) +;; +;;(defmacro defstruct +;; "Same as (def name (create-struct keys...))" +;; [name & keys] +;; `(def ~name (create-struct ~@keys))) +;; +;;(defn struct-map +;; "Returns a new structmap instance with the keys of the +;; structure-basis. keyvals may contain all, some or none of the basis +;; keys - where values are not supplied they will default to nil. +;; keyvals can also contain keys not in the basis." +;; [s & inits] +;; ;; (. clojure.lang.PersistentStructMap (create s inits)) +;; (throw "TODO: port struct-map")) +;; +;;(defn struct +;; "Returns a new structmap instance with the keys of the +;; structure-basis. vals must be supplied for basis keys in order - +;; where values are not supplied they will default to nil." +;; [s & vals] +;; ;; (. clojure.lang.PersistentStructMap (construct s vals)) +;; (throw "TODO: port struct")) +;; +;;(defn accessor +;; "Returns a fn that, given an instance of a structmap with the basis, +;; returns the value at the key. The key must be in the basis. The +;; returned function should be (slightly) more efficient than using +;; get, but such use of accessors should be limited to known +;; performance-critical areas." +;; [s key] +;; ;; (. clojure.lang.PersistentStructMap (getAccessor s key)) +;; (throw "TODO: port accessor")) +;; +;;(defn load-reader +;; "Sequentially read and evaluate the set of forms contained in the +;; stream/file" +;; [rdr] +;; ;; (. clojure.lang.Compiler (load rdr)) +;; (throw "TODO: port load-reader")) +;; +;;(defn load-string +;; "Sequentially read and evaluate the set of forms contained in the +;; string" +;; [s] +;; ;; (let [rdr (-> (java.io.StringReader. s) +;; ;; (clojure.lang.LineNumberingPushbackReader.))] +;; ;; (load-reader rdr)) +;; (throw "TODO: port load-string")) +;; +;;(defn- +;; filter-key [keyfn pred amap] +;; (loop [ret {} es (seq amap)] +;; (if es +;; (if (pred (keyfn (first es))) +;; (recur (assoc ret (key (first es)) (val (first es))) (next es)) +;; (recur ret (next es))) +;; ret))) +;; +;;(defn all-ns +;; "Returns a sequence of all namespaces." +;; [] +;; ;; (clojure.lang.Namespace/all) +;; (throw "TODO: port all-ns")) +;; +;;(defn ns-unmap +;; "Removes the mappings for the symbol from the namespace." +;; [ns sym] +;; (cpp/clojure.core_native.ns_unmap (the-ns ns) sym)) +;; +;;(defn ns-imports +;; "Returns a map of the import mappings for the namespace." +;; [ns] +;; ;; (filter-key val (partial instance? Class) (ns-map ns)) +;; (throw "TODO: port ns-imports")) +;; +;;(defn ns-interns +;; "Returns a map of the intern mappings for the namespace." +;; [ns] +;; (let [ns (the-ns ns)] +;; (filter-key val (fn [v] (and (var? v) +;; (= (ns-name ns) (-> v symbol namespace symbol)))) +;; (ns-map ns)))) +;; +;;(defn ns-refers +;; "Returns a map of the refer mappings for the namespace." +;; [ns] +;; ;; (let [ns (the-ns ns)] +;; ;; (filter-key val (fn [^clojure.lang.Var v] (and (instance? clojure.lang.Var v) +;; ;; (not= ns (.ns v)))) +;; ;; (ns-map ns))) +;; (throw "TODO: port ns-refers")) +;; +;;(defn ns-aliases +;; "Returns a map of the aliases for the namespace." +;; [ns] +;; ;; (.getAliases (the-ns ns)) +;; (throw "TODO: port ns-aliases")) +;; +;;(defn ns-unalias +;; "Removes the alias for the symbol from the namespace." +;; [ns sym] +;; (cpp/clojure.core_native.ns_unalias (the-ns ns) sym)) +;; +;;(defn var-set +;; "Sets the value in the var object to val. The var must be +;; thread-locally bound." +;; [#_clojure.lang.Var x val] +;; ;; (. x (set val)) +;; (throw "TODO: port var-set")) +;; +;;(defmacro with-local-vars +;; "varbinding=> symbol init-expr +;; +;; Executes the exprs in a context in which the symbols are bound to +;; vars with per-thread bindings to the init-exprs. The symbols refer +;; to the var objects themselves, and must be accessed with var-get and +;; var-set" +;; [name-vals-vec & body] +;; (assert-macro-args +;; (vector? name-vals-vec) "a vector for its binding" +;; (even? (count name-vals-vec)) "an even number of forms in binding vector") +;; ;; `(let [~@(interleave (take-nth 2 name-vals-vec) +;; ;; (repeat '(.. clojure.lang.Var create setDynamic)))] +;; ;; (. clojure.lang.Var (pushThreadBindings (hash-map ~@name-vals-vec))) +;; ;; (try +;; ;; (do ~@body) +;; ;; (finally (. clojure.lang.Var (popThreadBindings))))) +;; (throw "TODO: port with-local-vars")) +;; +;;(defn array-map +;; "Constructs an array-map. If any keys are equal, they are handled as +;; if by repeated uses of assoc." +;; ([] +;; ;; (. clojure.lang.PersistentArrayMap EMPTY) +;; (throw "TODO: port array-map")) +;; ([& keyvals] +;; ;; (let [ary (to-array keyvals)] +;; ;; (if (odd? (alength ary)) +;; ;; (throw (IllegalArgumentException. (str "No value supplied for key: " (last keyvals)))) +;; ;; (clojure.lang.PersistentArrayMap/createAsIfByAssoc ary))) +;; (throw "TODO: port array-map"))) +;; +;;(defn seq-to-map-for-destructuring +;; "Builds a map from a seq as described in +;; https://clojure.org/reference/special_forms#keyword-arguments" +;; [s] +;; ;; (if (next s) +;; ;; (clojure.lang.PersistentArrayMap/createAsIfByAssoc (to-array s)) +;; ;; (if (seq s) (first s) clojure.lang.PersistentArrayMap/EMPTY)) +;; (throw "TODO: port seq-to-map-for-destructuring")) +;; +;;(defmacro lazy-cat +;; "Expands to code which yields a lazy sequence of the concatenation +;; of the supplied colls. Each coll expr is not evaluated until it is +;; needed. +;; +;; (lazy-cat xs ys zs) === (concat (lazy-seq xs) (lazy-seq ys) (lazy-seq zs))" +;; [& colls] +;; `(concat ~@(map #(list `lazy-seq %) colls))) +;; +;;(defmacro with-out-str +;; "Evaluates exprs in a context in which *out* is bound to a fresh +;; StringWriter. Returns the string created by any nested printing +;; calls." +;; [& body] +;; ;; `(let [s# (new java.io.StringWriter)] +;; ;; (binding [*out* s#] +;; ;; ~@body +;; ;; (str s#))) +;; (throw "TODO: port with-out-str")) +;; +;;(defmacro with-in-str +;; "Evaluates body in a context in which *in* is bound to a fresh +;; StringReader initialized with the string s." +;; [s & body] +;; `(with-open [s# (-> (java.io.StringReader. ~s) clojure.lang.LineNumberingPushbackReader.)] +;; (binding [*in* s#] +;; ~@body))) +;; +;;(defn prn-str +;; "prn to a string, returning it" +;; [& xs] +;; ;; (with-out-str +;; ;; (apply prn xs)) +;; (throw "TODO: port prn-str")) +;; +;; +;;(defn print-str +;; "print to a string, returning it" +;; [& xs] +;; ;; (with-out-str +;; ;; (apply print xs)) +;; (throw "TODO: port print-str")) +;; +;;(defn println-str +;; "println to a string, returning it" +;; [& xs] +;; ;; (with-out-str +;; ;; (apply println xs)) +;; (throw "TODO: port println-str")) +;; +;;(defn ^:private elide-top-frames +;; [#_Throwable ex class-name] +;; ;; (let [tr (.getStackTrace ex)] +;; ;; (doto ex +;; ;; (.setStackTrace +;; ;; (when tr +;; ;; (into-array StackTraceElement +;; ;; (drop-while #(= class-name (.getClassName ^StackTraceElement %1)) tr)))))) +;; (throw "TODO: port elide-top-frames")) +;; +;;(defn test +;; "test [v] finds fn at key :test in var metadata and calls it, +;; presuming failure will throw exception" +;; [v] +;; (let [f (:test (meta v))] +;; (if f +;; (do (f) :ok) +;; :no-test))) +;; +;;(defn re-pattern +;; "Returns an instance of java.util.regex.Pattern, for use, e.g. in +;; re-matcher." +;; [s] +;; (cpp/jank.runtime.re_pattern s)) +;; +;;(defn re-matcher +;; "Returns an instance of java.util.regex.Matcher, for use, e.g. in +;; re-find." +;; [re s] +;; (cpp/jank.runtime.re_matcher re s)) +;; +;;(defn re-groups +;; "Returns the groups from the most recent match/find. If there are no +;; nested groups, returns a string of the entire match. If there are +;; nested groups, returns a vector of the groups, the first element +;; being the entire match." +;; [m] +;; (cpp/jank.runtime.re_groups m)) +;; +;;(defn re-matches +;; "Returns the match, if any, of string to pattern, using +;; java.util.regex.Matcher.matches(). Uses re-groups to return the +;; groups." +;; [re s] +;; (cpp/jank.runtime.re_matches re s)) +;; +;;(defn re-find +;; "Returns the next regex match, if any, of string to pattern, using +;; java.util.regex.Matcher.find(). Uses re-groups to return the +;; groups." +;; ([m] +;; (cpp/jank.runtime.re_find m)) +;; ([re s] +;; (let [m (re-matcher re s)] +;; (re-find m)))) +;; +;;(defn re-seq +;; "Returns a lazy sequence of successive matches of pattern in string, +;; using java.util.regex.Matcher.find(), each such match processed with +;; re-groups." +;; [re s] +;; (let [m (cpp/jank.runtime.re_matcher re s)] +;; ((fn step [] +;; (when (re-find m) +;; (cons (re-groups m) (lazy-seq (step)))))))) +;; +;;(defn rand-int +;; "Returns a random integer between 0 (inclusive) and n (exclusive)." +;; [n] (int (rand n))) +;; +;;(defn file-seq +;; "A tree seq on java.io.Files" +;; [dir] +;; ;; (tree-seq +;; ;; (fn [^java.io.File f] (. f (isDirectory))) +;; ;; (fn [^java.io.File d] (seq (. d (listFiles)))) +;; ;; dir) +;; (throw "TODO: port file-seq")) +;; +;;(defn xml-seq +;; "A tree seq on the xml elements as per xml/parse" +;; [root] +;; (tree-seq +;; (complement string?) +;; (comp seq :content) +;; root)) +;; +;;(defn special-symbol? +;; "Returns true if s names a special form" +;; [s] +;; ;; (contains? (. clojure.lang.Compiler specials) s) +;; (throw "TODO: port special-symbol?")) +;; +;;(defn max-key +;; "Returns the x for which (k x), a number, is greatest. +;; +;; If there are multiple such xs, the last one is returned." +;; ([k x] x) +;; ([k x y] (if (> (k x) (k y)) x y)) +;; ([k x y & more] +;; (let [kx (k x) ky (k y) +;; [v kv] (if (> kx ky) [x kx] [y ky])] +;; (loop [v v kv kv more more] +;; (if more +;; (let [w (first more) +;; kw (k w)] +;; (if (>= kw kv) +;; (recur w kw (next more)) +;; (recur v kv (next more)))) +;; v))))) +;; +;;(defn min-key +;; "Returns the x for which (k x), a number, is least. +;; +;; If there are multiple such xs, the last one is returned." +;; ([k x] x) +;; ([k x y] (if (< (k x) (k y)) x y)) +;; ([k x y & more] +;; (let [kx (k x) ky (k y) +;; [v kv] (if (< kx ky) [x kx] [y ky])] +;; (loop [v v kv kv more more] +;; (if more +;; (let [w (first more) +;; kw (k w)] +;; (if (<= kw kv) +;; (recur w kw (next more)) +;; (recur v kv (next more)))) +;; v))))) +;; +;;(defn replace +;; "Given a map of replacement pairs and a vector/collection, returns a +;; vector/seq with any elements = a key in smap replaced with the +;; corresponding val in smap. Returns a transducer when no collection +;; is provided." +;; ([smap] +;; (map #(if-let [e (find smap %)] (val e) %))) +;; ([smap coll] +;; (if (vector? coll) +;; (reduce (fn [v i] +;; (if-let [e (find smap (nth v i))] +;; (assoc v i (val e)) +;; v)) +;; coll (range (count coll))) +;; (map #(if-let [e (find smap %)] (val e) %) coll)))) +;; +;;(defmacro dosync +;; "Runs the exprs (in an implicit do) in a transaction that encompasses +;; exprs and any nested calls. Starts a transaction if none is already +;; running on this thread. Any uncaught exception will abort the +;; transaction and flow out of dosync. The exprs may be run more than +;; once, but any effects on Refs will be atomic." +;; [& exprs] +;; `(sync nil ~@exprs)) +;; +;;(defmacro with-precision +;; "Sets the precision and rounding mode to be used for BigDecimal operations. +;; +;; Usage: (with-precision 10 (/ 1M 3)) +;; or: (with-precision 10 :rounding HALF_DOWN (/ 1M 3)) +;; +;; The rounding mode is one of CEILING, FLOOR, HALF_UP, HALF_DOWN, +;; HALF_EVEN, UP, DOWN and UNNECESSARY; it defaults to HALF_UP." +;; [precision & exprs] +;; ;; (let [[body rm] (if (= (first exprs) :rounding) +;; ;; [(next (next exprs)) +;; ;; `((. java.math.RoundingMode ~(second exprs)))] +;; ;; [exprs nil])] +;; ;; `(binding [*math-context* (java.math.MathContext. ~precision ~@rm)] +;; ;; ~@body)) +;; (throw "TODO: port with-precision")) +;; +;;(defn- mk-bound-fn +;; [#_clojure.lang.Sorted sc test key] +;; ;; (fn [e] +;; ;; (test (.. sc comparator (compare (. sc entryKey e) key)) 0)) +;; (throw "TODO: port mk-bound-fn")) +;; +;;(defn subseq +;; "sc must be a sorted collection, test(s) one of <, <=, > or +;; >=. Returns a seq of those entries with keys ek for +;; which (test (.. sc comparator (compare ek key)) 0) is true" +;; ([#_clojure.lang.Sorted sc test key] +;; ;; (let [include (mk-bound-fn sc test key)] +;; ;; (if (#{> >=} test) +;; ;; (when-let [[e :as s] (. sc seqFrom key true)] +;; ;; (if (include e) s (next s))) +;; ;; (take-while include (. sc seq true)))) +;; (throw "TODO: port subseq")) +;; ([#_clojure.lang.Sorted sc start-test start-key end-test end-key] +;; ;; (when-let [[e :as s] (. sc seqFrom start-key true)] +;; ;; (take-while (mk-bound-fn sc end-test end-key) +;; ;; (if ((mk-bound-fn sc start-test start-key) e) s (next s)))) +;; (throw "TODO: port subseq"))) +;; +;;(defn rsubseq +;; "sc must be a sorted collection, test(s) one of <, <=, > or +;; >=. Returns a reverse seq of those entries with keys ek for +;; which (test (.. sc comparator (compare ek key)) 0) is true" +;; ([#_clojure.lang.Sorted sc test key] +;; ;; (let [include (mk-bound-fn sc test key)] +;; ;; (if (#{< <=} test) +;; ;; (when-let [[e :as s] (. sc seqFrom key false)] +;; ;; (if (include e) s (next s))) +;; ;; (take-while include (. sc seq false)))) +;; (throw "TODO: port rsubseq")) +;; ([#_clojure.lang.Sorted sc start-test start-key end-test end-key] +;; ;; (when-let [[e :as s] (. sc seqFrom end-key false)] +;; ;; (take-while (mk-bound-fn sc start-test start-key) +;; ;; (if ((mk-bound-fn sc end-test end-key) e) s (next s)))) +;; (throw "TODO: port rsubseq"))) +;; +;;(defn add-classpath +;; "DEPRECATED +;; +;; Adds the url (String or URL object) to the classpath per +;; URLClassLoader.addURL" +;; [url] +;; (println "WARNING: add-classpath is deprecated") +;; ;; (clojure.lang.RT/addURL url) +;; (throw "TODO: port add-classpath")) +;; +;;(defn mix-collection-hash +;; "Mix final collection hash for ordered or unordered collections. +;; hash-basis is the combined collection hash, count is the number +;; of elements included in the basis. Note this is the hash code +;; consistent with =, different from .hashCode. +;; See http://clojure.org/data_structures#hash for full algorithms." +;; #_long +;; [#_long hash-basis #_long count] +;; ;; (clojure.lang.Murmur3/mixCollHash hash-basis count) +;; (throw "TODO: port mix-collection-hash")) +;; +;;(defn hash-ordered-coll +;; "Returns the hash code, consistent with =, for an external ordered +;; collection implementing Iterable. +;; See http://clojure.org/data_structures#hash for full algorithms." +;; #_long +;; [coll] +;; ;; (clojure.lang.Murmur3/hashOrdered coll) +;; (throw "TODO: port hash-ordered-coll")) +;; +;;(defn hash-unordered-coll +;; "Returns the hash code, consistent with =, for an external unordered +;; collection implementing Iterable. For maps, the iterator should +;; return map entries whose hash is computed as +;; (hash-ordered-coll [k v]). +;; See http://clojure.org/data_structures#hash for full algorithms." +;; [coll] +;; (cpp/clojure.core_native.hash_unordered coll)) +;; +;;(defmacro definline +;; "Experimental - like defmacro, except defines a named function whose +;; body is the expansion, calls to which may be expanded inline as if +;; it were a macro. Cannot be used with variadic (&) args." +;; [name & decl] +;; (let [[pre-args [args expr]] (split-with (comp not vector?) decl)] +;; `(do +;; (defn ~name ~@pre-args ~args ~(apply (eval (list `fn args expr)) args)) +;; (alter-meta! (var ~name) assoc :inline (fn ~name ~args ~expr)) +;; (var ~name)))) +;; +;;(defmacro amap +;; "Maps an expression across an array a, using an index named idx, and +;; return value named ret, initialized to a clone of a, then setting +;; each element of ret to the evaluation of expr, returning the new +;; array ret." +;; [a idx ret expr] +;; `(let [a# ~a l# (alength a#) +;; ~ret (aclone a#)] +;; (loop [~idx 0] +;; (if (< ~idx l#) +;; (do +;; (aset ~ret ~idx ~expr) +;; (recur (unchecked-inc ~idx))) +;; ~ret)))) +;; +;;(defmacro areduce +;; "Reduces an expression across an array a, using an index named idx, +;; and return value named ret, initialized to init, setting ret to the +;; evaluation of expr at each step, returning ret." +;; [a idx ret init expr] +;; `(let [a# ~a l# (alength a#)] +;; (loop [~idx 0 ~ret ~init] +;; (if (< ~idx l#) +;; (recur (unchecked-inc-int ~idx) ~expr) +;; ~ret)))) +;; +;;(defn float-array +;; "Creates an array of floats" +;; ([size-or-seq] +;; ;; (. clojure.lang.Numbers float_array size-or-seq) +;; (throw "TODO: port float-array")) +;; ([size init-val-or-seq] +;; ;; (. clojure.lang.Numbers float_array size init-val-or-seq) +;; (throw "TODO: port float-array") )) +;; +;;(defn boolean-array +;; "Creates an array of booleans" +;; ([size-or-seq] +;; ;; (. clojure.lang.Numbers boolean_array size-or-seq) +;; (throw "TODO: port boolean-array")) +;; ([size init-val-or-seq] +;; ;; (. clojure.lang.Numbers boolean_array size init-val-or-seq) +;; (throw "TODO: port boolean-array"))) +;; +;;(defn byte-array +;; "Creates an array of bytes" +;; ([size-or-seq] +;; ;; (. clojure.lang.Numbers byte_array size-or-seq) +;; (throw "TODO: port byte-array")) +;; ([size init-val-or-seq] +;; ;; (. clojure.lang.Numbers byte_array size init-val-or-seq) +;; (throw "TODO: port byte-array"))) +;; +;;(defn char-array +;; "Creates an array of chars" +;; ([size-or-seq] +;; ;; (. clojure.lang.Numbers char_array size-or-seq) +;; (throw "TODO: port char-array")) +;; ([size init-val-or-seq] +;; ;; (. clojure.lang.Numbers char_array size init-val-or-seq) +;; (throw "TODO: port char-array"))) +;; +;;(defn short-array +;; "Creates an array of shorts" +;; ([size-or-seq] +;; ;; (. clojure.lang.Numbers short_array size-or-seq) +;; (throw "TODO: port short-array")) +;; ([size init-val-or-seq] +;; ;; (. clojure.lang.Numbers short_array size init-val-or-seq) +;; (throw "TODO: port short-array"))) +;; +;;(defn double-array +;; "Creates an array of doubles" +;; ([size-or-seq] +;; ;; (. clojure.lang.Numbers double_array size-or-seq) +;; (throw "TODO: port double-array")) +;; ([size init-val-or-seq] +;; ;; (. clojure.lang.Numbers double_array size init-val-or-seq) +;; (throw "TODO: port double-array"))) +;; +;;(defn object-array +;; "Creates an array of objects" +;; ([size-or-seq] +;; ;; (. clojure.lang.RT object_array size-or-seq) +;; (throw "TODO: port object-array"))) +;; +;;(defn int-array +;; "Creates an array of ints" +;; ([size-or-seq] +;; ;; (. clojure.lang.Numbers int_array size-or-seq) +;; (throw "TODO: port int-array")) +;; ([size init-val-or-seq] +;; ;; (. clojure.lang.Numbers int_array size init-val-or-seq) +;; (throw "TODO: port int-array"))) +;; +;;(defn long-array +;; "Creates an array of longs" +;; ([size-or-seq] +;; ;; (. clojure.lang.Numbers long_array size-or-seq) +;; (throw "TODO: port long-array")) +;; ([size init-val-or-seq] +;; ;; (. clojure.lang.Numbers long_array size init-val-or-seq) +;; (throw "TODO: port long-array"))) +;; +;;;; definline doesn't work without eval +;; +;;;; (definline booleans +;;;; "Casts to boolean[]" +;;;; [xs] +;;;; ;; `(. clojure.lang.Numbers booleans ~xs) +;;;; (throw "TODO: port")) +;; +;;;; (definline bytes +;;;; "Casts to bytes[]" +;;;; [xs] +;;;; ;; `(. clojure.lang.Numbers bytes ~xs) +;;;; (throw "TODO: port")) +;; +;;;; (definline chars +;;;; "Casts to chars[]" +;;;; [xs] +;;;; ;; `(. clojure.lang.Numbers chars ~xs) +;;;; (throw "TODO: port")) +;; +;;;; (definline shorts +;;;; "Casts to shorts[]" +;;;; [xs] +;;;; ;; `(. clojure.lang.Numbers shorts ~xs) +;;;; (throw "TODO: port")) +;; +;;;; (definline floats +;;;; "Casts to float[]" +;;;; [xs] +;;;; ;; `(. clojure.lang.Numbers floats ~xs) +;;;; (throw "TODO: port")) +;; +;;;; (definline ints +;;;; "Casts to int[]" +;;;; [xs] +;;;; ;; `(. clojure.lang.Numbers ints ~xs) +;;;; (throw "TODO: port")) +;; +;;;; (definline doubles +;;;; "Casts to double[]" +;;;; [xs] +;;;; ;; `(. clojure.lang.Numbers doubles ~xs) +;;;; (throw "TODO: port")) +;; +;;;; (definline longs +;;;; "Casts to long[]" +;;;; [xs] +;;;; ;; `(. clojure.lang.Numbers longs ~xs) +;;;; (throw "TODO: port")) +;; +;;(defn bytes? +;; "Return true if x is a byte array" +;; [x] +;; ;; (if (nil? x) +;; ;; false +;; ;; (-> x class .getComponentType (= Byte/TYPE))) +;; (throw "TODO: port bytes?")) +;; +;;(defn seque +;; "Creates a queued seq on another (presumably lazy) seq s. The queued +;; seq will produce a concrete seq in the background, and can get up to +;; n items ahead of the consumer. n-or-q can be an integer n buffer +;; size, or an instance of java.util.concurrent BlockingQueue. Note +;; that reading from a seque can block if the reader gets ahead of the +;; producer." +;; ([s] (seque 100 s)) +;; ([n-or-q s] +;; ;; (let [^BlockingQueue q (if (instance? BlockingQueue n-or-q) +;; ;; n-or-q +;; ;; (LinkedBlockingQueue. (int n-or-q))) +;; ;; NIL (Object.) ;nil sentinel since LBQ doesn't support nils +;; ;; agt (agent (lazy-seq s)) ; never start with nil; that signifies we've already put eos +;; ;; log-error (fn [q e] +;; ;; (if (.offer q q) +;; ;; (throw e) +;; ;; e)) +;; ;; fill (fn [s] +;; ;; (when s +;; ;; (if (instance? Exception s) ; we failed to .offer an error earlier +;; ;; (log-error q s) +;; ;; (try +;; ;; (loop [[x & xs :as s] (seq s)] +;; ;; (if s +;; ;; (if (.offer q (if (nil? x) NIL x)) +;; ;; (recur xs) +;; ;; s) +;; ;; (when-not (.offer q q) ; q itself is eos sentinel +;; ;; ()))) ; empty seq, not nil, so we know to put eos next time +;; ;; (catch Exception e +;; ;; (log-error q e)))))) +;; ;; drain (fn drain [] +;; ;; (lazy-seq +;; ;; (let [x (.take q)] +;; ;; (if (identical? x q) ;q itself is eos sentinel +;; ;; (do @agt nil) ;touch agent just to propagate errors +;; ;; (do +;; ;; (send-off agt fill) +;; ;; (release-pending-sends) +;; ;; (cons (if (identical? x NIL) nil x) (drain)))))))] +;; ;; (send-off agt fill) +;; ;; (drain)) +;; (throw "TODO: port seque"))) +;; +;;(defn class? +;; "Returns true if x is an instance of Class" +;; [x] +;; ;; (instance? Class x) +;; (throw "TODO: port class?")) +;; +;;(defn- is-annotation? [c] +;; ;; (and (class? c) +;; ;; (.isAssignableFrom java.lang.annotation.Annotation c)) +;; (throw "TODO: port is-annotation?")) +;; +;;(defn- is-runtime-annotation? [#_Class c] +;; ;; (boolean +;; ;; (and (is-annotation? c) +;; ;; (when-let [^java.lang.annotation.Retention r +;; ;; (.getAnnotation c java.lang.annotation.Retention)] +;; ;; (= (.value r) java.lang.annotation.RetentionPolicy/RUNTIME)))) +;; (throw "TODO: port is-runtime-annotation?")) +;; +;;(defn- descriptor [#_Class c] +;; ;; (clojure.asm.Type/getDescriptor c) +;; (throw "TODO: port descriptor")) +;; +;;(declare process-annotation) +;; +;;(defn- add-annotation [#_clojure.asm.AnnotationVisitor av name v] +;; ;; (cond +;; ;; (vector? v) (let [avec (.visitArray av name)] +;; ;; (doseq [vval v] +;; ;; (add-annotation avec "value" vval)) +;; ;; (.visitEnd avec)) +;; ;; (symbol? v) (let [ev (eval v)] +;; ;; (cond +;; ;; (instance? java.lang.Enum ev) +;; ;; (.visitEnum av name (descriptor (class ev)) (str ev)) +;; ;; (class? ev) (.visit av name (clojure.asm.Type/getType ev)) +;; ;; :else (throw (IllegalArgumentException. +;; ;; (str "Unsupported annotation value: " v " of class " (class ev)))))) +;; ;; (seq? v) (let [[nested nv] v +;; ;; c (resolve nested) +;; ;; nav (.visitAnnotation av name (descriptor c))] +;; ;; (process-annotation nav nv) +;; ;; (.visitEnd nav)) +;; ;; :else (.visit av name v)) +;; (throw "TODO: port add-annotation")) +;; +;;(defn- process-annotation [av v] +;; (if (map? v) +;; (doseq [[k v] v] +;; (add-annotation av (name k) v)) +;; (add-annotation av "value" v))) +;; +;;(defn- add-annotations +;; ([visitor m] (add-annotations visitor m nil)) +;; ([visitor m i] +;; ;; (doseq [[k v] m] +;; ;; (when (symbol? k) +;; ;; (when-let [c (resolve k)] +;; ;; (when (is-annotation? c) +;; ;; ;this is known duck/reflective as no common base of ASM Visitors +;; ;; (let [av (if i +;; ;; (.visitParameterAnnotation visitor i (descriptor c) +;; ;; (is-runtime-annotation? c)) +;; ;; (.visitAnnotation visitor (descriptor c) +;; ;; (is-runtime-annotation? c)))] +;; ;; (process-annotation av v) +;; ;; (.visitEnd av)))))) +;; (throw "TODO: port add-annotations"))) +;; +;;(defn bases +;; "Returns the immediate superclass and direct interfaces of c, if any" +;; [#_Class c] +;; ;; (when c +;; ;; (let [i (seq (.getInterfaces c)) +;; ;; s (.getSuperclass c)] +;; ;; (if s (cons s i) i))) +;; (throw "TODO: port bases")) +;; +;;(defn supers +;; "Returns the immediate and indirect superclasses and interfaces of c, if any" +;; [#_Class class] +;; (loop [ret (set (bases class)) cs ret] +;; (if (seq cs) +;; (let [c (first cs) bs (bases c)] +;; (recur (into ret bs) (into (disj cs c) bs))) +;; (not-empty ret)))) +;; +;; +;;(defn resultset-seq +;; "Creates and returns a lazy sequence of structmaps corresponding to +;; the rows in the java.sql.ResultSet rs" +;; [#_java.sql.ResultSet rs] +;; ;; (let [rsmeta (. rs (getMetaData)) +;; ;; idxs (range 1 (inc (. rsmeta (getColumnCount)))) +;; ;; keys (map (comp keyword #(.toLowerCase ^String %)) +;; ;; (map (fn [i] (. rsmeta (getColumnLabel i))) idxs)) +;; ;; check-keys +;; ;; (or (apply distinct? keys) +;; ;; (throw (Exception. "ResultSet must have unique column labels"))) +;; ;; row-struct (apply create-struct keys) +;; ;; row-values (fn [] (map (fn [^Integer i] (. rs (getObject i))) idxs)) +;; ;; rows (fn thisfn [] +;; ;; (when (. rs (next)) +;; ;; (cons (apply struct row-struct (row-values)) (lazy-seq (thisfn)))))] +;; ;; (rows)) +;; (throw "TODO: port resultset-seq")) +;; +;;(defn iterator-seq +;; "Returns a seq on a java.util.Iterator. Note that most collections +;; providing iterators implement Iterable and thus support seq directly. +;; Seqs cache values, thus iterator-seq should not be used on any +;; iterator that repeatedly returns the same mutable object." +;; [iter] +;; ;; (clojure.lang.RT/chunkIteratorSeq iter) +;; (throw "TODO: port iterator-seq")) +;; +;;(defn enumeration-seq +;; "Returns a seq on a java.util.Enumeration" +;; [e] +;; ;; (clojure.lang.EnumerationSeq/create e) +;; (throw "TODO: port enumeration-seq")) +;; +;;(defn format +;; "Formats a string using java.lang.String.format, see java.util.Formatter for format +;; string syntax" +;; #_String [fmt & args] +;; ;; (String/format fmt (to-array args)) +;; (throw "TODO: port format")) +;; +;;(defn printf +;; "Prints formatted output, as per format" +;; [fmt & args] +;; (print (apply format fmt args))) +;; +;;(declare gen-class) +;; +;;(defmacro with-loading-context [& body] +;; ;; `((fn loading# [] +;; ;; (. clojure.lang.Var (pushThreadBindings {clojure.lang.Compiler/LOADER +;; ;; (.getClassLoader (.getClass ^Object loading#))})) +;; ;; (try +;; ;; (do ~@body) +;; ;; (finally +;; ;; (. clojure.lang.Var (popThreadBindings)))))) +;; (throw "TODO: port with-loading-context")) +;; +;;(defonce +;; ^{:private true +;; :dynamic true +;; :doc "True while a verbose load is pending"} +;; *loading-verbosely* false) +;; +;;(defn- root-directory +;; "Returns the root resource path for a lib" +;; [lib] +;; ;; (let [d (root-resource lib)] +;; ;; (subs d 0 (.lastIndexOf d "/"))) +;; (throw "TODO: port root-resource")) +;; +;;(defn- serialized-require +;; "Like 'require', but serializes loading. +;; Interim function preferred over 'require' for known asynchronous loads. +;; Future changes may make these equivalent." +;; [& args] +;; ;; (locking clojure.lang.RT/REQUIRE_LOCK +;; ;; (apply require args)) +;; (throw "TODO: port serialized-require")) +;; +;;(defn requiring-resolve +;; "Resolves namespace-qualified sym per 'resolve'. If initial resolve +;;fails, attempts to require sym's namespace and retries." +;; [sym] +;; ;; (if (qualified-symbol? sym) +;; ;; (or (resolve sym) +;; ;; (do (-> sym namespace symbol serialized-require) +;; ;; (resolve sym))) +;; ;; (throw (IllegalArgumentException. (str "Not a qualified symbol: " sym)))) +;; (throw "TODO: port requiring-resolve")) +;; +;;(defn loaded-libs +;; "Returns a sorted set of symbols naming the currently loaded libs" +;; [] @*loaded-libs*) +;; +;;(defn sorted? +;; "Returns true if coll implements Sorted" +;; [coll] +;; (cpp/jank.runtime.is_sorted coll)) +;; +;;(defn counted? +;; "Returns true if coll implements count in constant time" +;; [coll] +;; (cpp/jank.runtime.is_counted coll)) +;; +;;(defn reversible? +;; "Returns true if coll implements Reversible" +;; [coll] +;; ;; (instance? clojure.lang.Reversible coll) +;; (throw "TODO: port reversible?")) +;; +;;(defn indexed? +;; "Return true if coll implements Indexed, indicating efficient lookup by index" +;; [coll] +;; ;; (instance? clojure.lang.Indexed coll) +;; (throw "TODO: port indexed?")) +;; +;;(def ^:dynamic +;; ^{:doc "bound in a repl thread to the most recent value printed"} +;; *1) +;; +;;(def ^:dynamic +;; ^{:doc "bound in a repl thread to the second most recent value printed"} +;; *2) +;; +;;(def ^:dynamic +;; ^{:doc "bound in a repl thread to the third most recent value printed"} +;; *3) +;; +;;(def ^:dynamic +;; ^{:doc "bound in a repl thread to the most recent exception caught by the repl"} +;; *e) +;; +;;(def ^:dynamic +;; ^{:doc "Bound to true in a repl thread"} +;; *repl* false) +;; +;;(defn trampoline +;; "trampoline can be used to convert algorithms requiring mutual +;; recursion without stack consumption. Calls f with supplied args, if +;; any. If f returns a fn, calls that fn with no arguments, and +;; continues to repeat, until the return value is not a fn, then +;; returns that non-fn value. Note that if you want to return a fn as a +;; final value, you must wrap it in some data structure and unpack it +;; after trampoline returns." +;; ([f] +;; (let [ret (f)] +;; (if (fn? ret) +;; (recur ret) +;; ret))) +;; ([f & args] +;; (trampoline #(apply f args)))) +;; +;;(defmacro while +;; "Repeatedly executes body while test expression is true. Presumes +;; some side-effect will cause test to become false/nil. Returns nil" +;; [test & body] +;; `(loop [] +;; (when ~test +;; ~@body +;; (recur)))) +;; +;;(defn memoize +;; "Returns a memoized version of a referentially transparent function. The +;; memoized version of the function keeps a cache of the mapping from arguments +;; to results and, when calls with the same arguments are repeated often, has +;; higher performance at the expense of higher memory use." +;; [f] +;; (let [mem (atom {})] +;; (fn [& args] +;; (if-let [e (find @mem args)] +;; (val e) +;; (let [ret (apply f args)] +;; (swap! mem assoc args ret) +;; ret))))) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; var documentation ;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;(defmacro add-doc-and-meta {:private true} [name docstring meta] +;; `(alter-meta! (var ~name) merge (assoc ~meta :doc ~docstring))) +;; +;;;; (add-doc-and-meta *file* +;;;; "The path of the file being evaluated, as a String. +;; +;;;; When there is no file, e.g. in the REPL, the value is not defined." +;;;; {}) +;; +;;;; (add-doc-and-meta *command-line-args* +;;;; "A sequence of the supplied command line arguments, or nil if +;;;; none were supplied" +;;;; {}) +;; +;;;; (add-doc-and-meta *warn-on-reflection* +;;;; "When set to true, the compiler will emit warnings when reflection is +;;;; needed to resolve Java method calls or field accesses. +;; +;;;; Defaults to false." +;;;; {}) +;; +;;;; (add-doc-and-meta *compile-path* +;;;; "Specifies the directory where 'compile' will write out .class +;;;; files. This directory must be in the classpath for 'compile' to +;;;; work. +;; +;;;; Defaults to \"classes\"" +;;;; {}) +;; +;;;; (add-doc-and-meta *compile-files* +;;;; "Set to true when compiling files, false otherwise." +;;;; {}) +;; +;;;; (add-doc-and-meta *unchecked-math* +;;;; "While bound to true, compilations of +, -, *, inc, dec and the +;;;; coercions will be done without overflow checks. While bound +;;;; to :warn-on-boxed, same behavior as true, and a warning is emitted +;;;; when compilation uses boxed math. Default: false." +;;;; {}) +;; +;;;; (add-doc-and-meta *compiler-options* +;;;; "A map of keys to options. +;;;; Note, when binding dynamically make sure to merge with previous value. +;;;; Supported options: +;;;; :elide-meta - a collection of metadata keys to elide during compilation. +;;;; :disable-locals-clearing - set to true to disable clearing, useful for using a debugger +;;;; :direct-linking - set to true to use direct static invocation of functions, rather than vars +;;;; Note that call sites compiled with direct linking will not be affected by var redefinition. +;;;; Use ^:redef (or ^:dynamic) on a var to prevent direct linking and allow redefinition. +;;;; See https://clojure.org/reference/compilation for more information." +;;;; {}) +;; +;;;; (add-doc-and-meta *in* +;;;; "A java.io.Reader object representing standard input for read operations. +;; +;;;; Defaults to System/in, wrapped in a LineNumberingPushbackReader" +;;;; {}) +;; +;;;; (add-doc-and-meta *err* +;;;; "A java.io.Writer object representing standard error for print operations. +;; +;;;; Defaults to System/err, wrapped in a PrintWriter" +;;;; {}) +;; +;;;; (add-doc-and-meta *flush-on-newline* +;;;; "When set to true, output will be flushed whenever a newline is printed. +;; +;;;; Defaults to true." +;;;; {}) +;; +;;;; (add-doc-and-meta *print-meta* +;;;; "If set to logical true, when printing an object, its metadata will also +;;;; be printed in a form that can be read back by the reader. +;; +;;;; Defaults to false." +;;;; {}) +;; +;;;; (add-doc-and-meta *print-dup* +;;;; "When set to logical true, objects will be printed in a way that preserves +;;;; their type when read in later. +;; +;;;; Defaults to false." +;;;; {}) +;; +;;;; (add-doc-and-meta *print-readably* +;;;; "When set to logical false, strings and characters will be printed with +;;;; non-alphanumeric characters converted to the appropriate escape sequences. +;; +;;;; Defaults to true" +;;;; {}) +;; +;;;; (add-doc-and-meta *read-eval* +;;;; "Defaults to true (or value specified by system property, see below) +;;;; ***This setting implies that the full power of the reader is in play, +;;;; including syntax that can cause code to execute. It should never be +;;;; used with untrusted sources. See also: clojure.edn/read.*** +;; +;;;; When set to logical false in the thread-local binding, +;;;; the eval reader (#=) and record/type literal syntax are disabled in read/load. +;;;; Example (will fail): (binding [*read-eval* false] (read-string \"#=(* 2 21)\")) +;; +;;;; The default binding can be controlled by the system property +;;;; 'clojure.read.eval' System properties can be set on the command line +;;;; like this: +;; +;;;; java -Dclojure.read.eval=false ... +;; +;;;; The system property can also be set to 'unknown' via +;;;; -Dclojure.read.eval=unknown, in which case the default binding +;;;; is :unknown and all reads will fail in contexts where *read-eval* +;;;; has not been explicitly bound to either true or false. This setting +;;;; can be a useful diagnostic tool to ensure that all of your reads +;;;; occur in considered contexts. You can also accomplish this in a +;;;; particular scope by binding *read-eval* to :unknown +;;;; " +;;;; {}) +;; +;;;; (add-doc-and-meta *assert* +;;;; "When set to logical false, 'assert' will omit assertion checks in +;;;; compiled code. Defaults to true." +;;;; {}) +;; +;;(defn future? +;; "Returns true if x is a future" +;; [x] +;; ;; (instance? java.util.concurrent.Future x) +;; (throw "TODO: port future?")) +;; +;;(defn future-done? +;; "Returns true if future f is done" +;; [#_java.util.concurrent.Future f] +;; ;; (.isDone f) +;; (throw "TODO: port future-done?")) +;; +;;(defmacro letfn +;; "fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+) +;; +;; Takes a vector of function specs and a body, and generates a set of +;; bindings of functions to their names. All of the names are available +;; in all of the definitions of the functions, as well as the body." +;; {:forms '[(letfn [fnspecs*] exprs*)], +;; :special-form true} +;; [fnspecs & body] +;; `(letfn* ~(vec (interleave (map first fnspecs) +;; (map #(cons `fn %) fnspecs))) +;; ~@body)) +;; +;;(defn stream-reduce! +;; "Works like reduce but takes a java.util.stream.BaseStream as its source. +;; Honors 'reduced', is a terminal operation on the stream" +;; ([f #_java.util.stream.BaseStream s] +;; ;; (clojure.core.protocols/iterator-reduce! (.iterator s) f) +;; (throw "TODO: port stream-reduce!")) +;; ([f init #_java.util.stream.BaseStream s] +;; ;; (clojure.core.protocols/iterator-reduce! (.iterator s) f init) +;; (throw "TODO: port stream-reduce!"))) +;; +;;(defn stream-seq! +;; "Takes a java.util.stream.BaseStream instance s and returns a seq of its +;; contents. This is a terminal operation on the stream." +;; [#_java.util.stream.BaseStream stream] +;; ;; (iterator-seq (.iterator stream)) +;; (throw "TODO: port stream-seq!")) +;; +;;(defn stream-transduce! +;; "Works like transduce but takes a java.util.stream.BaseStream as its source. +;; This is a terminal operation on the stream." +;; ([xform f #_java.util.stream.BaseStream stream] +;; (stream-transduce! xform f (f) stream)) +;; ([xform f init #_java.util.stream.BaseStream stream] +;; (let [f (xform f) +;; ret (stream-reduce! f init stream)] +;; (f ret)))) +;; +;;(defn stream-into! +;; "Returns a new coll consisting of coll with all of the items of the +;; stream conjoined. This is a terminal operation on the stream." +;; ([to #_java.util.stream.BaseStream stream] +;; ;; (if (instance? clojure.lang.IEditableCollection to) +;; ;; (with-meta (persistent! (stream-reduce! conj! (transient to) stream)) (meta to)) +;; ;; (stream-reduce! conj to stream)) +;; (throw "TODO: port stream-into!")) +;; ([to xform #_java.util.stream.BaseStream stream] +;; ;; (if (instance? clojure.lang.IEditableCollection to) +;; ;; (with-meta (persistent! (stream-transduce! xform conj! (transient to) stream)) (meta to)) +;; ;; (stream-transduce! xform conj to stream)) +;; (throw "TODO: port stream-into!"))) +;; +;; +;;(defmacro ^:private when-class [class-name & body] +;; ;; `(try +;; ;; (Class/forName ^String ~class-name) +;; ;; ~@body +;; ;; (catch ClassNotFoundException _#)) +;; (throw "TODO: port when-class")) +;; +;;;; (defprotocol Inst +;;;; (inst-ms* [inst])) +;; +;;;; (extend-protocol Inst +;;;; java.util.Date +;;;; (inst-ms* [inst] (.getTime ^java.util.Date inst))) +;; +;;(defn inst-ms +;; "Return the number of milliseconds since January 1, 1970, 00:00:00 GMT" +;; [inst] +;; (cpp/jank.runtime.inst_ms inst)) +;; +;;(defn inst? +;; "Return true if x satisfies Inst" +;; [x] +;; (cpp/jank.runtime.is_inst x)) +;; +;;;; (extend-protocol clojure.core/Inst +;;;; java.time.Instant +;;;; (inst-ms* [inst] (.toEpochMilli ^java.time.Instant inst))) +;; +;;(defn uuid? +;; "Return true if x is a java.util.UUID" +;; [x] +;; (cpp/jank.runtime.is_uuid x)) +;; +;;(defn random-uuid +;; "Returns a pseudo-randomly generated java.util.UUID instance (i.e. type 4). +;; +;; See: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID--" +;; [] +;; (cpp/jank.runtime.random_uuid)) +;; +;;;; (extend-protocol clojure.core.protocols/IKVReduce +;;;; nil +;;;; (kv-reduce +;;;; [_ f init] +;;;; init) +;; +;;;; ;;slow path default +;;;; java.lang.Object +;;;; (kv-reduce +;;;; [amap f init] +;;;; (reduce (fn [ret ^java.util.Map$Entry me] +;;;; (f ret +;;;; (.getKey me) +;;;; (.getValue me))) +;;;; init +;;;; amap)) +;; +;;;; clojure.lang.IKVReduce +;;;; (kv-reduce +;;;; [amap f init] +;;;; (.kvreduce amap f init))) +;; +;;(defn reduce-kv +;; "Reduces an associative collection. f should be a function of 3 +;; arguments. Returns the result of applying f to init, the first key +;; and the first value in coll, then applying f to that result and the +;; 2nd key and value, etc. If coll contains no entries, returns init +;; and f is not called. Note that reduce-kv is supported on vectors, +;; where the keys will be the ordinals." +;; ([f init coll] +;; ;; (clojure.core.protocols/kv-reduce coll f init) +;; (reduce (fn [s [k v]] (f s k v)) init coll))) +;; +;;(defn- normalize-slurp-opts +;; [opts] +;; (if (string? (first opts)) +;; (do +;; (println "WARNING: (slurp f enc) is deprecated, use (slurp f :encoding enc).") +;; [:encoding (first opts)]) +;; opts)) +;; +;;(defn slurp +;; "Opens a reader on f and reads all its contents, returning a string. +;; See clojure.java.io/reader for a complete list of supported arguments." +;; ([f & opts] +;; (let [opts (normalize-slurp-opts opts) +;; fname (cpp/cast (cpp/type "char const*") f) +;; file (cpp/std.ifstream. fname)] +;; (if-not (cpp/.is_open file) +;; (throw (str f " (No such file or directory)")) +;; (let [size (cpp/std.filesystem.file_size fname) +;; out (cpp/std.string. size (cpp/char 0))] +;; (cpp/.read file (cpp/& (cpp/.front out)) size) +;; out))))) +;; +;;(defn spit +;; "Opposite of slurp. Opens f with writer, writes content, then +;; closes f. Options passed to clojure.java.io/writer." +;; [f content & options] +;; (let [file (cpp/std.ofstream.)] +;; (cpp/.open file (cpp/cast (cpp/type "char const*") f)) +;; (cpp/<< file (cpp/cast (cpp/type "char const*") content)) +;; (cpp/.close file) +;; nil)) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; futures (needs proxy);;;;;;;;;;;;;;;;;; +;;(defn future-call +;; "Takes a function of no args and yields a future object that will +;; invoke the function in another thread, and will cache the result and +;; return it on all subsequent calls to deref/@. If the computation has +;; not yet finished, calls to deref/@ will block, unless the variant +;; of deref with timeout is used. See also - realized?." +;; [f] +;; ;; (let [f (binding-conveyor-fn f) +;; ;; fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)] +;; ;; (reify +;; ;; clojure.lang.IDeref +;; ;; (deref [_] (deref-future fut)) +;; ;; clojure.lang.IBlockingDeref +;; ;; (deref +;; ;; [_ timeout-ms timeout-val] +;; ;; (deref-future fut timeout-ms timeout-val)) +;; ;; clojure.lang.IPending +;; ;; (isRealized [_] (.isDone fut)) +;; ;; java.util.concurrent.Future +;; ;; (get [_] (.get fut)) +;; ;; (get [_ timeout unit] (.get fut timeout unit)) +;; ;; (isCancelled [_] (.isCancelled fut)) +;; ;; (isDone [_] (.isDone fut)) +;; ;; (cancel [_ interrupt?] (.cancel fut interrupt?)))) +;; (throw "TODO: port future-call")) +;; +;;(defmacro future +;; "Takes a body of expressions and yields a future object that will +;; invoke the body in another thread, and will cache the result and +;; return it on all subsequent calls to deref/@. If the computation has +;; not yet finished, calls to deref/@ will block, unless the variant of +;; deref with timeout is used. See also - realized?." +;; [& body] +;; ;; `(future-call (^{:once true} fn* [] ~@body)) +;; (throw "TODO: port future")) +;; +;;(defn future-cancel +;; "Cancels the future, if possible." +;; [#_java.util.concurrent.Future f] +;; ;; (.cancel f true) +;; (throw "TODO: port future-cancel")) +;; +;;(defn future-cancelled? +;; "Returns true if future f is cancelled" +;; [#_java.util.concurrent.Future f] +;; ;; (.isCancelled f) +;; (throw "TODO: port future-cancelled?")) +;; +;;(defn pmap +;; "Like map, except f is applied in parallel. Semi-lazy in that the +;; parallel computation stays ahead of the consumption, but doesn't +;; realize the entire result unless required. Only useful for +;; computationally intensive functions where the time of f dominates +;; the coordination overhead." +;; ([f coll] +;; ;; (let [n (+ 2 (.. Runtime getRuntime availableProcessors)) +;; ;; rets (map #(future (f %)) coll) +;; ;; step (fn step [[x & xs :as vs] fs] +;; ;; (lazy-seq +;; ;; (if-let [s (seq fs)] +;; ;; (cons (deref x) (step xs (rest s))) +;; ;; (map deref vs))))] +;; ;; (step rets (drop n rets))) +;; (throw "TODO: port pmap")) +;; ([f coll & colls] +;; ;; (let [step (fn step [cs] +;; ;; (lazy-seq +;; ;; (let [ss (map seq cs)] +;; ;; (when (every? identity ss) +;; ;; (cons (map first ss) (step (map rest ss)))))))] +;; ;; (pmap #(apply f %) (step (cons coll colls)))) +;; (throw "TODO: port pmap"))) +;; +;; +;;(defn pcalls +;; "Executes the no-arg fns in parallel, returning a lazy sequence of +;; their values" +;; [& fns] (pmap #(%) fns)) +;; +;;(defmacro pvalues +;; "Returns a lazy sequence of the values of the exprs, which are +;; evaluated in parallel" +;; [& exprs] +;; `(pcalls ~@(map #(list `fn [] %) exprs))) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; clojure version number ;;;;;;;;;;;;;;;;;;;;;; +;; +;;;; (let [^java.util.Properties +;;;; properties (with-open [version-stream (.getResourceAsStream +;;;; (clojure.lang.RT/baseLoader) +;;;; "clojure/version.properties")] +;;;; (doto (new java.util.Properties) +;;;; (.load version-stream))) +;;;; version-string (.getProperty properties "version") +;;;; [_ major minor incremental qualifier snapshot] +;;;; (re-matches +;;;; #"(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9_]+))?(?:-(SNAPSHOT))?" +;;;; version-string) +;;;; clojure-version {:major (Integer/valueOf ^String major) +;;;; :minor (Integer/valueOf ^String minor) +;;;; :incremental (Integer/valueOf ^String incremental) +;;;; :qualifier (if (= qualifier "SNAPSHOT") nil qualifier)}] +;;;; (def ^:dynamic *clojure-version* +;;;; (if (.contains version-string "SNAPSHOT") +;;;; (clojure.lang.RT/assoc clojure-version :interim true) +;;;; clojure-version))) +;; +;;;; (add-doc-and-meta *clojure-version* +;;;; "The version info for Clojure core, as a map containing :major :minor +;;;; :incremental and :qualifier keys. Feature releases may increment +;;;; :minor and/or :major, bugfix releases will increment :incremental. +;;;; Possible values of :qualifier include \"GA\", \"SNAPSHOT\", \"RC-x\" \"BETA-x\"" +;;;; {:added "1.0"}) +;; +;;(defn clojure-version +;; "Returns clojure version as a printable string." +;; [] +;; (cpp/clojure.core_native.jank_version)) +;; +;;(defn promise +;; "Returns a promise object that can be read with deref/@, and set, +;; once only, with deliver. Calls to deref/@ prior to delivery will +;; block, unless the variant of deref with timeout is used. All +;; subsequent derefs will return the same delivered value without +;; blocking. See also - realized?." +;; [] +;; ;; (let [d (java.util.concurrent.CountDownLatch. 1) +;; ;; v (atom d)] +;; ;; (reify +;; ;; clojure.lang.IDeref +;; ;; (deref [_] (.await d) @v) +;; ;; clojure.lang.IBlockingDeref +;; ;; (deref +;; ;; [_ timeout-ms timeout-val] +;; ;; (if (.await d timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS) +;; ;; @v +;; ;; timeout-val)) +;; ;; clojure.lang.IPending +;; ;; (isRealized [this] +;; ;; (zero? (.getCount d))) +;; ;; clojure.lang.IFn +;; ;; (invoke +;; ;; [this x] +;; ;; (when (and (pos? (.getCount d)) +;; ;; (compare-and-set! v d x)) +;; ;; (.countDown d) +;; ;; this)))) +;; (throw "TODO: port promise")) +;; +;;(defn deliver +;; "Delivers the supplied value to the promise, releasing any pending +;; derefs. A subsequent call to deliver on a promise will have no effect." +;; [promise val] (promise val)) +;; +;;(defn rand-nth +;; "Return a random element of the (sequential) collection. Will have +;; the same performance characteristics as nth for the given +;; collection." +;; [coll] +;; (nth coll (rand-int (count coll)))) +;; +;;(defn splitv-at +;; "Returns a vector of [(into [] (take n) coll) (drop n coll)]" +;; [n coll] +;; [(into [] (take n) coll) (drop n coll)]) +;; +;;(defn partitionv +;; "Returns a lazy sequence of vectors of n items each, at offsets step +;; apart. If step is not supplied, defaults to n, i.e. the partitions +;; do not overlap. If a pad collection is supplied, use its elements as +;; necessary to complete last partition upto n items. In case there are +;; not enough padding elements, return a partition with less than n items." +;; ([n coll] +;; (partitionv n n coll)) +;; ([n step coll] +;; (lazy-seq +;; (when-let [s (seq coll)] +;; (let [p (into [] (take n) s)] +;; (when (= n (count p)) +;; (cons p (partitionv n step (nthrest s step)))))))) +;; ([n step pad coll] +;; (lazy-seq +;; (when-let [s (seq coll)] +;; (let [p (into [] (take n) s)] +;; (if (= n (count p)) +;; (cons p (partitionv n step pad (nthrest s step))) +;; (list (into [] (take n) (concat p pad))))))))) +;; +;;(defn partitionv-all +;; "Returns a lazy sequence of vector partitions, but may include +;; partitions with fewer than n items at the end. +;; Returns a stateful transducer when no collection is provided." +;; ([n] +;; (partition-all n)) +;; ([n coll] +;; (partitionv-all n n coll)) +;; ([n step coll] +;; (lazy-seq +;; (when-let [s (seq coll)] +;; (let [seg (into [] (take n) coll)] +;; (cons seg (partitionv-all n step (drop step s)))))))) +;; +;;(defn shuffle +;; "Return a random permutation of coll" +;; [coll] +;; (cpp/jank.runtime.shuffle coll)) +;; +;;(defn bounded-count +;; "If coll is counted? returns its count, else will count at most the first n +;; elements of coll using its seq" +;; [n coll] +;; (if (counted? coll) +;; (count coll) +;; (loop [i 0 s (seq coll)] +;; (if (and s (< i n)) +;; (recur (inc i) (next s)) +;; i)))) +;; +;;(defn bounded-count +;; "If coll is counted? returns its count, else will count at most the first n +;; elements of coll using its seq" +;; [n coll] +;; (if (counted? coll) +;; (count coll) +;; (loop [i 0 s (seq coll)] +;; (if (and s (< i n)) +;; (recur (inc i) (next s)) +;; i)))) +;; +;;(defn- ^{:dynamic true} assert-valid-fdecl +;; "A good fdecl looks like (([a] ...) ([a b] ...)) near the end of defn." +;; [fdecl] +;; (when (empty? fdecl) (throw "Parameter declaration missing")) +;; (let [argdecls (map +;; #(if (seq? %) +;; (first %) +;; (throw (if (seq? (first fdecl)) +;; (str "Invalid signature \"" +;; % +;; "\" should be a list") +;; (str "Parameter declaration \"" +;; % +;; "\" should be a vector")))) +;; fdecl) +;; bad-args (seq (remove #(vector? %) argdecls))] +;; (when bad-args +;; (throw (str "Parameter declaration \"" (first bad-args) +;; "\" should be a vector"))))) +;; +;;(defn realized? +;; "Returns true if a value has been produced for a promise, delay, future or lazy sequence." +;; [#_clojure.lang.IPending x] +;; ;; (.isRealized x) +;; (throw "TODO: port realized?")) +;; +;;(defn random-sample +;; "Returns items from coll with random probability of prob (0.0 - +;; 1.0). Returns a transducer when no collection is provided." +;; ([prob] +;; (filter (fn [_] (< (rand) prob)))) +;; ([prob coll] +;; (filter (fn [_] (< (rand) prob)) coll))) +;; +;;;; (deftype Eduction [xform coll] +;;;; Iterable +;;;; (iterator [_] +;;;; (clojure.lang.TransformerIterator/create xform (clojure.lang.RT/iter coll))) +;; +;;;; clojure.lang.IReduceInit +;;;; (reduce [_ f init] +;;;; ;; NB (completing f) isolates completion of inner rf from outer rf +;;;; (transduce xform (completing f) init coll)) +;; +;;;; clojure.lang.Sequential) +;; +;;;; (defn eduction +;;;; "Returns a reducible/iterable application of the transducers +;;;; to the items in coll. Transducers are applied in order as if +;;;; combined with comp. Note that these applications will be +;;;; performed every time reduce/iterator is called." +;;;; [& xforms] +;;;; (Eduction. (apply comp (butlast xforms)) (last xforms))) +;; +;;;; (defmethod print-method Eduction [c, ^Writer w] +;;;; (if *print-readably* +;;;; (do +;;;; (print-sequential "(" pr-on " " ")" c w)) +;;;; (print-object c w))) +;; +;;(defn iteration +;; "Creates a seqable/reducible via repeated calls to step, +;; a function of some (continuation token) 'k'. The first call to step +;; will be passed initk, returning 'ret'. Iff (somef ret) is true, +;; (vf ret) will be included in the iteration, else iteration will +;; terminate and vf/kf will not be called. If (kf ret) is non-nil it +;; will be passed to the next step call, else iteration will terminate. +;; +;; This can be used e.g. to consume APIs that return paginated or batched data. +;; +;; step - (possibly impure) fn of 'k' -> 'ret' +;; +;; :somef - fn of 'ret' -> logical true/false, default 'some?' +;; :vf - fn of 'ret' -> 'v', a value produced by the iteration, default 'identity' +;; :kf - fn of 'ret' -> 'next-k' or nil (signaling 'do not continue'), default 'identity' +;; :initk - the first value passed to step, default 'nil' +;; +;; It is presumed that step with non-initk is unreproducible/non-idempotent. +;; If step with initk is unreproducible it is on the consumer to not consume twice." +;; [step & {:keys [somef vf kf initk] +;; :or {vf identity +;; kf identity +;; somef some? +;; initk nil}}] +;; ;; (reify +;; ;; clojure.lang.Seqable +;; ;; (seq [_] +;; ;; ((fn next [ret] +;; ;; (when (somef ret) +;; ;; (cons (vf ret) +;; ;; (when-some [k (kf ret)] +;; ;; (lazy-seq (next (step k))))))) +;; ;; (step initk))) +;; ;; clojure.lang.IReduceInit +;; ;; (reduce [_ rf init] +;; ;; (loop [acc init +;; ;; ret (step initk)] +;; ;; (if (somef ret) +;; ;; (let [acc (rf acc (vf ret))] +;; ;; (if (reduced? acc) +;; ;; @acc +;; ;; (if-some [k (kf ret)] +;; ;; (recur acc (step k)) +;; ;; acc))) +;; ;; acc)))) +;; (throw "TODO: port iteration")) +;; +;;(defn tagged-literal? +;; "Return true if the value is the data representation of a tagged literal" +;; [value] +;; (cpp/jank.runtime.is_tagged_literal value)) +;; +;;(defn tagged-literal +;; "Construct a data representation of a tagged literal from a +;; tag symbol and a form." +;; [tag form] +;; (cpp/jank.runtime.tagged_literal tag form)) +;; +;;(defn reader-conditional? +;; "Return true if the value is the data representation of a reader conditional" +;; [value] +;; ;; (instance? clojure.lang.ReaderConditional value) +;; (throw "TODO: port reader-conditional?")) +;; +;;(defn reader-conditional +;; "Construct a data representation of a reader conditional. +;; If true, splicing? indicates read-cond-splicing." +;; [form #_Boolean splicing?] +;; ;; (clojure.lang.ReaderConditional/create form splicing?) +;; (throw "TODO: port reader-conditional")) +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; data readers ;;;;;;;;;;;;;;;;;; +;; +;;(def default-data-readers +;; "Default map of data reader functions provided by Clojure. May be +;; overridden by binding *data-readers*." +;; (merge +;; ;; {'uuid #'clojure.uuid/default-uuid-reader} +;; ;; (when-class "java.sql.Timestamp" +;; ;; {'inst #'clojure.instant/read-instant-date}) +;; )) +;; +;;(def ^:dynamic *data-readers* +;; "Map from reader tag symbols to data reader Vars. +;; +;; When Clojure starts, it searches for files named 'data_readers.clj' +;; and 'data_readers.cljc' at the root of the classpath. Each such file +;; must contain a literal map of symbols, like this: +;; +;; {foo/bar my.project.foo/bar +;; foo/baz my.project/baz} +;; +;; The first symbol in each pair is a tag that will be recognized by +;; the Clojure reader. The second symbol in the pair is the +;; fully-qualified name of a Var which will be invoked by the reader to +;; parse the form following the tag. For example, given the +;; data_readers.clj file above, the Clojure reader would parse this +;; form: +;; +;; #foo/bar [1 2 3] +;; +;; by invoking the Var #'my.project.foo/bar on the vector [1 2 3]. The +;; data reader function is invoked on the form AFTER it has been read +;; as a normal Clojure data structure by the reader. +;; +;; Reader tags without namespace qualifiers are reserved for +;; Clojure. Default reader tags are defined in +;; clojure.core/default-data-readers but may be overridden in +;; data_readers.clj, data_readers.cljc, or by rebinding this Var." +;; {}) +;; +;;(def ^:dynamic *default-data-reader-fn* +;; "When no data reader is found for a tag and *default-data-reader-fn* +;; is non-nil, it will be called with two arguments, +;; the tag and the value. If *default-data-reader-fn* is nil (the +;; default), an exception will be thrown for the unknown tag." +;; nil) +;; +;;(defn- data-reader-urls [] +;; ;; (let [cl (.. Thread currentThread getContextClassLoader)] +;; ;; (concat +;; ;; (enumeration-seq (.getResources cl "data_readers.clj")) +;; ;; (enumeration-seq (.getResources cl "data_readers.cljc")))) +;; (throw "TODO: port data-reader-urls")) +;; +;;(defn- data-reader-var [sym] +;; (intern (create-ns (symbol (namespace sym))) +;; (symbol (name sym)))) +;; +;;(defn- load-data-reader-file [mappings #_java.net.URL url] +;; ;; (with-open [rdr (clojure.lang.LineNumberingPushbackReader. +;; ;; (java.io.InputStreamReader. +;; ;; (.openStream url) "UTF-8"))] +;; ;; (binding [*file* (.getFile url)] +;; ;; (let [read-opts (if (.endsWith (.getPath url) "cljc") +;; ;; {:eof nil :read-cond :allow} +;; ;; {:eof nil}) +;; ;; new-mappings (read read-opts rdr)] +;; ;; (when (not (map? new-mappings)) +;; ;; (throw (ex-info (str "Not a valid data-reader map") +;; ;; {:url url}))) +;; ;; (reduce +;; ;; (fn [m [k v]] +;; ;; (when (not (symbol? k)) +;; ;; (throw (ex-info (str "Invalid form in data-reader file") +;; ;; {:url url +;; ;; :form k}))) +;; ;; (let [v-var (data-reader-var v)] +;; ;; (when (and (contains? mappings k) +;; ;; (not= (mappings k) v-var)) +;; ;; (throw (ex-info "Conflicting data-reader mapping" +;; ;; {:url url +;; ;; :conflict k +;; ;; :mappings m}))) +;; ;; (assoc m k v-var))) +;; ;; mappings +;; ;; new-mappings)))) +;; (throw "TODO: port load-data-reader-file")) +;; +;;(defn- load-data-readers [] +;; ;; (alter-var-root #'*data-readers* +;; ;; (fn [mappings] +;; ;; (reduce load-data-reader-file +;; ;; mappings (data-reader-urls)))) +;; (throw "TODO: port load-data-readers")) +;; +;;;; (try +;;;; (load-data-readers) +;;;; (catch #_Throwable t +;;;; (.printStackTrace t) +;;;; (throw t))) +;; +;;(defonce ^:private tapset (atom #{})) +;; +;;;; (defonce ^:private ^java.util.concurrent.ArrayBlockingQueue tapq (java.util.concurrent.ArrayBlockingQueue. 1024)) +;; +;;(defonce ^:private tap-loop +;; ;; (delay +;; ;; (doto (Thread. +;; ;; #(let [t (.take tapq) +;; ;; x (if (identical? ::tap-nil t) nil t) +;; ;; taps @tapset] +;; ;; (doseq [tap taps] +;; ;; (try +;; ;; (tap x) +;; ;; (catch Throwable ex))) +;; ;; (recur)) +;; ;; "clojure.core/tap-loop") +;; ;; (.setDaemon true) +;; ;; (.start))) +;; nil) +;; +;;(defn add-tap +;; "adds f, a fn of one argument, to the tap set. This function will be called with anything sent via tap>. +;; This function may (briefly) block (e.g. for streams), and will never impede calls to tap>, +;; but blocking indefinitely may cause tap values to be dropped. +;; Remember f in order to remove-tap" +;; [f] +;; (force tap-loop) +;; (swap! tapset conj f) +;; nil) +;; +;;(defn remove-tap +;; "Remove f from the tap set." +;; [f] +;; (swap! tapset disj f) +;; nil) +;; +;;(defn tap> +;; "sends x to any taps. Will not block. Returns true if there was room in the queue, +;; false if not (dropped)." +;; [x] +;; (force tap-loop) +;; ;; (.offer tapq (if (nil? x) ::tap-nil x)) +;; (throw "TODO: port tap>")) +;; +;;(defn update-vals +;; "m f => {k (f v) ...} +;; +;; Given a map m and a function f of 1-argument, returns a new map where the keys of m +;; are mapped to result of applying f to the corresponding values of m." +;; [m f] +;; (with-meta +;; (persistent! +;; (reduce-kv (fn [acc k v] (assoc! acc k (f v))) +;; (if (transientable? m) +;; (transient m) +;; (transient {})) +;; m)) +;; (meta m))) +;; +;;(defn update-keys +;; "m f => {(f k) v ...} +;; +;; Given a map m and a function f of 1-argument, returns a new map whose +;; keys are the result of applying f to the keys of m, mapped to the +;; corresponding values of m. +;; f must return a unique key for each key of m, else the behavior is undefined." +;; [m f] +;; (let [ret (persistent! +;; (reduce-kv (fn [acc k v] (assoc! acc (f k) v)) +;; (transient {}) +;; m))] +;; (with-meta ret (meta m)))) +;; +;;(defn- parsing-err +;; "Construct message for parsing for non-string parsing error" +;; [val] +;; (str "Expected string, got " (if (nil? val) "nil" (type val)))) +;; +;;(defn parse-long +;; "Parse string of decimal digits with optional leading -/+ and return a +;; Long value, or nil if parse fails" +;; [s] +;; (cpp/jank.runtime.parse_long s)) +;; +;;(defn parse-double +;; "Parse string with floating point components and return a Double value, +;; or nil if parse fails. +;; +;; Grammar: https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#valueOf-java.lang.String-" +;; [s] +;; (cpp/jank.runtime.parse_double s)) +;; +;;(defn parse-uuid +;; "Parse a string representing a UUID and return a java.util.UUID instance, +;; or nil if parse fails. +;; +;; Grammar: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#toString--" +;; [s] +;; (cpp/jank.runtime.parse_uuid s)) +;; +;;(defn parse-boolean +;; "Parse strings \"true\" or \"false\" and return a boolean, or nil if invalid" +;; [s] +;; (if (string? s) +;; (case s +;; "true" true +;; "false" false +;; nil) +;; (throw (parsing-err s)))) +;; +;;(defn NaN? +;; "Returns true if num is NaN, else false" +;; [num] +;; (cpp/jank.runtime.is_nan num)) +;; +;;(defn infinite? +;; "Returns true if num is negative or positive infinity, else false" +;; [num] +;; (cpp/jank.runtime.is_infinite num)) From 88ddfa2cbe8c0073fc00c4d62e3f0671448d911d Mon Sep 17 00:00:00 2001 From: jeaye Date: Sun, 7 Dec 2025 10:31:15 -0800 Subject: [PATCH 068/122] Fix cppgen for tail position defs --- .../src/cpp/jank/codegen/processor.cpp | 23 +++++++++++++++---- .../src/cpp/jank/jit/processor.cpp | 2 +- .../src/cpp/jank/runtime/module/loader.cpp | 5 ++-- .../src/cpp/jank/runtime/object.cpp | 8 +++---- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 9142cb8ec..8b9e9ebb1 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -558,11 +558,26 @@ namespace jank::codegen { auto const dynamic{ truthy( get(expr->name->meta.unwrap(), __rt_ctx->intern_keyword("dynamic").expect_ok())) }; - return util::format("{}->with_meta({})->set_dynamic({})", var_tmp, meta.unwrap(), dynamic); + + auto v{ + util::format("{}->with_meta({})->set_dynamic({})", var_tmp, meta.unwrap(), dynamic) + }; + if(expr->position == expression_position::tail) + { + util::format_to(body_buffer, "return {};", v); + return none; + } + return v; } else { - return util::format("{}->with_meta(jank::runtime::jank_nil)", var_tmp); + auto v{ util::format("{}->with_meta(jank::runtime::jank_nil)", var_tmp) }; + if(expr->position == expression_position::tail) + { + util::format_to(body_buffer, "return {};", v); + return none; + } + return v; } } @@ -2693,7 +2708,7 @@ namespace jank::codegen if(target == compilation_target::module) { util::format_to(footer_buffer, - "void* {}(){", + "void {}(){", runtime::module::module_to_load_function(module)); auto const ns{ runtime::module::module_to_native_ns(module) }; @@ -2748,7 +2763,7 @@ namespace jank::codegen util::format_to(footer_buffer, ";"); } - util::format_to(footer_buffer, "return {}::{}{ }.call().erase();", ns, struct_name); + util::format_to(footer_buffer, "{}::{}{ }.call();", ns, struct_name); util::format_to(footer_buffer, "}"); } diff --git a/compiler+runtime/src/cpp/jank/jit/processor.cpp b/compiler+runtime/src/cpp/jank/jit/processor.cpp index 82443ad8e..4a8449eb6 100644 --- a/compiler+runtime/src/cpp/jank/jit/processor.cpp +++ b/compiler+runtime/src/cpp/jank/jit/processor.cpp @@ -240,7 +240,7 @@ namespace jank::jit profile::timer const timer{ "jit eval_string" }; auto const &formatted{ s }; //auto const &formatted{ util::format_cpp_source(s).expect_ok() }; - //util::println("// eval_string:\n{}\n", formatted); + util::println("// eval_string:\n{}\n", formatted); auto err(interpreter->ParseAndExecute({ formatted.data(), formatted.size() }, ret)); if(err) { diff --git a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp index 178c6fe4f..1abdcd973 100644 --- a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp @@ -979,7 +979,8 @@ namespace jank::runtime::module auto const existing_load{ __rt_ctx->jit_prc.find_symbol(load_function_name) }; if(existing_load.is_ok()) { - reinterpret_cast(existing_load.expect_ok())(); + /* TODO: Update LLVM IR for this. */ + reinterpret_cast(existing_load.expect_ok())(); return ok(); } @@ -1003,7 +1004,7 @@ namespace jank::runtime::module else { __rt_ctx->jit_prc.eval_string( - util::format("void* {}(); {}();", load_function_name, load_function_name)); + util::format("void {}(); {}();", load_function_name, load_function_name)); } return ok(); diff --git a/compiler+runtime/src/cpp/jank/runtime/object.cpp b/compiler+runtime/src/cpp/jank/runtime/object.cpp index e2596e24a..1872c641d 100644 --- a/compiler+runtime/src/cpp/jank/runtime/object.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/object.cpp @@ -10,19 +10,19 @@ namespace jank::runtime { ++ref_count; jank_debug_assert(ref_count > 0); - //util::println("retain {} type {} count {}", this, object_type_str(type), ref_count); + util::println("retain {} type {} count {}", this, object_type_str(type), ref_count); } void object::release() { jank_debug_assert(ref_count > 0); --ref_count; - //util::println("release {} type {} count {}", this, object_type_str(type), ref_count); + util::println("release {} type {} count {}", this, object_type_str(type), ref_count); if(ref_count == 0) { visit_object( - [](auto typed_this) { - using T = typename jtl::decay_t::value_type; + [](auto const typed_this) { + using T = typename decltype(typed_this)::value_type; delete static_cast(typed_this.data); }, From 41a17b5ac2f62ed6a711872f9e720ed20f1d4edc Mon Sep 17 00:00:00 2001 From: jeaye Date: Sun, 7 Dec 2025 10:59:04 -0800 Subject: [PATCH 069/122] Remove nil global and thus constexpr --- .../cpp/jank/runtime/convert/builtin.hpp | 88 ++++---- .../cpp/jank/runtime/core/make_box.hpp | 2 +- .../include/cpp/jank/runtime/obj/nil.hpp | 9 +- .../include/cpp/jank/runtime/oref.hpp | 194 +++++++++--------- .../cpp/jank/runtime/sequence_range.hpp | 4 +- .../include/cpp/jank/runtime/visit.hpp | 24 +-- .../include/cpp/jank/runtime/weak_oref.hpp | 174 ++++++++-------- .../src/cpp/clojure/core_native.cpp | 20 +- .../src/cpp/jank/analyze/processor.cpp | 16 +- compiler+runtime/src/cpp/jank/c_api.cpp | 2 +- .../src/cpp/jank/codegen/llvm_processor.cpp | 22 +- .../src/cpp/jank/codegen/processor.cpp | 30 +-- .../src/cpp/jank/compiler_native.cpp | 4 +- compiler+runtime/src/cpp/jank/evaluate.cpp | 10 +- compiler+runtime/src/cpp/jank/perf_native.cpp | 2 +- compiler+runtime/src/cpp/jank/read/parse.cpp | 4 +- .../cpp/jank/runtime/behavior/callable.cpp | 20 +- .../cpp/jank/runtime/behavior/metadatable.cpp | 2 +- .../src/cpp/jank/runtime/context.cpp | 8 +- .../src/cpp/jank/runtime/core.cpp | 20 +- .../src/cpp/jank/runtime/core/equal.cpp | 4 +- .../src/cpp/jank/runtime/core/meta.cpp | 12 +- .../src/cpp/jank/runtime/core/seq.cpp | 26 +-- .../src/cpp/jank/runtime/obj/chunked_cons.cpp | 4 +- .../src/cpp/jank/runtime/obj/iterator.cpp | 2 +- .../src/cpp/jank/runtime/obj/jit_closure.cpp | 2 +- .../src/cpp/jank/runtime/obj/jit_function.cpp | 2 +- .../cpp/jank/runtime/obj/lazy_sequence.cpp | 10 +- .../cpp/jank/runtime/obj/multi_function.cpp | 16 +- .../runtime/obj/native_function_wrapper.cpp | 2 +- .../src/cpp/jank/runtime/obj/nil.cpp | 11 +- .../jank/runtime/obj/persistent_array_map.cpp | 4 +- .../jank/runtime/obj/persistent_hash_map.cpp | 4 +- .../jank/runtime/obj/persistent_hash_set.cpp | 2 +- .../cpp/jank/runtime/obj/persistent_list.cpp | 4 +- .../runtime/obj/persistent_sorted_map.cpp | 4 +- .../runtime/obj/persistent_sorted_set.cpp | 2 +- .../jank/runtime/obj/persistent_string.cpp | 2 +- .../jank/runtime/obj/persistent_vector.cpp | 8 +- .../cpp/jank/runtime/obj/tagged_literal.cpp | 4 +- .../jank/runtime/obj/transient_array_map.cpp | 4 +- .../jank/runtime/obj/transient_hash_map.cpp | 4 +- .../jank/runtime/obj/transient_hash_set.cpp | 4 +- .../jank/runtime/obj/transient_sorted_map.cpp | 4 +- .../jank/runtime/obj/transient_sorted_set.cpp | 4 +- .../cpp/jank/runtime/obj/transient_vector.cpp | 4 +- .../src/cpp/jank/runtime/perf.cpp | 2 +- .../src/jank-and-cpp-modules/my_lib.cpp | 6 +- compiler+runtime/test/cpp/jank/read/lex.cpp | 2 +- compiler+runtime/test/cpp/jank/read/parse.cpp | 2 +- .../test/cpp/jank/runtime/core/seq.cpp | 6 +- .../jank/runtime/obj/persistent_string.cpp | 6 +- .../jank/runtime/obj/persistent_vector.cpp | 12 +- .../test/cpp/jank/runtime/obj/repeat.cpp | 4 +- 54 files changed, 410 insertions(+), 434 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp b/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp index edeff2b2b..3d59df5b3 100644 --- a/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp @@ -15,12 +15,12 @@ namespace jank::runtime template <> struct convert { - static constexpr object_ref into_object(object_ref const t) + static object_ref into_object(object_ref const t) { return t; } - static constexpr object_ref from_object(object_ref const t) + static object_ref from_object(object_ref const t) { return t; } @@ -29,12 +29,12 @@ namespace jank::runtime template <> struct convert { - static constexpr weak_object_ref into_object(weak_object_ref const t) + static weak_object_ref into_object(weak_object_ref const t) { return t; } - static constexpr weak_object_ref from_object(weak_object_ref const t) + static weak_object_ref from_object(weak_object_ref const t) { return t; } @@ -44,22 +44,22 @@ namespace jank::runtime requires(jtl::is_any_same) struct convert { - static constexpr object *into_object(T t) + static object *into_object(T t) { return const_cast(t); } - static constexpr object *into_object(object_ref const t) + static object *into_object(object_ref const t) { return t.erase(); } - static constexpr object *from_object(T t) + static object *from_object(T t) { return const_cast(t); } - static constexpr object *from_object(object_ref const t) + static object *from_object(object_ref const t) { return t.erase(); } @@ -70,17 +70,17 @@ namespace jank::runtime requires typed_object_ref struct convert { - static constexpr T into_object(T const t) + static T into_object(T const t) { return t; } - static constexpr T from_object(object_ref const t) + static T from_object(object_ref const t) { return try_object(t); } - static constexpr T from_object(T const t) + static T from_object(T const t) { return t; } @@ -91,12 +91,12 @@ namespace jank::runtime requires has_conversion_members struct convert { - static constexpr auto into_object(T const &t) + static auto into_object(T const &t) { return T::into_object(t); } - static constexpr T from_object(auto const o) + static T from_object(auto const o) { return T::from_object(o); } @@ -105,12 +105,12 @@ namespace jank::runtime template <> struct convert { - static constexpr obj::nil_ref into_object() + static obj::nil_ref into_object() { - return jank_nil; + return jank_nil(); } - static constexpr void from_object(object_ref) + static void from_object(object_ref) { } }; @@ -118,12 +118,12 @@ namespace jank::runtime template <> struct convert { - static constexpr obj::nil_ref into_object(jtl::nullptr_t) + static obj::nil_ref into_object(jtl::nullptr_t) { - return jank_nil; + return jank_nil(); } - static constexpr jtl::nullptr_t from_object(object_ref) + static jtl::nullptr_t from_object(object_ref) { return nullptr; } @@ -132,17 +132,17 @@ namespace jank::runtime template <> struct convert { - static constexpr obj::boolean_ref into_object(bool const o) + static obj::boolean_ref into_object(bool const o) { return make_box(o); } - static constexpr bool from_object(object_ref const o) + static bool from_object(object_ref const o) { return try_object(o)->data; } - static constexpr bool from_object(obj::boolean_ref const o) + static bool from_object(obj::boolean_ref const o) { return o->data; } @@ -151,17 +151,17 @@ namespace jank::runtime template <> struct convert { - static constexpr obj::character_ref into_object(char const o) + static obj::character_ref into_object(char const o) { return make_box(o); } - static constexpr char from_object(object_ref const o) + static char from_object(object_ref const o) { return try_object(o)->data[0]; } - static constexpr char from_object(obj::character_ref const o) + static char from_object(obj::character_ref const o) { return o->data[0]; } @@ -171,17 +171,17 @@ namespace jank::runtime requires std::is_enum_v struct convert { - static constexpr obj::integer_ref into_object(T const o) + static obj::integer_ref into_object(T const o) { return make_box(static_cast(o)); } - static constexpr T from_object(object_ref const o) + static T from_object(object_ref const o) { return try_object(o); } - static constexpr T from_object(obj::integer_ref const o) + static T from_object(obj::integer_ref const o) { return o->data; } @@ -193,17 +193,17 @@ namespace jank::runtime && !jtl::is_any_same) struct convert { - static constexpr obj::integer_ref into_object(T const o) + static obj::integer_ref into_object(T const o) { return make_box(static_cast(o)); } - static constexpr T from_object(object_ref const o) + static T from_object(object_ref const o) { return static_cast(try_object(o)->data); } - static constexpr T from_object(obj::integer_ref const o) + static T from_object(obj::integer_ref const o) { return static_cast(o->data); } @@ -213,7 +213,7 @@ namespace jank::runtime template <> struct convert { - static constexpr obj::big_integer_ref into_object(native_big_integer const &o) + static obj::big_integer_ref into_object(native_big_integer const &o) { return make_box(o); } @@ -234,17 +234,17 @@ namespace jank::runtime requires(std::is_floating_point_v) struct convert { - static constexpr obj::real_ref into_object(T const o) + static obj::real_ref into_object(T const o) { return make_box(static_cast(o)); } - static constexpr T from_object(object_ref const o) + static T from_object(object_ref const o) { return static_cast(try_object(o)->data); } - static constexpr T from_object(obj::real_ref const o) + static T from_object(obj::real_ref const o) { return static_cast(o->data); } @@ -255,21 +255,21 @@ namespace jank::runtime requires(jtl::is_any_same, char *, char const *>) struct convert { - static constexpr obj::persistent_string_ref into_object(char const * const o) + static obj::persistent_string_ref into_object(char const * const o) { if(o == nullptr) { - return jank_nil; + return jank_nil(); } return make_box(o); } - static constexpr char const *from_object(object_ref const o) + static char const *from_object(object_ref const o) { return try_object(o)->data.c_str(); } - static constexpr char const *from_object(obj::persistent_string_ref const o) + static char const *from_object(obj::persistent_string_ref const o) { return o->data.c_str(); } @@ -280,17 +280,17 @@ namespace jank::runtime requires(jtl::is_any_same) struct convert { - static constexpr obj::persistent_string_ref into_object(T const &o) + static obj::persistent_string_ref into_object(T const &o) { return make_box(o); } - static constexpr T from_object(object_ref const o) + static T from_object(object_ref const o) { return try_object(o)->data; } - static constexpr T from_object(obj::persistent_string_ref const o) + static T from_object(obj::persistent_string_ref const o) { return o->data; } @@ -312,12 +312,12 @@ namespace jank::runtime return make_box(trans); } - static constexpr V from_object(object_ref const o) + static V from_object(object_ref const o) { return from_object(try_object(o)); } - static constexpr V from_object(obj::persistent_vector_ref const o) + static V from_object(obj::persistent_vector_ref const o) { V ret; for(auto const &e : o->data) diff --git a/compiler+runtime/include/cpp/jank/runtime/core/make_box.hpp b/compiler+runtime/include/cpp/jank/runtime/core/make_box.hpp index bdb09ab89..f15b2711a 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/make_box.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/make_box.hpp @@ -16,7 +16,7 @@ namespace jank::runtime [[gnu::flatten, gnu::hot, gnu::visibility("default")]] inline auto make_box(std::nullptr_t const &) { - return jank_nil; + return jank_nil(); } [[gnu::flatten, gnu::hot, gnu::visibility("default")]] diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp index 3ea07f3ea..486fbbf4c 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp @@ -59,12 +59,5 @@ namespace jank::runtime bool operator==(object *, obj::nil_ref); bool operator!=(object *, obj::nil_ref); - /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ - extern obj::weak_nil_ref jank_nil; - - namespace detail - { - /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ - extern obj::nil *jank_nil_ptr; - } + obj::weak_nil_ref jank_nil(); } diff --git a/compiler+runtime/include/cpp/jank/runtime/oref.hpp b/compiler+runtime/include/cpp/jank/runtime/oref.hpp index ec026432b..9812e7497 100644 --- a/compiler+runtime/include/cpp/jank/runtime/oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/oref.hpp @@ -9,6 +9,8 @@ #include +extern "C" void *jank_const_nil(); + namespace jank::runtime { namespace obj @@ -22,12 +24,6 @@ namespace jank::runtime /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ extern oref jank_false; - namespace detail - { - /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ - extern obj::nil *jank_nil_ptr; - } - template struct oref; @@ -40,36 +36,36 @@ namespace jank::runtime { using value_type = object; - constexpr oref() - : data{ std::bit_cast(detail::jank_nil_ptr) } + oref() + : data{ std::bit_cast(jank_const_nil()) } { jank_debug_assert(data); } - constexpr oref(oref const &rhs) + oref(oref const &rhs) : data{ rhs.data } { jank_assert_throw(data); retain(); } - constexpr oref(oref &&rhs) noexcept + oref(oref &&rhs) noexcept : data{ jtl::move(rhs.data) } { jank_assert_throw(data); retain(); } - constexpr oref(nullptr_t) noexcept = delete; + oref(nullptr_t) noexcept = delete; - constexpr oref(value_type * const data) + oref(value_type * const data) : data{ data } { jank_assert_throw(data); retain(); } - constexpr oref(value_type const * const data) + oref(value_type const * const data) : data{ const_cast(data) } { jank_assert_throw(data); @@ -78,7 +74,7 @@ namespace jank::runtime template requires behavior::object_like - constexpr oref(T * const typed_data) + oref(T * const typed_data) : data{ &typed_data->base } { jank_assert_throw(this->data); @@ -87,7 +83,7 @@ namespace jank::runtime template requires behavior::object_like - constexpr oref(T const * const typed_data) + oref(T const * const typed_data) : data{ const_cast(&typed_data->base) } { jank_assert_throw(this->data); @@ -96,18 +92,18 @@ namespace jank::runtime template requires behavior::object_like - constexpr oref(oref const &typed_data) noexcept + oref(oref const &typed_data) noexcept : data{ typed_data.erase() } { retain(); } - constexpr ~oref() + ~oref() { release(); } - constexpr oref &retain() + oref &retain() { if(is_some()) { @@ -116,7 +112,7 @@ namespace jank::runtime return *this; } - constexpr void release() + void release() { if(is_some()) { @@ -124,24 +120,24 @@ namespace jank::runtime } } - constexpr void reset() + void reset() { - data = std::bit_cast(detail::jank_nil_ptr); + data = std::bit_cast(jank_const_nil()); } - constexpr value_type *operator->() const + value_type *operator->() const { jank_assert_throw(data); return data; } - constexpr value_type &operator*() const + value_type &operator*() const { jank_assert_throw(data); return *data; } - constexpr oref &operator=(oref const &rhs) noexcept + oref &operator=(oref const &rhs) noexcept { if(this == &rhs) { @@ -154,7 +150,7 @@ namespace jank::runtime return *this; } - constexpr oref &operator=(oref &&rhs) noexcept + oref &operator=(oref &&rhs) noexcept { if(this == &rhs) { @@ -169,7 +165,7 @@ namespace jank::runtime template requires behavior::object_like - constexpr oref &operator=(oref const &rhs) noexcept + oref &operator=(oref const &rhs) noexcept { if(data == &rhs->base) { @@ -182,50 +178,50 @@ namespace jank::runtime return *this; } - constexpr bool operator==(oref const &rhs) const noexcept + bool operator==(oref const &rhs) const noexcept { return data == rhs.data; } template requires behavior::object_like - constexpr bool operator==(oref const &rhs) const noexcept + bool operator==(oref const &rhs) const noexcept { return data == rhs.erase(); } - constexpr bool operator!=(oref const &rhs) const noexcept + bool operator!=(oref const &rhs) const noexcept { return data != rhs.data; } template requires behavior::object_like - constexpr bool operator!=(oref const &rhs) const noexcept + bool operator!=(oref const &rhs) const noexcept { return data != rhs.erase(); } - constexpr oref &operator=(jtl::nullptr_t) noexcept = delete; - constexpr bool operator==(jtl::nullptr_t) noexcept = delete; - constexpr bool operator!=(jtl::nullptr_t) noexcept = delete; + oref &operator=(jtl::nullptr_t) noexcept = delete; + bool operator==(jtl::nullptr_t) noexcept = delete; + bool operator!=(jtl::nullptr_t) noexcept = delete; - constexpr value_type *get() const noexcept + value_type *get() const noexcept { return data; } - constexpr value_type *erase() const noexcept + value_type *erase() const noexcept { return data; } - constexpr bool is_some() const noexcept + bool is_some() const noexcept { return data->type != object_type::nil; } - constexpr bool is_nil() const noexcept + bool is_nil() const noexcept { return data->type == object_type::nil; } @@ -242,33 +238,33 @@ namespace jank::runtime { using value_type = T; - constexpr oref() - : data{ std::bit_cast(detail::jank_nil_ptr) } + oref() + : data{ std::bit_cast(jank_const_nil()) } { } - constexpr oref(oref const &rhs) noexcept + oref(oref const &rhs) noexcept : data{ rhs.data } { retain(); } - constexpr oref(oref &&rhs) noexcept + oref(oref &&rhs) noexcept : data{ rhs.data } { retain(); } - constexpr oref(nullptr_t) = delete; + oref(nullptr_t) = delete; - constexpr oref(jtl::remove_const_t * const data) + oref(jtl::remove_const_t * const data) : data{ data } { jank_assert_throw(this->data); retain(); } - constexpr oref(T const * const data) + oref(T const * const data) : data{ const_cast(data) } { jank_assert_throw(this->data); @@ -277,7 +273,7 @@ namespace jank::runtime template requires jtl::is_convertible - constexpr oref(oref const &data) noexcept + oref(oref const &data) noexcept : data{ data.data } { retain(); @@ -285,17 +281,17 @@ namespace jank::runtime template requires(C::obj_type == object_type::nil) - constexpr oref(oref const &data) noexcept + oref(oref const &data) noexcept : data{ data.data } { } - constexpr ~oref() + ~oref() { release(); } - constexpr oref &retain() + oref &retain() { if(is_some()) { @@ -304,7 +300,7 @@ namespace jank::runtime return *this; } - constexpr void release() + void release() { if(is_some()) { @@ -312,12 +308,12 @@ namespace jank::runtime } } - constexpr void reset() + void reset() { - data = std::bit_cast(detail::jank_nil_ptr); + data = std::bit_cast(jank_const_nil()); } - constexpr T *operator->() const + T *operator->() const { /* TODO: Add type name. */ //jank_assert_fmt_throw(*this, "Null reference on oref<{}>", jtl::type_name()); @@ -325,38 +321,38 @@ namespace jank::runtime return reinterpret_cast(data); } - constexpr T &operator*() const + T &operator*() const { //jank_assert_fmt_throw(*this, "Null reference on oref<{}>", jtl::type_name()); jank_assert_throw(is_some()); return *reinterpret_cast(data); } - constexpr bool operator==(oref const &rhs) const + bool operator==(oref const &rhs) const { return erase() == rhs; } - constexpr bool operator!=(oref const &rhs) const + bool operator!=(oref const &rhs) const { return erase() != rhs; } template requires behavior::object_like - constexpr bool operator==(oref const &rhs) const + bool operator==(oref const &rhs) const { return data == rhs.data; } template requires behavior::object_like - constexpr bool operator!=(oref const &rhs) const + bool operator!=(oref const &rhs) const { return data != rhs.data; } - constexpr oref &operator=(oref const &rhs) noexcept + oref &operator=(oref const &rhs) noexcept { if(this == &rhs) { @@ -369,7 +365,7 @@ namespace jank::runtime return *this; } - constexpr oref &operator=(oref &&rhs) noexcept + oref &operator=(oref &&rhs) noexcept { if(this == &rhs) { @@ -382,7 +378,7 @@ namespace jank::runtime return *this; } - constexpr oref &operator=(std::remove_cv_t> * const rhs) + oref &operator=(std::remove_cv_t> * const rhs) { if(data == rhs) { @@ -396,7 +392,7 @@ namespace jank::runtime return *this; } - constexpr oref &operator=(std::remove_cv_t> const * const rhs) + oref &operator=(std::remove_cv_t> const * const rhs) { if(data == rhs) { @@ -412,7 +408,7 @@ namespace jank::runtime template requires(C::obj_type == object_type::nil) - constexpr oref &operator=(oref const &) noexcept + oref &operator=(oref const &) noexcept { if(is_nil()) { @@ -420,37 +416,37 @@ namespace jank::runtime } release(); - data = std::bit_cast(detail::jank_nil_ptr); + data = std::bit_cast(jank_const_nil()); retain(); return *this; } - constexpr oref &operator=(jtl::nullptr_t) noexcept = delete; - constexpr bool operator==(jtl::nullptr_t) noexcept = delete; - constexpr bool operator!=(jtl::nullptr_t) noexcept = delete; + oref &operator=(jtl::nullptr_t) noexcept = delete; + bool operator==(jtl::nullptr_t) noexcept = delete; + bool operator!=(jtl::nullptr_t) noexcept = delete; - constexpr object *get() const noexcept + object *get() const noexcept { return erase(); } - constexpr object *erase() const noexcept + object *erase() const noexcept { if(is_nil()) { - return std::bit_cast(detail::jank_nil_ptr); + return std::bit_cast(jank_const_nil()); } return &reinterpret_cast(data)->base; } - constexpr bool is_some() const noexcept + bool is_some() const noexcept { - return data != std::bit_cast(detail::jank_nil_ptr); + return data != std::bit_cast(jank_const_nil()); } - constexpr bool is_nil() const noexcept + bool is_nil() const noexcept { - return data == std::bit_cast(detail::jank_nil_ptr); + return data == std::bit_cast(jank_const_nil()); } void *data{}; @@ -461,20 +457,20 @@ namespace jank::runtime { using value_type = obj::nil; - constexpr oref() - : data{ std::bit_cast(detail::jank_nil_ptr) } + oref() + : data{ std::bit_cast(jank_const_nil()) } { } - constexpr oref(nullptr_t) = delete; + oref(nullptr_t) = delete; - constexpr oref(value_type * const data) + oref(value_type * const data) : data{ data } { jank_assert_throw(this->data); } - constexpr oref(value_type const * const data) + oref(value_type const * const data) : data{ const_cast(data) } { jank_assert_throw(this->data); @@ -482,76 +478,76 @@ namespace jank::runtime template requires jtl::is_convertible - constexpr oref(oref const &data) noexcept + oref(oref const &data) noexcept : data{ data.data } { } template requires(C::obj_type == object_type::nil) - constexpr oref(oref const &data) noexcept + oref(oref const &data) noexcept : data{ data.data } { } - constexpr void reset() + void reset() { } - constexpr value_type *operator->() const + value_type *operator->() const { return data; } - constexpr value_type &operator*() const + value_type &operator*() const { return *data; } - constexpr bool operator==(oref const &rhs) const + bool operator==(oref const &rhs) const { return rhs.is_nil(); } - constexpr bool operator!=(oref const &rhs) const + bool operator!=(oref const &rhs) const { return rhs.is_some(); } template requires behavior::object_like - constexpr bool operator==(oref const &rhs) const + bool operator==(oref const &rhs) const { return rhs.is_nil(); } template requires behavior::object_like - constexpr bool operator!=(oref const &rhs) const + bool operator!=(oref const &rhs) const { return rhs.is_some(); } - constexpr oref &operator=(jtl::nullptr_t) noexcept = delete; - constexpr bool operator==(jtl::nullptr_t) noexcept = delete; - constexpr bool operator!=(jtl::nullptr_t) noexcept = delete; + oref &operator=(jtl::nullptr_t) noexcept = delete; + bool operator==(jtl::nullptr_t) noexcept = delete; + bool operator!=(jtl::nullptr_t) noexcept = delete; - constexpr object *get() const noexcept + object *get() const noexcept { return erase(); } - constexpr object *erase() const noexcept + object *erase() const noexcept { return std::bit_cast(data); } - constexpr bool is_some() const noexcept + bool is_some() const noexcept { return false; } - constexpr bool is_nil() const noexcept + bool is_nil() const noexcept { return true; } @@ -560,20 +556,20 @@ namespace jank::runtime }; template - constexpr jtl::ref make_box(jtl::ref const &o) + jtl::ref make_box(jtl::ref const &o) { static_assert(sizeof(jtl::ref) == sizeof(T *)); return o; } template - constexpr oref make_box(oref const &o) + oref make_box(oref const &o) { static_assert(sizeof(oref) == sizeof(T *)); return o; } - /* TODO: Constexpr these. */ + /* TODO: these. */ template jtl::ref make_box(Args &&...args) { @@ -604,7 +600,7 @@ namespace jank::runtime } template - constexpr jtl::ref make_array_box() + jtl::ref make_array_box() { /* TODO: Figure out cleanup for this. */ auto const ret(new T[N]{}); @@ -616,7 +612,7 @@ namespace jank::runtime } template - constexpr jtl::ref make_array_box(usize const length) + jtl::ref make_array_box(usize const length) { /* TODO: Figure out cleanup for this. */ auto const ret(new T[length]{}); diff --git a/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp b/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp index 38962ede5..38ab3607f 100644 --- a/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp @@ -65,7 +65,7 @@ namespace jank::runtime iterator end() const { - return { jank_nil }; + return { jank_nil() }; } sequence_range skip(usize const n) const @@ -143,7 +143,7 @@ namespace jank::runtime iterator end() const { - return { jank_nil }; + return { jank_nil() }; } sequence_range skip(usize const n) const diff --git a/compiler+runtime/include/cpp/jank/runtime/visit.hpp b/compiler+runtime/include/cpp/jank/runtime/visit.hpp index 0f7f60297..1210ccba2 100644 --- a/compiler+runtime/include/cpp/jank/runtime/visit.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/visit.hpp @@ -68,7 +68,7 @@ namespace jank::runtime template requires behavior::object_like [[gnu::hot]] - constexpr auto visit_object(F const &fn, weak_oref const not_erased, Args &&...args) + auto visit_object(F const &fn, weak_oref const not_erased, Args &&...args) { return fn(const_cast(¬_erased->base), std::forward(args)...); } @@ -227,7 +227,7 @@ namespace jank::runtime /* Allows the visiting of a single type. */ template [[gnu::hot]] - constexpr auto visit_type(F const &fn, object_ref const erased, Args &&...args) + auto visit_type(F const &fn, object_ref const erased, Args &&...args) { if(erased->type == T::obj_type) { @@ -243,8 +243,7 @@ namespace jank::runtime template requires(visitable && !std::convertible_to) [[gnu::hot]] - constexpr auto - visit_seqable(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) + auto visit_seqable(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -318,7 +317,7 @@ namespace jank::runtime /* Throws if the object isn't seqable. */ template [[gnu::hot]] - constexpr auto visit_seqable(F1 const &fn, object_ref const erased, Args &&...args) + auto visit_seqable(F1 const &fn, object_ref const erased, Args &&...args) { return visit_seqable( fn, @@ -336,8 +335,7 @@ namespace jank::runtime template requires(map_visitable && !std::convertible_to) [[gnu::hot]] - constexpr auto - visit_map_like(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) + auto visit_map_like(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -359,7 +357,7 @@ namespace jank::runtime /* Throws if the object isn't map-like. */ template [[gnu::hot]] - constexpr auto visit_map_like(F1 const &fn, object_ref const erased, Args &&...args) + auto visit_map_like(F1 const &fn, object_ref const erased, Args &&...args) { return visit_map_like( fn, @@ -373,8 +371,7 @@ namespace jank::runtime template requires(visitable && !std::convertible_to) [[gnu::hot]] - constexpr auto - visit_set_like(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) + auto visit_set_like(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -394,7 +391,7 @@ namespace jank::runtime /* Throws if the object isn't set-like. */ template [[gnu::hot]] - constexpr auto visit_set_like(F1 const &fn, object_ref const erased, Args &&...args) + auto visit_set_like(F1 const &fn, object_ref const erased, Args &&...args) { return visit_set_like( fn, @@ -408,8 +405,7 @@ namespace jank::runtime template requires(!std::convertible_to) [[gnu::hot]] - constexpr auto - visit_number_like(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) + auto visit_number_like(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -434,7 +430,7 @@ namespace jank::runtime /* Throws if the object isn't number-like. */ template [[gnu::hot]] - constexpr auto visit_number_like(F1 const &fn, object_ref const erased, Args &&...args) + auto visit_number_like(F1 const &fn, object_ref const erased, Args &&...args) { return visit_number_like( fn, diff --git a/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp b/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp index ef190e2fc..2484a112d 100644 --- a/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp @@ -16,28 +16,28 @@ namespace jank::runtime { using value_type = object; - constexpr weak_oref() - : data{ std::bit_cast(detail::jank_nil_ptr) } + weak_oref() + : data{ std::bit_cast(jank_const_nil()) } { } - constexpr weak_oref(weak_oref const &rhs) = default; - constexpr weak_oref(weak_oref &&) noexcept = default; + weak_oref(weak_oref const &rhs) = default; + weak_oref(weak_oref &&) noexcept = default; - constexpr weak_oref(oref const &rhs) + weak_oref(oref const &rhs) : data{ rhs.data } { } - constexpr weak_oref(nullptr_t) noexcept = delete; + weak_oref(nullptr_t) noexcept = delete; - constexpr weak_oref(value_type * const data) + weak_oref(value_type * const data) : data{ data } { jank_assert_throw(data); } - constexpr weak_oref(value_type const * const data) + weak_oref(value_type const * const data) : data{ const_cast(data) } { jank_assert_throw(data); @@ -45,7 +45,7 @@ namespace jank::runtime template requires behavior::object_like - constexpr weak_oref(T * const typed_data) + weak_oref(T * const typed_data) : data{ &typed_data->base } { jank_assert_throw(this->data); @@ -53,7 +53,7 @@ namespace jank::runtime template requires behavior::object_like - constexpr weak_oref(T const * const typed_data) + weak_oref(T const * const typed_data) : data{ const_cast(&typed_data->base) } { jank_assert_throw(this->data); @@ -61,95 +61,95 @@ namespace jank::runtime template requires behavior::object_like - constexpr weak_oref(weak_oref const typed_data) noexcept + weak_oref(weak_oref const typed_data) noexcept : data{ typed_data.erase() } { } template requires behavior::object_like - constexpr weak_oref(oref const typed_data) noexcept + weak_oref(oref const typed_data) noexcept : data{ typed_data.erase() } { } - constexpr value_type *operator->() const + value_type *operator->() const { jank_assert_throw(data); return data; } - constexpr value_type &operator*() const + value_type &operator*() const { jank_assert_throw(data); return *data; } - constexpr weak_oref &operator=(weak_oref const &rhs) noexcept = default; - constexpr weak_oref &operator=(weak_oref &&rhs) noexcept = default; + weak_oref &operator=(weak_oref const &rhs) noexcept = default; + weak_oref &operator=(weak_oref &&rhs) noexcept = default; template requires behavior::object_like - constexpr weak_oref &operator=(weak_oref const &rhs) noexcept + weak_oref &operator=(weak_oref const &rhs) noexcept { data = &rhs->base; return *this; } - constexpr bool operator==(weak_oref const &rhs) const noexcept + bool operator==(weak_oref const &rhs) const noexcept { return data == rhs.data; } template requires behavior::object_like - constexpr bool operator==(weak_oref const &rhs) const noexcept + bool operator==(weak_oref const &rhs) const noexcept { return data == rhs.erase(); } - constexpr bool operator!=(weak_oref const &rhs) const noexcept + bool operator!=(weak_oref const &rhs) const noexcept { return data != rhs.data; } template requires behavior::object_like - constexpr bool operator!=(weak_oref const &rhs) const noexcept + bool operator!=(weak_oref const &rhs) const noexcept { return data != rhs.erase(); } - constexpr weak_oref &operator=(jtl::nullptr_t) noexcept = delete; - constexpr bool operator==(jtl::nullptr_t) noexcept = delete; - constexpr bool operator!=(jtl::nullptr_t) noexcept = delete; + weak_oref &operator=(jtl::nullptr_t) noexcept = delete; + bool operator==(jtl::nullptr_t) noexcept = delete; + bool operator!=(jtl::nullptr_t) noexcept = delete; - constexpr operator oref() const noexcept + operator oref() const noexcept { return data; } - constexpr oref strong() const noexcept + oref strong() const noexcept { return data; } - constexpr value_type *get() const noexcept + value_type *get() const noexcept { return data; } - constexpr value_type *erase() const noexcept + value_type *erase() const noexcept { return data; } - constexpr bool is_some() const noexcept + bool is_some() const noexcept { return data->type != object_type::nil; } - constexpr bool is_nil() const noexcept + bool is_nil() const noexcept { return data->type == object_type::nil; } @@ -166,20 +166,20 @@ namespace jank::runtime { using value_type = T; - constexpr weak_oref() - : data{ std::bit_cast(detail::jank_nil_ptr) } + weak_oref() + : data{ std::bit_cast(jank_const_nil()) } { } - constexpr weak_oref(nullptr_t) = delete; + weak_oref(nullptr_t) = delete; - constexpr weak_oref(jtl::remove_const_t * const data) + weak_oref(jtl::remove_const_t * const data) : data{ data } { jank_assert_throw(this->data); } - constexpr weak_oref(T const * const data) + weak_oref(T const * const data) : data{ const_cast(data) } { jank_assert_throw(this->data); @@ -187,33 +187,33 @@ namespace jank::runtime template requires jtl::is_convertible - constexpr weak_oref(weak_oref const data) noexcept + weak_oref(weak_oref const data) noexcept : data{ data.data } { } template requires jtl::is_convertible - constexpr weak_oref(oref const data) noexcept + weak_oref(oref const data) noexcept : data{ data.data } { } template requires(C::obj_type == object_type::nil) - constexpr weak_oref(weak_oref const data) noexcept + weak_oref(weak_oref const data) noexcept : data{ data.data } { } template requires(C::obj_type == object_type::nil) - constexpr weak_oref(oref const data) noexcept + weak_oref(oref const data) noexcept : data{ data.data } { } - constexpr T *operator->() const + T *operator->() const { /* TODO: Add type name. */ //jank_assert_fmt_throw(*this, "Null reference on weak_oref<{}>", jtl::type_name()); @@ -221,45 +221,45 @@ namespace jank::runtime return reinterpret_cast(data); } - constexpr T &operator*() const + T &operator*() const { //jank_assert_fmt_throw(*this, "Null reference on weak_oref<{}>", jtl::type_name()); jank_assert_throw(is_some()); return *reinterpret_cast(data); } - constexpr bool operator==(weak_oref const &rhs) const + bool operator==(weak_oref const &rhs) const { return erase() == rhs.erase(); } - constexpr bool operator!=(weak_oref const &rhs) const + bool operator!=(weak_oref const &rhs) const { return erase() != rhs.erase(); } template requires behavior::object_like - constexpr bool operator==(weak_oref const &rhs) const + bool operator==(weak_oref const &rhs) const { return data == rhs.data; } template requires behavior::object_like - constexpr bool operator!=(weak_oref const &rhs) const + bool operator!=(weak_oref const &rhs) const { return data != rhs.data; } - constexpr weak_oref &operator=(std::remove_cv_t> * const rhs) + weak_oref &operator=(std::remove_cv_t> * const rhs) { data = rhs; jank_assert_throw(data); return *this; } - constexpr weak_oref &operator=(std::remove_cv_t> const * const rhs) + weak_oref &operator=(std::remove_cv_t> const * const rhs) { data = const_cast(rhs); jank_assert_throw(data); @@ -268,17 +268,17 @@ namespace jank::runtime template requires(C::obj_type == object_type::nil) - constexpr weak_oref &operator=(weak_oref const &) noexcept + weak_oref &operator=(weak_oref const &) noexcept { - data = std::bit_cast(detail::jank_nil_ptr); + data = std::bit_cast(jank_const_nil()); return *this; } - constexpr weak_oref &operator=(jtl::nullptr_t) noexcept = delete; - constexpr bool operator==(jtl::nullptr_t) noexcept = delete; - constexpr bool operator!=(jtl::nullptr_t) noexcept = delete; + weak_oref &operator=(jtl::nullptr_t) noexcept = delete; + bool operator==(jtl::nullptr_t) noexcept = delete; + bool operator!=(jtl::nullptr_t) noexcept = delete; - constexpr operator oref() const noexcept + operator oref() const noexcept { if(is_nil()) { @@ -287,38 +287,38 @@ namespace jank::runtime return reinterpret_cast(data); } - constexpr operator oref() const noexcept + operator oref() const noexcept { return erase(); } - constexpr oref strong() const noexcept + oref strong() const noexcept { return static_cast>(*this); } - constexpr object *get() const noexcept + object *get() const noexcept { return erase(); } - constexpr object *erase() const noexcept + object *erase() const noexcept { if(is_nil()) { - return std::bit_cast(detail::jank_nil_ptr); + return std::bit_cast(jank_const_nil()); } return &reinterpret_cast(data)->base; } - constexpr bool is_some() const noexcept + bool is_some() const noexcept { - return data != std::bit_cast(detail::jank_nil_ptr); + return data != std::bit_cast(jank_const_nil()); } - constexpr bool is_nil() const noexcept + bool is_nil() const noexcept { - return data == std::bit_cast(detail::jank_nil_ptr); + return data == std::bit_cast(jank_const_nil()); } void *data{}; @@ -329,20 +329,20 @@ namespace jank::runtime { using value_type = obj::nil; - constexpr weak_oref() - : data{ std::bit_cast(detail::jank_nil_ptr) } + weak_oref() + : data{ std::bit_cast(jank_const_nil()) } { } - constexpr weak_oref(nullptr_t) = delete; + weak_oref(nullptr_t) = delete; - constexpr weak_oref(value_type * const data) + weak_oref(value_type * const data) : data{ data } { jank_assert_throw(this->data); } - constexpr weak_oref(value_type const * const data) + weak_oref(value_type const * const data) : data{ const_cast(data) } { jank_assert_throw(this->data); @@ -350,96 +350,96 @@ namespace jank::runtime template requires jtl::is_convertible - constexpr weak_oref(oref const data) noexcept + weak_oref(oref const data) noexcept : data{ data.data } { } template requires(C::obj_type == object_type::nil) - constexpr weak_oref(weak_oref const data) noexcept + weak_oref(weak_oref const data) noexcept : data{ data.data } { } template requires(C::obj_type == object_type::nil) - constexpr weak_oref(oref const data) noexcept + weak_oref(oref const data) noexcept : data{ data.data } { } - constexpr value_type *operator->() const + value_type *operator->() const { return data; } - constexpr value_type &operator*() const + value_type &operator*() const { return *data; } - constexpr bool operator==(weak_oref const &rhs) const + bool operator==(weak_oref const &rhs) const { return rhs.is_nil(); } - constexpr bool operator!=(weak_oref const &rhs) const + bool operator!=(weak_oref const &rhs) const { return rhs.is_some(); } template requires behavior::object_like - constexpr bool operator==(weak_oref const &rhs) const + bool operator==(weak_oref const &rhs) const { return rhs.is_nil(); } template requires behavior::object_like - constexpr bool operator!=(weak_oref const &rhs) const + bool operator!=(weak_oref const &rhs) const { return rhs.is_some(); } - constexpr weak_oref &operator=(jtl::nullptr_t) noexcept = delete; - constexpr bool operator==(jtl::nullptr_t) noexcept = delete; - constexpr bool operator!=(jtl::nullptr_t) noexcept = delete; + weak_oref &operator=(jtl::nullptr_t) noexcept = delete; + bool operator==(jtl::nullptr_t) noexcept = delete; + bool operator!=(jtl::nullptr_t) noexcept = delete; template requires behavior::object_like - constexpr operator oref() const noexcept + operator oref() const noexcept { return {}; } - constexpr operator oref() const noexcept + operator oref() const noexcept { return {}; } - constexpr oref strong() const noexcept + oref strong() const noexcept { return {}; } - constexpr object *get() const noexcept + object *get() const noexcept { return erase(); } - constexpr object *erase() const noexcept + object *erase() const noexcept { return std::bit_cast(data); } - constexpr bool is_some() const noexcept + bool is_some() const noexcept { return false; } - constexpr bool is_nil() const noexcept + bool is_nil() const noexcept { return true; } @@ -448,7 +448,7 @@ namespace jank::runtime }; template - constexpr weak_oref make_box(weak_oref const &o) + weak_oref make_box(weak_oref const &o) { static_assert(sizeof(weak_oref) == sizeof(T *)); return o; diff --git a/compiler+runtime/src/cpp/clojure/core_native.cpp b/compiler+runtime/src/cpp/clojure/core_native.cpp index 28db6e3ec..71bee7c3f 100644 --- a/compiler+runtime/src/cpp/clojure/core_native.cpp +++ b/compiler+runtime/src/cpp/clojure/core_native.cpp @@ -173,7 +173,7 @@ namespace clojure::core_native object_ref sleep(object_ref const ms) { std::this_thread::sleep_for(std::chrono::milliseconds(to_int(ms))); - return jank_nil; + return jank_nil(); } object_ref current_time() @@ -186,7 +186,7 @@ namespace clojure::core_native object_ref in_ns(object_ref const sym) { __rt_ctx->current_ns_var->set(__rt_ctx->intern_ns(try_object(sym))).expect_ok(); - return jank_nil; + return jank_nil(); } object_ref intern_ns(object_ref const sym) @@ -241,19 +241,19 @@ namespace clojure::core_native try_object(current_ns) ->add_alias(try_object(alias), try_object(remote_ns)) .expect_ok(); - return jank_nil; + return jank_nil(); } object_ref ns_unalias(object_ref const current_ns, object_ref const alias) { try_object(current_ns)->remove_alias(try_object(alias)); - return jank_nil; + return jank_nil(); } object_ref ns_unmap(object_ref const current_ns, object_ref const sym) { try_object(current_ns)->unmap(try_object(sym)).expect_ok(); - return jank_nil; + return jank_nil(); } object_ref refer(object_ref const current_ns, object_ref const sym, object_ref const var) @@ -261,19 +261,19 @@ namespace clojure::core_native expect_object(current_ns) ->refer(try_object(sym), expect_object(var)) .expect_ok(); - return jank_nil; + return jank_nil(); } object_ref load_module(object_ref const path) { __rt_ctx->load_module(runtime::to_string(path), module::origin::latest).expect_ok(); - return jank_nil; + return jank_nil(); } object_ref compile(object_ref const path) { __rt_ctx->compile_module(runtime::to_string(path)).expect_ok(); - return jank_nil; + return jank_nil(); } object_ref eval(object_ref const expr) @@ -588,7 +588,7 @@ extern "C" jank_object_ref jank_load_clojure_core_native() return jank_false.erase(); } - for(auto it(fresh_seq(rest)); it != jank_nil; it = next_in_place(it)) + for(auto it(fresh_seq(rest)); it != jank_nil(); it = next_in_place(it)) { if(!is_equiv(l, first(it))) { @@ -849,5 +849,5 @@ extern "C" jank_object_ref jank_load_clojure_core_native() intern_fn_obj("repeat", fn); } - return jank_nil.erase(); + return jank_nil().erase(); } diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index 4ca2dc765..70693f98d 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -79,7 +79,7 @@ namespace jank::analyze auto const expansion( runtime::get(meta, __rt_ctx->intern_keyword("jank/macro-expansion").expect_ok())); - if(expansion == jank_nil) + if(expansion == jank_nil()) { return nullptr; } @@ -93,7 +93,7 @@ namespace jank::analyze { if(expansions.empty()) { - return jank_nil; + return jank_nil(); } /* Try to find an expansion which specifically has the `jank/macro-expansion` key @@ -104,7 +104,7 @@ namespace jank::analyze auto const expansion( runtime::get(latest_meta, __rt_ctx->intern_keyword("jank/macro-expansion").expect_ok())); - if(expansion != jank_nil) + if(expansion != jank_nil()) { return expansion; } @@ -1332,7 +1332,7 @@ namespace jank::analyze latest_expansion(macro_expansions)) ->add_usage(read::parse::reparse_nth(l, 2)); } - auto const meta_with_doc(runtime::assoc(qualified_sym->meta.unwrap_or(runtime::jank_nil), + auto const meta_with_doc(runtime::assoc(qualified_sym->meta.unwrap_or(runtime::jank_nil()), __rt_ctx->intern_keyword("doc").expect_ok(), docstring_obj)); qualified_sym = qualified_sym->with_meta(meta_with_doc); @@ -2076,7 +2076,7 @@ namespace jank::analyze if(ret.values.empty()) { auto const nil{ - analyze_primitive_literal(jank_nil, current_frame, position, fn_ctx, needs_box) + analyze_primitive_literal(jank_nil(), current_frame, position, fn_ctx, needs_box) }; if(nil.is_err()) { @@ -2195,7 +2195,7 @@ namespace jank::analyze if(ret->body->values.empty()) { - auto const nil{ analyze_primitive_literal(jank_nil, + auto const nil{ analyze_primitive_literal(jank_nil(), ret->frame, expression_position::tail, fn_ctx, @@ -2328,7 +2328,7 @@ namespace jank::analyze if(ret->body->values.empty()) { - auto const nil{ analyze_primitive_literal(jank_nil, + auto const nil{ analyze_primitive_literal(jank_nil(), ret->frame, expression_position::tail, fn_ctx, @@ -3932,7 +3932,7 @@ namespace jank::analyze /* Since we're reusing analyze_cpp_call, we need to rebuild our list a bit. We * want to remove the cpp/cast and the type and then add back in a new head. Since * cpp_call takes in a cpp_value, it doesn't look at the head, but it needs to be there. */ - auto const call_l{ make_box(l->data.rest().rest().conj(jank_nil)) }; + auto const call_l{ make_box(l->data.rest().rest().conj(jank_nil())) }; return analyze_cpp_call(call_l, cpp_value, current_frame, position, fn_ctx, needs_box); } if(cpp_util::is_any_object(type_expr->type) && cpp_util::is_trait_convertible(value_type)) diff --git a/compiler+runtime/src/cpp/jank/c_api.cpp b/compiler+runtime/src/cpp/jank/c_api.cpp index f1e106097..535a36692 100644 --- a/compiler+runtime/src/cpp/jank/c_api.cpp +++ b/compiler+runtime/src/cpp/jank/c_api.cpp @@ -365,7 +365,7 @@ extern "C" jank_object_ref jank_const_nil() { - return jank_nil.erase(); + return jank_nil().erase(); } jank_object_ref jank_const_true() diff --git a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp index 2b9593e06..f1a6bd7ee 100644 --- a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp @@ -772,7 +772,7 @@ namespace jank::codegen continue; } - gen_ret(gen_global(jank_nil)); + gen_ret(gen_global(jank_nil())); } if(target != compilation_target::function) @@ -863,8 +863,8 @@ namespace jank::codegen auto const set_dynamic_fn( llvm_module->getOrInsertFunction("jank_var_set_dynamic", set_dynamic_fn_type)); - auto const dynamic{ truthy( - get(expr->name->meta.unwrap_or(jank_nil), __rt_ctx->intern_keyword("dynamic").expect_ok())) }; + auto const dynamic{ truthy(get(expr->name->meta.unwrap_or(jank_nil()), + __rt_ctx->intern_keyword("dynamic").expect_ok())) }; auto const dynamic_global{ gen_global(make_box(dynamic)) }; @@ -1590,7 +1590,7 @@ namespace jank::codegen } else { - else_ = gen_global(jank_nil); + else_ = gen_global(jank_nil()); if(expr->position == expression_position::tail) { else_ = gen_ret(else_); @@ -1664,7 +1664,7 @@ namespace jank::codegen /* Since this code path never completes, it doesn't matter what we return. * Using `jank_nil` to satisfy some IR requirements. */ - auto const ret{ gen_global(jank_nil) }; + auto const ret{ gen_global(jank_nil()) }; if(expr->position == expression_position::tail) { return gen_ret(ret); @@ -1730,7 +1730,7 @@ namespace jank::codegen llvm::AllocaInst *result_slot{ entry_builder.CreateAlloca(ptr_ty, nullptr, "try.result.slot") }; llvm::BasicBlock *finally_bb{}; llvm::BasicBlock *unwind_action_bb{}; - ctx->builder->CreateStore(gen_global(jank_nil), result_slot); + ctx->builder->CreateStore(gen_global(jank_nil()), result_slot); if(has_finally) { @@ -1923,7 +1923,7 @@ namespace jank::codegen { if(!catch_val) { - catch_val = gen_global(jank_nil); + catch_val = gen_global(jank_nil()); } ctx->builder->CreateStore(catch_val, result_slot); if(has_finally) @@ -2158,7 +2158,7 @@ namespace jank::codegen } link_module(*ctx, parse_res->TheModule.get()); - auto const ret{ gen_global(jank_nil) }; + auto const ret{ gen_global(jank_nil()) }; if(expr->position == expression_position::tail) { return gen_ret(ret); @@ -2443,7 +2443,7 @@ namespace jank::codegen { if(is_void) { - return gen_ret(gen_global(jank_nil)); + return gen_ret(gen_global(jank_nil())); } auto const ret_load{ ctx->builder->CreateLoad(ctx->builder->getPtrTy(), ret_alloc, "ret") }; @@ -2452,7 +2452,7 @@ namespace jank::codegen if(is_void) { - return gen_global(jank_nil); + return gen_global(jank_nil()); } return ret_alloc; } @@ -2831,7 +2831,7 @@ namespace jank::codegen llvm::SmallVector const args{ val }; ctx->builder->CreateCall(fn, args); - auto const ret{ gen_global(jank_nil) }; + auto const ret{ gen_global(jank_nil()) }; if(expr->position == expression_position::tail) { return gen_ret(ret); diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 8b9e9ebb1..c9361e9f7 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -57,7 +57,7 @@ /* TODO: Size optimizations: * - Remove object requirement for if condition - * - Remove extra if_n = jank_nil on empty branches + * - Remove extra if_n = jank_nil() on empty branches */ namespace jank::codegen @@ -160,7 +160,7 @@ namespace jank::codegen if constexpr(std::same_as) { - util::format_to(buffer, "jank::runtime::jank_nil"); + util::format_to(buffer, "jank::runtime::jank_nil()"); } else if constexpr(std::same_as) { @@ -571,7 +571,7 @@ namespace jank::codegen } else { - auto v{ util::format("{}->with_meta(jank::runtime::jank_nil)", var_tmp) }; + auto v{ util::format("{}->with_meta(jank::runtime::jank_nil())", var_tmp) }; if(expr->position == expression_position::tail) { util::format_to(body_buffer, "return {};", v); @@ -597,7 +597,7 @@ namespace jank::codegen } else { - return util::format("{}->bind_root({})->with_meta(jank::runtime::jank_nil)", + return util::format("{}->bind_root({})->with_meta(jank::runtime::jank_nil())", var_tmp, val.str(true)); } @@ -620,7 +620,7 @@ namespace jank::codegen else { util::format_to(body_buffer, - "{}->bind_root({})->with_meta(jank::runtime::jank_nil);", + "{}->bind_root({})->with_meta(jank::runtime::jank_nil());", var_tmp, val.str(true)); } @@ -1068,7 +1068,7 @@ namespace jank::codegen handle ret; if(expr->data->type == runtime::object_type::nil) { - ret = handle{ "jank::runtime::jank_nil" }; + ret = handle{ "jank::runtime::jank_nil()" }; } else if(expr->data->type == runtime::object_type::boolean) { @@ -1646,7 +1646,7 @@ namespace jank::codegen case analyze::expression_position::tail: if(last.is_none()) { - util::format_to(body_buffer, "return jank::runtime::jank_nil;"); + util::format_to(body_buffer, "return jank::runtime::jank_nil();"); } else { @@ -1715,10 +1715,10 @@ namespace jank::codegen if(expr->position == analyze::expression_position::tail) { - util::format_to(body_buffer, "return jank::runtime::jank_nil;"); + util::format_to(body_buffer, "return jank::runtime::jank_nil();"); } - return "jank::runtime::jank_nil"; + return "jank::runtime::jank_nil()"; } jtl::option @@ -1844,7 +1844,7 @@ namespace jank::codegen if(expr->position == analyze::expression_position::tail) { - util::format_to(body_buffer, "return jank::runtime::jank_nil;"); + util::format_to(body_buffer, "return jank::runtime::jank_nil();"); return none; } return none; @@ -1904,10 +1904,10 @@ namespace jank::codegen { if(expr->position == expression_position::tail) { - util::format_to(body_buffer, "return jank::runtime::jank_nil;"); + util::format_to(body_buffer, "return jank::runtime::jank_nil();"); return none; } - return "jank::runtime::jank_nil"; + return "jank::runtime::jank_nil()"; } /* We can rely on the C++ type system to handle conversion from typed objects @@ -2388,11 +2388,11 @@ namespace jank::codegen if(expr->position == expression_position::tail) { - util::format_to(body_buffer, "return jank::runtime::jank_nil;"); + util::format_to(body_buffer, "return jank::runtime::jank_nil();"); return none; } - return "jank::runtime::jank_nil"; + return "jank::runtime::jank_nil()"; } jtl::immutable_string processor::declaration_str() @@ -2667,7 +2667,7 @@ namespace jank::codegen if(arity.body->values.empty()) { - util::format_to(body_buffer, "return jank::runtime::jank_nil;"); + util::format_to(body_buffer, "return jank::runtime::jank_nil();"); } if(arity.fn_ctx->is_recur_recursive) diff --git a/compiler+runtime/src/cpp/jank/compiler_native.cpp b/compiler+runtime/src/cpp/jank/compiler_native.cpp index 0f8bcbfbe..db0a94f7d 100644 --- a/compiler+runtime/src/cpp/jank/compiler_native.cpp +++ b/compiler+runtime/src/cpp/jank/compiler_native.cpp @@ -46,7 +46,7 @@ namespace jank::compiler_native util::println("{}\n", util::format_cpp_source(cg_prc.declaration_str()).expect_ok()); } - return jank_nil; + return jank_nil(); } } @@ -66,5 +66,5 @@ extern "C" jank_object_ref jank_load_jank_compiler_native() }); intern_fn("native-source", &compiler_native::native_source); - return jank_nil.erase(); + return jank_nil().erase(); } diff --git a/compiler+runtime/src/cpp/jank/evaluate.cpp b/compiler+runtime/src/cpp/jank/evaluate.cpp index b94925aa7..7ede2a152 100644 --- a/compiler+runtime/src/cpp/jank/evaluate.cpp +++ b/compiler+runtime/src/cpp/jank/evaluate.cpp @@ -214,7 +214,7 @@ namespace jank::evaluate return wrap_expression(jtl::make_ref(expression_position::tail, an_prc.root_frame, true, - jank_nil), + jank_nil()), name, {}); } @@ -267,7 +267,7 @@ namespace jank::evaluate auto var(__rt_ctx->intern_var(expr->name).expect_ok()); var->meta = expr->name->meta; - auto const meta(var->meta.unwrap_or(jank_nil)); + auto const meta(var->meta.unwrap_or(jank_nil())); auto const dynamic(get(meta, __rt_ctx->intern_keyword("dynamic").expect_ok())); var->set_dynamic(truthy(dynamic)); @@ -633,7 +633,7 @@ namespace jank::evaluate object_ref eval(expr::do_ref const expr) { - object_ref ret{ jank_nil }; + object_ref ret{ jank_nil() }; for(auto const &form : expr->values) { ret = eval(form); @@ -662,7 +662,7 @@ namespace jank::evaluate { return eval(expr->else_.unwrap()); } - return jank_nil; + return jank_nil(); } object_ref eval(expr::throw_ref const expr) @@ -708,7 +708,7 @@ namespace jank::evaluate object_ref eval(expr::cpp_raw_ref const expr) { __rt_ctx->jit_prc.eval_string(expr->code); - return runtime::jank_nil; + return runtime::jank_nil(); } object_ref eval(expr::cpp_type_ref const) diff --git a/compiler+runtime/src/cpp/jank/perf_native.cpp b/compiler+runtime/src/cpp/jank/perf_native.cpp index 6ec170a8a..63c0594b2 100644 --- a/compiler+runtime/src/cpp/jank/perf_native.cpp +++ b/compiler+runtime/src/cpp/jank/perf_native.cpp @@ -24,5 +24,5 @@ jank_object_ref jank_load_jank_perf_native() }); intern_fn("benchmark", &perf::benchmark); - return jank_nil.erase(); + return jank_nil().erase(); } diff --git a/compiler+runtime/src/cpp/jank/read/parse.cpp b/compiler+runtime/src/cpp/jank/read/parse.cpp index 93e8e6c92..21e1c6dfe 100644 --- a/compiler+runtime/src/cpp/jank/read/parse.cpp +++ b/compiler+runtime/src/cpp/jank/read/parse.cpp @@ -1429,7 +1429,7 @@ namespace jank::read::parse } auto const meta{ runtime::meta(form) }; - if(meta != jank_nil) + if(meta != jank_nil()) { /* We quote the meta as well, to ensure it doesn't get evaluated. * Note that Clojure removes the source info from the meta here. We're keeping it @@ -1536,7 +1536,7 @@ namespace jank::read::parse processor::object_result processor::parse_nil() { ++token_current; - return object_source_info{ jank_nil, latest_token, latest_token }; + return object_source_info{ jank_nil(), latest_token, latest_token }; } processor::object_result processor::parse_boolean() diff --git a/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp b/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp index 6261eb0cf..18cf846ae 100644 --- a/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp @@ -33,7 +33,7 @@ namespace jank::runtime switch(arity_flags) { case callable::mask_variadic_arity(0): - return typed_source->call(jank_nil); + return typed_source->call(jank_nil()); default: return typed_source->call(); } @@ -66,7 +66,7 @@ namespace jank::runtime case callable::mask_variadic_arity(1): if(!callable::is_variadic_ambiguous(arity_flags)) { - return typed_source->call(a1, jank_nil); + return typed_source->call(a1, jank_nil()); } default: return typed_source->call(a1); @@ -112,7 +112,7 @@ namespace jank::runtime case callable::mask_variadic_arity(2): if(!callable::is_variadic_ambiguous(arity_flags)) { - return typed_source->call(a1, a2, jank_nil); + return typed_source->call(a1, a2, jank_nil()); } default: return typed_source->call(a1, a2); @@ -160,7 +160,7 @@ namespace jank::runtime case callable::mask_variadic_arity(3): if(!callable::is_variadic_ambiguous(arity_flags)) { - return typed_source->call(a1, a2, a3, jank_nil); + return typed_source->call(a1, a2, a3, jank_nil()); } default: return typed_source->call(a1, a2, a3); @@ -204,7 +204,7 @@ namespace jank::runtime case callable::mask_variadic_arity(4): if(!callable::is_variadic_ambiguous(arity_flags)) { - return typed_source->call(a1, a2, a3, a4, jank_nil); + return typed_source->call(a1, a2, a3, a4, jank_nil()); } default: return typed_source->call(a1, a2, a3, a4); @@ -251,7 +251,7 @@ namespace jank::runtime case callable::mask_variadic_arity(5): if(!callable::is_variadic_ambiguous(arity_flags)) { - return typed_source->call(a1, a2, a3, a4, a5, jank_nil); + return typed_source->call(a1, a2, a3, a4, a5, jank_nil()); } default: return typed_source->call(a1, a2, a3, a4, a5); @@ -313,7 +313,7 @@ namespace jank::runtime case callable::mask_variadic_arity(6): if(!callable::is_variadic_ambiguous(arity_flags)) { - return typed_source->call(a1, a2, a3, a4, a5, a6, jank_nil); + return typed_source->call(a1, a2, a3, a4, a5, a6, jank_nil()); } default: return typed_source->call(a1, a2, a3, a4, a5, a6); @@ -380,7 +380,7 @@ namespace jank::runtime case callable::mask_variadic_arity(7): if(!callable::is_variadic_ambiguous(arity_flags)) { - return typed_source->call(a1, a2, a3, a4, a5, a6, a7, jank_nil); + return typed_source->call(a1, a2, a3, a4, a5, a6, a7, jank_nil()); } default: return typed_source->call(a1, a2, a3, a4, a5, a6, a7); @@ -452,7 +452,7 @@ namespace jank::runtime case callable::mask_variadic_arity(8): if(!callable::is_variadic_ambiguous(arity_flags)) { - return typed_source->call(a1, a2, a3, a4, a5, a6, a7, a8, jank_nil); + return typed_source->call(a1, a2, a3, a4, a5, a6, a7, a8, jank_nil()); } default: return typed_source->call(a1, a2, a3, a4, a5, a6, a7, a8); @@ -526,7 +526,7 @@ namespace jank::runtime case callable::mask_variadic_arity(9): if(!callable::is_variadic_ambiguous(arity_flags)) { - return typed_source->call(a1, a2, a3, a4, a5, a6, a7, a8, a9, jank_nil); + return typed_source->call(a1, a2, a3, a4, a5, a6, a7, a8, a9, jank_nil()); } default: return typed_source->call(a1, a2, a3, a4, a5, a6, a7, a8, a9); diff --git a/compiler+runtime/src/cpp/jank/runtime/behavior/metadatable.cpp b/compiler+runtime/src/cpp/jank/runtime/behavior/metadatable.cpp index 6599d78c3..03ef403eb 100644 --- a/compiler+runtime/src/cpp/jank/runtime/behavior/metadatable.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/behavior/metadatable.cpp @@ -8,7 +8,7 @@ namespace jank::runtime::behavior::detail { object_ref validate_meta(object_ref const m) { - if(!is_map(m) && m != jank_nil) + if(!is_map(m) && m != jank_nil()) { throw std::runtime_error{ util::format("invalid meta: {}", runtime::to_string(m)) }; } diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index db46be2e6..78ff1a694 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -160,7 +160,7 @@ namespace jank::runtime read::lex::processor l_prc{ code }; read::parse::processor p_prc{ l_prc.begin(), l_prc.end() }; - object_ref ret{ jank_nil }; + object_ref ret{ jank_nil() }; native_vector forms{}; for(auto const &form : p_prc) { @@ -262,12 +262,12 @@ namespace jank::runtime /* When reading an arbitrary string, we don't want the last *current-file* to * be set as source file, so we need to bind it to nil. */ binding_scope const preserve{ obj::persistent_hash_map::create_unique( - std::make_pair(current_file_var, jank_nil)) }; + std::make_pair(current_file_var, jank_nil())) }; read::lex::processor l_prc{ code }; read::parse::processor p_prc{ l_prc.begin(), l_prc.end() }; - object_ref ret{ jank_nil }; + object_ref ret{ jank_nil() }; for(auto const &form : p_prc) { ret = form.expect_ok().unwrap().ptr; @@ -661,7 +661,7 @@ namespace jank::runtime } /* TODO: Provide &env. */ - auto const args(cons(cons(rest(typed_o), jank_nil), typed_o)); + auto const args(cons(cons(rest(typed_o), jank_nil()), typed_o)); return apply_to(var->deref(), args); } }, diff --git a/compiler+runtime/src/cpp/jank/runtime/core.cpp b/compiler+runtime/src/cpp/jank/runtime/core.cpp index 87eadc610..e5a13393c 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core.cpp @@ -16,7 +16,7 @@ namespace jank::runtime bool is_nil(object_ref const o) { - return o == jank_nil; + return o == jank_nil(); } bool is_true(object_ref const o) @@ -31,7 +31,7 @@ namespace jank::runtime bool is_some(object_ref const o) { - return o != jank_nil; + return o != jank_nil(); } bool is_string(object_ref const o) @@ -119,7 +119,7 @@ namespace jank::runtime } }, args); - return jank_nil; + return jank_nil(); } object_ref println(object_ref const args) @@ -151,7 +151,7 @@ namespace jank::runtime } }, args); - return jank_nil; + return jank_nil(); } object_ref pr(object_ref const args) @@ -178,7 +178,7 @@ namespace jank::runtime } }, args); - return jank_nil; + return jank_nil(); } object_ref prn(object_ref const args) @@ -210,7 +210,7 @@ namespace jank::runtime } }, args); - return jank_nil; + return jank_nil(); } f64 to_real(object_ref const o) @@ -302,7 +302,7 @@ namespace jank::runtime auto const ns(typed_o->get_namespace()); if(ns.empty()) { - return jank_nil; + return jank_nil(); } return make_box(ns); } @@ -550,7 +550,7 @@ namespace jank::runtime switch(size) { case 0: - return jank_nil; + return jank_nil(); case 1: { return make_box(match_results[0].str()); @@ -613,7 +613,7 @@ namespace jank::runtime if(!match_results.suffix().str().empty()) { - return jank_nil; + return jank_nil(); } return smatch_to_vector(match_results); @@ -629,7 +629,7 @@ namespace jank::runtime } catch(...) { - return jank_nil; + return jank_nil(); } } else diff --git a/compiler+runtime/src/cpp/jank/runtime/core/equal.cpp b/compiler+runtime/src/cpp/jank/runtime/core/equal.cpp index fd7962b27..f234d01c3 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/equal.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/equal.cpp @@ -37,9 +37,9 @@ namespace jank::runtime return 0; } - if(l != jank_nil) + if(l != jank_nil()) { - if(r == jank_nil) + if(r == jank_nil()) { return 1; } diff --git a/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp b/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp index 162ec0995..903c9eb53 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp @@ -23,11 +23,11 @@ namespace jank::runtime if constexpr(behavior::metadatable) { - return typed_m->meta.unwrap_or(jank_nil); + return typed_m->meta.unwrap_or(jank_nil()); } else { - return jank_nil; + return jank_nil(); } }, m); @@ -105,15 +105,15 @@ namespace jank::runtime { using namespace jank::runtime; - auto const meta(o.unwrap_or(jank_nil)); + auto const meta(o.unwrap_or(jank_nil())); auto const source(get(meta, __rt_ctx->intern_keyword("jank/source").expect_ok())); - if(source == jank_nil) + if(source == jank_nil()) { return read::source::unknown(); } auto const file(get(source, __rt_ctx->intern_keyword("file").expect_ok())); - if(file == jank_nil) + if(file == jank_nil()) { return read::source::unknown(); } @@ -150,7 +150,7 @@ namespace jank::runtime read::source object_source(object_ref const o) { auto const meta(runtime::meta(o)); - if(meta == jank_nil) + if(meta == jank_nil()) { return read::source::unknown(); } diff --git a/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp b/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp index 7ee83ee28..3ea0e78eb 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp @@ -578,7 +578,7 @@ namespace jank::runtime } else { - return jank_nil; + return jank_nil(); } }, m); @@ -623,7 +623,7 @@ namespace jank::runtime } else { - return jank_nil; + return jank_nil(); } }, m); @@ -645,7 +645,7 @@ namespace jank::runtime ret = get(ret, e); } - if(ret == jank_nil) + if(ret == jank_nil()) { return fallback; } @@ -655,7 +655,7 @@ namespace jank::runtime } else { - return jank_nil; + return jank_nil(); } }, m); @@ -678,7 +678,7 @@ namespace jank::runtime } else { - return jank_nil; + return jank_nil(); } }, s, @@ -720,7 +720,7 @@ namespace jank::runtime } else if constexpr(behavior::associatively_writable) { - using R = decltype(assoc(typed_m, jank_nil, jank_nil)); + using R = decltype(assoc(typed_m, jank_nil(), jank_nil())); return visit_map_like( [](auto const typed_other, auto const typed_m) -> object_ref { @@ -756,7 +756,7 @@ namespace jank::runtime using T = typename decltype(typed_m)::value_type; if constexpr(behavior::associatively_writable_in_place) { - using R = decltype(assoc_in_place(typed_m, jank_nil, jank_nil)); + using R = decltype(assoc_in_place(typed_m, jank_nil(), jank_nil())); return visit_map_like( [](auto const typed_other, auto const typed_m) -> object_ref { @@ -809,7 +809,7 @@ namespace jank::runtime { throw std::runtime_error{ util::format("index out of bounds: {}", index) }; } - else if(o == jank_nil) + else if(o == jank_nil()) { return o; } @@ -846,7 +846,7 @@ namespace jank::runtime object_ref nth(object_ref const o, object_ref const idx, object_ref const fallback) { auto const index(to_int(idx)); - if(index < 0 || o == jank_nil) + if(index < 0 || o == jank_nil()) { return fallback; } @@ -882,7 +882,7 @@ namespace jank::runtime object_ref peek(object_ref const o) { - if(o == jank_nil) + if(o == jank_nil()) { return o; } @@ -905,7 +905,7 @@ namespace jank::runtime object_ref pop(object_ref const o) { - if(o == jank_nil) + if(o == jank_nil()) { return o; } @@ -939,7 +939,7 @@ namespace jank::runtime } else { - return jank_nil; + return jank_nil(); } }, o); @@ -1107,7 +1107,7 @@ namespace jank::runtime { auto const buffer(try_object(buff)); buffer->append(val); - return jank_nil; + return jank_nil(); } object_ref chunk(object_ref const buff) diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/chunked_cons.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/chunked_cons.cpp index 7f4bdc6c0..f6c730922 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/chunked_cons.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/chunked_cons.cpp @@ -90,9 +90,9 @@ namespace jank::runtime::obj { o->head = typed_tail->first(); o->tail = typed_tail->next(); - if(o->tail == jank_nil) + if(o->tail == jank_nil()) { - o->tail = jank_nil; + o->tail = jank_nil(); } return o; } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/iterator.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/iterator.cpp index c147b1220..ccc3b3fcb 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/iterator.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/iterator.cpp @@ -45,7 +45,7 @@ namespace jank::runtime::obj if(cached_next.is_some()) { current = cached_next->first(); - cached_next = jank_nil; + cached_next = jank_nil(); } else { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/jit_closure.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/jit_closure.cpp index 65d791826..91dbd0741 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/jit_closure.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/jit_closure.cpp @@ -36,7 +36,7 @@ namespace jank::runtime::obj void jit_closure::to_string(jtl::string_builder &buff) { - auto const name(get(meta.unwrap_or(jank_nil), __rt_ctx->intern_keyword("name").expect_ok())); + auto const name(get(meta.unwrap_or(jank_nil()), __rt_ctx->intern_keyword("name").expect_ok())); util::format_to( buff, "#object [{} {} {}]", diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/jit_function.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/jit_function.cpp index 5a8187d53..6964b681e 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/jit_function.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/jit_function.cpp @@ -35,7 +35,7 @@ namespace jank::runtime::obj void jit_function::to_string(jtl::string_builder &buff) { - auto const name(get(meta.unwrap_or(jank_nil), __rt_ctx->intern_keyword("name").expect_ok())); + auto const name(get(meta.unwrap_or(jank_nil()), __rt_ctx->intern_keyword("name").expect_ok())); util::format_to( buff, "#object [{} {} {}]", diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp index 328597091..dade9af1a 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp @@ -37,8 +37,8 @@ namespace jank::runtime::obj return {}; } auto const r(runtime::fresh_seq(s)); - jank_debug_assert(r != jank_nil); - return make_box(jank_nil, r); + jank_debug_assert(r != jank_nil()); + return make_box(jank_nil(), r); } object_ref lazy_sequence::first() const @@ -104,7 +104,7 @@ namespace jank::runtime::obj if(sv.is_some()) { auto ls{ sv }; - sv = jank_nil; + sv = jank_nil(); if(ls.is_some() && ls->type == object_type::lazy_sequence) { ls = unwrap(ls); @@ -118,7 +118,7 @@ namespace jank::runtime::obj if(fn.is_some()) { sv = dynamic_call(fn); - fn = jank_nil; + fn = jank_nil(); } } @@ -152,7 +152,7 @@ namespace jank::runtime::obj lazy_sequence_ref lazy_sequence::with_meta(object_ref const m) const { - auto const ret(make_box(jank_nil, seq())); + auto const ret(make_box(jank_nil(), seq())); auto const meta(behavior::detail::validate_meta(m)); ret->meta = meta; return ret; diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/multi_function.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/multi_function.cpp index 2817fc676..ba1906465 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/multi_function.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/multi_function.cpp @@ -199,7 +199,7 @@ namespace jank::runtime::obj multi_function_ref multi_function::reset() { std::lock_guard const locked{ data_lock }; - cached_hierarchy = jank_nil; + cached_hierarchy = jank_nil(); method_table = prefer_table = method_cache = persistent_hash_map::empty(); return this; } @@ -255,7 +255,7 @@ namespace jank::runtime::obj object_ref const y) const { auto const x_prefs(prefer_table->get(x)); - if(x_prefs != jank_nil && expect_object(x_prefs)->contains(y)) + if(x_prefs != jank_nil() && expect_object(x_prefs)->contains(y)) { return true; } @@ -264,7 +264,7 @@ namespace jank::runtime::obj __rt_ctx->intern_var("clojure.core", "parents").expect_ok()->deref() }; - for(auto it(fresh_seq(dynamic_call(parents, hierarchy, y))); it != jank_nil; + for(auto it(fresh_seq(dynamic_call(parents, hierarchy, y))); it != jank_nil(); it = next_in_place(it)) { if(is_preferred(hierarchy, x, first(it))) @@ -273,7 +273,7 @@ namespace jank::runtime::obj } } - for(auto it(fresh_seq(dynamic_call(parents, hierarchy, x))); it != jank_nil; + for(auto it(fresh_seq(dynamic_call(parents, hierarchy, x))); it != jank_nil(); it = next_in_place(it)) { if(is_preferred(hierarchy, first(it), y)) @@ -303,7 +303,7 @@ namespace jank::runtime::obj object_ref multi_function::get_fn(object_ref const dispatch_val) { auto const target(get_method(dispatch_val)); - if(target == jank_nil) + if(target == jank_nil()) { throw std::runtime_error{ util::format("No method in multimethod '{}' for dispatch value: {}", runtime::to_string(name), @@ -320,7 +320,7 @@ namespace jank::runtime::obj } auto const target(method_cache->get(dispatch_val)); - if(target != jank_nil) + if(target != jank_nil()) { return target; } @@ -332,7 +332,7 @@ namespace jank::runtime::obj { /* TODO: Clojure uses a RW lock here for better parallelism. */ std::lock_guard const locked{ data_lock }; - object_ref best_value{ jank_nil }; + object_ref best_value{ jank_nil() }; persistent_vector_sequence_ref best_entry{}; for(auto it(method_table->fresh_seq()); it.is_some(); it = it->next_in_place()) @@ -367,7 +367,7 @@ namespace jank::runtime::obj else { best_value = method_table->get(default_dispatch_value); - if(best_value == jank_nil) + if(best_value == jank_nil()) { return best_value; } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp index 1645ebb90..a70fea469 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp @@ -72,7 +72,7 @@ namespace jank::runtime::obj { auto const name_kw(__rt_ctx->intern_keyword("name").expect_ok()); auto const name_meta(runtime::get(f.meta.unwrap(), name_kw)); - if(name_meta != jank_nil) + if(name_meta != jank_nil()) { name = to_string(name_meta); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp index d678b0bc8..2c4719dde 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp @@ -108,19 +108,10 @@ namespace jank::runtime return lhs->type != object_type::nil; } - static obj::weak_nil_ref nil_const() + obj::weak_nil_ref jank_nil() { static obj::nil n; n.base.retain(); return &n; } - - namespace detail - { - /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ - obj::nil *jank_nil_ptr{ nil_const().data }; - } - - /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ - obj::weak_nil_ref jank_nil{ nil_const() }; } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_array_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_array_map.cpp index 7b40f1e9d..6bee67e1a 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_array_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_array_map.cpp @@ -29,7 +29,7 @@ namespace jank::runtime::obj object_ref persistent_array_map::get(object_ref const key) const { - return data.find(key).unwrap_or(jank_nil); + return data.find(key).unwrap_or(jank_nil()); } object_ref persistent_array_map::get(object_ref const key, object_ref const fallback) const @@ -44,7 +44,7 @@ namespace jank::runtime::obj { return make_box(std::in_place, key, res.unwrap()); } - return jank_nil; + return jank_nil(); } bool persistent_array_map::contains(object_ref const key) const diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp index 793e95923..c3f0e5d8b 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp @@ -79,7 +79,7 @@ namespace jank::runtime::obj { return *res; } - return jank_nil; + return jank_nil(); } object_ref persistent_hash_map::get(object_ref const key, object_ref const fallback) const @@ -99,7 +99,7 @@ namespace jank::runtime::obj { return make_box(std::in_place, key, *res); } - return jank_nil; + return jank_nil(); } bool persistent_hash_map::contains(object_ref const key) const diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp index f9ce7b519..81eb92527 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp @@ -133,7 +133,7 @@ namespace jank::runtime::obj auto const found(data.find(o)); if(!found) { - return jank_nil; + return jank_nil(); } return *found; } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp index 87709932e..15530a216 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp @@ -126,7 +126,7 @@ namespace jank::runtime::obj auto const first(data.first()); if(first.is_none()) { - return jank_nil; + return jank_nil(); } return first.unwrap(); } @@ -161,7 +161,7 @@ namespace jank::runtime::obj object_ref persistent_list::peek() const { - return data.first().unwrap_or(jank_nil); + return data.first().unwrap_or(jank_nil()); } persistent_list_ref persistent_list::pop() const diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp index 212a26131..fcdeaced3 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp @@ -75,7 +75,7 @@ namespace jank::runtime::obj { return res->second; } - return jank_nil; + return jank_nil(); } object_ref persistent_sorted_map::get(object_ref const key, object_ref const fallback) const @@ -95,7 +95,7 @@ namespace jank::runtime::obj { return make_box(std::in_place, key, res->second); } - return jank_nil; + return jank_nil(); } bool persistent_sorted_map::contains(object_ref const key) const diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp index 69b36ce3d..aa2c368ed 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp @@ -143,7 +143,7 @@ namespace jank::runtime::obj { return *found; } - return jank_nil; + return jank_nil(); } transient_sorted_set_ref persistent_sorted_set::to_transient() const diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp index 7221ddef5..e06d9c195 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp @@ -62,7 +62,7 @@ namespace jank::runtime::obj object_ref persistent_string::get(object_ref const key) const { - return get(key, jank_nil); + return get(key, jank_nil()); } object_ref persistent_string::get(object_ref const key, object_ref const fallback) const diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp index 53b5e200d..b94956b04 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp @@ -196,7 +196,7 @@ namespace jank::runtime::obj object_ref persistent_vector::get(object_ref const key) const { - return get(key, jank_nil); + return get(key, jank_nil()); } object_ref persistent_vector::get(object_ref const key, object_ref const fallback) const @@ -223,14 +223,14 @@ namespace jank::runtime::obj auto const i(expect_object(key)->data); if(i < 0 || data.size() <= static_cast(i)) { - return jank_nil; + return jank_nil(); } /* TODO: Map entry type? */ return make_box(std::in_place, key, data[i]); } else { - return jank_nil; + return jank_nil(); } } @@ -281,7 +281,7 @@ namespace jank::runtime::obj { if(data.empty()) { - return jank_nil; + return jank_nil(); } return data[data.size() - 1]; diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp index eb05c786b..04a5bbd69 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp @@ -82,7 +82,7 @@ namespace jank::runtime::obj object_ref tagged_literal::get(object_ref const key) const { - return get(key, jank_nil); + return get(key, jank_nil()); } object_ref tagged_literal::get_entry(object_ref const key) const @@ -100,7 +100,7 @@ namespace jank::runtime::obj return make_box(std::in_place, form_kw, form); } - return jank_nil; + return jank_nil(); } bool tagged_literal::contains(object_ref const key) const diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_array_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_array_map.cpp index fdd6d8816..f6a4c9917 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_array_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_array_map.cpp @@ -64,7 +64,7 @@ namespace jank::runtime::obj object_ref transient_array_map::get(object_ref const key) const { assert_active(); - return data.find(key).unwrap_or(jank_nil); + return data.find(key).unwrap_or(jank_nil()); } object_ref transient_array_map::get(object_ref const key, object_ref const fallback) const @@ -79,7 +79,7 @@ namespace jank::runtime::obj { return make_box(std::in_place, key, res.unwrap()); } - return jank_nil; + return jank_nil(); } bool transient_array_map::contains(object_ref const key) const diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_map.cpp index 538a6be5c..9001a44a4 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_map.cpp @@ -81,7 +81,7 @@ namespace jank::runtime::obj { return *res; } - return jank_nil; + return jank_nil(); } object_ref transient_hash_map::get(object_ref const key, object_ref const fallback) const @@ -103,7 +103,7 @@ namespace jank::runtime::obj { return make_box(std::in_place, key, *res); } - return jank_nil; + return jank_nil(); } bool transient_hash_map::contains(object_ref const key) const diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_set.cpp index c254e8791..9d6e927ba 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_set.cpp @@ -81,7 +81,7 @@ namespace jank::runtime::obj auto const found(data.find(elem)); if(!found) { - return jank_nil; + return jank_nil(); } return *found; } @@ -110,7 +110,7 @@ namespace jank::runtime::obj object_ref transient_hash_set::get_entry(object_ref const elem) const { auto const found = call(elem); - auto const nil(jank_nil); + auto const nil(jank_nil()); if(found == nil) { return nil; diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp index 530c8e4cb..9a7c9f994 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp @@ -67,7 +67,7 @@ namespace jank::runtime::obj { return res->second; } - return jank_nil; + return jank_nil(); } object_ref transient_sorted_map::get(object_ref const key, object_ref const fallback) const @@ -89,7 +89,7 @@ namespace jank::runtime::obj { return make_box(std::in_place, key, res->second); } - return jank_nil; + return jank_nil(); } bool transient_sorted_map::contains(object_ref const key) const diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp index cba4ce9af..a18120004 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp @@ -78,7 +78,7 @@ namespace jank::runtime::obj { return *found; } - return jank_nil; + return jank_nil(); } object_ref transient_sorted_set::call(object_ref const elem, object_ref const fallback) @@ -105,7 +105,7 @@ namespace jank::runtime::obj object_ref transient_sorted_set::get_entry(object_ref const elem) { auto const found{ call(elem) }; - if(found == jank_nil) + if(found == jank_nil()) { return found; } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_vector.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_vector.cpp index 4c9ce26a2..c90ea73d8 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_vector.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_vector.cpp @@ -107,7 +107,7 @@ namespace jank::runtime::obj auto const i(expect_object(idx)->data); if(i < 0 || data.size() <= static_cast(i)) { - return jank_nil; + return jank_nil(); } return data[i]; @@ -146,7 +146,7 @@ namespace jank::runtime::obj auto const i(expect_object(idx)->data); if(i < 0 || data.size() <= static_cast(i)) { - return jank_nil; + return jank_nil(); } /* TODO: Map entry type? */ return make_box(std::in_place, idx, data[i]); diff --git a/compiler+runtime/src/cpp/jank/runtime/perf.cpp b/compiler+runtime/src/cpp/jank/runtime/perf.cpp index eff588226..84f9325ed 100644 --- a/compiler+runtime/src/cpp/jank/runtime/perf.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/perf.cpp @@ -45,6 +45,6 @@ namespace jank::runtime::perf }, f, label_str); - return jank_nil; + return jank_nil(); } } diff --git a/compiler+runtime/test/bash/ahead-of-time/src/jank-and-cpp-modules/my_lib.cpp b/compiler+runtime/test/bash/ahead-of-time/src/jank-and-cpp-modules/my_lib.cpp index fcd4b04d8..727fb8952 100644 --- a/compiler+runtime/test/bash/ahead-of-time/src/jank-and-cpp-modules/my_lib.cpp +++ b/compiler+runtime/test/bash/ahead-of-time/src/jank-and-cpp-modules/my_lib.cpp @@ -19,7 +19,7 @@ using namespace jank::runtime; static object_ref greet_str(object_ref name) { auto const s_obj(try_object(name)); - auto const new_str{ "Hello from cpp module, " + s_obj->to_string() + "!"}; + auto const new_str{ "Hello from cpp module, " + s_obj->to_string() + "!" }; return make_box(new_str).erase(); } @@ -41,6 +41,6 @@ extern "C" jank_object_ref jank_load_my_lib() intern_fn("greet-str", &greet_str); __rt_ctx->module_loader.set_is_loaded(ns_name); - std::cout<<"Loaded '"<current_ns_var->deref()), { offset, 1, offset + 1 }, { offset + width, 1, offset + width + 1 }, - runtime::jank_nil + runtime::jank_nil() }); } diff --git a/compiler+runtime/test/cpp/jank/read/parse.cpp b/compiler+runtime/test/cpp/jank/read/parse.cpp index 0110ca58c..cd5730002 100644 --- a/compiler+runtime/test/cpp/jank/read/parse.cpp +++ b/compiler+runtime/test/cpp/jank/read/parse.cpp @@ -39,7 +39,7 @@ namespace jank::read::parse lex::processor lp{ "nil" }; processor p{ lp.begin(), lp.end() }; auto const r(p.next()); - CHECK(equal(r.expect_ok().unwrap().ptr, jank_nil)); + CHECK(equal(r.expect_ok().unwrap().ptr, jank_nil())); CHECK(r.expect_ok().unwrap().start == lex::token{ 0, 3, lex::token_kind::nil }); CHECK(r.expect_ok().unwrap().end == r.expect_ok().unwrap().start); } diff --git a/compiler+runtime/test/cpp/jank/runtime/core/seq.cpp b/compiler+runtime/test/cpp/jank/runtime/core/seq.cpp index 26b019034..37bb4f315 100644 --- a/compiler+runtime/test/cpp/jank/runtime/core/seq.cpp +++ b/compiler+runtime/test/cpp/jank/runtime/core/seq.cpp @@ -12,9 +12,9 @@ namespace jank::runtime::core { TEST_CASE("sequence_equal") { - CHECK(sequence_equal(jank_nil, make_box())); - CHECK(sequence_equal(make_box(), jank_nil)); - CHECK(sequence_equal(make_box(), jank_nil)); + CHECK(sequence_equal(jank_nil(), make_box())); + CHECK(sequence_equal(make_box(), jank_nil())); + CHECK(sequence_equal(make_box(), jank_nil())); CHECK(sequence_equal(make_box(std::in_place, make_box('f')), make_box(std::in_place, make_box('f')))); CHECK(!sequence_equal(make_box(std::in_place, make_box('f')), diff --git a/compiler+runtime/test/cpp/jank/runtime/obj/persistent_string.cpp b/compiler+runtime/test/cpp/jank/runtime/obj/persistent_string.cpp index 34d631281..cc75ad9e1 100644 --- a/compiler+runtime/test/cpp/jank/runtime/obj/persistent_string.cpp +++ b/compiler+runtime/test/cpp/jank/runtime/obj/persistent_string.cpp @@ -25,9 +25,9 @@ namespace jank::runtime::obj CHECK(equal(s.get(min), min_char)); CHECK(equal(s.get(mid), mid_char)); CHECK(equal(s.get(max), max_char)); - CHECK(equal(s.get(over), jank_nil)); - CHECK(equal(s.get(under), jank_nil)); - CHECK(equal(s.get(non_int), jank_nil)); + CHECK(equal(s.get(over), jank_nil())); + CHECK(equal(s.get(under), jank_nil())); + CHECK(equal(s.get(non_int), jank_nil())); } TEST_CASE("get with fallback") { diff --git a/compiler+runtime/test/cpp/jank/runtime/obj/persistent_vector.cpp b/compiler+runtime/test/cpp/jank/runtime/obj/persistent_vector.cpp index 630192322..b17bdda7e 100644 --- a/compiler+runtime/test/cpp/jank/runtime/obj/persistent_vector.cpp +++ b/compiler+runtime/test/cpp/jank/runtime/obj/persistent_vector.cpp @@ -32,9 +32,9 @@ namespace jank::runtime::obj CHECK(equal(v->get(min), min_char)); CHECK(equal(v->get(mid), mid_char)); CHECK(equal(v->get(max), max_char)); - CHECK(equal(v->get(over), jank_nil)); - CHECK(equal(v->get(under), jank_nil)); - CHECK(equal(v->get(non_int), jank_nil)); + CHECK(equal(v->get(over), jank_nil())); + CHECK(equal(v->get(under), jank_nil())); + CHECK(equal(v->get(non_int), jank_nil())); } TEST_CASE("get with fallback") { @@ -59,9 +59,9 @@ namespace jank::runtime::obj CHECK(equal(v->get_entry(min), make_box(std::in_place, min, min_char))); CHECK(equal(v->get_entry(mid), make_box(std::in_place, mid, mid_char))); CHECK(equal(v->get_entry(max), make_box(std::in_place, max, max_char))); - CHECK(equal(v->get_entry(over), jank_nil)); - CHECK(equal(v->get_entry(under), jank_nil)); - CHECK(equal(v->get_entry(non_int), jank_nil)); + CHECK(equal(v->get_entry(over), jank_nil())); + CHECK(equal(v->get_entry(under), jank_nil())); + CHECK(equal(v->get_entry(non_int), jank_nil())); } TEST_CASE("equal") { diff --git a/compiler+runtime/test/cpp/jank/runtime/obj/repeat.cpp b/compiler+runtime/test/cpp/jank/runtime/obj/repeat.cpp index 0ddc5a372..1dab68e58 100644 --- a/compiler+runtime/test/cpp/jank/runtime/obj/repeat.cpp +++ b/compiler+runtime/test/cpp/jank/runtime/obj/repeat.cpp @@ -28,11 +28,11 @@ namespace jank::runtime::obj !equal(repeat::create(make_box(1), make_box(1)), repeat::create(make_box(0), make_box(1)))); CHECK(equal(repeat::create(make_box(0), make_box(0)), persistent_list::empty())); - CHECK(equal(seq(repeat::create(make_box(0), make_box(0))), jank_nil)); + CHECK(equal(seq(repeat::create(make_box(0), make_box(0))), jank_nil())); } TEST_CASE("seq") { - CHECK(equal(seq(repeat::create(make_box(0), make_box(0))), jank_nil)); + CHECK(equal(seq(repeat::create(make_box(0), make_box(0))), jank_nil())); } } } From bb526ef9f50d24e7b6efce65658e43c81850ffb5 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sun, 7 Dec 2025 23:27:04 -0800 Subject: [PATCH 070/122] Fix cppgen .o loading with global ctors --- .../include/cpp/jank/runtime/oref.hpp | 27 +++++++++++++++++++ .../src/cpp/jank/codegen/processor.cpp | 11 +++++--- .../src/cpp/jank/jit/processor.cpp | 2 +- .../src/cpp/jank/runtime/context.cpp | 5 ++++ .../src/cpp/jank/runtime/object.cpp | 4 +-- compiler+runtime/src/jank/clojure/core.jank | 3 ++- 6 files changed, 44 insertions(+), 8 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/runtime/oref.hpp b/compiler+runtime/include/cpp/jank/runtime/oref.hpp index 9812e7497..980eb060c 100644 --- a/compiler+runtime/include/cpp/jank/runtime/oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/oref.hpp @@ -125,6 +125,11 @@ namespace jank::runtime data = std::bit_cast(jank_const_nil()); } + void reset(object * const o) + { + data = o; + } + value_type *operator->() const { jank_assert_throw(data); @@ -241,6 +246,7 @@ namespace jank::runtime oref() : data{ std::bit_cast(jank_const_nil()) } { + jank_debug_assert(data); } oref(oref const &rhs) noexcept @@ -313,6 +319,26 @@ namespace jank::runtime data = std::bit_cast(jank_const_nil()); } + void reset(object * const o) + { + data = o; + } + + void reset(oref const &o) + { + data = o.data; + } + + void reset(T * const o) + { + data = o->base; + } + + void reset(oref const &o) + { + data = o.data; + } + T *operator->() const { /* TODO: Add type name. */ @@ -460,6 +486,7 @@ namespace jank::runtime oref() : data{ std::bit_cast(jank_const_nil()) } { + jank_debug_assert(data); } oref(nullptr_t) = delete; diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index c9361e9f7..25969c79b 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -2736,11 +2736,14 @@ namespace jank::codegen for(auto const &v : lifted_vars) { + /* Since global ctors don't run when loading object files, we + * need to manually initialize these. By using .reset, we ignore + * that they contain nullptr and we just imbue the new value. */ if(v.second.owned) { util::format_to( footer_buffer, - R"({}::{} = jank::runtime::__rt_ctx->intern_owned_var("{}").expect_ok();)", + R"({}::{}.reset(jank::runtime::__rt_ctx->intern_owned_var("{}").expect_ok());)", ns, v.second.native_name, v.first); @@ -2748,7 +2751,7 @@ namespace jank::codegen else { util::format_to(footer_buffer, - R"({}::{} = jank::runtime::__rt_ctx->intern_var("{}").expect_ok();)", + R"({}::{}.reset(jank::runtime::__rt_ctx->intern_var("{}").expect_ok());)", ns, v.second.native_name, v.first); @@ -2758,9 +2761,9 @@ namespace jank::codegen for(auto const &v : lifted_constants) { - util::format_to(footer_buffer, "{}::{} = ", ns, v.second); + util::format_to(footer_buffer, "{}::{}.reset(", ns, v.second); detail::gen_constant(v.first, footer_buffer, true); - util::format_to(footer_buffer, ";"); + util::format_to(footer_buffer, ");"); } util::format_to(footer_buffer, "{}::{}{ }.call();", ns, struct_name); diff --git a/compiler+runtime/src/cpp/jank/jit/processor.cpp b/compiler+runtime/src/cpp/jank/jit/processor.cpp index 4a8449eb6..82443ad8e 100644 --- a/compiler+runtime/src/cpp/jank/jit/processor.cpp +++ b/compiler+runtime/src/cpp/jank/jit/processor.cpp @@ -240,7 +240,7 @@ namespace jank::jit profile::timer const timer{ "jit eval_string" }; auto const &formatted{ s }; //auto const &formatted{ util::format_cpp_source(s).expect_ok() }; - util::println("// eval_string:\n{}\n", formatted); + //util::println("// eval_string:\n{}\n", formatted); auto err(interpreter->ParseAndExecute({ formatted.data(), formatted.size() }, ret)); if(err) { diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 78ff1a694..67bed46fa 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -185,6 +185,11 @@ namespace jank::runtime auto const &module(runtime::to_string(current_module_var->deref())); auto const name{ module::module_to_load_function(module) }; + if(forms.empty()) + { + forms.emplace_back(jank_nil()); + } + auto const form{ runtime::conj( runtime::conj(runtime::conj(make_box(jtl::move(forms)), obj::persistent_vector::empty()), diff --git a/compiler+runtime/src/cpp/jank/runtime/object.cpp b/compiler+runtime/src/cpp/jank/runtime/object.cpp index 1872c641d..dcdee8bc8 100644 --- a/compiler+runtime/src/cpp/jank/runtime/object.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/object.cpp @@ -10,14 +10,14 @@ namespace jank::runtime { ++ref_count; jank_debug_assert(ref_count > 0); - util::println("retain {} type {} count {}", this, object_type_str(type), ref_count); + //util::println("retain {} type {} count {}", this, object_type_str(type), ref_count); } void object::release() { jank_debug_assert(ref_count > 0); --ref_count; - util::println("release {} type {} count {}", this, object_type_str(type), ref_count); + //util::println("release {} type {} count {}", this, object_type_str(type), ref_count); if(ref_count == 0) { visit_object( diff --git a/compiler+runtime/src/jank/clojure/core.jank b/compiler+runtime/src/jank/clojure/core.jank index 21cf54045..919a10c2d 100644 --- a/compiler+runtime/src/jank/clojure/core.jank +++ b/compiler+runtime/src/jank/clojure/core.jank @@ -18,8 +18,9 @@ ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +:ok ; Defined in runtime::context ctor. -(def ^:dynamic *ns*) +;(def ^:dynamic *ns*) ;(def ^:dynamic *assert*) ;(def ^:dynamic *compile-files*) ;(def ^:dynamic *file*) From 5ef85e74bf9c30f3eed71c799c5da6014b4c43c0 Mon Sep 17 00:00:00 2001 From: jeaye Date: Mon, 8 Dec 2025 11:59:25 -0800 Subject: [PATCH 071/122] Fix atom ref counting --- .../include/cpp/jank/runtime/obj/atom.hpp | 4 + .../include/cpp/jank/runtime/oref.hpp | 5 + .../src/cpp/jank/codegen/processor.cpp | 23 +- .../src/cpp/jank/jit/processor.cpp | 1 + .../src/cpp/jank/runtime/context.cpp | 2 +- .../src/cpp/jank/runtime/obj/atom.cpp | 43 +- compiler+runtime/src/jank/clojure/core.jank | 15027 ++++++++-------- 7 files changed, 7576 insertions(+), 7529 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp index 479708a68..8048dc0fa 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp @@ -17,6 +17,7 @@ namespace jank::runtime::obj atom() = default; atom(object_ref o); + ~atom(); /* behavior::object_like */ bool equal(object const &) const; @@ -52,6 +53,9 @@ namespace jank::runtime::obj void remove_watch(object_ref key); object base{ obj_type }; + /* We have to hold only a raw pointer here, since std::atomic doesn't + * support more complex types. However, that means we need to manually + * handle reference counting for held values when swapping, resetting, etc. */ std::atomic val{}; /* Since watches is a 'persistent_hash_map", there in no guarantee in which * order watches are invoked. */ diff --git a/compiler+runtime/include/cpp/jank/runtime/oref.hpp b/compiler+runtime/include/cpp/jank/runtime/oref.hpp index 980eb060c..69210d50d 100644 --- a/compiler+runtime/include/cpp/jank/runtime/oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/oref.hpp @@ -130,6 +130,11 @@ namespace jank::runtime data = o; } + void reset(oref const &o) + { + data = o.data; + } + value_type *operator->() const { jank_assert_throw(data); diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 25969c79b..6142a1674 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -2737,31 +2737,36 @@ namespace jank::codegen for(auto const &v : lifted_vars) { /* Since global ctors don't run when loading object files, we - * need to manually initialize these. By using .reset, we ignore - * that they contain nullptr and we just imbue the new value. */ + * need to manually initialize these. We use placement new to + * properly run ctors, just like what would happen normally. */ if(v.second.owned) { util::format_to( footer_buffer, - R"({}::{}.reset(jank::runtime::__rt_ctx->intern_owned_var("{}").expect_ok());)", + R"(new (&{}::{}) jank::runtime::var_ref(jank::runtime::__rt_ctx->intern_owned_var("{}").expect_ok());)", ns, v.second.native_name, v.first); } else { - util::format_to(footer_buffer, - R"({}::{}.reset(jank::runtime::__rt_ctx->intern_var("{}").expect_ok());)", - ns, - v.second.native_name, - v.first); + util::format_to( + footer_buffer, + R"(new (&{}::{}) jank::runtime::var_ref(jank::runtime::__rt_ctx->intern_var("{}").expect_ok());)", + ns, + v.second.native_name, + v.first); } } for(auto const &v : lifted_constants) { - util::format_to(footer_buffer, "{}::{}.reset(", ns, v.second); + util::format_to(footer_buffer, + "new (&{}::{}) {}(", + ns, + v.second, + detail::gen_constant_type(v.first, true)); detail::gen_constant(v.first, footer_buffer, true); util::format_to(footer_buffer, ");"); } diff --git a/compiler+runtime/src/cpp/jank/jit/processor.cpp b/compiler+runtime/src/cpp/jank/jit/processor.cpp index 82443ad8e..889397b4f 100644 --- a/compiler+runtime/src/cpp/jank/jit/processor.cpp +++ b/compiler+runtime/src/cpp/jank/jit/processor.cpp @@ -239,6 +239,7 @@ namespace jank::jit { profile::timer const timer{ "jit eval_string" }; auto const &formatted{ s }; + /* TODO: There is some sort of immutable_string or result bug here. */ //auto const &formatted{ util::format_cpp_source(s).expect_ok() }; //util::println("// eval_string:\n{}\n", formatted); auto err(interpreter->ParseAndExecute({ formatted.data(), formatted.size() }, ret)); diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 67bed46fa..27db98825 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -211,7 +211,7 @@ namespace jank::runtime { profile::timer const timer{ "rt compile-module parse + write" }; codegen::processor cg_prc{ fn, module, codegen::compilation_target::module }; - util::println("{}\n", util::format_cpp_source(cg_prc.declaration_str()).expect_ok()); + //util::println("{}\n", util::format_cpp_source(cg_prc.declaration_str()).expect_ok()); auto const code{ cg_prc.declaration_str() }; auto parse_res{ jit_prc.interpreter->Parse({ code.data(), code.size() }) }; if(!parse_res) diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp index c3fe810cd..414f2f63c 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp @@ -11,6 +11,12 @@ namespace jank::runtime::obj : val{ o.data } , watches{ persistent_hash_map::empty() } { + o->retain(); + } + + atom::~atom() + { + val.load()->release(); } bool atom::equal(object const &o) const @@ -64,6 +70,8 @@ namespace jank::runtime::obj auto const v(val.load()); val = o.data; notify_watches(this, v, o); + o->retain(); + v->release(); return o; } @@ -75,7 +83,10 @@ namespace jank::runtime::obj if(val.compare_exchange_weak(v, o.data)) { notify_watches(this, v, o); - return make_box(std::in_place, v, o); + auto ret{ make_box(std::in_place, v, o) }; + o->retain(); + v->release(); + return ret; } } } @@ -90,6 +101,8 @@ namespace jank::runtime::obj if(val.compare_exchange_weak(v, next.data)) { notify_watches(this, v, next); + next->retain(); + v->release(); return next; } } @@ -105,6 +118,8 @@ namespace jank::runtime::obj if(val.compare_exchange_weak(v, next.data)) { notify_watches(this, v, next); + next->retain(); + v->release(); return next; } } @@ -120,6 +135,8 @@ namespace jank::runtime::obj if(val.compare_exchange_weak(v, next.data)) { notify_watches(this, v, next); + next->retain(); + v->release(); return next; } } @@ -137,6 +154,8 @@ namespace jank::runtime::obj if(val.compare_exchange_weak(v, next.data)) { notify_watches(this, v, next); + next->retain(); + v->release(); return next; } } @@ -151,7 +170,10 @@ namespace jank::runtime::obj if(val.compare_exchange_weak(v, next.data)) { notify_watches(this, v, next); - return make_box(std::in_place, v, next); + auto ret{ make_box(std::in_place, v, next) }; + next->retain(); + v->release(); + return ret; } } } @@ -165,7 +187,10 @@ namespace jank::runtime::obj if(val.compare_exchange_weak(v, next.data)) { notify_watches(this, v, next); - return make_box(std::in_place, v, next); + auto ret{ make_box(std::in_place, v, next) }; + next->retain(); + v->release(); + return ret; } } } @@ -180,7 +205,10 @@ namespace jank::runtime::obj if(val.compare_exchange_weak(v, next.data)) { notify_watches(this, v, next); - return make_box(std::in_place, v, next); + auto ret{ make_box(std::in_place, v, next) }; + next->retain(); + v->release(); + return ret; } } } @@ -198,7 +226,10 @@ namespace jank::runtime::obj if(val.compare_exchange_weak(v, next.data)) { notify_watches(this, v, next); - return make_box(std::in_place, v, next); + auto ret{ make_box(std::in_place, v, next) }; + next->retain(); + v->release(); + return ret; } } } @@ -211,6 +242,8 @@ namespace jank::runtime::obj if(ret) { notify_watches(this, old_val, new_val); + new_val->retain(); + old_val->release(); } return make_box(ret); } diff --git a/compiler+runtime/src/jank/clojure/core.jank b/compiler+runtime/src/jank/clojure/core.jank index 919a10c2d..c614b5efd 100644 --- a/compiler+runtime/src/jank/clojure/core.jank +++ b/compiler+runtime/src/jank/clojure/core.jank @@ -18,7519 +18,7518 @@ ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -:ok ; Defined in runtime::context ctor. -;(def ^:dynamic *ns*) -;(def ^:dynamic *assert*) -;(def ^:dynamic *compile-files*) -;(def ^:dynamic *file*) -; -;(def ^:dynamic *in* nil) -;(def ^:dynamic *out* nil) -;(def ^:dynamic *command-line-args* nil) -;(def ^:dynamic *warn-on-reflection* nil) -;(def ^:dynamic *compile-path* nil) -;(def ^:dynamic *unchecked-math* nil) -;(def ^:dynamic *compiler-options* nil) -;(def ^:dynamic *err* nil) -;(def ^:dynamic *flush-on-newline* nil) -;(def ^:dynamic *print-meta* nil) -;(def ^:dynamic *print-dup* nil) -;(def ^:dynamic *print-readably* nil) -;(def ^:dynamic *read-eval* nil) -; -;(cpp/raw "#include ") -;(cpp/raw "#include ") -;(cpp/raw "#include ") -; -;(cpp/raw "#include ") -;(cpp/raw "#include ") -;(cpp/raw "#include ") -;(cpp/raw "#include ") -; -;; Syntax quoting. -;(def unquote -; (fn* unquote [_] -; (throw "~ cannot be used outside of syntax quote"))) -;(def unquote-splicing -; (fn* unquote-splicing [_] -; (throw "~@ cannot be used outside of syntax quote"))) -; -;(def type (fn* type [o] -; (cpp/jank.runtime.object_type_str (cpp/.-type o)))) -; -;; Exceptions -;(def ex-info -; "Create an instance of ExceptionInfo, a RuntimeException subclass -; that carries a map of additional data." -; (fn* ex-info -; ([msg map] -; {:error msg -; :data map}) -; ([msg map cause] -; {:error msg -; :data map -; :cause cause}))) -; -;(def ex-message -; "Returns the message attached to ex if ex is a Throwable. -; Otherwise returns nil." -; :error) -; -;(def ex-data -; "Returns exception data (a map) if ex is an IExceptionInfo. -; Otherwise returns nil." -; :data) -; -;(def ex-cause -; "Returns the cause of ex if ex is a Throwable. -; Otherwise returns nil." -; :cause) -; -;; Relations. -;;; Miscellaneous. -;(def nil? -; "Returns true if x is nil, false otherwise." -; (fn* nil? [o] -; (cpp/== (cpp/.-type o) cpp/jank.runtime.object_type.nil))) -; -;(def identical? -; "Tests if 2 arguments are the same object, meaning the same pointer address." -; (fn* identical? [lhs rhs] -; (cpp/== lhs rhs))) -; -;; Collections. -;(def empty? -; "Returns true if coll has no items - same as (not (seq coll))." -; (fn* empty? [o] -; (cpp/jank.runtime.is_empty o))) -;(def empty -; "Returns an empty collection of the same category as coll, or nil" -; (fn* empty [o] -; (cpp/jank.runtime.empty o))) -;(def count -; "Returns the number of items in the collection. (count nil) returns -; 0. Also works on strings, arrays, and Java Collections and Maps" -; (fn* [coll] -; (cpp/jank.runtime.sequence_length coll))) -; -;; Numbers. -;(def boolean -; "Coerce to boolean" -; (fn* boolean [o] -; (cpp/jank.runtime.truthy o))) -;(def int -; "Coerce to int" -; (fn* int [o] -; (cpp/jank.runtime.to_int o))) -;(def float -; "Coerce to float" -; (fn* real [o] -; (cpp/jank.runtime.to_real o))) -; -;;; Sequences. -;(def seq -; "Returns a seq on the collection. If the collection is -; empty, returns nil. (seq nil) returns nil. seq also works on -; Strings, native Java arrays (of reference types) and any objects -; that implement Iterable. Note that seqs cache values, thus seq -; should not be used on any Iterable whose iterator repeatedly -; returns the same mutable object." -; (fn* seq [o] -; (cpp/jank.runtime.seq o))) -;(def fresh-seq -; (fn* fresh-seq [o] -; (cpp/jank.runtime.fresh_seq o))) -;(def first -; "Returns the first item in the collection. Calls seq on its -; argument. If coll is nil, returns nil." -; (fn* first [o] -; (cpp/jank.runtime.first o))) -;(def ffirst -; "Same as (first (first x))" -; (fn* ffirst [o] -; (first (first o)))) -;(def next -; "Returns a seq of the items after the first. Calls seq on its -; argument. If there are no more items, returns nil." -; (fn* next [o] -; (cpp/jank.runtime.next o))) -;(def next-in-place -; (fn* next-in-place [o] -; (cpp/jank.runtime.next_in_place o))) -;(def nnext -; "Same as (next (next x))" -; (fn* nnext [o] -; (next (next o)))) -;(def second -; "Same as (first (next x))" -; (fn* second [o] -; (cpp/jank.runtime.second o))) -;(def rest -; "Returns a possibly empty seq of the items after the first. Calls seq on its -; argument." -; (fn* rest [o] -; (cpp/jank.runtime.rest o))) -;(def cons -; "Returns a new seq where x is the first element and seq is -; the rest." -; (fn* cons [head tail] -; (cpp/jank.runtime.cons head tail))) -;(def coll? -; "Returns true if x implements IPersistentCollection" -; (fn* coll? [o] -; (cpp/jank.runtime.is_collection o))) -;(def seq? -; "Return true if x implements ISeq" -; (fn* seq? [o] -; (cpp/jank.runtime.is_seq o))) -;(def seqable? -; "Return true if the seq function is supported for x" -; (fn* seqable? [o] -; (cpp/jank.runtime.is_seqable o))) -; -;(def ^:private reverse* -; (fn* reverse* [coll] -; (loop* [acc '() -; coll (seq coll)] -; (if (empty? coll) -; acc -; (recur (cons (first coll) acc) -; (rest coll)))))) -; -;; XXX: The real concat will be defined later on, to be lazy. -;(def ^:private concat* -; (fn* concat* -; ([] -; '()) -; ([x] -; (seq x)) -; ([x y] -; (loop* [acc y -; x (reverse* x)] -; (if (empty? x) -; acc -; (recur (cons (first x) acc) -; (rest x))))) -; ([x y & zs] -; (let* [r (concat* x y)] -; (if (empty? zs) -; r -; (recur r (first zs) (rest zs))))))) -; -;; Lists. -;(def list? -; "Returns true if x implements IPersistentList" -; (fn* list? [o] -; (cpp/jank.runtime.is_list o))) -;(def list -; "Creates a new list containing the items." -; (fn* list [& args] -; (cpp/jank.runtime.list args))) -; -;;; Vectors. -;(def vector? -; "Return true if x implements IPersistentVector" -; (fn* vector? [o] -; (cpp/jank.runtime.is_vector o))) -;(def vec -; "Creates a new vector containing the contents of coll. Java arrays -; will be aliased and should not be modified." -; (fn* vec [o] -; (cpp/jank.runtime.vec o))) -; -;(def subvec -; "Returns a persistent vector of the items in vector from -; start (inclusive) to end (exclusive). If end is not supplied, -; defaults to (count vector). This operation is O(1) and very fast, as -; the resulting vector shares structure with the original and no -; trimming is done." -; (fn* subvec -; ([v start] -; (subvec v start (count v))) -; ([v start end] -; (cpp/jank.runtime.subvec v start end)))) -; -;(def conj -; "conj[oin]. Returns a new collection with the xs -; 'added'. (conj nil item) returns (item). -; (conj coll) returns coll. (conj) returns []. -; The 'addition' may happen at different 'places' depending -; on the concrete type." -; (fn* conj -; ([] -; []) -; ([coll] -; coll) -; ([coll x] -; (cpp/jank.runtime.conj coll x)) -; ([coll x & args] -; (let* [res (conj coll x)] -; (if (empty? args) -; res -; (recur res (first args) (next args))))))) -; -;(def last -; "Return the last item in coll, in linear time." -; (fn* last [s] -; (if (next s) -; (recur (next s)) -; (first s)))) -; -;(def butlast -; "Return a seq of all but the last item in coll, in linear time." -; (fn* butlast [s] -; (loop* [ret [] -; s s] -; (if (next s) -; (recur (conj ret (first s)) (next s)) -; (seq ret))))) -; -;;; Maps. -;(def hash-map -; "keyval => key val -; Returns a new hash map with supplied mappings. If any keys are -; equal, they are handled as if by repeated uses of assoc." -; (fn* hash-map -; ([] (cpp/jank.runtime.obj.persistent_hash_map.empty)) -; ([& keyvals] -; (cpp/jank.runtime.obj.persistent_hash_map.create_from_seq keyvals)))) -; -;(def sorted-map -; "keyval => key val -; Returns a new sorted map with supplied mappings. If any keys are -; equal, they are handled as if by repeated uses of assoc." -; (fn* sorted-map -; ([] (cpp/jank.runtime.obj.persistent_sorted_map.empty)) -; ([& keyvals] -; (cpp/jank.runtime.obj.persistent_sorted_map.create_from_seq keyvals)))) -; -;(def map? -; "Return true if x implements IPersistentMap" -; (fn* map? [o] -; (cpp/jank.runtime.is_map o))) -; -;(def associative? -; "Returns true if coll implements Associative" -; (fn* associative? [o] -; (cpp/jank.runtime.is_associative o))) -; -;(def assoc -; "assoc[iate]. When applied to a map, returns a new map of the -; same (hashed/sorted) type, that contains the mapping of key(s) to -; val(s). When applied to a vector, returns a new vector that -; contains val at index. Note - index must be <= (count vector)." -; (fn* assoc -; ([map key val] -; (cpp/jank.runtime.assoc map key val)) -; ([map key val & kvs] -; (let* [res (assoc map key val)] -; (if kvs -; (if (next kvs) -; (recur res (first kvs) (second kvs) (nnext kvs)) -; (throw "assoc expects even number of args after the first")) -; res))))) -; -;;; Strings. -;(def string? -; "Return true if x is a String" -; (fn* string? [o] -; (cpp/jank.runtime.is_string o))) -; -;(def char? -; "Return true if x is a Character" -; (fn* char? [o] -; (cpp/jank.runtime.is_char o))) -; -;(def str -; "With no args, returns the empty string. With one arg x, returns -; x.toString(). (str nil) returns the empty string. With more than -; one arg, returns the concatenation of the str values of the args." -; (fn* str -; ([] -; "") -; ([o] -; (if (nil? o) -; "" -; (cpp/jank.runtime.to_string o))) -; ([o & args] -; (cpp/jank.runtime.str o args)))) -; -;;; Symbols. -;(def symbol? -; "Return true if x is a Symbol" -; (fn* symbol? [o] -; (cpp/jank.runtime.is_symbol o))) -;(def -; symbol -; "Returns a Symbol with the given namespace and name. Arity-1 works -; on strings, keywords, and vars." -; (fn* symbol -; ([o] -; (cpp/jank.runtime.to_unqualified_symbol o)) -; ([ns o] -; (if (nil? ns) -; (symbol o) -; (cpp/jank.runtime.to_qualified_symbol ns o))))) -;(def simple-symbol? -; "Return true if x is a symbol without a namespace" -; (fn* simple-symbol? [x] -; (cpp/jank.runtime.is_simple_symbol x))) -;(def qualified-symbol? -; "Return true if x is a symbol with a namespace" -; (fn* qualified-symbol? [x] -; (cpp/jank.runtime.is_qualified_symbol x))) -; -;; Relations. -;;; Miscellaneous. -;(def true? -; "Returns true if x is the value true, false otherwise." -; (fn* true? [x] -; (cpp/jank.runtime.is_true x))) -;(def false? -; "Returns true if x is the value false, false otherwise." -; (fn* false? [x] -; (cpp/jank.runtime.is_false x))) -;(def not -; "Returns true if x is logical false, false otherwise." -; (fn* not [x] -; (cpp/clojure.core_native.not_ x))) -;(def some? -; "Returns true if x is not nil, false otherwise." -; (fn* some? [x] -; (cpp/jank.runtime.is_some x))) -; -;;; Metadata. -;(def meta -; "Returns the metadata of obj, returns nil if there is no metadata." -; (fn* meta [obj] -; (cpp/jank.runtime.meta obj))) -;(def with-meta -; "Returns an object of the same type and value as obj, with -; map m as its metadata." -; (fn* with-meta [obj m] -; (cpp/jank.runtime.with_meta obj m))) -;(def reset-meta! -; "Atomically resets the metadata for a namespace/var/ref/agent/atom" -; (fn* [iref metadata-map] -; (cpp/jank.runtime.reset_meta iref metadata-map))) -; -;;; Input/output. -;(def print -; "Prints the object(s) to the output stream that is the current value -; of *out*. print and println produce output for human consumption." -; (fn* print [& more] -; (cpp/jank.runtime.print more))) -;(def println -; "Same as print followed by (newline)" -; (fn* println [& more] -; (cpp/jank.runtime.println more))) -;(def pr -; "Prints the object(s) to the output stream that is the current value -; of *out*. Prints the object(s), separated by spaces if there is -; more than one. By default, pr and prn print in a way that objects -; can be read by the reader" -; (fn* pr [& more] -; (cpp/jank.runtime.pr more))) -;(def prn -; "Same as pr followed by (newline). Observes *flush-on-newline*" -; (fn* prn [& more] -; (cpp/jank.runtime.prn more))) -;(def pr-str -; "pr to a string, returning it" -; ;; TODO: support multiple parameters, preserving current behavior -; (fn* pr-str [x] -; (cpp/jank.runtime.to_code_string x))) -; -;;; Utils. -;; The full `apply` will be defined below, but it requires more helpers to support -;; all of its arities. This version of apply* is used by the parser for syntax quoting. -;; This allows us to use syntax quoting sooner and also have more easily inlinable -;; syntax quoting code, since this version of apply is lighter than the full version. -;(def ^:private apply* -; (fn* apply* [source args] -; (cpp/jank.runtime.apply_to source args))) -; -;(def ^{:macro true} let -; (fn* let [&form &env & decl] -; `(let* ~@decl))) -; -;(def ^{:macro true} loop -; (fn* loop [&form &env & decl] -; `(loop* ~@decl))) -; -;(def ^{:macro true} fn -; (fn* fn [&form &env & decl] -; (with-meta `(fn* ~@decl) (meta &form)))) -; -;(def = -; "Equality. Returns true if x equals y, false if not. It also works -; for nil and compares numbers and collections in a type-independent -; manner. Clojure's immutable data structures define equals() (and -; thus =) as a value, not an identity, comparison." -; (fn* = -; ([x] true) -; ([x y] -; (cpp/jank.runtime.equal x y)) -; ([x y & more] -; (if (cpp/jank.runtime.equal x y) -; (if (next more) -; (recur y (first more) (next more)) -; (cpp/jank.runtime.equal y (first more))) -; false)))) -; -;(def == -; "Returns non-nil if nums all have the equivalent -; value (type-independent), otherwise false" -; (fn* == -; ([x] true) -; ([x y] -; (cpp/jank.runtime.is_equiv x y)) -; ([x y & more] -; (if (cpp/jank.runtime.is_equiv x y) -; (if (next more) -; (recur y (first more) (next more)) -; (cpp/jank.runtime.is_equiv y (first more))) -; false)))) -; -;(def ^:private sigs -; (fn* [fdecl] -; (let* [asig (fn* asig [fdecl] -; (let* [arglist (first fdecl) -; ;elide implicit macro args -; arglist (if (= '&form (first arglist)) -; (subvec arglist 2 (count arglist)) -; arglist) -; body (next fdecl)] -; (if (map? (first body)) -; (if (next body) -; (with-meta arglist (conj (if (meta arglist) -; (meta arglist) -; {}) -; (first body))) -; arglist) -; arglist)))] -; (if (seq? (first fdecl)) -; (loop* [ret [] -; fdecls fdecl] -; (if fdecls -; (recur (conj ret (asig (first fdecls))) (next fdecls)) -; (seq ret))) -; (list (asig fdecl)))))) -; -;; Macros. -;(def ^{:macro true -; :doc "Same as (def name (fn [params* ] exprs*)) or (def -; name (fn ([params* ] exprs*)+)) with any doc-string or attrs added -; to the var metadata. prepost-map defines a map with optional keys -; :pre and :post that contain collections of pre or post conditions."} -; defn -; (fn* defn [&form &env name & fdecl] -; ;; Note: Cannot delegate this check to def because of the call to (with-meta name ..) -; (if (not (symbol? name)) -; (throw "First argument to defn must be a symbol")) -; (let* [m (if (string? (first fdecl)) -; {:doc (first fdecl)} -; {}) -; fdecl (if (string? (first fdecl)) -; (next fdecl) -; fdecl) -; m (if (map? (first fdecl)) -; (conj m (first fdecl)) -; m) -; fdecl (if (map? (first fdecl)) -; (next fdecl) -; fdecl) -; fdecl (if (vector? (first fdecl)) -; (list fdecl) -; fdecl) -; m (if (map? (last fdecl)) -; (conj m (last fdecl)) -; m) -; fdecl (if (map? (last fdecl)) -; (butlast fdecl) -; fdecl) -; m (conj {:arglists (list 'quote (sigs fdecl))} m) -; m (let* [inline (:inline m) -; ifn (first inline) -; iname (second inline)] -; ;; same as: (if (and (= 'fn ifn) (not (symbol? iname))) ...) -; (if (if (= 'fn ifn) -; (if (symbol? iname) -; false -; true)) -; ;; inserts the same fn name to the inline fn if it does not have one -; (assoc m :inline (cons ifn (cons (symbol (str iname "__inliner")) -; (next inline)))) -; m)) -; m (conj (if (meta name) (meta name) {}) m)] -; `(def ~(with-meta name m) -; ~(with-meta `(fn ~name ~@fdecl) {:rettag (:tag m)}))))) -; -;(defn macroexpand-1 -; "If form represents a macro form, returns its expansion, -; else returns form." -; [form] -; (cpp/jank.runtime.macroexpand1 form)) -;(defn macroexpand -; "Repeatedly calls macroexpand-1 on form until it no longer -; represents a macro form, then returns it. Note neither -; macroexpand-1 nor macroexpand expand macros in subforms." -; [form] -; (cpp/jank.runtime.macroexpand form)) -; -;(defn gensym -; "Returns a new symbol with a unique name. If a prefix string is -; supplied, the name is prefix# where # is some unique number. If -; prefix is not supplied, the prefix is 'G__'." -; ([] -; (cpp/jank.runtime.gensym "G__")) -; ([prefix-string] -; (cpp/jank.runtime.gensym prefix-string))) -; -;(defn -; ^{:macro true -; :doc "Like defn, but the resulting function name is declared as a -; macro and will be used as a macro by the compiler when it is -; called."} -; defmacro -; [&form &env name & args] -; (let [prefix (loop [p (list name) args args] -; (let [f (first args)] -; (if (string? f) -; (recur (cons f p) (next args)) -; (if (map? f) -; (recur (cons f p) (next args)) -; p)))) -; fdecl (loop [fd args] -; (if (string? (first fd)) -; (recur (next fd)) -; (if (map? (first fd)) -; (recur (next fd)) -; fd))) -; fdecl (if (vector? (first fdecl)) -; (list fdecl) -; fdecl) -; add-implicit-args (fn [fd] -; (let [args (first fd)] -; (cons (vec (cons '&form (cons '&env args))) (next fd)))) -; add-args (fn [acc ds] -; (if (nil? ds) -; acc -; (let [d (first ds)] -; (if (map? d) -; (conj acc d) -; (recur (conj acc (add-implicit-args d)) (next ds)))))) -; fdecl (seq (add-args [] fdecl)) -; decl (loop [p prefix d fdecl] -; (if p -; (recur (next p) (cons (first p) d)) -; d))] -; (list 'do -; (cons `defn decl) -; (list `reset-meta! (list 'var name) (list 'assoc -; (list 'meta (list 'var name)) -; :macro -; true)) -; (list 'var name)))) -; -;(defmacro defn- -; "Same as defn, yielding non-public def." -; {:added "1.0"} -; [name & decls] -; (cons `defn (cons (with-meta name (assoc (meta name) :private true)) decls))) -; -;(defmacro when -; "Evaluates test. If logical true, evaluates body in an implicit do." -; [condition & body] -; (list 'if condition -; (cons 'do body) -; nil)) -; -;(defmacro when-not -; "Evaluates test. If logical false, evaluates body in an implicit do." -; [condition & body] -; (list 'if (list 'clojure.core/not condition) -; (cons 'do body) -; nil)) -; -;(defmacro cond -; "Takes a set of test/expr pairs. It evaluates each test one at a -; time. If a test returns logical true, cond evaluates and returns -; the value of the corresponding expr and doesn't evaluate any of the -; other tests or exprs. (cond) returns nil." -; [& clauses] -; (when clauses -; (list 'if (first clauses) -; (if (next clauses) -; (second clauses) -; (let [err "cond requires an even number of forms"] -; (list 'throw (list 'clojure.core/ex-info "invalid cond" {:err err})))) -; (cons 'clojure.core/cond (next (next clauses)))))) -; -;(defmacro or -; "Evaluates exprs one at a time, from left to right. If a form -; returns a logical true value, or returns that value and doesn't -; evaluate any of the other expressions, otherwise it returns the -; value of the last expression. (or) returns nil." -; ([] -; nil) -; ([x] -; x) -; ([x & more] -; (let [x-res (gensym)] -; (list `let [x-res x] -; (list 'if x-res -; x-res -; (cons `or more)))))) -; -;(defmacro and -; "Evaluates exprs one at a time, from left to right. If a form -; returns logical false (nil or false), and returns that value and -; doesn't evaluate any of the other expressions, otherwise it returns -; the value of the last expr. (and) returns true." -; ([] -; true) -; ([x] -; x) -; ([x & more] -; (let [x-res (gensym)] -; (list `let [x-res x] -; (list 'if x-res -; (cons `and more) -; x-res))))) -; -;(defmacro assert -; "Evaluates expr and throws an exception if it does not evaluate to -; logical true." -; ([x] -; (when *assert* -; (list `when-not x -; (list 'throw (list `ex-info -; "assertion failed" -; {:assertion (pr-str x)}))))) -; ([x message] -; (when *assert* -; (list `when-not x -; (list 'throw (list `ex-info -; "assertion failed" -; {:assertion (pr-str x) -; :message message})))))) -; -;(defmacro comment -; "Ignores body, yields nil" -; [& body]) -; -;;; Transients. -;(defn- transientable? -; "Returns a whether the collection can be made transient." -; [coll] -; (cpp/jank.runtime.is_transientable coll)) -; -;(defn transient -; "Returns a new, transient version of the collection, in constant time." -; [coll] -; (cpp/jank.runtime.transient coll)) -; -;(defn persistent! -; "Returns a new, persistent version of the transient collection, in -; constant time. The transient collection cannot be used after this -; call, any such use will throw an exception." -; [coll] -; (cpp/jank.runtime.persistent coll)) -; -;(defn conj! -; "Adds x to the transient collection, and return coll. The 'addition' -; may happen at different 'places' depending on the concrete type." -; ([] -; (transient [])) -; ([coll] -; coll) -; ([coll x] -; (cpp/jank.runtime.conj_in_place coll x))) -; -;(defn assoc! -; "When applied to a transient map, adds mapping of key(s) to -; val(s). When applied to a transient vector, sets the val at index. -; Note - index must be <= (count vector). Returns coll." -; ([coll k v] -; (cpp/jank.runtime.assoc_in_place coll k v)) -; ([coll k v & kvs] -; (let [ret (assoc! coll k v)] -; (if kvs -; (recur ret (first kvs) (second kvs) (nnext kvs)) -; ret)))) -; -;(defn dissoc! -; "Returns a transient map that doesn't contain a mapping for key(s)." -; ([coll k] -; (cpp/jank.runtime.dissoc_in_place coll k)) -; ([coll k & ks] -; (let [ret (dissoc! coll k)] -; (if ks -; (recur ret (first ks) (next ks)) -; ret)))) -; -;(defn pop! -; "Removes the last item from a transient vector. If -; the collection is empty, throws an exception. Returns coll" -; [coll] -; (cpp/jank.runtime.pop_in_place coll)) -; -;(defn disj! -; "disj[oin]. Returns a transient set of the same (hashed/sorted) type, that -; does not contain key(s)." -; ([set] set) -; ([set elem] -; (cpp/jank.runtime.dissoc_in_place set elem)) -; ([set elem & elems] -; (let [ret (disj! set elem)] -; (if elems -; (recur ret (first elems) (next elems)) -; ret)))) -; -;;; Functions. -;(defn- spread -; [arglist] -; (cond -; (nil? arglist) nil -; (nil? (next arglist)) (seq (first arglist)) -; :else (cons (first arglist) (spread (next arglist))))) -; -;(defn list* -; "Creates a new seq containing the items prepended to the rest, the -; last of which will be treated as a sequence." -; ([args] -; (seq args)) -; ([a args] -; (cons a args)) -; ([a b args] -; (cons a (cons b args))) -; ([a b c args] -; (cons a (cons b (cons c args)))) -; ([a b c d & more] -; (cons a (cons b (cons c (cons d (spread more))))))) -; -;(defn apply -; "Applies fn f to the argument list formed by prepending intervening arguments to args." -; ([f args] -; (cpp/jank.runtime.apply_to f args)) -; ([f x args] -; (cpp/jank.runtime.apply_to f (list* x args))) -; ([f x y args] -; (cpp/jank.runtime.apply_to f (list* x y args))) -; ([f x y z args] -; (cpp/jank.runtime.apply_to f (list* x y z args))) -; ([f a b c d & args] -; (cpp/jank.runtime.apply_to f (cons a (cons b (cons c (cons d (spread args)))))))) -; -;(defn constantly -; "Returns a function that takes any number of arguments and returns x." -; [x] -; (fn [& args] -; x)) -; -;(defn identity -; "Returns its argument." -; [x] -; x) -; -;(defn complement -; "Takes a fn f and returns a fn that takes the same arguments as f, -; has the same effects, if any, and returns the opposite truth value." -; [f] -; (fn -; ([] (not (f))) -; ([x] (not (f x))) -; ([x y] (not (f x y))) -; ([x y & zs] (not (apply f x y zs))))) -; +(def ^:dynamic *ns*) +(def ^:dynamic *assert*) +(def ^:dynamic *compile-files*) +(def ^:dynamic *file*) + +(def ^:dynamic *in* nil) +(def ^:dynamic *out* nil) +(def ^:dynamic *command-line-args* nil) +(def ^:dynamic *warn-on-reflection* nil) +(def ^:dynamic *compile-path* nil) +(def ^:dynamic *unchecked-math* nil) +(def ^:dynamic *compiler-options* nil) +(def ^:dynamic *err* nil) +(def ^:dynamic *flush-on-newline* nil) +(def ^:dynamic *print-meta* nil) +(def ^:dynamic *print-dup* nil) +(def ^:dynamic *print-readably* nil) +(def ^:dynamic *read-eval* nil) + +(cpp/raw "#include ") +(cpp/raw "#include ") +(cpp/raw "#include ") + +(cpp/raw "#include ") +(cpp/raw "#include ") +(cpp/raw "#include ") +(cpp/raw "#include ") + +; Syntax quoting. +(def unquote + (fn* unquote [_] + (throw "~ cannot be used outside of syntax quote"))) +(def unquote-splicing + (fn* unquote-splicing [_] + (throw "~@ cannot be used outside of syntax quote"))) + +(def type (fn* type [o] + (cpp/jank.runtime.object_type_str (cpp/.-type o)))) + +; Exceptions +(def ex-info + "Create an instance of ExceptionInfo, a RuntimeException subclass + that carries a map of additional data." + (fn* ex-info + ([msg map] + {:error msg + :data map}) + ([msg map cause] + {:error msg + :data map + :cause cause}))) + +(def ex-message + "Returns the message attached to ex if ex is a Throwable. + Otherwise returns nil." + :error) + +(def ex-data + "Returns exception data (a map) if ex is an IExceptionInfo. + Otherwise returns nil." + :data) + +(def ex-cause + "Returns the cause of ex if ex is a Throwable. + Otherwise returns nil." + :cause) + +; Relations. +;; Miscellaneous. +(def nil? + "Returns true if x is nil, false otherwise." + (fn* nil? [o] + (cpp/== (cpp/.-type o) cpp/jank.runtime.object_type.nil))) + +(def identical? + "Tests if 2 arguments are the same object, meaning the same pointer address." + (fn* identical? [lhs rhs] + (cpp/== lhs rhs))) + +; Collections. +(def empty? + "Returns true if coll has no items - same as (not (seq coll))." + (fn* empty? [o] + (cpp/jank.runtime.is_empty o))) +(def empty + "Returns an empty collection of the same category as coll, or nil" + (fn* empty [o] + (cpp/jank.runtime.empty o))) +(def count + "Returns the number of items in the collection. (count nil) returns + 0. Also works on strings, arrays, and Java Collections and Maps" + (fn* [coll] + (cpp/jank.runtime.sequence_length coll))) + +; Numbers. +(def boolean + "Coerce to boolean" + (fn* boolean [o] + (cpp/jank.runtime.truthy o))) +(def int + "Coerce to int" + (fn* int [o] + (cpp/jank.runtime.to_int o))) +(def float + "Coerce to float" + (fn* real [o] + (cpp/jank.runtime.to_real o))) + +;; Sequences. +(def seq + "Returns a seq on the collection. If the collection is + empty, returns nil. (seq nil) returns nil. seq also works on + Strings, native Java arrays (of reference types) and any objects + that implement Iterable. Note that seqs cache values, thus seq + should not be used on any Iterable whose iterator repeatedly + returns the same mutable object." + (fn* seq [o] + (cpp/jank.runtime.seq o))) +(def fresh-seq + (fn* fresh-seq [o] + (cpp/jank.runtime.fresh_seq o))) +(def first + "Returns the first item in the collection. Calls seq on its + argument. If coll is nil, returns nil." + (fn* first [o] + (cpp/jank.runtime.first o))) +(def ffirst + "Same as (first (first x))" + (fn* ffirst [o] + (first (first o)))) +(def next + "Returns a seq of the items after the first. Calls seq on its + argument. If there are no more items, returns nil." + (fn* next [o] + (cpp/jank.runtime.next o))) +(def next-in-place + (fn* next-in-place [o] + (cpp/jank.runtime.next_in_place o))) +(def nnext + "Same as (next (next x))" + (fn* nnext [o] + (next (next o)))) +(def second + "Same as (first (next x))" + (fn* second [o] + (cpp/jank.runtime.second o))) +(def rest + "Returns a possibly empty seq of the items after the first. Calls seq on its + argument." + (fn* rest [o] + (cpp/jank.runtime.rest o))) +(def cons + "Returns a new seq where x is the first element and seq is + the rest." + (fn* cons [head tail] + (cpp/jank.runtime.cons head tail))) +(def coll? + "Returns true if x implements IPersistentCollection" + (fn* coll? [o] + (cpp/jank.runtime.is_collection o))) +(def seq? + "Return true if x implements ISeq" + (fn* seq? [o] + (cpp/jank.runtime.is_seq o))) +(def seqable? + "Return true if the seq function is supported for x" + (fn* seqable? [o] + (cpp/jank.runtime.is_seqable o))) + +(def ^:private reverse* + (fn* reverse* [coll] + (loop* [acc '() + coll (seq coll)] + (if (empty? coll) + acc + (recur (cons (first coll) acc) + (rest coll)))))) + +; XXX: The real concat will be defined later on, to be lazy. +(def ^:private concat* + (fn* concat* + ([] + '()) + ([x] + (seq x)) + ([x y] + (loop* [acc y + x (reverse* x)] + (if (empty? x) + acc + (recur (cons (first x) acc) + (rest x))))) + ([x y & zs] + (let* [r (concat* x y)] + (if (empty? zs) + r + (recur r (first zs) (rest zs))))))) + +; Lists. +(def list? + "Returns true if x implements IPersistentList" + (fn* list? [o] + (cpp/jank.runtime.is_list o))) +(def list + "Creates a new list containing the items." + (fn* list [& args] + (cpp/jank.runtime.list args))) + +;; Vectors. +(def vector? + "Return true if x implements IPersistentVector" + (fn* vector? [o] + (cpp/jank.runtime.is_vector o))) +(def vec + "Creates a new vector containing the contents of coll. Java arrays + will be aliased and should not be modified." + (fn* vec [o] + (cpp/jank.runtime.vec o))) + +(def subvec + "Returns a persistent vector of the items in vector from + start (inclusive) to end (exclusive). If end is not supplied, + defaults to (count vector). This operation is O(1) and very fast, as + the resulting vector shares structure with the original and no + trimming is done." + (fn* subvec + ([v start] + (subvec v start (count v))) + ([v start end] + (cpp/jank.runtime.subvec v start end)))) + +(def conj + "conj[oin]. Returns a new collection with the xs + 'added'. (conj nil item) returns (item). + (conj coll) returns coll. (conj) returns []. + The 'addition' may happen at different 'places' depending + on the concrete type." + (fn* conj + ([] + []) + ([coll] + coll) + ([coll x] + (cpp/jank.runtime.conj coll x)) + ([coll x & args] + (let* [res (conj coll x)] + (if (empty? args) + res + (recur res (first args) (next args))))))) + +(def last + "Return the last item in coll, in linear time." + (fn* last [s] + (if (next s) + (recur (next s)) + (first s)))) + +(def butlast + "Return a seq of all but the last item in coll, in linear time." + (fn* butlast [s] + (loop* [ret [] + s s] + (if (next s) + (recur (conj ret (first s)) (next s)) + (seq ret))))) + +;; Maps. +(def hash-map + "keyval => key val + Returns a new hash map with supplied mappings. If any keys are + equal, they are handled as if by repeated uses of assoc." + (fn* hash-map + ([] (cpp/jank.runtime.obj.persistent_hash_map.empty)) + ([& keyvals] + (cpp/jank.runtime.obj.persistent_hash_map.create_from_seq keyvals)))) + +(def sorted-map + "keyval => key val + Returns a new sorted map with supplied mappings. If any keys are + equal, they are handled as if by repeated uses of assoc." + (fn* sorted-map + ([] (cpp/jank.runtime.obj.persistent_sorted_map.empty)) + ([& keyvals] + (cpp/jank.runtime.obj.persistent_sorted_map.create_from_seq keyvals)))) + +(def map? + "Return true if x implements IPersistentMap" + (fn* map? [o] + (cpp/jank.runtime.is_map o))) + +(def associative? + "Returns true if coll implements Associative" + (fn* associative? [o] + (cpp/jank.runtime.is_associative o))) + +(def assoc + "assoc[iate]. When applied to a map, returns a new map of the + same (hashed/sorted) type, that contains the mapping of key(s) to + val(s). When applied to a vector, returns a new vector that + contains val at index. Note - index must be <= (count vector)." + (fn* assoc + ([map key val] + (cpp/jank.runtime.assoc map key val)) + ([map key val & kvs] + (let* [res (assoc map key val)] + (if kvs + (if (next kvs) + (recur res (first kvs) (second kvs) (nnext kvs)) + (throw "assoc expects even number of args after the first")) + res))))) + +;; Strings. +(def string? + "Return true if x is a String" + (fn* string? [o] + (cpp/jank.runtime.is_string o))) + +(def char? + "Return true if x is a Character" + (fn* char? [o] + (cpp/jank.runtime.is_char o))) + +(def str + "With no args, returns the empty string. With one arg x, returns + x.toString(). (str nil) returns the empty string. With more than + one arg, returns the concatenation of the str values of the args." + (fn* str + ([] + "") + ([o] + (if (nil? o) + "" + (cpp/jank.runtime.to_string o))) + ([o & args] + (cpp/jank.runtime.str o args)))) + +;; Symbols. +(def symbol? + "Return true if x is a Symbol" + (fn* symbol? [o] + (cpp/jank.runtime.is_symbol o))) +(def + symbol + "Returns a Symbol with the given namespace and name. Arity-1 works + on strings, keywords, and vars." + (fn* symbol + ([o] + (cpp/jank.runtime.to_unqualified_symbol o)) + ([ns o] + (if (nil? ns) + (symbol o) + (cpp/jank.runtime.to_qualified_symbol ns o))))) +(def simple-symbol? + "Return true if x is a symbol without a namespace" + (fn* simple-symbol? [x] + (cpp/jank.runtime.is_simple_symbol x))) +(def qualified-symbol? + "Return true if x is a symbol with a namespace" + (fn* qualified-symbol? [x] + (cpp/jank.runtime.is_qualified_symbol x))) + +; Relations. +;; Miscellaneous. +(def true? + "Returns true if x is the value true, false otherwise." + (fn* true? [x] + (cpp/jank.runtime.is_true x))) +(def false? + "Returns true if x is the value false, false otherwise." + (fn* false? [x] + (cpp/jank.runtime.is_false x))) +(def not + "Returns true if x is logical false, false otherwise." + (fn* not [x] + (cpp/clojure.core_native.not_ x))) +(def some? + "Returns true if x is not nil, false otherwise." + (fn* some? [x] + (cpp/jank.runtime.is_some x))) + +;; Metadata. +(def meta + "Returns the metadata of obj, returns nil if there is no metadata." + (fn* meta [obj] + (cpp/jank.runtime.meta obj))) +(def with-meta + "Returns an object of the same type and value as obj, with + map m as its metadata." + (fn* with-meta [obj m] + (cpp/jank.runtime.with_meta obj m))) +(def reset-meta! + "Atomically resets the metadata for a namespace/var/ref/agent/atom" + (fn* [iref metadata-map] + (cpp/jank.runtime.reset_meta iref metadata-map))) + +;; Input/output. +(def print + "Prints the object(s) to the output stream that is the current value + of *out*. print and println produce output for human consumption." + (fn* print [& more] + (cpp/jank.runtime.print more))) +(def println + "Same as print followed by (newline)" + (fn* println [& more] + (cpp/jank.runtime.println more))) +(def pr + "Prints the object(s) to the output stream that is the current value + of *out*. Prints the object(s), separated by spaces if there is + more than one. By default, pr and prn print in a way that objects + can be read by the reader" + (fn* pr [& more] + (cpp/jank.runtime.pr more))) +(def prn + "Same as pr followed by (newline). Observes *flush-on-newline*" + (fn* prn [& more] + (cpp/jank.runtime.prn more))) +(def pr-str + "pr to a string, returning it" + ;; TODO: support multiple parameters, preserving current behavior + (fn* pr-str [x] + (cpp/jank.runtime.to_code_string x))) + ;; Utils. -;(defn deref -; "Also reader macro: @ref/@agent/@var/@atom/@delay/@future/@promise. Within a transaction, -; returns the in-transaction-value of ref, else returns the -; most-recently-committed value of ref. When applied to a var, agent -; or atom, returns its current state. When applied to a delay, forces -; it if not already forced. When applied to a future, will block if -; computation not complete. When applied to a promise, will block -; until a value is delivered. The variant taking a timeout can be -; used for blocking references (futures and promises), and will return -; timeout-val if the timeout (in milliseconds) is reached before a -; value is available. See also - realized?." -; ([ref] -; (cpp/jank.runtime.deref ref)) -; ; TODO: Blocking. -; ([ref timeout-ms timeout-val] -; ;(if (instance? clojure.lang.IBlockingDeref ref) -; ; (.deref ^clojure.lang.IBlockingDeref ref timeout-ms timeout-val) -; ; (deref-future ref timeout-ms timeout-val)) -; )) -; -;(defn reduced -; "Wraps x in a way such that a reduce will terminate with the value x" -; [x] -; (cpp/jank.runtime.reduced x)) -; -;(defn reduced? -; "Returns true if x is the result of a call to reduced" -; [x] -; (cpp/jank.runtime.is_reduced x)) -; -;(defn ensure-reduced -; "If x is already reduced?, returns it, else returns (reduced x)" -; [x] -; (if (reduced? x) -; x -; (reduced x))) -; -;(defn unreduced -; "If x is reduced?, returns (deref x), else returns x" -; [x] -; (if (reduced? x) -; (deref x) -; x)) -; -;(defn reduce -; "f should be a function of 2 arguments. If val is not supplied, -; returns the result of applying f to the first 2 items in coll, then -; applying f to that result and the 3rd item, etc. If coll contains no -; items, f must accept no arguments as well, and reduce returns the -; result of calling f with no arguments. If coll has only 1 item, it -; is returned and f is not called. If val is supplied, returns the -; result of applying f to val and the first item in coll, then -; applying f to that result and the 2nd item, etc. If coll contains no -; items, returns val and f is not called." -; ([f coll] -; (let [s (seq coll)] -; (if s -; (reduce f (first s) (next s)) -; (f)))) -; ([f init coll] -; ; TODO: Chunking support. -; (cpp/jank.runtime.reduce f init coll))) -; -;(defn completing -; "Takes a reducing function f of 2 args and returns a fn suitable for -; transduce by adding an arity-1 signature that calls cf (default - -; identity) on the result argument." -; ([f] (completing f identity)) -; ([f cf] -; (fn -; ([] (f)) -; ([x] (cf x)) -; ([x y] (f x y))))) -; -;(defn transduce -; "reduce with a transformation of rf (xf). If init is not -; supplied, (rf) will be called to produce it. f should be a reducing -; step function that accepts both 1 and 2 arguments, if it accepts -; only 2 you can add the arity-1 with 'completing'. Returns the result -; of applying (the transformed) xf to init and the first item in coll, -; then applying xf to that result and the 2nd item, etc. If coll -; contains no items, returns init and rf is not called. Note that -; certain transforms may inject or skip items." -; ([xform rf coll] -; (transduce xform rf (rf) coll)) -; ([xform rf init coll] -; (let [f (xform rf) -; ret (reduce f init coll)] -; (f ret)))) -; -;;; TODO: private -;(defn preserving-reduced -; [rf] -; #(let [ret (rf %1 %2)] -; (if (reduced? ret) -; (reduced ret) -; ret))) -; -;(defn cat -; "A transducer which concatenates the contents of each input, which must be a -; collection, into the reduction." -; [rf] -; (let [rrf (preserving-reduced rf)] -; (fn -; ([] (rf)) -; ([result] (rf result)) -; ([result input] -; (reduce rrf result input))))) -; -;(defn run! -; "Runs the supplied procedure (via reduce), for purposes of side -; effects, on successive items in the collection. Returns nil" -; [proc coll] -; (reduce #(proc %2) nil coll) -; nil) -; -;(defn comp -; "Takes a set of functions and returns a fn that is the composition -; of those fns. The returned fn takes a variable number of args, -; applies the rightmost of fns to the args, the next -; fn (right-to-left) to the result, etc." -; ([] identity) -; ([f] f) -; ([f g] -; (let [a 1] (fn -; ([] (f (g))) -; ([x] (f (g x))) -; ([x y] (f (g x y))) -; ([x y z] (f (g x y z))) -; ([x y z & args] (f (apply g x y z args)))))) -; ([f g & fs] -; (reduce comp (list* f g fs)))) -; -;(defn peek -; "For a list or queue, same as first, for a vector, same as, but much -; more efficient than, last. If the collection is empty, returns nil." -; [coll] -; (cpp/jank.runtime.peek coll)) -; -;(defn pop -; "For a list or queue, returns a new list/queue without the first -; item, for a vector, returns a new vector without the last item. If -; the collection is empty, throws an exception. Note - not the same -; as next/butlast." -; [coll] -; (cpp/jank.runtime.pop coll)) -; -;(defn vary-meta -; "Returns an object of the same type and value as obj, with -; (apply f (meta obj) args) as its metadata." -; [o f & args] -; (with-meta o (apply f (meta o) args))) -; -;(defn alter-meta! -; "Atomically sets the metadata for a namespace/var/ref/agent/atom to be: -; -; (apply f its-current-meta args) -; -; f must be free of side-effects" -; [o f & args] -; ; TODO: Atomics. -; (reset-meta! o (apply f (meta o) args))) -; -;;; Atoms. -;(defn atom -; "Creates and returns an Atom with an initial value of x and zero or -; more options (in any order): -; -; :meta metadata-map -; -; :validator validate-fn -; -; If metadata-map is supplied, it will become the metadata on the -; atom. validate-fn must be nil or a side-effect-free fn of one -; argument, which will be passed the intended new state on any state -; change. If the new state is unacceptable, the validate-fn should -; return false or throw an exception." -; ([x] -; (cpp/jank.runtime.atom x)) -; ; TODO: Validators. -; #_([x & options] -; (setup-reference (atom x) options))) -; -;(defn swap! -; "Atomically swaps the value of atom to be: -; (apply f current-value-of-atom args). Note that f may be called -; multiple times, and thus should be free of side effects. Returns -; the value that was swapped in." -; ([atom f] -; (cpp/jank.runtime.swap_atom atom f)) -; ([atom f x] -; (cpp/jank.runtime.swap_atom atom f x)) -; ([atom f x y] -; (cpp/jank.runtime.swap_atom atom f x y)) -; ([atom f x y & args] -; (cpp/jank.runtime.swap_atom atom f x y args))) -; -;(defn swap-vals! -; "Atomically swaps the value of atom to be: -; (apply f current-value-of-atom args). Note that f may be called -; multiple times, and thus should be free of side effects. -; Returns [old new], the value of the atom before and after the swap." -; ([atom f] -; (cpp/jank.runtime.swap_vals atom f)) -; ([atom f x] -; (cpp/jank.runtime.swap_vals atom f x)) -; ([atom f x y] -; (cpp/jank.runtime.swap_vals atom f x y)) -; ([atom f x y & args] -; (cpp/jank.runtime.swap_vals atom f x y args))) -; -;(defn compare-and-set! -; "Atomically sets the value of atom to newval if and only if the -; current value of the atom is identical to oldval. Returns true if -; set happened, else false" -; [atom oldval newval] -; (cpp/jank.runtime.compare_and_set atom oldval newval)) -; -;(defn reset! -; "Sets the value of atom to newval without regard for the -; current value. Returns newval." -; [atom newval] -; (cpp/jank.runtime.reset atom newval)) -; -;(defn reset-vals! -; "Sets the value of atom to newval. Returns [old new], the value of the -; atom before and after the reset." -; [atom newval] -; (cpp/jank.runtime.reset_vals atom newval)) -; -;;; Volatiles. -;(defn volatile! -; "Creates and returns a volatile with an initial value of val." -; [val] -; (cpp/jank.runtime.volatile_ val)) -; -;(defn vreset! -; "Sets the value of volatile to newval without regard for the -; current value. Returns newval." -; [vol newval] -; (cpp/jank.runtime.vreset vol newval)) -; -;; TODO: In Clojure, this is a macro (for perf reasons). -;(defn vswap! -; "Non-atomically swaps the value of the volatile as if: -; (apply f current-value-of-vol args). Returns the value that -; was swapped in." -; ([vol f] -; (cpp/jank.runtime.vswap vol f)) -; ([vol f & args] -; (cpp/jank.runtime.vswap vol f args))) -; -;(defn volatile? -; "Returns true if x is a volatile." -; [x] -; (cpp/jank.runtime.is_volatile x)) -; -;(defn- delay* [f] (cpp/clojure.core_native.delay f)) -; -;(defmacro delay -; "Takes a body of expressions and yields a Delay object that will -; invoke the body only the first time it is forced (with force or deref/@), and -; will cache the result and return it on all subsequent force -; calls. See also - realized?" -; [& body] -; (list `delay* (cons `fn (cons '[] body)))) -; -;(defn force -; "If x is a Delay, returns the (possibly cached) value of its expression, else returns x" -; [x] -; (cpp/jank.runtime.force x)) -; -;;; Primitives. -;;;; Arithmetic. -;(defn -; ^{:arities {2 {:supports-unboxed-input? true -; :unboxed-output? true}}} -; + -; ([] -; 0) -; ([x] -; x) -; ([l r] -; (cpp/jank.runtime.add l r)) -; ([l r & args] -; (let [res (cpp/jank.runtime.add l r)] -; (if (empty? args) -; res -; (recur res (first args) (next args)))))) -; -;(defn -; ^{:arities {2 {:supports-unboxed-input? true -; :unboxed-output? true}}} -; - -; ([x] -; (- 0 x)) -; ([l r] -; (cpp/jank.runtime.sub l r)) -; ([l r & args] -; (let [res (cpp/jank.runtime.sub l r)] -; (if (empty? args) -; res -; (recur res (first args) (next args)))))) -; -;(defn -; ^{:arities {2 {:supports-unboxed-input? true -; :unboxed-output? true}}} -; * -; ([] -; 1) -; ([x] -; x) -; ([l r] -; (cpp/jank.runtime.mul l r)) -; ([l r & args] -; (let [res (cpp/jank.runtime.mul l r)] -; (if (empty? args) -; res -; (recur res (first args) (next args)))))) -; -;(defn -; ^{:arities {2 {:supports-unboxed-input? true -; :unboxed-output? true}}} -; / -; ([x] -; (/ 1 x)) -; ([l r] -; (cpp/jank.runtime.div l r)) -; ([l r & args] -; (let [res (cpp/jank.runtime.div l r)] -; (if (empty? args) -; res -; (recur res (first args) (next args)))))) -; -;;; Bit operations. -;; TODO: Unboxing and inlining for these. -;(defn bit-not -; "Bitwise complement" -; [x] -; (cpp/jank.runtime.bit_not x)) -; -;(defn bit-and -; "Bitwise and" -; ([x y] -; (cpp/jank.runtime.bit_and x y)) -; ([x y & more] -; (reduce bit-and (bit-and x y) more))) -; -;(defn bit-or -; "Bitwise or" -; ([x y] -; (cpp/jank.runtime.bit_or x y)) -; ([x y & more] -; (reduce bit-or (bit-or x y) more))) -; -;(defn bit-xor -; "Bitwise exclusive or" -; ([x y] -; (cpp/jank.runtime.bit_xor x y)) -; ([x y & more] -; (reduce bit-xor (bit-xor x y) more))) -; -;(defn bit-and-not -; "Bitwise and with complement" -; ([x y] -; (cpp/jank.runtime.bit_and_not x y)) -; ([x y & more] -; (reduce bit-and-not (bit-and-not x y) more))) -; -;(defn bit-clear -; "Clear bit at index n" -; [x n] -; (cpp/jank.runtime.bit_clear x n)) -; -;(defn bit-set -; "Set bit at index n" -; [x n] -; (cpp/jank.runtime.bit_set x n)) -; -;(defn bit-flip -; "Flip bit at index n" -; [x n] -; (cpp/jank.runtime.bit_flip x n)) -; -;(defn bit-test -; "Test bit at index n" -; [x n] -; (cpp/jank.runtime.bit_test x n)) -; -;(defn bit-shift-left -; "Bitwise shift left" -; [x n] -; (cpp/jank.runtime.bit_shift_left x n)) -; -;(defn bit-shift-right -; "Bitwise shift right" -; [x n] -; (cpp/jank.runtime.bit_shift_right x n)) -; -;(defn unsigned-bit-shift-right -; "Bitwise shift right, without sign-extension." -; [x n] -; (cpp/jank.runtime.bit_unsigned_shift_right x n)) -; -;(defn not= -; ([x] -; false) -; ([x y] -; (not (= x y))) -; ([x y & more] -; (not (apply = x y more)))) -; -;(defn -; ^{:arities {2 {:supports-unboxed-input? true -; :unboxed-output? true}}} -; < -; ([x] -; true) -; ([l r] -; (cpp/jank.runtime.lt l r)) -; ([l r & args] -; (if (cpp/jank.runtime.lt l r) -; (if (next args) -; (recur r (first args) (next args)) -; (cpp/jank.runtime.lt r (first args))) -; false))) -; -;(defn -; ^{:arities {2 {:supports-unboxed-input? true -; :unboxed-output? true}}} -; <= -; ([x] -; true) -; ([l r] -; (cpp/jank.runtime.lte l r)) -; ([l r & args] -; (if (cpp/jank.runtime.lte l r) -; (if (next args) -; (recur r (first args) (next args)) -; (cpp/jank.runtime.lte r (first args))) -; false))) -; -;(defn -; ^{:arities {2 {:supports-unboxed-input? true -; :unboxed-output? true}}} -; > -; ([x] -; true) -; ([l r] -; (cpp/jank.runtime.lt r l)) -; ([l r & args] -; (if (cpp/jank.runtime.lt r l) -; (if (next args) -; (recur r (first args) (next args)) -; (cpp/jank.runtime.lt (first args) r)) -; false))) -; -;(defn -; ^{:arities {2 {:supports-unboxed-input? true -; :unboxed-output? true}}} -; >= -; ([x] -; true) -; ([l r] -; (cpp/jank.runtime.lte r l)) -; ([l r & args] -; (if (cpp/jank.runtime.lte r l) -; (if (next args) -; (recur r (first args) (next args)) -; (cpp/jank.runtime.lte (first args) r)) -; false))) -; -;(defn -; ^{:arities {2 {:supports-unboxed-input? true -; :unboxed-output? true}}} -; min -; ([x] -; x) -; ([l r] -; (cpp/jank.runtime.min l r)) -; ([l r & args] -; (let [res (cpp/jank.runtime.min l r)] -; (if (empty? args) -; res -; (recur res (first args) (next args)))))) -; -;(defn -; ^{:arities {2 {:supports-unboxed-input? true -; :unboxed-output? true}}} -; max -; ([x] -; x) -; ([l r] -; (cpp/jank.runtime.max l r)) -; ([l r & args] -; (let [res (cpp/jank.runtime.max l r)] -; (if (empty? args) -; res -; (recur res (first args) (next args)))))) -; -;(defn inc -; "Returns a number one greater than num. Does not auto-promote -; longs, will throw on overflow. See also: inc'" -; [x] -; (cpp/jank.runtime.inc x)) -;(defn dec -; "Returns a number one less than num. Does not auto-promote -; longs, will throw on overflow. See also: dec" -; [x] -; (cpp/jank.runtime.dec x)) -; -;(defn pos? -; "Returns true if num is greater than zero, else false" -; [num] -; (cpp/jank.runtime.is_pos num)) -;(defn neg? -; "Returns true if num is less than zero, else false" -; [num] -; (cpp/jank.runtime.is_neg num)) -;(defn zero? -; "Returns true if num is zero, else false" -; [num] -; (cpp/jank.runtime.is_zero num)) -; -;(defn rem -; "Returns the remainder of dividing numerator by denominator." -; [num div] -; (cpp/jank.runtime.rem num div)) -;(defn quot -; "quot[ient] of dividing numerator by denominator." -; [num div] -; (cpp/jank.runtime.quot num div)) -; -;(defn mod -; "Modulus of num and div. Truncates toward negative infinity." -; [num div] -; (let [m (rem num div)] -; (if (or (zero? m) (= (pos? num) (pos? div))) -; m -; (+ m div)))) -; -;;; Numbers. -;(defn integer? -; "Returns true if n is an integer" -; [n] -; (cpp/jank.runtime.is_integer n)) -;(defn float? -; "Returns true if n is a floating point number" -; [n] -; (cpp/jank.runtime.is_real n)) -;(defn boolean? -; "Returns true if x is a boolean" -; [x] -; (cpp/jank.runtime.is_boolean x)) -;(defn number? -; "Returns true if x is a number" -; [x] -; (cpp/jank.runtime.is_number x)) -; -;(defn even? -; "Returns true if n is even, throws an exception if n is not an integer" -; [n] -; (cpp/jank.runtime.is_even n)) -;(defn odd? -; "Returns true if n is odd, throws an exception if n is not an integer" -; [n] -; (cpp/jank.runtime.is_odd n)) -; -;;; Random. -;(defn rand -; "Returns a random floating point number between 0 (inclusive) and -; n (default 1) (exclusive)." -; ([] -; (cpp/jank.runtime.rand)) -; ([n] -; (* (rand) n))) -; -;;; Strings. -;(defn subs -; "Returns the substring of s beginning at start inclusive, and ending -; at end (defaults to length of string), exclusive." -; ([s start] -; (cpp/jank.runtime.subs s start)) -; ([s start end] -; (cpp/jank.runtime.subs s start end))) -; -;;; Sequences (again). -;(defn sequential? -; "Returns true if coll implements sequential" -; [coll] -; (cpp/jank.runtime.is_sequential coll)) -; -;(defn reverse -; "Returns a seq of the items in coll in reverse order. Not lazy." -; [coll] -; (reduce conj '() coll)) -; -;(defn every? -; "Returns true if (pred x) is logical true for every x in coll, else false." -; [pred coll] -; (cond -; (nil? (seq coll)) true -; (pred (first coll)) (recur pred (next coll)) -; :else false)) -; -;(defn vector -; "Creates a new vector containing the args." -; ([] -; []) -; ([a] -; [a]) -; ([a b] -; [a b]) -; ([a b c] -; [a b c]) -; ([a b c d] -; [a b c d]) -; ([a b c d e] -; [a b c d e]) -; ([a b c d e f] -; [a b c d e f]) -; ([a b c d e f & args] -; ; TODO: LazilyPersistentVector -; (vec (concat* [a b c d e f] args)))) -; -;(defn- lazy-seq* [o] (cpp/clojure.core_native.lazy_seq o)) -; -;(defmacro lazy-seq -; "Takes a body of expressions that returns an ISeq or nil, and yields -; a Seqable object that will invoke the body only the first time seq -; is called, and will cache the result and return it on all subsequent -; seq calls. See also - realized?" -; [& body] -; (list `lazy-seq* (list* `fn `lazy-seq# [] body))) -; -;(defn chunk-buffer -; [capacity] -; (cpp/jank.runtime.chunk_buffer capacity)) -; -;(defn chunk-append -; [b x] -; (cpp/jank.runtime.chunk_append b x)) -; -;(defn chunk -; [b] -; (cpp/jank.runtime.chunk b)) -; -;(defn chunk-first -; [s] -; (cpp/jank.runtime.chunk_first s)) -; -;(defn chunk-next -; [s] -; (cpp/jank.runtime.chunk_next s)) -; -;(defn chunk-rest -; [s] -; (cpp/jank.runtime.chunk_rest s)) -; -;(defn chunk-cons [chunk rest] -; (if (empty? chunk) -; rest -; (cpp/jank.runtime.chunk_cons chunk rest))) -; -;(defn chunked-seq? -; [s] -; (cpp/jank.runtime.is_chunked_seq s)) -; -;; TODO: Support more bindings -;; TODO: Support `for` functionality -;(defmacro doseq -; "Repeatedly executes body (presumably for side-effects) with -; bindings and filtering as provided by `for`. Does not retain -; the head of the sequence. Returns nil." -; [bindings & body] -; (let [arg (first bindings) -; s (second bindings)] -; (list 'clojure.core/reduce (concat* (list 'clojure.core/fn ['_ arg]) -; body -; [nil]) -; nil -; s))) -; -;(defn concat -; "Returns a lazy seq representing the concatenation of the elements in the supplied colls." -; ([] (lazy-seq nil)) -; ([x] (lazy-seq x)) -; ([x y] -; (lazy-seq -; (let [s (seq x)] -; (if s -; (if (chunked-seq? s) -; (chunk-cons (chunk-first s) (concat (chunk-rest s) y)) -; (cons (first s) (concat (rest s) y))) -; y)))) -; ([x y & zs] -; (let [cat* (fn cat* [xys zs] -; (lazy-seq -; (let [xys (seq xys)] -; (if xys -; (if (chunked-seq? xys) -; (chunk-cons (chunk-first xys) -; (cat* (chunk-rest xys) zs)) -; (cons (first xys) (cat* (rest xys) zs))) -; (when zs -; (cat* (first zs) (next zs)))))))] -; (cat* (concat x y) zs)))) -; -;(defn juxt -; "Takes a set of functions and returns a fn that is the juxtaposition -; of those fns. The returned fn takes a variable number of args, and -; returns a vector containing the result of applying each fn to the -; args (left-to-right). -; ((juxt a b c) x) => [(a x) (b x) (c x)]" -; ([f] -; (fn -; ([] [(f)]) -; ([x] [(f x)]) -; ([x y] [(f x y)]) -; ([x y z] [(f x y z)]) -; ([x y z & args] [(apply f x y z args)]))) -; ([f g] -; (fn -; ([] [(f) (g)]) -; ([x] [(f x) (g x)]) -; ([x y] [(f x y) (g x y)]) -; ([x y z] [(f x y z) (g x y z)]) -; ([x y z & args] [(apply f x y z args) (apply g x y z args)]))) -; ([f g h] -; (fn -; ([] [(f) (g) (h)]) -; ([x] [(f x) (g x) (h x)]) -; ([x y] [(f x y) (g x y) (h x y)]) -; ([x y z] [(f x y z) (g x y z) (h x y z)]) -; ([x y z & args] [(apply f x y z args) (apply g x y z args) (apply h x y z args)]))) -; ([f g h & fs] -; (let [fs (list* f g h fs)] -; (fn -; ([] (reduce #(conj %1 (%2)) [] fs)) -; ([x] (reduce #(conj %1 (%2 x)) [] fs)) -; ([x y] (reduce #(conj %1 (%2 x y)) [] fs)) -; ([x y z] (reduce #(conj %1 (%2 x y z)) [] fs)) -; ([x y z & args] (reduce #(conj %1 (apply %2 x y z args)) [] fs)))))) -; -;(defn partial -; "Takes a function f and fewer than the normal arguments to f, and -; returns a fn that takes a variable number of additional args. When -; called, the returned function calls f with args + additional args." -; ([f] f) -; ([f arg1] -; (fn -; ([] (f arg1)) -; ([x] (f arg1 x)) -; ([x y] (f arg1 x y)) -; ([x y z] (f arg1 x y z)) -; ([x y z & args] (apply f arg1 x y z args)))) -; ([f arg1 arg2] -; (fn -; ([] (f arg1 arg2)) -; ([x] (f arg1 arg2 x)) -; ([x y] (f arg1 arg2 x y)) -; ([x y z] (f arg1 arg2 x y z)) -; ([x y z & args] (apply f arg1 arg2 x y z args)))) -; ([f arg1 arg2 arg3] -; (fn -; ([] (f arg1 arg2 arg3)) -; ([x] (f arg1 arg2 arg3 x)) -; ([x y] (f arg1 arg2 arg3 x y)) -; ([x y z] (f arg1 arg2 arg3 x y z)) -; ([x y z & args] (apply f arg1 arg2 arg3 x y z args)))) -; ([f arg1 arg2 arg3 & more] -; (fn [& args] (apply f arg1 arg2 arg3 (concat more args))))) -; -;(defn fnil -; "Takes a function f, and returns a function that calls f, replacing -; a nil first argument to f with the supplied value x. Higher arity -; versions can replace arguments in the second and third -; positions (y, z). Note that the function f can take any number of -; arguments, not just the one(s) being nil-patched." -; ([f x] -; (fn -; ([a] (f (if (nil? a) x a))) -; ([a b] (f (if (nil? a) x a) b)) -; ([a b c] (f (if (nil? a) x a) b c)) -; ([a b c & ds] (apply f (if (nil? a) x a) b c ds)))) -; ([f x y] -; (fn -; ([a b] (f (if (nil? a) x a) (if (nil? b) y b))) -; ([a b c] (f (if (nil? a) x a) (if (nil? b) y b) c)) -; ([a b c & ds] (apply f (if (nil? a) x a) (if (nil? b) y b) c ds)))) -; ([f x y z] -; (fn -; ([a b] (f (if (nil? a) x a) (if (nil? b) y b))) -; ([a b c] (f (if (nil? a) x a) (if (nil? b) y b) (if (nil? c) z c))) -; ([a b c & ds] (apply f (if (nil? a) x a) (if (nil? b) y b) (if (nil? c) z c) ds))))) -; -;(defn some -; "Returns the first logical true value of (pred x) for any x in coll, -; else nil. One common idiom is to use a set as pred, for example -; this will return :fred if :fred is in the sequence, otherwise nil: -; (some #{:fred} coll)" -; [pred coll] -; (let [s (seq coll)] -; (when s -; (or (pred (first s)) (recur pred (next s)))))) -; -; -;(defn every-pred -; "Takes a set of predicates and returns a function f that returns true if all of its -; composing predicates return a logical true value against all of its arguments, else it returns -; false. Note that f is short-circuiting in that it will stop execution on the first -; argument that triggers a logical false result against the original predicates." -; ([p] -; (fn ep1 -; ([] true) -; ([x] (boolean (p x))) -; ([x y] (boolean (and (p x) (p y)))) -; ([x y z] (boolean (and (p x) (p y) (p z)))) -; ([x y z & args] (boolean (and (ep1 x y z) -; (every? p args)))))) -; ([p1 p2] -; (fn ep2 -; ([] true) -; ([x] (boolean (and (p1 x) (p2 x)))) -; ([x y] (boolean (and (p1 x) (p1 y) (p2 x) (p2 y)))) -; ([x y z] (boolean (and (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z)))) -; ([x y z & args] (boolean (and (ep2 x y z) -; (every? #(and (p1 %) (p2 %)) args)))))) -; ([p1 p2 p3] -; (fn ep3 -; ([] true) -; ([x] (boolean (and (p1 x) (p2 x) (p3 x)))) -; ([x y] (boolean (and (p1 x) (p1 y) (p2 x) (p2 y) (p3 x) (p3 y)))) -; ([x y z] (boolean (and (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z) (p3 x) (p3 y) (p3 z)))) -; ([x y z & args] (boolean (and (ep3 x y z) -; (every? #(and (p1 %) (p2 %) (p3 %)) args)))))) -; ([p1 p2 p3 & ps] -; (let [ps (list* p1 p2 p3 ps)] -; (fn epn -; ([] true) -; ([x] (every? #(% x) ps)) -; ([x y] (every? #(and (% x) (% y)) ps)) -; ([x y z] (every? #(and (% x) (% y) (% z)) ps)) -; ([x y z & args] (boolean (and (epn x y z) -; (every? #(every? % args) ps)))))))) -; -;(defn some-fn -; "Takes a set of predicates and returns a function f that returns the first logical true value -; returned by one of its composing predicates against any of its arguments, else it returns -; logical false. Note that f is short-circuiting in that it will stop execution on the first -; argument that triggers a logical true result against the original predicates." -; ([p] -; (fn sp1 -; ([] nil) -; ([x] (p x)) -; ([x y] (or (p x) (p y))) -; ([x y z] (or (p x) (p y) (p z))) -; ([x y z & args] (or (sp1 x y z) -; (some p args))))) -; ([p1 p2] -; (fn sp2 -; ([] nil) -; ([x] (or (p1 x) (p2 x))) -; ([x y] (or (p1 x) (p1 y) (p2 x) (p2 y))) -; ([x y z] (or (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z))) -; ([x y z & args] (or (sp2 x y z) -; (some #(or (p1 %) (p2 %)) args))))) -; ([p1 p2 p3] -; (fn sp3 -; ([] nil) -; ([x] (or (p1 x) (p2 x) (p3 x))) -; ([x y] (or (p1 x) (p1 y) (p2 x) (p2 y) (p3 x) (p3 y))) -; ([x y z] (or (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z) (p3 x) (p3 y) (p3 z))) -; ([x y z & args] (or (sp3 x y z) -; (some #(or (p1 %) (p2 %) (p3 %)) args))))) -; ([p1 p2 p3 & ps] -; (let [ps (list* p1 p2 p3 ps)] -; (fn spn -; ([] nil) -; ([x] (some #(% x) ps)) -; ([x y] (some #(or (% x) (% y)) ps)) -; ([x y z] (some #(or (% x) (% y) (% z)) ps)) -; ([x y z & args] (or (spn x y z) -; (some #(some % args) ps))))))) -; -; -;(defn not-any? [pred coll] -; (not (some pred coll))) -; -;(defmacro -> -; "Threads the expr through the forms. Inserts x as the -; second item in the first form, making a list of it if it is not a -; list already. If there are more forms, inserts the first form as the -; second item in second form, etc." -; [x & forms] -; (loop* [x x -; forms forms] -; (if forms -; (let [form (first forms) -; threaded (if (seq? form) -; (with-meta `(~(first form) ~x ~@(next form)) (meta form)) -; (list form x))] -; (recur threaded (next forms))) -; x))) -; -;(defmacro ->> -; "Threads the expr through the forms. Inserts x as the -; last item in the first form, making a list of it if it is not a -; list already. If there are more forms, inserts the first form as the -; last item in second form, etc." -; [x & forms] -; (loop* [x x -; forms forms] -; (if forms -; (let [form (first forms) -; threaded (if (seq? form) -; (with-meta `(~(first form) ~@(next form) ~x) (meta form)) -; (list form x))] -; (recur threaded (next forms))) -; x))) -; -;;; Maps. -;(defn key -; "Returns the key of the map entry." -; [e] -; (first e)) -; -;(defn val -; "Returns the value in the map entry." -; [e] -; (second e)) -; -;(defn keys -; "Returns a sequence of the map's keys, in the same order as (seq map)." -; [m] -; ; TODO: Use a proper key seq instead. -; (reduce (fn [acc kv] -; (conj acc (first kv))) -; [] -; m)) -; -;(defn vals -; "Returns a sequence of the map's values, in the same order as (seq map)." -; [m] -; ; TODO: Use a proper val seq instead. -; (reduce (fn [acc kv] -; (conj acc (second kv))) -; [] -; m)) -; -;(defn get -; "Returns the value mapped to key, not-found or nil if key not present -; in associative collection, set, string, array, or ILookup instance." -; ([map key] -; (cpp/jank.runtime.get map key)) -; ([map key not-found] -; (cpp/jank.runtime.get map key not-found))) -;(defn get-in -; "Returns the value in a nested associative structure, -; where ks is a sequence of keys. Returns nil if the key -; is not present, or the not-found value if supplied." -; ([m ks] -; (cpp/jank.runtime.get_in m ks)) -; ([m ks not-found] -; (cpp/jank.runtime.get_in m ks not-found))) -; -;(defn dissoc -; "dissoc[iate]. Returns a new map of the same (hashed/sorted) type, -; that does not contain a mapping for key(s)." -; ([m] -; m) -; ([m k] -; (cpp/jank.runtime.dissoc m k)) -; ([m k & ks] -; (let* [ret (dissoc m k)] -; (if ks -; (recur ret (first ks) (next ks)) -; ret)))) -; -;(defn contains? -; "Returns true if key is present in the given collection, otherwise -; returns false. Note that for numerically indexed collections like -; vectors and Java arrays, this tests if the numeric key is within the -; range of indexes. 'contains?' operates constant or logarithmic time; -; it will not perform a linear search for a value. See also 'some'." -; [coll key] -; (cpp/jank.runtime.contains coll key)) -; -;(defn find -; "Returns the map entry for key, or nil if key not present." -; [map key] -; (cpp/jank.runtime.find map key)) -; -;(defn select-keys -; "Returns a map containing only those entries in map whose key is in keys" -; [m ks] -; (reduce (fn [acc k] -; (let [e (find m k)] -; (if e -; (conj acc e) -; acc))) -; {} -; ks)) -; -;(defn zipmap -; "Returns a map with the keys mapped to the corresponding vals." -; [keys vals] -; (loop* [map (transient (hash-map)) -; ks (seq keys) -; vs (seq vals)] -; (if (and ks vs) -; (recur (assoc! map (first ks) (first vs)) -; (next ks) -; (next vs)) -; (persistent! map)))) -; -;;; Sets. -;(defn hash-set -; "Returns a new hash set with supplied keys. Any equal keys are -; handled as if by repeated uses of conj." -; ([] (cpp/jank.runtime.obj.persistent_hash_set.empty)) -; ([& keys] -; (cpp/jank.runtime.obj.persistent_hash_set.create_from_seq keys))) -; -;(defn sorted-set -; "Returns a new sorted set with supplied keys. Any equal keys are -; handled as if by repeated uses of conj." -; ([] (cpp/jank.runtime.obj.persistent_sorted_set.empty)) -; ([& keys] -; (cpp/jank.runtime.obj.persistent_sorted_set.create_from_seq keys))) -; -;(defn sorted-set-by -; "Returns a new sorted set with supplied keys, using the supplied -; comparator. Any equal keys are handled as if by repeated uses of -; conj." -; ([comparator & keys] -; (throw "not yet implemented: sorted-set-by"))) -; -;(defn disj -; "disj[oin]. Returns a new set of the same (hashed/sorted) type, that -; does not contain key(s)." -; ([set] -; set) -; ([set key] -; (cpp/jank.runtime.disj set key)) -; ([set key & ks] -; (let* [res (disj set key)] -; (if (empty? ks) -; res -; (recur res (first ks) (next ks)))))) -; -;(defn set? -; "Returns true if x implements IPersistentSet" -; [x] -; (cpp/jank.runtime.is_set x)) -; -;(defn set -; "Returns a set of the distinct elements of coll." -; [coll] -; (if (set? coll) -; (with-meta coll nil) -; (persistent! (reduce (fn [acc e] -; (conj! acc e)) -; (transient #{}) -; coll)))) -; -;;; Other. -;(defn hash -; "Returns the hash code of its argument. Note this is the hash code -; consistent with =, and thus is different than .hashCode for Integer, -; Short, Byte and Clojure collections." -; [o] -; (cpp/jank.runtime.to_hash o)) -; -;(defn- named? -; [x] -; (cpp/jank.runtime.is_named x)) -; -;(defn name -; "Returns the name String of a string, symbol or keyword." -; [x] -; (cpp/jank.runtime.name x)) -; -;(defn namespace -; "Returns the namespace String of a symbol or keyword, or nil if not present." -; [x] -; (cpp/jank.runtime.namespace_ x)) -; -;;; Sequences. -;; This is defined to be lazy later on. -;(defn drop -; ([n coll] -; (let [step (fn [n acc] -; (let [s (seq acc)] -; (if (and (pos? n) s) -; (recur (dec n) (rest s)) -; acc)))] -; (step n coll)))) -; -;;; Vars. -;(defn var? -; "Returns true if v is a var." -; [x] -; (cpp/clojure.core_native.is_var x)) -; -;(defn var-get -; "Gets the value in the var object." -; [x] -; (cpp/clojure.core_native.var_get x)) -; -;(defn alter-var-root -; "Atomically alters the root binding of var v by applying f to its -; current value plus any args" -; [v f & args] -; (cpp/clojure.core_native.alter_var_root v f args)) -; -;(defn bound? -; "Returns true if all of the vars provided as arguments have any bound value, root or thread-local. -; Implies that deref'ing the provided vars will succeed. Returns true if no vars are provided." -; [& vars] -; (every? #(cpp/clojure.core_native.is_var_bound %) vars)) -; -;(defn thread-bound? -; "Returns true if all of the vars provided as arguments have thread-local bindings. -; Implies that set!'ing the provided vars will succeed. Returns true if no vars are provided." -; [& vars] -; (every? #(cpp/clojure.core_native.is_var_thread_bound %) vars)) -; -;(defmacro ^:private assert-macro-args -; [& pairs] -; (list 'do -; (list 'clojure.core/when-not (first pairs) -; ; TODO: No need for ex-info, if we had a simpler exception type -; (list 'throw (list 'clojure.core/ex-info -; (list 'clojure.core/str -; '&form -; " requires " -; (second pairs) -; " in " -; 'clojure.core/*ns* -; ":" -; (:line (meta '&form))) -; {}))) -; (let [more (next (next pairs))] -; (when more -; (list* 'clojure.core/assert-macro-args more))))) -; -;(defmacro if-let -; "bindings => binding-form test -; -; If test is true, evaluates then with binding-form bound to the value of -; test, if not, yields else" -; ([bindings then] -; `(if-let ~bindings ~then nil)) -; ([bindings then else & oldform] -; (assert-macro-args -; (vector? bindings) "a vector for its binding" -; (nil? oldform) "1 or 2 forms after binding vector" -; (= 2 (count bindings)) "exactly 2 forms in binding vector") -; (let [form (get bindings 0) -; tst (get bindings 1)] -; `(let [temp# ~tst] -; (if temp# -; (let [~form temp#] -; ~then) -; ~else))))) -; -;(defmacro when-let -; "bindings => binding-form test -; -; When test is true, evaluates body with binding-form bound to the value of test" -; [bindings & body] -; (assert-macro-args -; (vector? bindings) "a vector for its binding" -; (= 2 (count bindings)) "exactly 2 forms in binding vector") -; (let [form (get bindings 0) -; tst (get bindings 1)] -; `(let [temp# ~tst] -; (when temp# -; (let [~form temp#] -; ~@body))))) -; -;(defmacro if-some -; "bindings => binding-form test -; -; If test is not nil, evaluates then with binding-form bound to the -; value of test, if not, yields else" -; ([bindings then] -; `(if-some ~bindings ~then nil)) -; ([bindings then else & oldform] -; (assert-macro-args -; (vector? bindings) "a vector for its binding" -; (nil? oldform) "1 or 2 forms after binding vector" -; (= 2 (count bindings)) "exactly 2 forms in binding vector") -; (let [form (get bindings 0) tst (get bindings 1)] -; `(let [temp# ~tst] -; (if (nil? temp#) -; ~else -; (let [~form temp#] -; ~then)))))) -; -;(defmacro when-some -; "bindings => binding-form test -; -; When test is not nil, evaluates body with binding-form bound to the -; value of test" -; [bindings & body] -; (assert-macro-args -; (vector? bindings) "a vector for its binding" -; (= 2 (count bindings)) "exactly 2 forms in binding vector") -; (let [form (get bindings 0) -; tst (get bindings 1)] -; `(let [temp# ~tst] -; (if (nil? temp#) -; nil -; (let [~form temp#] -; ~@body))))) -; -;(defmacro dotimes -; "bindings => name n -; -; Repeatedly executes body (presumably for side-effects) with name -; bound to integers from 0 through n-1." -; [bindings & body] -; (assert-macro-args -; (vector? bindings) "a vector for its binding" -; (= 2 (count bindings)) "exactly 2 forms in binding vector") -; (let [i (first bindings) -; n (second bindings)] -; `(let [n# (int ~n)] -; (loop [~i 0] -; (when (< ~i n#) -; ~@body -; ; TODO: unchecked-inc -; (recur (inc ~i))))))) -; -;(defn push-thread-bindings -; "WARNING: This is a low-level function. Prefer high-level macros like -; binding where ever possible. -; -; Takes a map of Var/value pairs. Binds each Var to the associated value for -; the current thread. Each call *MUST* be accompanied by a matching call to -; pop-thread-bindings wrapped in a try-finally! -; -; (push-thread-bindings bindings) -; (try -; ... -; (finally -; (pop-thread-bindings)))" -; [bindings] -; (cpp/jank.runtime.push_thread_bindings bindings)) -; -;(defn pop-thread-bindings -; "Pop one set of bindings pushed with push-binding before. It is an error to -; pop bindings without pushing before." -; [] -; (cpp/jank.runtime.pop_thread_bindings)) -; -;(defn get-thread-bindings -; "Get a map with the Var/value pairs which is currently in effect for the -; current thread." -; [] -; (cpp/jank.runtime.get_thread_bindings)) -; -;(defmacro binding -; "binding => var-symbol init-expr -; -; Creates new bindings for the (already-existing) vars, with the -; supplied initial values, executes the exprs in an implicit do, then -; re-establishes the bindings that existed before. The new bindings -; are made in parallel (unlike let); all init-exprs are evaluated -; before the vars are bound to their new values." -; [bindings & body] -; (assert-macro-args -; (vector? bindings) "a vector for its binding" -; (even? (count bindings)) "an even number of forms in binding vector") -; (let [->var-pairs (fn ->var-pairs [var-vals] -; (loop [ret [] -; vvs (seq var-vals)] -; (if vvs -; (recur (conj (conj ret `(var ~(first vvs))) (second vvs)) -; (next (next vvs))) -; (seq ret))))] -; `(do -; (push-thread-bindings (hash-map ~@(->var-pairs bindings))) -; (try -; (do ~@body) -; (finally -; (pop-thread-bindings)))))) -; -;;; Keywords. -;(defn keyword? -; "Return true if x is a Keyword" -; [x] -; (cpp/jank.runtime.is_keyword x)) -;(defn simple-keyword? -; "Return true if x is a keyword without a namespace" -; [x] -; (cpp/jank.runtime.is_simple_keyword x)) -;(defn qualified-keyword? -; "Return true if x is a keyword with a namespace" -; [x] -; (cpp/jank.runtime.is_qualified_keyword x)) -; -;(defn keyword -; "Returns a Keyword with the given namespace and name. Do not use : -; in the keyword strings, it will be added automatically." -; ([name] -; (cond -; (keyword? name) name -; (symbol? name) (cpp/jank.runtime.keyword nil (str name)) -; (string? name) (cpp/jank.runtime.keyword nil name))) -; ([ns name] -; (cpp/jank.runtime.keyword ns name))) -; -;(defn ident? -; "Returns true if x is a symbol or keyword" -; [x] -; (or (keyword? x) (symbol? x))) -; -;(defn simple-ident? -; "Returns true if x is a symbol or keyword without a namespace" -; [x] -; (and (ident? x) (nil? (namespace x)))) -; -;(defn qualified-ident? -; "Returns true if x is a symbol or keyword with a namespace" -; [x] -; (boolean (and (ident? x) (namespace x) true))) -; -;;; Sequences. -;(defn iterate -; "Returns a lazy (infinite!) sequence of x, (f x), (f (f x)) etc. -; f must be free of side-effects" -; [fn x] -; (cpp/jank.runtime.iterate fn x)) -; -;(defn range -; "Returns a lazy seq of nums from start (inclusive) to end -; (exclusive), by step, where start defaults to 0, step to 1, and end to -; infinity. When step is equal to 0, returns an infinite sequence of -; start. When start is equal to end, returns empty list." -; ([] -; (iterate inc 0)) -; ([end] -; (if (integer? end) -; (cpp/jank.runtime.obj.integer_range.create end) -; (cpp/jank.runtime.obj.range.create end))) -; ([start end] -; (if (and (integer? start) (integer? end)) -; (cpp/jank.runtime.obj.integer_range.create start end) -; (cpp/jank.runtime.obj.range.create start end))) -; ([start end step] -; (if (and (integer? start) (integer? end) (integer? step)) -; (cpp/jank.runtime.obj.integer_range.create start end step) -; (cpp/jank.runtime.obj.range.create start end step)))) -; -;(defn nth -; "Returns the value at the index. get returns nil if index out of -; bounds, nth throws an exception unless not-found is supplied. nth -; also works for strings, Java arrays, regex Matchers and Lists, and, -; in O(n) time, for sequences." -; ([coll index] -; (cpp/jank.runtime.nth coll index)) -; ([coll index not-found] -; (cpp/jank.runtime.nth coll index not-found))) -; -;(defn nthnext -; "Returns the nth next of coll, (seq coll) when n is 0." -; [coll n] -; ;; TODO add support for IDrop -; (loop [n n xs (seq coll)] -; (if (and xs (pos? n)) -; (recur (dec n) (next xs)) -; xs))) -; -;(defn nthrest -; "Returns the nth rest of coll, coll when n is 0." -; [coll n] -; ;; TODO add support for IDrop -; (if (pos? n) -; (if-let [xs (seq coll)] -; (recur (rest xs) (dec n)) -; (or (seq coll) ())) -; coll)) -; -;(defn take-nth -; "Returns a lazy seq of every nth item in coll. Returns a stateful -; transducer when no collection is provided." -; ([n] -; (fn [rf] -; (let [iv (volatile! -1)] -; (fn -; ([] (rf)) -; ([result] (rf result)) -; ([result input] -; (let [i (vswap! iv inc)] -; (if (zero? (rem i n)) -; (rf result input) -; result))))))) -; ([n coll] -; (lazy-seq -; (when-let [s (seq coll)] -; (cons (first s) (take-nth n (drop n s))))))) -; -;(defn map -; "Returns a lazy sequence consisting of the result of applying f to -; the set of first items of each coll, followed by applying f to the -; set of second items in each coll, until any one of the colls is -; exhausted. Any remaining items in other colls are ignored. Function -; f should accept number-of-colls arguments. Returns a transducer when -; no collection is provided." -; ([f] -; (fn [rf] -; (fn -; ([] (rf)) -; ([result] (rf result)) -; ([result input] -; (rf result (f input))) -; ([result input & inputs] -; (rf result (apply f input inputs)))))) -; ([f coll] -; (lazy-seq -; (when-let [s (seq coll)] -; (if (chunked-seq? s) -; (let [c (chunk-first s) -; size (int (count c)) -; b (chunk-buffer size)] -; (dotimes [i size] -; (chunk-append b (f (nth c i)))) -; (chunk-cons (chunk b) (map f (chunk-rest s)))) -; (cons (f (first s)) (map f (rest s))))))) -; ([f c1 c2] -; (lazy-seq -; (let [s1 (seq c1) -; s2 (seq c2)] -; (when (and s1 s2) -; (cons (f (first s1) (first s2)) -; (map f (rest s1) (rest s2))))))) -; ([f c1 c2 c3] -; (lazy-seq -; (let [s1 (seq c1) -; s2 (seq c2) -; s3 (seq c3)] -; (when (and s1 s2 s3) -; (cons (f (first s1) (first s2) (first s3)) -; (map f (rest s1) (rest s2) (rest s3))))))) -; ([f c1 c2 c3 & colls] -; (let [step (fn step [cs] -; (lazy-seq -; (let [ss (map seq cs)] -; (when (every? identity ss) -; (cons (map first ss) (step (map rest ss)))))))] -; (map #(apply f %) (step (conj colls c3 c2 c1)))))) -; -;(defmacro doto -; "Evaluates x then calls all of the methods and functions with the -; value of x supplied at the front of the given arguments. The forms -; are evaluated in order. Returns x." -; [x & forms] -; (let [gx (gensym)] -; `(let [~gx ~x] -; ~@(map (fn [f] -; (with-meta -; (if (seq? f) -; `(~(first f) ~gx ~@(next f)) -; `(~f ~gx)) -; (meta f))) -; forms) -; ~gx))) -; -;(defn map-indexed -; "Returns a lazy sequence consisting of the result of applying f to 0 -; and the first item of coll, followed by applying f to 1 and the second -; item in coll, etc, until coll is exhausted. Thus function f should -; accept 2 arguments, index and item. Returns a stateful transducer when -; no collection is provided." -; ([f] -; (fn [rf] -; (let [i (volatile! -1)] -; (fn -; ([] (rf)) -; ([result] (rf result)) -; ([result input] -; (rf result (f (vswap! i inc) input))))))) -; ([f coll] -; (let [mapi (fn mapi [idx coll] -; (lazy-seq -; (when-let [s (seq coll)] -; (if (chunked-seq? s) -; (let [c (chunk-first s) -; size (int (count c)) -; b (chunk-buffer size)] -; (dotimes [i size] -; (chunk-append b (f (+ idx i) (nth c i)))) -; (chunk-cons (chunk b) (mapi (+ idx size) (chunk-rest s)))) -; (cons (f idx (first s)) (mapi (inc idx) (rest s)))))))] -; (mapi 0 coll)))) -; -;(defn keep -; "Returns a lazy sequence of the non-nil results of (f item). Note, -; this means false return values will be included. f must be free of -; side-effects. Returns a transducer when no collection is provided." -; ([f] -; (fn [rf] -; (fn -; ([] (rf)) -; ([result] (rf result)) -; ([result input] -; (let [v (f input)] -; (if (nil? v) -; result -; (rf result v))))))) -; ([f coll] -; (lazy-seq -; (when-let [s (seq coll)] -; (if (chunked-seq? s) -; (let [c (chunk-first s) -; size (count c) -; b (chunk-buffer size)] -; (dotimes [i size] -; (let [x (f (nth c i))] -; (when-not (nil? x) -; (chunk-append b x)))) -; (chunk-cons (chunk b) (keep f (chunk-rest s)))) -; (let [x (f (first s))] -; (if (nil? x) -; (keep f (rest s)) -; (cons x (keep f (rest s)))))))))) -; -;(defn keep-indexed -; "Returns a lazy sequence of the non-nil results of (f index item). Note, -; this means false return values will be included. f must be free of -; side-effects. Returns a stateful transducer when no collection is -; provided." -; ([f] -; (fn [rf] -; (let [iv (volatile! -1)] -; (fn -; ([] (rf)) -; ([result] (rf result)) -; ([result input] -; (let [i (vswap! iv inc) -; v (f i input)] -; (if (nil? v) -; result -; (rf result v)))))))) -; ([f coll] -; (let [keepi (fn keepi [idx coll] -; (lazy-seq -; (when-let [s (seq coll)] -; (if (chunked-seq? s) -; (let [c (chunk-first s) -; size (count c) -; b (chunk-buffer size)] -; (dotimes [i size] -; (let [x (f (+ idx i) (nth c i))] -; (when-not (nil? x) -; (chunk-append b x)))) -; (chunk-cons (chunk b) (keepi (+ idx size) (chunk-rest s)))) -; (let [x (f idx (first s))] -; (if (nil? x) -; (keepi (inc idx) (rest s)) -; (cons x (keepi (inc idx) (rest s)))))))))] -; (keepi 0 coll)))) -; -;(defn take -; "Returns a lazy sequence of the first n items in coll, or all items if -; there are fewer than n. Returns a stateful transducer when -; no collection is provided." -; ([n] -; (fn [rf] -; (let [nv (volatile! n)] -; (fn -; ([] (rf)) -; ([result] (rf result)) -; ([result input] -; (let [n (deref nv) -; nn (vswap! nv dec) -; result (if (pos? n) -; (rf result input) -; result)] -; (if (not (pos? nn)) -; (ensure-reduced result) -; result))))))) -; ([n coll] -; (lazy-seq -; (when (pos? n) -; (when-let [s (seq coll)] -; (cons (first s) (take (dec n) (rest s)))))))) -; -;(defn repeatedly -; "Takes a function of no args, presumably with side effects, and -; returns an infinite (or length n if supplied) lazy sequence of calls -; to it" -; ([f] (lazy-seq (cons (f) (repeatedly f)))) -; ([n f] (take n (repeatedly f)))) -; -;(defn take-while -; "Returns a lazy sequence of successive items from coll while -; (pred item) returns logical true. pred must be free of side-effects. -; Returns a transducer when no collection is provided" -; ([pred] -; (fn [rf] -; (fn -; ([] (rf)) -; ([result] (rf result)) -; ([result input] -; (if (pred input) -; (rf result input) -; (reduced result)))))) -; ([pred coll] -; (lazy-seq -; (when-let [s (seq coll)] -; (when (pred (first s)) -; (cons (first s) (take-while pred (rest s)))))))) -; -;(defn drop -; "Returns a lazy sequence of all but the first n items in coll. -; Returns a stateful transducer when no collection is provided." -; ([n] -; (fn [rf] -; (let [nv (volatile! n)] -; (fn -; ([] (rf)) -; ([result] (rf result)) -; ([result input] -; (let [n (deref nv)] -; (vswap! nv dec) -; (if (pos? n) -; result -; (rf result input)))))))) -; ([n coll] -; (let [step (fn [n coll] -; (let [s (seq coll)] -; (if (and (pos? n) s) -; (recur (dec n) (rest s)) -; s)))] -; (lazy-seq (step n coll))))) -; -;(defn drop-last -; "Return a lazy sequence of all but the last n (default 1) items in coll" -; ([coll] (drop-last 1 coll)) -; ([n coll] (map (fn [x _] x) coll (drop n coll)))) -; -;(defn drop-while -; "Returns a lazy sequence of the items in coll starting from the -; first item for which (pred item) returns logical false. Returns a -; stateful transducer when no collection is provided." -; ([pred] -; (fn [rf] -; (let [dv (volatile! true)] -; (fn -; ([] (rf)) -; ([result] (rf result)) -; ([result input] -; (let [drop? (deref dv)] -; (if (and drop? (pred input)) -; result -; (do -; (vreset! dv nil) -; (rf result input))))))))) -; ([pred coll] -; (let [step (fn [pred coll] -; (let [s (seq coll)] -; (if (and s (pred (first s))) -; (recur pred (rest s)) -; s)))] -; (lazy-seq (step pred coll))))) -; -;(defn cycle -; "Returns a lazy (infinite!) sequence of repetitions of the items in coll." -; [coll] -; ; TODO: Custom cycle object -; (lazy-seq (concat coll (cycle coll)))) -; -;(defn repeat -; "Returns a lazy (infinite!, or length n if supplied) sequence of val." -; ([x] -; (cpp/jank.runtime.obj.repeat.create x)) -; ([n x] -; (cpp/jank.runtime.obj.repeat.create n x))) -; -;(defn split-at -; "Returns a vector of [(take n coll) (drop n coll)]" -; [n coll] -; [(take n coll) (drop n coll)]) -; -;(defn split-with -; "Returns a vector of [(take-while pred coll) (drop-while pred coll)]" -; [pred coll] -; [(take-while pred coll) (drop-while pred coll)]) -; -;(defn interleave -; "Returns a lazy seq of the first item in each coll, then the second etc." -; ([] ()) -; ([c1] (lazy-seq c1)) -; ([c1 c2] -; (lazy-seq -; (let [s1 (seq c1) s2 (seq c2)] -; (when (and s1 s2) -; (cons (first s1) (cons (first s2) -; (interleave (rest s1) (rest s2)))))))) -; ([c1 c2 & colls] -; (lazy-seq -; (let [ss (map seq (conj colls c2 c1))] -; (when (every? identity ss) -; (concat (map first ss) (apply interleave (map rest ss)))))))) -; -;(defn interpose -; "Returns a lazy seq of the elements of coll separated by sep. -; Returns a stateful transducer when no collection is provided." -; ([sep] -; (fn [rf] -; (let [started (volatile! false)] -; (fn -; ([] (rf)) -; ([result] (rf result)) -; ([result input] -; (if (deref started) -; (let [sepr (rf result sep)] -; (if (reduced? sepr) -; sepr -; (rf sepr input))) -; (do -; (vreset! started true) -; (rf result input)))))))) -; ([sep coll] -; (drop 1 (interleave (repeat sep) coll)))) -; -;(defn dorun -; "When lazy sequences are produced via functions that have side -; effects, any effects other than those needed to produce the first -; element in the seq do not occur until the seq is consumed. dorun can -; be used to force any effects. Walks through the successive nexts of -; the seq, does not retain the head and returns nil." -; ([coll] -; (when-let [s (seq coll)] -; (recur (next s)))) -; ([n coll] -; (when (and (seq coll) (pos? n)) -; (recur (dec n) (next coll))))) -; -;(defn doall -; "When lazy sequences are produced via functions that have side -; effects, any effects other than those needed to produce the first -; element in the seq do not occur until the seq is consumed. doall can -; be used to force any effects. Walks through the successive nexts of -; the seq, retains the head and returns it, thus causing the entire -; seq to reside in memory at one time." -; ([coll] -; (dorun coll) -; coll) -; ([n coll] -; (dorun n coll) -; coll)) -; -;(defn partition -; "Returns a lazy sequence of lists of n items each, at offsets step -; apart. If step is not supplied, defaults to n, i.e. the partitions -; do not overlap. If a pad collection is supplied, use its elements as -; necessary to complete last partition upto n items. In case there are -; not enough padding elements, return a partition with less than n items." -; ([n coll] -; (partition n n coll)) -; ([n step coll] -; (lazy-seq -; (when-let [s (seq coll)] -; (let [p (doall (take n s))] -; (when (= n (count p)) -; (cons p (partition n step (nthrest s step)))))))) -; ([n step pad coll] -; (lazy-seq -; (when-let [s (seq coll)] -; (let [p (doall (take n s))] -; (if (= n (count p)) -; (cons p (partition n step pad (nthrest s step))) -; (list (take n (concat p pad))))))))) -; -;(defn partition-all -; "Returns a lazy sequence of lists like partition, but may include -; partitions with fewer than n items at the end. Returns a stateful -; transducer when no collection is provided." -; ([n] -; (fn [rf] -; ;; OPTIMIZE: jvm clojure uses an array here for perf -; (let [part (volatile! [])] -; (fn -; ([] (rf)) -; ([result] -; (let [p (deref part) -; result (if (empty? p) -; result -; (unreduced (rf result p)))] -; (rf result))) -; ([result input] -; (let [p (vswap! part conj input)] -; (if (= n (count p)) -; (do (vreset! part []) -; (rf result p)) -; result))))))) -; ([n coll] -; (partition-all n n coll)) -; ([n step coll] -; (lazy-seq -; (when-let [s (seq coll)] -; (let [seg (doall (take n s))] -; (cons seg (partition-all n step (nthrest s step)))))))) -; -;(defn partition-by -; "Applies f to each value in coll, splitting it each time f returns a -; new value. Returns a lazy seq of partitions. Returns a stateful -; transducer when no collection is provided." -; ([f] -; (fn [rf] -; ;; OPTIMIZE: jvm clojure uses an array here for perf -; (let [vv (volatile! []) -; pv (volatile! ::none)] -; (fn -; ([] (rf)) -; ([result] -; (let [v (deref vv) -; result (if (empty? v) -; result -; (unreduced (rf result v)))] -; (rf result))) -; ([result input] -; (let [pval (deref pv) -; val (f input)] -; (vreset! pv val) -; (if (or (identical? pval ::none) -; (= val pval)) -; (do -; (vswap! vv conj input) -; result) -; (let [v (deref vv) -; ret (rf result v)] -; (when-not (reduced? ret) -; (vreset! vv [input])) -; ret)))))))) -; ([f coll] -; (lazy-seq -; (when-let [s (seq coll)] -; (let [fst (first s) -; fv (f fst) -; run (cons fst (take-while #(= fv (f %)) (next s)))] -; (cons run (partition-by f (lazy-seq (drop (count run) s))))))))) -; -;(defn frequencies -; "Returns a map from distinct items in coll to the number of times -; they appear." -; [coll] -; (persistent! -; (reduce -; (fn [counts x] -; (assoc! counts x (inc (get counts x 0)))) -; (transient {}) -; coll))) -; -;(defn group-by -; "Returns a map of the elements of coll keyed by the result of -; f on each element. The value at each key will be a vector of the -; corresponding elements, in the order they appeared in coll." -; [f coll] -; (persistent! -; (reduce -; (fn [ret x] -; (let [k (f x)] -; (assoc! ret k (conj (get ret k []) x)))) -; (transient {}) -; coll))) -; -;(defn reductions -; "Returns a lazy seq of the intermediate values of the reduction (as -; per reduce) of coll by f, starting with init." -; ([f coll] -; (lazy-seq -; (if-let [s (seq coll)] -; (reductions f (first s) (rest s)) -; (list (f))))) -; ([f init coll] -; (if (reduced? init) -; (list (deref init)) -; (cons init -; (lazy-seq -; (when-let [s (seq coll)] -; (reductions f (f init (first s)) (rest s)))))))) -; -;(defn into -; "Returns a new coll consisting of to-coll with all of the items of -; from-coll conjoined. A transducer may be supplied." -; ([] []) -; ([to] to) -; ([to from] -; (if (transientable? to) -; (with-meta (persistent! (reduce conj! (transient to) from)) (meta to)) -; (reduce conj to from))) -; ([to xform from] -; (if (transientable? to) -; (with-meta (persistent! (transduce xform conj! (transient to) from)) (meta to)) -; (transduce xform conj to from)))) -; -;; Redefine let and loop with destructuring. -;(defn destructure -; [bindings] -; (let [bents (partition 2 bindings) -; pb (fn pb [bvec b v] -; (let [pvec -; (fn pvec [bvec b val] -; (let [gvec (gensym "vec") -; gseq (gensym "seq") -; gfirst (gensym "first") -; has-rest (some #{'&} b)] -; (loop [ret (let [ret (conj bvec gvec val)] -; (if has-rest -; (conj ret gseq (list `seq gvec)) -; ret)) -; n 0 -; bs b -; seen-rest? false] -; (if (seq bs) -; (let [firstb (first bs)] -; (cond -; (= firstb '&) (recur (pb ret (second bs) gseq) -; n -; (nnext bs) -; true) -; (= firstb :as) (pb ret (second bs) gvec) -; :else (if seen-rest? -; (throw "Unsupported binding form, only :as can follow & parameter") -; (recur (pb (if has-rest -; (conj ret -; gfirst `(first ~gseq) -; gseq `(next ~gseq)) -; ret) -; firstb -; (if has-rest -; gfirst -; (list `nth gvec n nil))) -; (inc n) -; (next bs) -; seen-rest?)))) -; ret)))) -; pmap -; (fn pmap [bvec b v] -; (let [gmap (gensym "map") -; defaults (:or b)] -; (loop [ret (-> bvec -; (conj gmap) (conj v) -; (conj gmap) (conj `(if (seq? ~gmap) -; (if (next ~gmap) -; (into {} ~gmap) -; (if (seq ~gmap) -; (first ~gmap) -; {})) -; ~gmap)) -; ((fn pmap#ret [ret] -; (if (:as b) -; (conj ret (:as b) gmap) -; ret)))) -; bes (let [transforms -; (reduce -; (fn pmap#transforms [transforms mk] -; (if (keyword? mk) -; (let [mkns (namespace mk) -; mkn (name mk)] -; (cond (= mkn "keys") (assoc transforms mk #(keyword (or mkns (namespace %)) (name %))) -; (= mkn "syms") (assoc transforms mk #(list `quote (symbol (or mkns (namespace %)) (name %)))) -; (= mkn "strs") (assoc transforms mk str) -; :else transforms)) -; transforms)) -; {} -; (keys b))] -; (reduce -; (fn pmap#bes [bes entry] -; (reduce #(assoc %1 %2 ((val entry) %2)) -; (dissoc bes (key entry)) -; ((key entry) bes))) -; (dissoc b :as :or) -; transforms))] -; (if (seq bes) -; (let [bb (key (first bes)) -; bk (val (first bes)) -; local (if (named? bb) -; (with-meta (symbol nil (name bb)) (meta bb)) -; bb) -; bv (if (contains? defaults local) -; (list `get gmap bk (defaults local)) -; (list `get gmap bk))] -; (recur (if (ident? bb) -; (-> ret (conj local bv)) -; (pb ret bb bv)) -; (next bes))) -; ret))))] -; (cond -; (symbol? b) (-> bvec (conj b) (conj v)) -; (vector? b) (pvec bvec b v) -; (map? b) (pmap bvec b v) -; :else (throw (str "Unsupported binding form: " b))))) -; process-entry (fn process-entry [bvec b] -; (pb bvec (first b) (second b)))] -; (if (every? symbol? (map first bents)) -; bindings -; (reduce process-entry [] bents)))) -; -;(defmacro let -; "binding => binding-form init-expr -; binding-form => name, or destructuring-form -; destructuring-form => map-destructure-form, or seq-destructure-form -; -; Evaluates the exprs in a lexical context in which the symbols in -; the binding-forms are bound to their respective init-exprs or parts -; therein. -; -; See https://clojure.org/reference/special_forms#binding-forms for -; more information about destructuring." -; [bindings & body] -; (assert-macro-args -; (vector? bindings) "a vector for its binding" -; (even? (count bindings)) "an even number of forms in binding vector") -; `(let* ~(destructure bindings) ~@body)) -; -;(defn maybe-destructured -; {:private true} -; [params body] -; (if (every? symbol? params) -; (cons params body) -; (loop [params params -; new-params (with-meta [] (meta params)) -; lets []] -; (if params -; (if (symbol? (first params)) -; (recur (next params) (conj new-params (first params)) lets) -; (let [gparam (gensym "p__")] -; (recur (next params) (conj new-params gparam) -; (-> lets (conj (first params)) (conj gparam))))) -; `(~new-params -; (let ~lets -; ~@body)))))) -; -;(defmacro fn -; "params => positional-params*, or positional-params* & rest-param -; positional-param => binding-form -; rest-param => binding-form -; binding-form => name, or destructuring-form -; -; Defines a function. -; -; See https://clojure.org/reference/special_forms#fn for more information" -; [& sigs] -; (let [name (if (symbol? (first sigs)) (first sigs) nil) -; sigs (if name (next sigs) sigs) -; sigs (if (vector? (first sigs)) -; (list sigs) -; (if (seq? (first sigs)) -; sigs -; ; Assume single arity syntax -; (throw (if (seq sigs) -; (str "Parameter declaration " -; (first sigs) -; " should be a vector") -; (str "Parameter declaration missing"))))) -; psig (fn* [sig] -; ; Ensure correct type before destructuring sig -; (when (not (seq? sig)) -; (throw (str "Invalid signature " sig -; " should be a list"))) -; (let [[params & body] sig -; _ (when (not (vector? params)) -; (throw (if (seq? (first sigs)) -; (str "Parameter declaration " params -; " should be a vector") -; (str "Invalid signature " sig -; " should be a list")))) -; conds (when (and (next body) (map? (first body))) -; (first body)) -; body (if conds (next body) body) -; conds (or conds (meta params)) -; pre (:pre conds) -; post (:post conds) -; body (if post -; `((let [~'% ~(if (< 1 (count body)) -; `(do ~@body) -; (first body))] -; ~@(map (fn* [c] -; `(assert ~c)) post) -; ~'%)) -; body) -; body (if pre -; (concat (map (fn* [c] -; `(assert ~c)) pre) -; body) -; body)] -; (maybe-destructured params body))) -; new-sigs (map psig sigs)] -; (with-meta -; (if name -; `(fn* ~name ~@new-sigs) -; `(fn* ~@new-sigs)) -; (meta &form)))) -; -;(defmacro loop -; "Evaluates the exprs in a lexical context in which the symbols in -; the binding-forms are bound to their respective init-exprs or parts -; therein. Acts as a recur target." -; [all-bindings & body] -; (assert-macro-args -; (vector? all-bindings) "a vector for its binding" -; (even? (count all-bindings)) "an even number of forms in binding vector") -; (let [db (destructure all-bindings)] -; (if (= db all-bindings) -; `(loop* ~all-bindings ~@body) -; (let [values (take-nth 2 (drop 1 all-bindings)) -; bindings (take-nth 2 all-bindings) -; syms (map (fn [b] -; (if (symbol? b) -; b -; (gensym))) -; bindings) -; final-bindings (reduce (fn [ret [b v g]] -; (if (symbol? b) -; (conj ret g v) -; (conj ret g v b g))) -; [] -; (map vector bindings values syms))] -; `(let ~final-bindings -; (loop* ~(vec (interleave syms syms)) -; (let ~(vec (interleave bindings syms)) -; ~@body))))))) -; -;(defmacro for -; "List comprehension. Takes a vector of one or more -; binding-form/collection-expr pairs, each followed by zero or more -; modifiers, and yields a lazy sequence of evaluations of expr. -; Collections are iterated in a nested fashion, rightmost fastest, -; and nested coll-exprs can refer to bindings created in prior -; binding-forms. Supported modifiers are: :let [binding-form expr ...], -; :while test, :when test. -; -; (take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))" -; [seq-exprs body-expr] -; (assert-macro-args -; (vector? seq-exprs) "a vector for its binding" -; (even? (count seq-exprs)) "an even number of forms in binding vector") -; (let [to-groups (fn [seq-exprs] -; (reduce (fn [groups [k v]] -; (if (keyword? k) -; (conj (pop groups) (conj (peek groups) [k v])) -; (conj groups [k v]))) -; [] (partition 2 seq-exprs))) -; err (fn [& msg] (throw (apply str msg))) -; emit-bind (fn emit-bind [[[bind expr & mod-pairs] -; & [[_ next-expr] :as next-groups]]] -; (let [giter (gensym "iter__") -; gxs (gensym "s__") -; do-mod (fn do-mod [[[k v :as pair] & etc]] -; (cond -; (= k :let) `(let ~v ~(do-mod etc)) -; (= k :while) `(when ~v ~(do-mod etc)) -; (= k :when) `(if ~v -; ~(do-mod etc) -; (recur (rest ~gxs))) -; (keyword? k) (err "Invalid 'for' keyword " k) -; next-groups -; `(let [iterys# ~(emit-bind next-groups) -; fs# (seq (iterys# ~next-expr))] -; (if fs# -; (concat fs# (~giter (rest ~gxs))) -; (recur (rest ~gxs)))) -; :else (do -; `(cons ~body-expr -; (~giter (rest ~gxs))))))] -; (if next-groups -; ; not the inner-most loop -; `(fn ~giter [~gxs] -; (lazy-seq -; (loop [~gxs ~gxs] -; (when-first [~bind ~gxs] -; ~(do-mod mod-pairs))))) -; ; inner-most loop -; (let [gi (gensym "i__") -; gb (gensym "b__") -; do-cmod (fn do-cmod [[[k v :as pair] & etc]] -; (cond -; (= k :let) `(let ~v ~(do-cmod etc)) -; (= k :while) `(when ~v ~(do-cmod etc)) -; (= k :when) `(if ~v -; ~(do-cmod etc) -; (recur -; ; TODO: unchecked-inc -; (inc ~gi))) -; (keyword? k) -; (err "Invalid 'for' keyword " k) -; :else -; `(do (chunk-append ~gb ~body-expr) -; ; TODO: unchecked-inc -; (recur (inc ~gi)))))] -; `(fn ~giter [~gxs] -; (lazy-seq -; (loop [~gxs ~gxs] -; (when-let [~gxs (seq ~gxs)] -; (if (chunked-seq? ~gxs) -; (let [c# (chunk-first ~gxs) -; size# (int (count c#)) -; ~gb (chunk-buffer size#)] -; (if (loop [~gi (int 0)] -; (if (< ~gi size#) -; (let [~bind (nth c# ~gi)] -; ~(do-cmod mod-pairs)) -; true)) -; (chunk-cons -; (chunk ~gb) -; (~giter (chunk-rest ~gxs))) -; (chunk-cons (chunk ~gb) nil))) -; (let [~bind (first ~gxs)] -; ~(do-mod mod-pairs)))))))))))] -; `(let [iter# ~(emit-bind (to-groups seq-exprs))] -; (iter# ~(second seq-exprs))))) -; -;(defn not-empty -; "If coll is empty, returns nil, else coll" -; [coll] -; (when (seq coll) -; coll)) -; -;(defn get-in -; "Returns the value in a nested associative structure, -; where ks is a sequence of keys. Returns nil if the key -; is not present, or the not-found value if supplied." -; ([m ks] -; (reduce get m ks)) -; ([m ks not-found] -; (loop [m m -; ks (seq ks)] -; (if ks -; (let [m (get m (first ks) ::none)] -; (if (identical? ::none m) -; not-found -; (recur m (next ks)))) -; m)))) -; -;(defn assoc-in -; "Associates a value in a nested associative structure, where ks is a -; sequence of keys and v is the new value and returns a new nested structure. -; If any levels do not exist, hash-maps will be created." -; [m [k & ks] v] -; (if ks -; (assoc m k (assoc-in (get m k) ks v)) -; (assoc m k v))) -; -;(defn update-in -; "'Updates' a value in a nested associative structure, where ks is a -; sequence of keys and f is a function that will take the old value -; and any supplied args and return the new value, and returns a new -; nested structure. If any levels do not exist, hash-maps will be -; created." -; [m ks f & args] -; (let [up (fn up [m ks f args] -; (let [[k & ks] ks] -; (if ks -; (assoc m k (up (get m k) ks f args)) -; (assoc m k (apply f (get m k) args)))))] -; (up m ks f args))) -; -;(defn update -; "'Updates' a value in an associative structure, where k is a -; key and f is a function that will take the old value -; and any supplied args and return the new value, and returns a new -; structure. If the key does not exist, nil is passed as the old value." -; ([m k f] -; (assoc m k (f (get m k)))) -; ([m k f x] -; (assoc m k (f (get m k) x))) -; ([m k f x y] -; (assoc m k (f (get m k) x y))) -; ([m k f x y z] -; (assoc m k (f (get m k) x y z))) -; ([m k f x y z & more] -; (assoc m k (apply f (get m k) x y z more)))) -; -;(defmacro when-first -; "bindings => x xs -; -; Roughly the same as (when (seq xs) (let [x (first xs)] body)) but xs is evaluated only once" -; [bindings & body] -; (assert-macro-args -; (vector? bindings) "a vector for its binding" -; (= 2 (count bindings)) "exactly 2 forms in binding vector") -; (let [[x xs] bindings] -; `(when-let [xs# (seq ~xs)] -; (let [~x (first xs#)] -; ~@body)))) -; -;(defn take-last -; "Returns a seq of the last n items in coll. Depending on the type -; of coll may be no better than linear time. For vectors, see also subvec." -; [n coll] -; (loop [s (seq coll) -; lead (seq (drop n coll))] -; (if lead -; (recur (next s) (next lead)) -; s))) -; -;(defn mapv -; "Returns a vector consisting of the result of applying f to the -; set of first items of each coll, followed by applying f to the set -; of second items in each coll, until any one of the colls is -; exhausted. Any remaining items in other colls are ignored. Function -; f should accept number-of-colls arguments." -; ([f coll] -; (-> (reduce (fn [v o] -; (conj! v (f o))) -; (transient []) -; coll) -; persistent!)) -; ([f c1 c2] -; (into [] (map f c1 c2))) -; ([f c1 c2 c3] -; (into [] (map f c1 c2 c3))) -; ([f c1 c2 c3 & colls] -; (into [] (apply map f c1 c2 c3 colls)))) -; -;(defn filterv -; "Returns a vector of the items in coll for which -; (pred item) returns logical true. pred must be free of side-effects." -; [pred coll] -; (-> (reduce (fn [v o] -; (if (pred o) -; (conj! v o) -; v)) -; (transient []) -; coll) -; persistent!)) -; -;(defn mapcat -; "Returns the result of applying concat to the result of applying map -; to f and colls. Thus function f should return a collection. Returns -; a transducer when no collections are provided" -; ([f] (comp (map f) cat)) -; ; TODO: Variadic. -; ([f coll] -; (apply concat (map f coll)))) -; -;(defn tree-seq -; "Returns a lazy sequence of the nodes in a tree, via a depth-first walk. -; branch? must be a fn of one arg that returns true if passed a node -; that can have children (but may not). children must be a fn of one -; arg that returns a sequence of the children. Will only be called on -; nodes for which branch? returns true. Root is the root node of the -; tree." -; [branch? children root] -; (let [walk (fn walk [node] -; (lazy-seq -; (cons node -; (when (branch? node) -; (mapcat walk (children node))))))] -; (walk root))) -; -;(defn distinct -; "Returns a lazy sequence of the elements of coll with duplicates removed. -; Returns a stateful transducer when no collection is provided." -; ([] -; (fn [rf] -; (let [seen (volatile! #{})] -; (fn -; ([] (rf)) -; ([result] (rf result)) -; ([result input] -; (if (contains? (deref seen) input) -; result -; (do (vswap! seen conj input) -; (rf result input)))))))) -; ([coll] -; (let [step (fn step [xs seen] -; (lazy-seq -; ((fn [[f :as xs] seen] -; (when-let [s (seq xs)] -; (if (contains? seen f) -; (recur (rest s) seen) -; (cons f (step (rest s) (conj seen f)))))) -; xs seen)))] -; (step coll #{})))) -; -;(defn distinct? -; "Returns true if no two of the arguments are =" -; ([x] true) -; ([x y] (not (= x y))) -; ([x y & more] -; (if (not= x y) -; (loop [s #{x y} -; [x & etc :as xs] more] -; (if xs -; (if (contains? s x) -; false -; (recur (conj s x) etc)) -; true)) -; false))) -; -;(defn filter -; "Returns a lazy sequence of the items in coll for which -; (pred item) returns logical true. pred must be free of side-effects. -; Returns a transducer when no collection is provided." -; ([pred] -; (fn [rf] -; (fn -; ([] (rf)) -; ([result] (rf result)) -; ([result input] -; (if (pred input) -; (rf result input) -; result))))) -; ([pred coll] -; (lazy-seq -; (when-let [s (seq coll)] -; (if (chunked-seq? s) -; (let [c (chunk-first s) -; size (count c) -; b (chunk-buffer size)] -; (dotimes [i size] -; (let [v (nth c i)] -; (when (pred v) -; (chunk-append b v)))) -; (chunk-cons (chunk b) (filter pred (chunk-rest s)))) -; (let [f (first s) r (rest s)] -; (if (pred f) -; (cons f (filter pred r)) -; (filter pred r)))))))) -; -;(defn flatten -; "Takes any nested combination of sequential things (lists, vectors, -; etc.) and returns their contents as a single, flat lazy sequence. -; (flatten nil) returns an empty sequence." -; [x] -; (filter (complement sequential?) -; (rest (tree-seq sequential? seq x)))) -; -;(defn remove -; "Returns a lazy sequence of the items in coll for which -; (pred item) returns logical false. pred must be free of side-effects. -; Returns a transducer when no collection is provided." -; ([pred] -; (filter (complement pred))) -; ([pred coll] -; (filter (complement pred) coll))) -; -;(defn dedupe -; "Returns a lazy sequence removing consecutive duplicates in coll. -; Returns a transducer when no collection is provided." -; ([] -; (fn [rf] -; (let [pv (volatile! ::none)] -; (fn -; ([] (rf)) -; ([result] (rf result)) -; ([result input] -; (let [prior (deref pv)] -; (vreset! pv input) -; (if (= prior input) -; result -; (rf result input)))))))) -; ([coll] -; (let [step (fn step [prior xs] -; (lazy-seq -; (when-some [[x & more] (seq xs)] -; (if (= x prior) -; (step prior more) -; (cons x (step x more))))))] -; (step ::none coll)))) -; -;(defmacro condp -; "Takes a binary predicate, an expression, and a set of clauses. -; Each clause can take the form of either: -; -; test-expr result-expr -; -; test-expr :>> result-fn -; -; Note :>> is an ordinary keyword. -; -; For each clause, (pred test-expr expr) is evaluated. If it returns -; logical true, the clause is a match. If a binary clause matches, the -; result-expr is returned, if a ternary clause matches, its result-fn, -; which must be a unary function, is called with the result of the -; predicate as its argument, the result of that call being the return -; value of condp. A single default expression can follow the clauses, -; and its value will be returned if no clause matches. If no default -; expression is provided and no clause matches, an -; IllegalArgumentException is thrown." -; [pred expr & clauses] -; (let [gpred (gensym "pred__") -; gexpr (gensym "expr__") -; emit (fn emit [pred expr args] -; (let [[[a b c :as clause] more] -; (split-at (if (= :>> (second args)) 3 2) args) -; n (count clause)] -; (cond -; (= 0 n) `(throw (str "No matching clause: " ~expr)) -; (= 1 n) a -; (= 2 n) `(if (~pred ~a ~expr) -; ~b -; ~(emit pred expr more)) -; :else `(if-let [p# (~pred ~a ~expr)] -; (~c p#) -; ~(emit pred expr more)))))] -; `(let [~gpred ~pred -; ~gexpr ~expr] -; ~(emit gpred gexpr clauses)))) -; -;(defmacro cond-> -; "Takes an expression and a set of test/form pairs. Threads expr (via ->) -; through each form for which the corresponding test -; expression is true. Note that, unlike cond branching, cond-> threading does -; not short circuit after the first true test expression." -; [expr & clauses] -; (assert (even? (count clauses))) -; (let [g (gensym) -; steps (map (fn [test+step] -; (let [test (first test+step) -; step (second test+step)] -; `(if ~test -; (-> ~g ~step) -; ~g))) -; (partition 2 clauses))] -; `(let [~g ~expr -; ~@(interleave (repeat g) (butlast steps))] -; ~(if (empty? steps) -; g -; (last steps))))) -; -;(defmacro cond->> -; "Takes an expression and a set of test/form pairs. Threads expr (via ->>) -; through each form for which the corresponding test expression -; is true. Note that, unlike cond branching, cond->> threading does not short circuit -; after the first true test expression." -; [expr & clauses] -; (assert (even? (count clauses))) -; (let [g (gensym) -; steps (map (fn [[test step]] `(if ~test (->> ~g ~step) ~g)) -; (partition 2 clauses))] -; `(let [~g ~expr -; ~@(interleave (repeat g) (butlast steps))] -; ~(if (empty? steps) -; g -; (last steps))))) -; -;(defmacro as-> -; "Binds name to expr, evaluates the first form in the lexical context -; of that binding, then binds name to that result, repeating for each -; successive form, returning the result of the last form." -; [expr name & forms] -; `(let [~name ~expr -; ~@(interleave (repeat name) (butlast forms))] -; ~(if (empty? forms) -; name -; (last forms)))) -; -;(defmacro some-> -; "When expr is not nil, threads it into the first form (via ->), -; and when that result is not nil, through the next etc" -; [expr & forms] -; (let [g (gensym) -; steps (map (fn [step] `(if (nil? ~g) nil (-> ~g ~step))) -; forms)] -; `(let [~g ~expr -; ~@(interleave (repeat g) (butlast steps))] -; ~(if (empty? steps) -; g -; (last steps))))) -; -;(defmacro some->> -; "When expr is not nil, threads it into the first form (via ->>), -; and when that result is not nil, through the next etc" -; [expr & forms] -; (let [g (gensym) -; steps (map (fn [step] `(if (nil? ~g) nil (->> ~g ~step))) -; forms)] -; `(let [~g ~expr -; ~@(interleave (repeat g) (butlast steps))] -; ~(if (empty? steps) -; g -; (last steps))))) -; -;;; Functions. -;(defn ifn? -; "Returns true if x implements IFn. Note that many data structures -; (e.g. sets and maps) implement IFn" -; [x] -; (cpp/jank.runtime.is_callable x)) -;(defn fn? -; "Returns true if x implements Fn, i.e. is an object created via fn." -; [x] -; (cpp/clojure.core_native.is_fn x)) -; -;;; Multimethods. -;(defn- check-valid-options -; "Throws an exception if the given option map contains keys not listed -; as valid, else returns nil." -; [options & valid-keys] -; (when (seq (apply disj (apply hash-set (keys options)) valid-keys)) -; (throw (apply str "Only these options are valid: " -; (first valid-keys) -; (map #(str ", " %) (rest valid-keys)))))) -; -;(defn- multi-fn? -; [x] -; (cpp/clojure.core_native.is_multi_fn x)) -; -;(defn- multi-fn* -; [name dispatch_fn default hierarchy] -; (cpp/clojure.core_native.multi_fn name dispatch_fn default hierarchy)) -; -;(def global-hierarchy) -; -;(defmacro defmulti -; "Creates a new multimethod with the associated dispatch function. -; The docstring and attr-map are optional. -; -; Options are key-value pairs and may be one of: -; -; :default -; -; The default dispatch value, defaults to :default -; -; :hierarchy -; -; The value used for hierarchical dispatch (e.g. ::square is-a ::shape) -; -; Hierarchies are type-like relationships that do not depend upon type -; inheritance. By default Clojure's multimethods dispatch off of a -; global hierarchy map. However, a hierarchy relationship can be -; created with the derive function used to augment the root ancestor -; created with make-hierarchy. -; -; Multimethods expect the value of the hierarchy option to be supplied as -; a reference type e.g. a var (i.e. via the Var-quote dispatch macro #' -; or the var special form)." -; [mm-name & options] -; (let [docstring (if (string? (first options)) -; (first options) -; nil) -; options (if (string? (first options)) -; (next options) -; options) -; m (if (map? (first options)) -; (first options) -; {}) -; options (if (map? (first options)) -; (next options) -; options) -; dispatch-fn (first options) -; options (next options) -; m (if docstring -; (assoc m :doc docstring) -; m) -; m (if (meta mm-name) -; (conj (meta mm-name) m) -; m) -; mm-name (with-meta mm-name m)] -; (let [options (apply hash-map options) -; default (get options :default :default) -; hierarchy (get options :hierarchy #'global-hierarchy)] -; (check-valid-options options :default :hierarchy) -; ; TODO: This returns nil, due to an issue with let*. Why? -; `(let [v# (def ~mm-name)] -; (when-not (multi-fn? (deref v#)) -; (def ~mm-name (multi-fn* '~(symbol *ns* mm-name) ~dispatch-fn ~default ~hierarchy))))))) -; -;(defn- defmethod* -; [multifn dispatch-val f] -; (cpp/clojure.core_native.defmethod multifn dispatch-val f)) -; -;(defmacro defmethod -; "Creates and installs a new method of multimethod associated with dispatch-value. " -; [multifn dispatch-val & fn-tail] -; `(defmethod* ~multifn ~dispatch-val (fn ~@fn-tail))) -; -;(defn remove-all-methods -; "Removes all of the methods of multimethod." -; [multifn] -; (cpp/clojure.core_native.remove_all_methods multifn)) -; -;(defn remove-method -; "Removes the method of multimethod associated with dispatch-value." -; [multifn dispatch-val] -; (cpp/clojure.core_native.remove_method multifn dispatch-val)) -; -;(defn prefer-method -; "Causes the multimethod to prefer matches of dispatch-val-x over dispatch-val-y -; when there is a conflict" -; [multifn dispatch-val-x dispatch-val-y] -; (cpp/clojure.core_native.prefer_method multifn dispatch-val-x dispatch-val-y)) -; -;(defn methods -; "Given a multimethod, returns a map of dispatch values -> dispatch fns" -; [multifn] -; (cpp/clojure.core_native.methods multifn)) -; -;(defn get-method -; "Given a multimethod and a dispatch value, returns the dispatch fn -; that would apply to that value, or nil if none apply and no default" -; [multifn dispatch-val] -; (cpp/clojure.core_native.get_method multifn dispatch-val)) -; -;(defn prefers -; "Given a multimethod, returns a map of preferred value -> set of other values" -; [multifn] -; (cpp/clojure.core_native.prefers multifn)) -; -;;; Hierarchies. -;(defn make-hierarchy -; "Creates a hierarchy object for use with derive, isa? etc." -; [] -; {:parents {} -; :descendants {} -; :ancestors {}}) -; -;(def ^:private global-hierarchy (make-hierarchy)) -; -;(defn isa? -; "Returns true if (= child parent), or child is directly or indirectly derived from -; parent, either via a Java type inheritance relationship or a -; relationship established via derive. h must be a hierarchy obtained -; from make-hierarchy, if not supplied defaults to the global -; hierarchy" -; ([child parent] -; (isa? global-hierarchy child parent)) -; ([h child parent] -; (or (= child parent) -; (contains? (get (:ancestors h) child) parent) -; (and (vector? parent) (vector? child) -; (= (count parent) (count child)) -; (loop [ret true -; i 0] -; (if (or (not ret) (= i (count parent))) -; ret -; (recur (isa? h (get child i) (get parent i)) (inc i)))))))) -; -;(defn parents -; "Returns the immediate parents of tag, either via a Java type -; inheritance relationship or a relationship established via derive. h -; must be a hierarchy obtained from make-hierarchy, if not supplied -; defaults to the global hierarchy" -; ([tag] -; (parents global-hierarchy tag)) -; ([h tag] -; (not-empty (get (:parents h) tag)))) -; -;(defn ancestors -; "Returns the immediate and indirect parents of tag, either via a Java type -; inheritance relationship or a relationship established via derive. h -; must be a hierarchy obtained from make-hierarchy, if not supplied -; defaults to the global hierarchy" -; ([tag] -; (ancestors global-hierarchy tag)) -; ([h tag] -; (not-empty (get (:ancestors h) tag)))) -; -;(defn descendants -; "Returns the immediate and indirect children of tag, through a -; relationship established via derive. h must be a hierarchy obtained -; from make-hierarchy, if not supplied defaults to the global -; hierarchy. Note: does not work on Java type inheritance -; relationships." -; ([tag] -; (descendants global-hierarchy tag)) -; ([h tag] -; (not-empty (get (:descendants h) tag)))) -; -;(defn derive -; "Establishes a parent/child relationship between parent and -; tag. Parent must be a namespace-qualified symbol or keyword and -; child can be either a namespace-qualified symbol or keyword or a -; class. h must be a hierarchy obtained from make-hierarchy, if not -; supplied defaults to, and modifies, the global hierarchy." -; ([tag parent] -; (assert (namespace parent)) -; (assert (and (named? tag) (namespace tag))) -; (alter-var-root #'global-hierarchy derive tag parent) -; nil) -; ([h tag parent] -; (assert (not= tag parent)) -; (assert (named? tag)) -; (assert (named? parent)) -; (let [tp (:parents h) -; td (:descendants h) -; ta (:ancestors h) -; tf (fn [m source sources target targets] -; (reduce (fn [ret k] -; (assoc ret -; k -; (reduce conj -; (get targets k #{}) -; (cons target (targets target))))) -; m -; (cons source (sources source))))] -; (or -; (when-not (contains? (tp tag) parent) -; (when (contains? (ta tag) parent) -; (throw (str tag " already has " parent " as ancestor"))) -; (when (contains? (ta parent) tag) -; (throw (str "Cyclic derivation: " parent " has " tag " as ancestor"))) -; {:parents (assoc (:parents h) tag (conj (get tp tag #{}) parent)) -; :ancestors (tf (:ancestors h) tag td parent ta) -; :descendants (tf (:descendants h) parent ta tag td)}) -; h)))) -; -;(defn underive -; "Removes a parent/child relationship between parent and -; tag. h must be a hierarchy obtained from make-hierarchy, if not -; supplied defaults to, and modifies, the global hierarchy." -; ([tag parent] -; (alter-var-root #'global-hierarchy underive tag parent) nil) -; ([h tag parent] -; (let [parent-map (:parents h) -; child-parents (if (parent-map tag) -; (disj (parent-map tag) parent) -; #{}) -; new-parents (if (not-empty child-parents) -; (assoc parent-map tag child-parents) -; (dissoc parent-map tag)) -; deriv-seq (flatten (map #(cons (key %) (interpose (key %) (val %))) -; (seq new-parents)))] -; (if (contains? (parent-map tag) parent) -; (reduce #(apply derive %1 %2) -; (make-hierarchy) -; (partition 2 deriv-seq)) -; h)))) -; -;(defmacro defonce -; "defs name to have the root value of the expr iff the named var has no root value, -; else expr is unevaluated" -; [name expr] -; `(let [v# (def ~name)] -; (when-not (bound? v#) -; (def ~name ~expr)))) -; -;;; Case. -;(def ^:private max-mask-bits 13) -;(def ^:private max-switch-table-size (bit-shift-left 1 max-mask-bits)) -; -;(defn- i64? [n] -; (and (integer? n) -; (>= n (cpp/value "std::numeric_limits::min()")) -; (<= n (cpp/value "std::numeric_limits::max()")))) -; -;(defn- i32? [n] -; (and (integer? n) -; (>= n (cpp/value "std::numeric_limits::min()")) -; (<= n (cpp/value "std::numeric_limits::max()")))) -; -;(defn- shift-mask [shift mask x] -; (-> x (bit-shift-right shift) (bit-and mask))) -; -;(defn- case-hash -; "Returns the input if it is within the range of a 32-bit signed integer, otherwise returns the hash of the -; input. The native hash returns a int32 int so this is to make sure that (case-hash (case-hash x)) == (case-hash x). -; A key may be hashed more than once and we need to make sure its value does not change in later hashing." -; [input] -; (if (i32? input) -; input -; (hash input))) -; -;(defn- maybe-min-hash -; "Takes a collection of hashes and returns [shift mask] or nil if none found" -; [hashes] -; (first -; (filter -; (fn [[s m]] -; (apply distinct? (map #(shift-mask s m %) hashes))) -; (for [mask -; (map #(dec (bit-shift-left 1 %)) (range 1 (inc max-mask-bits))) -; shift -; (range 0 31)] -; [shift mask])))) -; -;(defn- case-map-with-check -; "Transforms a sequence of test constants and their corresponding branch expressions -; into a sorted map for consumption by `case*`. This version is used when no hash collisions -; are detected (i.e. the skip-check set is empty). -; -; Returns a sorted map where each key is the transformed test constant and each value is a `condp` form -; that checks the original expression against the test constant before selecting the branch." -; [expr-sym default case-f test-f tests thens] -; (into (sorted-map) -; (zipmap (map case-f tests) -; (map -; (fn [key then] -; (let [key -; (if (symbol? key) -; (list 'quote key) -; key)] -; `(condp = ~expr-sym ~key ~then -; ~default))) -; (map test-f tests) -; thens)))) -; -;(defn- case-map-collison-merged -; "Transforms a sequence of test constants and their corresponding branch expressions -; into a sorted map for consumption by `case*`. -; -; This version is selected when hash collisions have been detected (i.e. the skip-check set is nonempty) -; and resolved (typically via merging in `merge-hash-collisions`). In these cases, the branch expressions -; have already been pre-wrapped in `condp` forms to handle multiple colliding constants. Therefore, no additional -; wrapping is needed here-the transformed test constants are mapped directly to their corresponding branch expressions. -; -; Returns a sorted map mapping each transformed test constant directly to its branch expression." -; [case-f test-f tests thens] -; (into (sorted-map) -; (zipmap (map case-f tests) thens))) -; -;(defn- case-map -; [expr-sym default case-f test-f tests thens skip-check] -; (if (empty? skip-check) -; (case-map-with-check expr-sym default case-f test-f tests thens) -; (case-map-collison-merged case-f test-f tests thens))) -; -;(defn- fits-table? -; "Returns true if the collection of ints can fit within the -; max-table-switch-size, false otherwise." -; [ints] -; (< (- (apply max (seq ints)) (apply min (seq ints))) max-switch-table-size)) -; -;(defn- prep-ints -; "Takes a sequence of int-sized test constants and a corresponding sequence of -; then expressions. Returns a tuple of [shift mask case-map] where -; case-map is a map of int case values to [test then] tuples" -; [expr-sym default tests thens] -; (if (fits-table? tests) -; ; compact case ints, no shift-mask -; [0 0 (case-map expr-sym default int int tests thens #{})] -; (let [[shift mask] (or (maybe-min-hash (map int tests)) [0 0])] -; (if (zero? mask) -; ; sparse case ints, no shift-mask -; [0 0 (case-map expr-sym default int int tests thens #{})] -; ; compact case ints, with shift-mask -; [shift -; mask -; (case-map expr-sym default #(shift-mask shift mask (int %)) int tests thens #{})])))) -; -;(defn- merge-hash-collisions -; "Takes a case expression, default expression, and a sequence of test constants -; and a corresponding sequence of then expressions. Returns a tuple of -; [tests thens skip-check-set] where no tests have the same hash. Each set of -; input test constants with the same hash is replaced with a single test -; constant (the case int), and their respective thens are combined into: -; (condp = expr -; test-1 then-1 -; ... -; test-n then-n -; default). -; The skip-check is a set of case ints for which post-switch equivalence -; checking must not be done (the cases holding the above condp thens)." -; [expr-sym default tests thens] -; (let [buckets -; (loop [m {} -; ks tests -; vs thens] -; (if (and ks vs) -; (recur -; (update m (case-hash (first ks)) (fnil conj []) [(first ks) (first vs)]) -; (next ks) (next vs)) -; m)) -; assoc-multi -; (fn [m h bucket] -; (let [testexprs -; (mapcat (fn [kv] [(list 'quote (first kv)) (second kv)]) bucket) -; expr -; `(condp = ~expr-sym ~@testexprs ~default)] -; (assoc m h expr))) -; hmap -; (reduce -; (fn [m [h bucket]] -; (if (== 1 (count bucket)) -; (assoc m (ffirst bucket) (second (first bucket))) -; (assoc-multi m h bucket))) -; {} buckets) -; skip-check -; (->> buckets -; (filter #(< 1 (count (second %)))) -; (map first) -; (into #{}))] -; [(keys hmap) (vals hmap) skip-check])) -; -;(defn- prep-hashes -; "Takes a sequence of test constants and a corresponding sequence of then -; expressions. Returns a tuple of [shift mask case-map] -; where case-map is a map of int case values to [test then] tuples." -; [expr-sym default tests thens skip-check] -; (let [hashes (into #{} (map case-hash tests))] -; (if (== (count tests) (count hashes)) -; (if (fits-table? hashes) -; ; compact case ints, no shift-mask -; [0 0 -; (case-map expr-sym default case-hash identity tests thens skip-check)] -; (let [[shift mask] (or (maybe-min-hash hashes) [0 0])] -; (if (zero? mask) -; ; sparse case ints, no shift-mask -; [0 0 -; (case-map expr-sym default case-hash identity tests thens skip-check)] -; ; compact case ints, with shift-mask -; [shift mask -; (case-map expr-sym default #(shift-mask shift mask (case-hash %)) identity tests thens skip-check)]))) -; ; resolve hash collisions and try again -; (let [[tests thens skip-check] -; (merge-hash-collisions expr-sym default tests thens) -; [shift mask case-map] -; (prep-hashes expr-sym default tests thens skip-check) -; skip-check -; (if (zero? mask) -; skip-check -; (into #{} (map #(shift-mask shift mask %) skip-check)))] -; [shift mask case-map])))) -; -;(defmacro case -; "Takes an expression, and a set of clauses. -; -; Each clause can take the form of either: -; -; test-constant result-expr -; -; (test-constant1 ... test-constantN) result-expr -; -; The test-constants are not evaluated. They must be compile-time -; literals, and need not be quoted. If the expression is equal to a -; test-constant, the corresponding result-expr is returned. A single -; default expression can follow the clauses, and its value will be -; returned if no clause matches. If no default expression is provided -; and no clause matches, an IllegalArgumentException is thrown. -; -; Unlike cond and condp, case does a constant-time dispatch, the -; clauses are not considered sequentially. All manner of constant -; expressions are acceptable in case, including numbers, strings, -; symbols, keywords, and (Clojure) composites thereof. Note that since -; lists are used to group multiple constants that map to the same -; expression, a vector can be used to match a list if needed. The -; test-constants need not be all of the same type." -; {:added "1.2"} -; -; [e & clauses] -; (let [ge -; (gensym) -; default -; (if (odd? (count clauses)) -; (last clauses) -; `(throw (str "No matching clause: " ~ge)))] -; (if (> 2 (count clauses)) -; `(let [~ge ~e] ~default) -; (let [pairs -; (partition 2 clauses) -; assoc-test -; (fn assoc-test [m test expr] -; (if (contains? m test) -; (throw (str "Duplicate case test constant: " test)) -; (assoc m test expr))) -; pairs -; (reduce -; (fn [m [test expr]] -; (if (seq? test) -; (reduce #(assoc-test %1 %2 expr) m test) -; (assoc-test m test expr))) -; {} pairs) -; tests -; (keys pairs) -; thens -; (vals pairs) -; mode -; (cond -; (every? i64? tests) -; :ints -; -; (every? keyword? tests) -; :identity -; -; :else -; :hashes)] -; (condp = mode -; :ints -; (let [[shift mask imap] (prep-ints ge default tests thens)] -; `(let [~ge ~e] (case* ~ge ~shift ~mask ~default ~imap))) -; :hashes -; (let [[shift mask imap] -; (prep-hashes ge default tests thens #{})] -; `(let [~ge ~e] -; (case* ~ge ~shift ~mask ~default ~imap))) -; :identity -; (let [[shift mask imap] -; (prep-hashes ge default tests thens #{})] -; `(let [~ge ~e] -; (case* ~ge ~shift ~mask ~default ~imap)))))))) -; -;;; Miscellaneous. -;; TODO: jank.core -;(defn- sleep [ms] -; (cpp/clojure.core_native.sleep ms)) -;(defn- current-time [] -; (cpp/clojure.core_native.current_time)) -; -;(defmacro time -; "Evaluates expr and prints the time it took. Returns the value of expr." -; [expr] -; `(let [start# (current-time) -; ret# ~expr -; end# (current-time)] -; (println (str "Elapsed time: " (/ (- end# start#) 1000000.0) " ms")) -; ret#)) -; -;(defn with-redefs-fn -; "Temporarily redefines Vars during a call to func. Each val of -; binding-map will replace the root value of its key which must be -; a Var. After func is called with no args, the root values of all -; the Vars will be set back to their old values. These temporary -; changes will be visible in all threads. Useful for mocking out -; functions during testing." -; [binding-map fun] -; (let [root-bind (fn root-bind [m] -; (doseq [kv m] -; (cpp/clojure.core_native.var_bind_root (first kv) (second kv)))) -; old-vals (zipmap (keys binding-map) -; (map #(cpp/clojure.core_native.var_get_root %) (keys binding-map)))] -; (try -; (root-bind binding-map) -; (fun) -; (finally -; (root-bind old-vals))))) -; -;(defmacro with-redefs -; "binding => var-symbol temp-value-expr -; -; Temporarily redefines Vars while executing the body. The -; temp-value-exprs will be evaluated and each resulting value will -; replace in parallel the root value of its Var. After the body is -; executed, the root values of all the Vars will be set back to their -; old values. These temporary changes will be visible in all threads. -; Useful for mocking out functions during testing." -; [bindings & body] -; (list `with-redefs-fn -; (zipmap (map (fn [v] -; (list 'var v)) -; (take-nth 2 bindings)) -; (take-nth 2 (next bindings))) -; (list* `fn [] -; body))) -; -;;; Namespaces. -;(defn in-ns -; "Sets *ns* to the namespace named by the symbol, creating it if needed." -; [name] -; (cpp/clojure.core_native.in_ns name)) -; -;(defn create-ns -; "Create a new namespace named by the symbol if one doesn't already -; exist, returns it or the already-existing namespace of the same -; name." -; [sym] -; (cpp/clojure.core_native.intern_ns sym)) -; -; -;(defn find-ns -; "Returns the namespace named by the symbol or nil if it doesn't exist." -; [sym] -; (cpp/clojure.core_native.find_ns sym)) -; -;(defn find-var -; "Returns the global var named by the namespace-qualified symbol, or -; nil if no var with that name." -; [sym] -; (cpp/clojure.core_native.find_var sym)) -; -;(defn remove-ns -; "Removes the namespace named by the symbol. Use with caution. -; Cannot be used to remove the clojure namespace." -; [sym] -; (cpp/clojure.core_native.remove_ns sym)) -; -;(defn the-ns -; "If passed a namespace, returns it. Else, when passed a symbol, -; returns the namespace named by it, throwing an exception if not -; found." -; [ns-or-sym] -; (if (cpp/clojure.core_native.is_ns ns-or-sym) -; ns-or-sym -; (let [found (find-ns ns-or-sym)] -; (if (nil? found) -; (throw (ex-info :not-an-ns-or-sym {:value ns-or-sym})) -; found)))) -; -;(defn ns-name -; "Returns the name of the namespace, a symbol." -; [ns-sym] -; (let [ns (the-ns ns-sym)] -; (cpp/clojure.core_native.ns_name ns))) -; -;(defn ns-map -; "Returns a map of all the mappings for the namespace." -; [ns-sym] -; (let [ns (the-ns ns-sym)] -; (cpp/clojure.core_native.ns_map ns))) -; -;(defn ns-publics -; "Returns a map of the public intern mappings for the namespace." -; [ns-sym] -; (let [ns (the-ns ns-sym)] -; ; TODO: It may be faster to start with the whole map and dissoc. -; ; TODO: Good use case for transients. -; (reduce (fn [acc kv] -; (let [k (first kv) -; v (second kv)] -; ; TODO: Check for visibility. -; (if (var? v) -; (if (= ns (cpp/clojure.core_native.var_ns v)) -; (assoc acc k v) -; acc) -; acc))) -; {} -; (ns-map ns)))) -; -;(defn ns-resolve -; "Returns the var to which a symbol will be resolved in the -; namespace (unless found in the environment), else nil. Note that -; if the symbol is fully qualified, the var to which it resolves -; need not be present in the namespace." -; ([ns sym] -; (ns-resolve ns nil sym)) -; ([ns env sym] -; (when-not (contains? env sym) -; (cpp/clojure.core_native.ns_resolve (the-ns ns) sym)))) -; -;(defn resolve -; "Same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)" -; ([sym] -; (ns-resolve *ns* sym)) -; ([env sym] -; (ns-resolve *ns* env sym))) -; -;(defn- libspec? [x] -; (or (symbol? x) -; (and (vector? x) -; (or (nil? (second x)) -; (keyword? (second x)))))) -; -;(defn- prependss [x coll] -; (if (symbol? x) -; (cons x coll) -; (concat x coll))) -; -;(defn- root-resource [lib] -; (str "/" (name lib))) -; -;(defn- throw-if [pred msg] -; (when pred -; (throw (ex-info :assertion-failure {:msg msg})))) -; -;(defn alias -; "Add an alias in the current namespace to another -; namespace. Arguments are two symbols: the alias to be used, and -; the symbolic name of the target namespace. Use :as in the ns macro in preference -; to calling this directly." -; [alias ns-sym] -; (let [ns-obj (the-ns ns-sym)] -; (cpp/clojure.core_native.alias *ns* ns-obj alias))) -; -;(defn refer -; "refers to all public vars of ns, subject to filters. -; filters can include at most one each of: -; -; :exclude list-of-symbols -; :only list-of-symbols -; :rename map-of-fromsymbol-tosymbol -; -; For each public interned var in the namespace named by the symbol, -; adds a mapping from the name of the var to the var to the current -; namespace. Throws an exception if name is already mapped to -; something else in the current namespace. Filters can be used to -; select a subset, via inclusion or exclusion, or to provide a mapping -; to a symbol different from the var's name, in order to prevent -; clashes. Use :use in the ns macro in preference to calling this directly." -; [ns-sym & filters] -; (let [ns (find-ns ns-sym) -; _ (when (nil? ns) -; (throw (ex-info :unknown-namespace {:value ns-sym}))) -; filters (apply hash-map filters) -; rename (or (:rename filters) {}) -; exclude? (set (:exclude filters)) -; sym->var (ns-publics ns) -; to-refer (if (= :all (get filters :refer)) -; (keys sym->var) -; (or (get filters :refer) (get filters :only) (keys sym->var)))] -; ; TODO: Loop -; (reduce (fn [acc sym] -; (when (not (exclude? sym)) -; (let [v (get sym->var sym) -; sym (rename sym sym)] -; (when (nil? v) -; (throw (ex-info :var-does-not-exist {:value sym}))) -; (cpp/clojure.core_native.refer *ns* sym v)))) -; nil -; to-refer))) -; -;;; TODO: Should be a ref instead of atom -;(defonce -; ^{:private true -; :dynamic true -; :doc "An atom holding a sorted set of symbols representing loaded libs"} -; *loaded-libs* (atom (sorted-set))) -; -;(defonce -; ^{:private true -; :dynamic true -; :doc "A stack of paths currently being loaded by this thread"} -; *pending-paths* ()) -; -;(defn- check-cyclic-dependency -; "Detects and rejects non-trivial cyclic load dependencies. The -; exception message shows the dependency chain with the cycle -; highlighted. Ignores the trivial case of a file attempting to load -; itself because that can occur when a gen-class'd class loads its -; implementation." -; [path] -; (when (some #{path} (rest *pending-paths*)) -; (let [pending (map #(if (= % path) (str "[ " % " ]") %) -; (cons path *pending-paths*)) -; chain (apply str (interpose "->" pending))] -; (throw-if true (str "Cyclic load dependency: " chain))))) -; -;(defn load -; "Loads Clojure code from resources in the module path. A path is interpreted as -; module-path-relative if it begins with a slash or relative to the root -; directory for the current namespace otherwise." -; [& paths] -; (doseq [path paths] -; (check-cyclic-dependency path) -; (when-not (= path (first *pending-paths*)) -; (binding [*pending-paths* (conj *pending-paths* path)] -; (clojure.core-native/load-module path))))) -; -;(defn- load-one -; "Loads a lib given its name. If `need-ns?`, ensures that the associated -; namespace exists after loading. If `require?`, records the load so any -; duplicate loads can be skipped." -; [lib need-ns? require?] -; (load (root-resource lib)) -; (throw-if (and need-ns? (not (find-ns lib))) -; (str "namespace " lib " not found after loading " (root-resource lib))) -; (when require? -; (swap! *loaded-libs* conj lib))) -; -;(defn- load-all -; "Loads a lib given its name and forces a load of any libs it directly or -; indirectly loads. If need-ns?, ensures that the associated namespace -; exists after loading. If require?, records the load so any duplicate loads -; can be skipped." -; [lib need-ns? require?] -; (swap! *loaded-libs* #(reduce conj %1 %2) -; (binding [*loaded-libs* (atom (sorted-set))] -; (load-one lib need-ns? require?) -; @*loaded-libs*))) -; -;(defn- load-lib -; "Loads a lib with options" -; [lib & options] -; (let [opts (apply hash-map options) -; ; TODO: Map destructuring. -; as (:as opts) -; reload (:reload opts) -; reload-all (:reload-all opts) -; require (:require opts) -; use (:use opts) -; verbose (:verbose opts) -; as-alias (:as-alias opts) -; loaded? (contains? @*loaded-libs* lib) -; need-ns? (or as use) -; load (cond reload-all load-all -; reload load-one -; (not loaded?) (cond need-ns? load-one -; as-alias (fn [lib _need _require] -; (create-ns lib)) -; :else load-one)) -; -; filter-opts (select-keys opts [:exclude :only :rename :refer]) -; undefined-on-entry? (not (find-ns lib))] -; (if load -; (try -; (load lib need-ns? require) -; (catch e -; (when undefined-on-entry? -; (remove-ns lib)) -; (throw e))) -; (throw-if (and need-ns? (not (find-ns lib))) -; (str "namespace " lib " not found"))) -; (when as -; (alias as lib)) -; (when as-alias -; (alias as-alias lib)) -; (when (or use (:refer filter-opts)) -; (apply refer lib (mapcat seq filter-opts))))) -; -;(defn- load-libs -; "Loads libs, interpreting libspecs, prefix lists, and flags for -; forwarding to load-lib" -; [& args] -; (let [flags (filter keyword? args) -; opts (interleave flags (repeat true)) -; args (remove keyword? args)] -; (let [supported #{:as :reload :reload-all :require :use :verbose :refer :as-alias} -; unsupported (seq (remove supported flags))] -; (throw-if unsupported -; (str "Unsupported option(s) supplied: " unsupported))) -; (throw-if (not (seq args)) "Nothing specified to load") -; (doseq [arg args] -; (throw-if (not (libspec? arg)) (str "not a libspec: " arg)) -; (apply load-lib (prependss arg opts))))) -; -;(defn compile -; "Compiles the namespace named by the symbol lib into a set of -; classfiles. The source for the lib must be in a proper -; module-path-relative directory. The output files will go into the -; directory specified by *compile-path*, and that directory too must -; be in the module path." -; [path] -; (cpp/clojure.core_native.compile path)) -; -;(defn require -; "Loads libs, skipping any that are already loaded. Each argument is -; either a libspec that identifies a lib, a prefix list that identifies -; multiple libs whose names share a common prefix, or a flag that modifies -; how all the identified libs are loaded. Use :require in the ns macro -; in preference to calling this directly. -; -; Libs -; -; A 'lib' is a named set of resources in module path whose contents define a -; library of Clojure code. Lib names are symbols and each lib is associated -; with a Clojure namespace and a Java package that share its name. A lib's -; name also locates its root directory within module path using Java's -; package name to module path-relative path mapping. All resources in a lib -; should be contained in the directory structure under its root directory. -; All definitions a lib makes should be in its associated namespace. -; -; 'require loads a lib by loading its root resource. The root resource path -; is derived from the lib name in the following manner: -; Consider a lib named by the symbol 'x.y.z; it has the root directory -; /x/y/, and its root resource is /x/y/z.clj, or -; /x/y/z.cljc if /x/y/z.clj does not exist. The -; root resource should contain code to create the lib's -; namespace (usually by using the ns macro) and load any additional -; lib resources. -; -; Libspecs -; -; A libspec is a lib name or a vector containing a lib name followed by -; options expressed as sequential keywords and arguments. -; -; Recognized options: -; :as takes a symbol as its argument and makes that symbol an alias to the -; lib's namespace in the current namespace. -; :as-alias takes a symbol as its argument and aliases like :as, however -; the lib will not be loaded. If the lib has not been loaded, a new -; empty namespace will be created (as with create-ns). -; :refer takes a list of symbols to refer from the namespace or the :all -; keyword to bring in all public vars. -; -; Prefix Lists -; -; It's common for Clojure code to depend on several libs whose names have -; the same prefix. When specifying libs, prefix lists can be used to reduce -; repetition. A prefix list contains the shared prefix followed by libspecs -; with the shared prefix removed from the lib names. After removing the -; prefix, the names that remain must not contain any periods. -; -; Flags -; -; A flag is a keyword. -; Recognized flags: :reload, :reload-all, :verbose -; :reload forces loading of all the identified libs even if they are -; already loaded (has no effect on libspecs using :as-alias) -; :reload-all implies :reload and also forces loading of all libs that the -; identified libs directly or indirectly load via require or use -; (has no effect on libspecs using :as-alias) -; :verbose triggers printing information about each load, alias, and refer -; -; Example: -; -; The following would load the libraries clojure.zip and clojure.set -; abbreviated as 's'. -; -; (require '(clojure zip [set :as s]))" -; [& args] -; (apply load-libs :require args)) -; -;(defn use -; "Like 'require, but also refers to each lib's namespace using -; clojure.core/refer. Use :use in the ns macro in preference to calling -; this directly. -; -; 'use accepts additional options in libspecs: :exclude, :only, :rename. -; The arguments and semantics for :exclude, :only, and :rename are the same -; as those documented for clojure.core/refer." -; [& args] -; (apply load-libs :require :use args)) -; -;(defmacro ns -; "Sets *ns* to the namespace named by name (unevaluated), creating it -; if needed. References can be zero or more of: (:refer-clojure ...) -; (:require ...) (:use ...) (:load ...) -; with the syntax of refer-clojure/require/use/load respectively." -; [name & references] -; (let [process-reference (fn [reference] -; (let [kname (first reference) -; args (rest reference)] -; (cons (symbol "clojure.core" (clojure.core/name kname)) -; (map (fn [a] -; (list 'quote a)) -; args)))) -; refer-full-clojure? (not-any? (fn [ref] -; (= :refer-clojure (first ref))) -; references)] -; `(do -; (clojure.core/in-ns '~name) -; ; TODO: with-loading-context -; (do ; with-loading-context -; ~@(when (and (not= name 'clojure.core) refer-full-clojure?) -; `((clojure.core/refer '~'clojure.core))) -; ~@(map process-reference references)) -; (if (= '~name '~'clojure.core) -; nil -; (do (swap! @#'*loaded-libs* conj '~name) nil))))) -; -;(defmacro refer-clojure -; "Same as (refer 'clojure.core )" -; [& filters] -; `(clojure.core/refer '~'clojure.core ~@filters)) -; -;(defn intern -; "Finds or creates a var named by the symbol name in the namespace -; ns (which can be a symbol or a namespace), setting its root binding -; to val if supplied. The namespace must exist. The var will adopt any -; metadata from the name symbol. Returns the var." -; ([ns name] -; (let [v (cpp/clojure.core_native.intern_var -; (cpp/jank.runtime.to_qualified_symbol -; (the-ns ns) name))] -; (when (meta name) (cpp/jank.runtime.reset_meta v (meta name))) -; v)) -; ([ns name val] -; (let [v (cpp/clojure.core_native.intern_var -; (cpp/jank.runtime.to_qualified_symbol -; (the-ns ns) name))] -; (cpp/clojure.core_native.var_bind_root v val) -; (when (meta name) (cpp/jank.runtime.reset_meta v (meta name))) -; v))) -; -;(defn nfirst -; "Same as (next (first x))" -; [x] -; (next (first x))) -; -;(defn fnext -; "Same as (first (next x))" -; [x] -; (first (next x))) -; -;(defn instance? -; "Evaluates x and tests if it is an instance of the class -; c. Returns true or false" -; [c x] -; ;; (. c (isInstance x)) -; (throw "TODO: port instance?")) -; -;(def ^{:private true :dynamic true} -; assert-valid-fdecl (fn [fdecl])) -; -;(defn to-array -; "Returns an array of Objects containing the contents of coll, which -; can be any Collection. Maps to java.util.Collection.toArray()." -; [coll] -; ;; (. clojure.lang.RT (toArray coll)) -; (throw "TODO: port to-array")) -; -;(defn cast -; "Throws a ClassCastException if x is not a c, else returns x." -; [c x] -; ;; (. c (cast x)) -; (throw "TODO: port cast")) -; -;(defn sorted-map-by -; "keyval => key val -; Returns a new sorted map with supplied mappings, using the supplied -; comparator. If any keys are equal, they are handled as if by -; repeated uses of assoc." -; ([comparator & keyvals] -; ;; (clojure.lang.PersistentTreeMap/create comparator keyvals) -; (throw "TODO: port sorted-map-by"))) -; -;(defn any? -; "Returns true given any argument." -; [x] true) -; -;(defn find-keyword -; "Returns a Keyword with the given namespace and name if one already -; exists. This function will not intern a new keyword. If the keyword -; has not already been interned, it will return nil. Do not use : -; in the keyword strings, it will be added automatically." -; ([name] -; ;; (cond (keyword? name) name -; ;; (symbol? name) (clojure.lang.Keyword/find ^clojure.lang.Symbol name) -; ;; (string? name) (clojure.lang.Keyword/find ^String name)) -; (throw "TODO: port find-keyword")) -; ([ns name] -; ;; (clojure.lang.Keyword/find ns name) -; (throw "TODO: port find-keyword"))) -; -;(defn delay? -; "returns true if x is a Delay created with delay" -; [x] -; ;; (instance? clojure.lang.Delay x) -; (throw "TODO: port delay?")) -; -;(defmacro if-not -; "Evaluates test. If logical false, evaluates and returns then expr, -; otherwise else expr, if supplied, else nil." -; ([test then] `(if-not ~test ~then nil)) -; ([test then else] -; `(if (not ~test) ~then ~else))) -; -;(defn compare -; "Comparator. Returns a negative number, zero, or a positive number -; when x is logically 'less than', 'equal to', or 'greater than' -; y. Same as Java x.compareTo(y) except it also works for nil, and -; compares numbers and collections in a type-independent manner. x -; must implement Comparable" -; [x y] -; (cpp/jank.runtime.compare x y)) -; -;(defn inc' -; "Returns a number one greater than num. Supports arbitrary precision. -; See also: inc" -; [x] -; ;; (. clojure.lang.Numbers (incP x)) -; (throw "TODO: port inc'")) -; -;;; ;;math stuff -;;; (defn ^:private nary-inline -;;; ([op] (nary-inline op op)) -;;; ([op unchecked-op] -;;; (fn -;;; ([x] (let [op (if *unchecked-math* unchecked-op op)] -;;; `(. clojure.lang.Numbers (~op ~x)))) -;;; ([x y] (let [op (if *unchecked-math* unchecked-op op)] -;;; `(. clojure.lang.Numbers (~op ~x ~y)))) -;;; ([x y & more] -;;; (let [op (if *unchecked-math* unchecked-op op)] -;;; (reduce1 -;;; (fn [a b] `(. clojure.lang.Numbers (~op ~a ~b))) -;;; `(. clojure.lang.Numbers (~op ~x ~y)) more)))))) -; -;;; (defn ^:private >1? [n] (clojure.lang.Numbers/gt n 1)) -; -;;; (defn ^:private >0? [n] (clojure.lang.Numbers/gt n 0)) -; -;(defn +' -; "Returns the sum of nums. (+') returns 0. Supports arbitrary precision. -; See also: +" -; ([] 0) -; ([x] -; ;; (cast Number x) -; (throw "TODO: port +'")) -; ([x y] -; ;; (. clojure.lang.Numbers (addP x y)) -; (throw "TODO: port +'")) -; ([x y & more] -; (reduce +' (+' x y) more))) -; -;(defn *' -; "Returns the product of nums. (*') returns 1. Supports arbitrary precision. -; See also: *" -; ([] 1) -; ([x] -; ;; (cast Number x) -; (throw "TODO: port *'")) -; ([x y] -; ;; (. clojure.lang.Numbers (multiplyP x y)) -; (throw "TODO: port *'")) -; ([x y & more] -; (reduce *' (*' x y) more))) -; -;(defn -' -; "If no ys are supplied, returns the negation of x, else subtracts -; the ys from x and returns the result. Supports arbitrary precision. -; See also: -" -; ([x] -; ;; (. clojure.lang.Numbers (minusP x)) -; (throw "TODO: port -'")) -; ([x y] -; ;; (. clojure.lang.Numbers (minusP x y)) -; (throw "TODO: port -'")) -; ([x y & more] -; (reduce -' (-' x y) more))) -; -;(defn abs -; "Returns the absolute value of a. -; If a is Long/MIN_VALUE => Long/MIN_VALUE -; If a is a double and zero => +0.0 -; If a is a double and ##Inf or ##-Inf => ##Inf -; If a is a double and ##NaN => ##NaN" -; [a] -; (cpp/jank.runtime.abs a)) -; -;(defn dec' -; "Returns a number one less than num. Supports arbitrary precision. -; See also: dec" -; [x] -; ;; (. clojure.lang.Numbers (decP x)) -; (throw "TODO: port dec'")) -; -;(defn unchecked-inc-int -; "Returns a number one greater than x, an int. -; Note - uses a primitive operator subject to overflow." -; [x] -; ;; (. clojure.lang.Numbers (unchecked_int_inc x)) -; (throw "TODO: port unchecked-inc-int")) -; -;(defn unchecked-inc -; "Returns a number one greater than x, a long. -; Note - uses a primitive operator subject to overflow." -; [x] -; ;; (. clojure.lang.Numbers (unchecked_inc x)) -; (throw "TODO: port unchecked-inc")) -; -;(defn unchecked-dec-int -; "Returns a number one less than x, an int. -; Note - uses a primitive operator subject to overflow." -; [x] -; ;; (. clojure.lang.Numbers (unchecked_int_dec x)) -; (throw "TODO: port unchecked-dec-int")) -; -;(defn unchecked-dec -; "Returns a number one less than x, a long. -; Note - uses a primitive operator subject to overflow." -; [x] -; ;; (. clojure.lang.Numbers (unchecked_dec x)) -; (throw "TODO: port unchecked-dec")) -; -;(defn unchecked-negate-int -; "Returns the negation of x, an int. -; Note - uses a primitive operator subject to overflow." -; [x] -; ;; (. clojure.lang.Numbers (unchecked_int_negate x)) -; (throw "TODO: port unchecked-negate-int")) -; -;(defn unchecked-negate -; "Returns the negation of x, a long. -; Note - uses a primitive operator subject to overflow." -; [x] -; ;; (. clojure.lang.Numbers (unchecked_minus x)) -; (throw "TODO: port unchecked-negate")) -; -;(defn unchecked-add-int -; "Returns the sum of x and y, both int. -; Note - uses a primitive operator subject to overflow." -; [x y] -; ;; (. clojure.lang.Numbers (unchecked_int_add x y)) -; (throw "TODO: port unchecked-add-int")) -; -;(defn unchecked-add -; "Returns the sum of x and y, both long. -; Note - uses a primitive operator subject to overflow." -; [x y] -; ;; (. clojure.lang.Numbers (unchecked_add x y)) -; (throw "TODO: port unchecked-add")) -; -;(defn unchecked-subtract-int -; "Returns the difference of x and y, both int. -; Note - uses a primitive operator subject to overflow." -; [x y] -; ;; (. clojure.lang.Numbers (unchecked_int_subtract x y)) -; (throw "TODO: port unchecked-subtract-int")) -; -;(defn unchecked-subtract -; "Returns the difference of x and y, both long. -; Note - uses a primitive operator subject to overflow." -; [x y] -; ;; (. clojure.lang.Numbers (unchecked_minus x y)) -; (throw "TODO: port unchecked-subtract")) -; -;(defn unchecked-multiply-int -; "Returns the product of x and y, both int. -; Note - uses a primitive operator subject to overflow." -; [x y] -; ;; (. clojure.lang.Numbers (unchecked_int_multiply x y)) -; (throw "TODO: port unchecked-multiply-int")) -; -;(defn unchecked-multiply -; "Returns the product of x and y, both long. -; Note - uses a primitive operator subject to overflow." -; [x y] -; ;; (. clojure.lang.Numbers (unchecked_multiply x y)) -; (throw "TODO: port unchecked-multiply")) -; -;(defn unchecked-divide-int -; "Returns the division of x by y, both int. -; Note - uses a primitive operator subject to truncation." -; [x y] -; ;; (. clojure.lang.Numbers (unchecked_int_divide x y)) -; (throw "TODO: port unchecked-divide-int")) -; -;(defn unchecked-remainder-int -; "Returns the remainder of division of x by y, both int. -; Note - uses a primitive operator subject to truncation." -; [x y] -; ;; (. clojure.lang.Numbers (unchecked_int_remainder x y)) -; (throw "TODO: port unchecked-remainder-int")) -; -;(defn rationalize -; "returns the rational value of num" -; [num] -; ;; (. clojure.lang.Numbers (rationalize num)) -; (throw "TODO: port rationalize")) -; -;(defn int? -; "Return true if x is a fixed precision integer" -; [x] -; (integer? x)) -; -;(defn pos-int? -; "Return true if x is a positive fixed precision integer" -; [x] (and (int? x) -; (pos? x))) -; -;(defn neg-int? -; "Return true if x is a negative fixed precision integer" -; [x] (and (int? x) -; (neg? x))) -; -;(defn nat-int? -; "Return true if x is a non-negative fixed precision integer" -; [x] (and (int? x) -; (not (neg? x)))) -; -;(defn double? -; "Return true if x is a Double" -; [x] -; (float? x)) -; -;;;map stuff -; -;(defn map-entry? -; "Return true if x is a map entry" -; [x] -; (and (vector? x) -; (== 2 (count x)))) -; -;(defn rseq -; "Returns, in constant time, a seq of the items in rev (which -; can be a vector or sorted-map), in reverse order. If rev is empty returns nil" -; [#_clojure.lang.Reversible rev] -; ;; (. rev (rseq)) -; (throw "TODO: port rseq")) -; -;(defmacro locking -; "Executes exprs in an implicit do, while holding the monitor of x. -; Will release the monitor of x in all circumstances." -; [x & body] -; `(let [lockee# ~x] -; (try -; (let [locklocal# lockee#] -; (monitor-enter locklocal#) -; (try -; (do ~@body) -; (finally -; (monitor-exit locklocal#))))))) -; -;;; (defmacro .. -;;; "form => fieldName-symbol or (instanceMethodName-symbol args*) -; -;;; Expands into a member access (.) of the first member on the first -;;; argument, followed by the next member on the result, etc. For -;;; instance: -; -;;; (.. System (getProperties) (get \"os.name\")) -; -;;; expands to: -; -;;; (. (. System (getProperties)) (get \"os.name\")) -; -;;; but is easier to write, read, and understand." -;;; ([x form] -;;; ;; `(. ~x ~form) -;;; (throw "TODO: port")) -;;; ([x form & more] -;;; ;; `(.. (. ~x ~form) ~@more)) -;;; (throw "TODO: port")) -; -; -;;;;;;;;;; var stuff -; -;;(defn with-bindings* -;; "Takes a map of Var/value pairs. Installs for the given Vars the associated -;; values as thread-local bindings. Then calls f with the supplied arguments. -;; Pops the installed bindings after f returned. Returns whatever f returns." -;; [binding-map f & args] -;; (push-thread-bindings (if (= "persistent_array_map" (type binding-map)) -;; (into (hash-map) binding-map) -;; binding-map)) -;; (try -;; (apply f args) -;; (finally -;; (pop-thread-bindings)))) -;; -;;(defmacro with-bindings -;; "Takes a map of Var/value pairs. Installs for the given Vars the associated -;; values as thread-local bindings. Then executes body. Pops the installed -;; bindings after body was evaluated. Returns the value of body." -;; [binding-map & body] -;; `(with-bindings* ~binding-map (fn [] ~@body))) -;; -;;(defn bound-fn* -;; "Returns a function, which will install the same bindings in effect as in -;; the thread at the time bound-fn* was called and then call f with any given -;; arguments. This may be used to define a helper function which runs on a -;; different thread, but needs the same bindings in place." -;; [f] -;; (let [bindings (get-thread-bindings)] -;; (fn [& args] -;; (apply with-bindings* bindings f args)))) -;; -;;(defmacro bound-fn -;; "Returns a function defined by the given fntail, which will install the -;; same bindings in effect as in the thread at the time bound-fn was called. -;; This may be used to define a helper function which runs on a different -;; thread, but needs the same bindings in place." -;; [& fntail] -;; `(bound-fn* (fn ~@fntail))) -;; -;;(defn- binding-conveyor-fn -;; [f] -;; ;; (let [frame (clojure.lang.Var/cloneThreadBindingFrame)] -;; ;; (fn -;; ;; ([] -;; ;; (clojure.lang.Var/resetThreadBindingFrame frame) -;; ;; (f)) -;; ;; ([x] -;; ;; (clojure.lang.Var/resetThreadBindingFrame frame) -;; ;; (f x)) -;; ;; ([x y] -;; ;; (clojure.lang.Var/resetThreadBindingFrame frame) -;; ;; (f x y)) -;; ;; ([x y z] -;; ;; (clojure.lang.Var/resetThreadBindingFrame frame) -;; ;; (f x y z)) -;; ;; ([x y z & args] -;; ;; (clojure.lang.Var/resetThreadBindingFrame frame) -;; ;; (apply f x y z args)))) -;; (throw "TODO: port binding-conveyor-fn")) -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Refs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;(defn- -;; setup-reference [#_clojure.lang.ARef r options] -;; ;; (let [opts (apply hash-map options)] -;; ;; (when (:meta opts) -;; ;; (.resetMeta r (:meta opts))) -;; ;; (when (:validator opts) -;; ;; (.setValidator r (:validator opts))) -;; ;; r) -;; (throw "TODO: port setup-reference")) -;; -;;(defn agent -;; "Creates and returns an agent with an initial value of state and -;; zero or more options (in any order): -;; -;; :meta metadata-map -;; -;; :validator validate-fn -;; -;; :error-handler handler-fn -;; -;; :error-mode mode-keyword -;; -;; If metadata-map is supplied, it will become the metadata on the -;; agent. validate-fn must be nil or a side-effect-free fn of one -;; argument, which will be passed the intended new state on any state -;; change. If the new state is unacceptable, the validate-fn should -;; return false or throw an exception. handler-fn is called if an -;; action throws an exception or if validate-fn rejects a new state -- -;; see set-error-handler! for details. The mode-keyword may be either -;; :continue (the default if an error-handler is given) or :fail (the -;; default if no error-handler is given) -- see set-error-mode! for -;; details." -;; ([state & options] -;; ;; (let [a (new clojure.lang.Agent state) -;; ;; opts (apply hash-map options)] -;; ;; (setup-reference a options) -;; ;; (when (:error-handler opts) -;; ;; (.setErrorHandler a (:error-handler opts))) -;; ;; (.setErrorMode a (or (:error-mode opts) -;; ;; (if (:error-handler opts) :continue :fail))) -;; ;; a) -;; (throw "TODO: port agent"))) -;; -;;(defn set-agent-send-executor! -;; "Sets the ExecutorService to be used by send" -;; [executor] -;; ;; (set! clojure.lang.Agent/pooledExecutor executor) -;; (throw "TODO: port set-agent-send-executor!")) -;; -;;(defn set-agent-send-off-executor! -;; "Sets the ExecutorService to be used by send-off" -;; [executor] -;; ;; (set! clojure.lang.Agent/soloExecutor executor) -;; (throw "TODO: port set-agent-send-off-executor!")) -;; -;;(defn send-via -;; "Dispatch an action to an agent. Returns the agent immediately. -;; Subsequently, in a thread supplied by executor, the state of the agent -;; will be set to the value of: -;; -;; (apply action-fn state-of-agent args)" -;; [executor #_clojure.lang.Agent a f & args] -;; ;; (.dispatch a (binding [*agent* a] (binding-conveyor-fn f)) args executor) -;; (throw "TODO: port send-via")) -;; -;;(defn send -;; "Dispatch an action to an agent. Returns the agent immediately. -;; Subsequently, in a thread from a thread pool, the state of the agent -;; will be set to the value of: -;; -;; (apply action-fn state-of-agent args)" -;; [#_clojure.lang.Agent a f & args] -;; ;; (apply send-via clojure.lang.Agent/pooledExecutor a f args) -;; (throw "TODO: port send")) -;; -;;(defn send-off -;; "Dispatch a potentially blocking action to an agent. Returns the -;; agent immediately. Subsequently, in a separate thread, the state of -;; the agent will be set to the value of: -;; -;; (apply action-fn state-of-agent args)" -;; [#_clojure.lang.Agent a f & args] -;; ;; (apply send-via clojure.lang.Agent/soloExecutor a f args) -;; (throw "TODO: port send-off")) -;; -;;(defn release-pending-sends -;; "Normally, actions sent directly or indirectly during another action -;; are held until the action completes (changes the agent's -;; state). This function can be used to dispatch any pending sent -;; actions immediately. This has no impact on actions sent during a -;; transaction, which are still held until commit. If no action is -;; occurring, does nothing. Returns the number of actions dispatched." -;; [] -;; ;; (clojure.lang.Agent/releasePendingSends) -;; (throw "TODO: port release-pending-sends")) -;; -;;(defn add-watch -;; "Adds a watch function to an agent/atom/var/ref reference. The watch -;; fn must be a fn of 4 args: a key, the reference, its old-state, its -;; new-state. Whenever the reference's state might have been changed, -;; any registered watches will have their functions called. The watch fn -;; will be called synchronously, on the agent's thread if an agent, -;; before any pending sends if agent or ref. Note that an atom's or -;; ref's state may have changed again prior to the fn call, so use -;; old/new-state rather than derefing the reference. Note also that watch -;; fns may be called from multiple threads simultaneously. Var watchers -;; are triggered only by root binding changes, not thread-local -;; set!s. Keys must be unique per reference, and can be used to remove -;; the watch with remove-watch, but are otherwise considered opaque by -;; the watch mechanism." -;; [reference key f] -;; (cpp/jank.runtime.add_watch reference key f)) -;; -;;(defn remove-watch -;; "Removes a watch (set by add-watch) from a reference" -;; [reference key] -;; (cpp/jank.runtime.remove_watch reference key)) -;; -;;(defn agent-error -;; "Returns the exception thrown during an asynchronous action of the -;; agent if the agent is failed. Returns nil if the agent is not -;; failed." -;; [#_clojure.lang.Agent a] -;; ;; (.getError a) -;; (throw "TODO: port agent-error")) -;; -;;(defn restart-agent -;; "When an agent is failed, changes the agent state to new-state and -;; then un-fails the agent so that sends are allowed again. If -;; a :clear-actions true option is given, any actions queued on the -;; agent that were being held while it was failed will be discarded, -;; otherwise those held actions will proceed. The new-state must pass -;; the validator if any, or restart will throw an exception and the -;; agent will remain failed with its old state and error. Watchers, if -;; any, will NOT be notified of the new state. Throws an exception if -;; the agent is not failed." -;; [#_clojure.lang.Agent a, new-state & options] -;; ;; (let [opts (apply hash-map options)] -;; ;; (.restart a new-state (if (:clear-actions opts) true false))) -;; (throw "TODO: port restart-agent")) -;; -;;(defn set-error-handler! -;; "Sets the error-handler of agent a to handler-fn. If an action -;; being run by the agent throws an exception or doesn't pass the -;; validator fn, handler-fn will be called with two arguments: the -;; agent and the exception." -;; [#_clojure.lang.Agent a, handler-fn] -;; ;; (.setErrorHandler a handler-fn) -;; (throw "TODO: port set-error-handler!")) -;; -;;(defn error-handler -;; "Returns the error-handler of agent a, or nil if there is none. -;; See set-error-handler!" -;; [#_clojure.lang.Agent a] -;; ;; (.getErrorHandler a) -;; (throw "TODO: port error-handler")) -;; -;;(defn set-error-mode! -;; "Sets the error-mode of agent a to mode-keyword, which must be -;; either :fail or :continue. If an action being run by the agent -;; throws an exception or doesn't pass the validator fn, an -;; error-handler may be called (see set-error-handler!), after which, -;; if the mode is :continue, the agent will continue as if neither the -;; action that caused the error nor the error itself ever happened. -;; -;; If the mode is :fail, the agent will become failed and will stop -;; accepting new 'send' and 'send-off' actions, and any previously -;; queued actions will be held until a 'restart-agent'. Deref will -;; still work, returning the state of the agent before the error." -;; [#_clojure.lang.Agent a, mode-keyword] -;; ;; (.setErrorMode a mode-keyword) -;; (throw "TODO: port set-error-mode!")) -;; -;;(defn error-mode -;; "Returns the error-mode of agent a. See set-error-mode!" -;; [#_clojure.lang.Agent a] -;; ;; (.getErrorMode a) -;; (throw "TODO: port error-mode")) -;; -;;(defn agent-errors -;; "DEPRECATED: Use 'agent-error' instead. -;; Returns a sequence of the exceptions thrown during asynchronous -;; actions of the agent." -;; [a] -;; (when-let [e (agent-error a)] -;; (list e))) -;; -;;(defn clear-agent-errors -;; "DEPRECATED: Use 'restart-agent' instead. -;; Clears any exceptions thrown during asynchronous actions of the -;; agent, allowing subsequent actions to occur." -;; [#_clojure.lang.Agent a] -;; ;; (restart-agent a (.deref a)) -;; (throw "TODO: port clear-agent-errors")) -;; -;;(defn shutdown-agents -;; "Initiates a shutdown of the thread pools that back the agent -;; system. Running actions will complete, but no new actions will be -;; accepted" -;; [] -;; ;; (. clojure.lang.Agent shutdown) -;; (throw "TODO: port shutdown-agents")) -;; -;;(defn ref -;; "Creates and returns a Ref with an initial value of x and zero or -;; more options (in any order): -;; -;; :meta metadata-map -;; -;; :validator validate-fn -;; -;; :min-history (default 0) -;; :max-history (default 10) -;; -;; If metadata-map is supplied, it will become the metadata on the -;; ref. validate-fn must be nil or a side-effect-free fn of one -;; argument, which will be passed the intended new state on any state -;; change. If the new state is unacceptable, the validate-fn should -;; return false or throw an exception. validate-fn will be called on -;; transaction commit, when all refs have their final values. -;; -;; Normally refs accumulate history dynamically as needed to deal with -;; read demands. If you know in advance you will need history you can -;; set :min-history to ensure it will be available when first needed (instead -;; of after a read fault). History is limited, and the limit can be set -;; with :max-history." -;; ([x] -;; ;; (new clojure.lang.Ref x) -;; (throw "TODO: port ref")) -;; ([x & options] -;; ;; (let [r ^clojure.lang.Ref (setup-reference (ref x) options) -;; ;; opts (apply hash-map options)] -;; ;; (when (:max-history opts) -;; ;; (.setMaxHistory r (:max-history opts))) -;; ;; (when (:min-history opts) -;; ;; (.setMinHistory r (:min-history opts))) -;; ;; r) -;; (throw "TODO: port ref"))) -;; -;;(defn- deref-future -;; ([#_java.util.concurrent.Future fut] -;; ;; (.get fut) -;; (throw "TODO: port deref-future")) -;; ([#_java.util.concurrent.Future fut timeout-ms timeout-val] -;; ;; (try (.get fut timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS) -;; ;; (catch java.util.concurrent.TimeoutException e -;; ;; timeout-val)) -;; (throw "TODO: port deref-future"))) -;; -;;(defn set-validator! -;; "Sets the validator-fn for a var/ref/agent/atom. validator-fn must be nil or a -;; side-effect-free fn of one argument, which will be passed the intended -;; new state on any state change. If the new state is unacceptable, the -;; validator-fn should return false or throw an exception. If the current state (root -;; value if var) is not acceptable to the new validator, an exception -;; will be thrown and the validator will not be changed." -;; [#_clojure.lang.IRef iref validator-fn] -;; ;; (. iref (setValidator validator-fn)) -;; (throw "TODO: port set-validator!")) -;; -;;(defn get-validator -;; "Gets the validator-fn for a var/ref/agent/atom." -;; [#_clojure.lang.IRef iref] -;; ;; (. iref (getValidator)) -;; (throw "TODO: port get-validator")) -;; -;;(defn commute -;; "Must be called in a transaction. Sets the in-transaction-value of -;; ref to: -;; -;; (apply fun in-transaction-value-of-ref args) -;; -;; and returns the in-transaction-value of ref. -;; -;; At the commit point of the transaction, sets the value of ref to be: -;; -;; (apply fun most-recently-committed-value-of-ref args) -;; -;; Thus fun should be commutative, or, failing that, you must accept -;; last-one-in-wins behavior. commute allows for more concurrency than -;; ref-set." -;; [#_clojure.lang.Ref ref fun & args] -;; ;; (. ref (commute fun args)) -;; (throw "TODO: port commute")) -;; -;;(defn alter -;; "Must be called in a transaction. Sets the in-transaction-value of -;; ref to: -;; -;; (apply fun in-transaction-value-of-ref args) -;; -;; and returns the in-transaction-value of ref." -;; [#_clojure.lang.Ref ref fun & args] -;; ;; (. ref (alter fun args)) -;; (throw "TODO: port alter")) -;; -;;(defn ref-set -;; "Must be called in a transaction. Sets the value of ref. -;; Returns val." -;; [#_clojure.lang.Ref ref val] -;; ;; (. ref (set val)) -;; (throw "TODO: port ref-set")) -;; -;;(defn ref-history-count -;; "Returns the history count of a ref" -;; [#_clojure.lang.Ref ref] -;; ;; (.getHistoryCount ref) -;; (throw "TODO: port ref-history-count")) -;; -;;(defn ref-min-history -;; "Gets the min-history of a ref, or sets it and returns the ref" -;; ([#_clojure.lang.Ref ref] -;; ;; (.getMinHistory ref) -;; (throw "TODO: port ref-min-history")) -;; ([#_clojure.lang.Ref ref n] -;; ;; (.setMinHistory ref n) -;; (throw "TODO: port ref-min-history"))) -;; -;;(defn ref-max-history -;; "Gets the max-history of a ref, or sets it and returns the ref" -;; ([#_clojure.lang.Ref ref] -;; ;; (.getMaxHistory ref) -;; (throw "TODO: port ref-max-history")) -;; ([#_clojure.lang.Ref ref n] -;; ;; (.setMaxHistory ref n) -;; (throw "TODO: port ref-max-history"))) -;; -;;(defn ensure -;; "Must be called in a transaction. Protects the ref from modification -;; by other transactions. Returns the in-transaction-value of -;; ref. Allows for more concurrency than (ref-set ref @ref)" -;; [#_clojure.lang.Ref ref] -;; ;; (. ref (touch)) -;; ;; (. ref (deref)) -;; (throw "TODO: port ensure")) -;; -;;(defmacro sync -;; "transaction-flags => TBD, pass nil for now -;; -;; Runs the exprs (in an implicit do) in a transaction that encompasses -;; exprs and any nested calls. Starts a transaction if none is already -;; running on this thread. Any uncaught exception will abort the -;; transaction and flow out of sync. The exprs may be run more than -;; once, but any effects on Refs will be atomic." -;; [flags-ignored-for-now & body] -;; ;; `(. clojure.lang.LockingTransaction -;; ;; (runInTransaction (fn [] ~@body))) -;; (throw "TODO: port sync")) -;; -;;(defmacro io! -;; "If an io! block occurs in a transaction, throws an -;; IllegalStateException, else runs body in an implicit do. If the -;; first expression in body is a literal string, will use that as the -;; exception message." -;; [& body] -;; ;; (let [message (when (string? (first body)) (first body)) -;; ;; body (if message (next body) body)] -;; ;; `(if (clojure.lang.LockingTransaction/isRunning) -;; ;; (throw (new IllegalStateException ~(or message "I/O in transaction"))) -;; ;; (do ~@body))) -;; (throw "TODO: port io!")) -;; -;;;;;;;;;;;;;;;;;;;;; sequence fns ;;;;;;;;;;;;;;;;;;;;;;; -;; -;;(defn sequence -;; "Coerces coll to a (possibly empty) sequence, if it is not already -;; one. Will not force a lazy seq. (sequence nil) yields (), When a -;; transducer is supplied, returns a lazy sequence of applications of -;; the transform to the items in coll(s), i.e. to the set of first -;; items of each coll, followed by the set of second -;; items in each coll, until any one of the colls is exhausted. Any -;; remaining items in other colls are ignored. The transform should accept -;; number-of-colls arguments" -;; ([coll] -;; (if (seq? coll) coll -;; (or (seq coll) ()))) -;; ([xform coll] -;; ;; (or (clojure.lang.RT/chunkIteratorSeq -;; ;; (clojure.lang.TransformerIterator/create xform (clojure.lang.RT/iter coll))) -;; ;; ()) -;; (throw "TODO: port sequence")) -;; ([xform coll & colls] -;; ;; (or (clojure.lang.RT/chunkIteratorSeq -;; ;; (clojure.lang.TransformerIterator/createMulti -;; ;; xform -;; ;; (map #(clojure.lang.RT/iter %) (cons coll colls)))) -;; ;; ()) -;; (throw "TODO: port sequence"))) -;; -;;(defn not-every? -;; "Returns false if (pred x) is logical true for every x in -;; coll, else true." -;; [pred coll] -;; (not (every? pred coll))) -;; -;;(defmacro declare -;; "defs the supplied var names with no bindings, useful for making forward declarations." -;; [& names] `(do ~@(map #(list 'def (vary-meta % assoc :declared true)) names))) -;; -;;(defn replicate -;; "DEPRECATED: Use 'repeat' instead. -;; Returns a lazy seq of n xs." -;; [n x] (take n (repeat x))) -;; -;;(defn merge -;; "Returns a map that consists of the rest of the maps conj-ed onto -;; the first. If a key occurs in more than one map, the mapping from -;; the latter (left-to-right) will be the mapping in the result." -;; [& maps] -;; (when (some identity maps) -;; (reduce #(conj (or %1 {}) %2) maps))) -;; -;;(defn merge-with -;; "Returns a map that consists of the rest of the maps conj-ed onto -;; the first. If a key occurs in more than one map, the mapping(s) -;; from the latter (left-to-right) will be combined with the mapping in -;; the result by calling (f val-in-result val-in-latter)." -;; [f & maps] -;; (when (some identity maps) -;; (let [merge-entry (fn [m e] -;; (let [k (key e) v (val e)] -;; (if (contains? m k) -;; (assoc m k (f (get m k) v)) -;; (assoc m k v)))) -;; merge2 (fn [m1 m2] -;; (reduce merge-entry (or m1 {}) (seq m2)))] -;; (reduce merge2 maps)))) -;; -;;(defn line-seq -;; "Returns the lines of text from rdr as a lazy sequence of strings. -;; rdr must implement java.io.BufferedReader." -;; [#_java.io.BufferedReader rdr] -;; ;; (when-let [line (.readLine rdr)] -;; ;; (cons line (lazy-seq (line-seq rdr)))) -;; (throw "TODO: port line-seq")) -;; -;;(defn comparator -;; "Returns an implementation of java.util.Comparator based upon pred." -;; [pred] -;; (fn [x y] -;; (cond (pred x y) -1 (pred y x) 1 :else 0))) -;; -;;(defn sort -;; "Returns a sorted sequence of the items in coll. If no comparator is -;; supplied, uses compare. comparator must implement -;; java.util.Comparator. Guaranteed to be stable: equal elements will -;; not be reordered. If coll is a Java array, it will be modified. To -;; avoid this, sort a copy of the array." -;; [coll] -;; (cpp/jank.runtime.sort coll)) -;; -;;(defn sort-by -;; "Returns a sorted sequence of the items in coll, where the sort -;; order is determined by comparing (keyfn item). If no comparator is -;; supplied, uses compare. comparator must implement -;; java.util.Comparator. Guaranteed to be stable: equal elements will -;; not be reordered. If coll is a Java array, it will be modified. To -;; avoid this, sort a copy of the array." -;; ([keyfn coll] -;; (sort-by keyfn compare coll)) -;; ([keyfn #_java.util.Comparator comp coll] -;; ;; (sort (fn [x y] (. comp (compare (keyfn x) (keyfn y)))) coll) -;; (throw "TODO: port sort-by"))) -;; -;;;; evaluation -;; -;;(defn eval -;; "Evaluates the form data structure (not text!) and returns the result." -;; [form] -;; (cpp/clojure.core_native.eval form)) -;; -;;(defn await -;; "Blocks the current thread (indefinitely!) until all actions -;; dispatched thus far, from this thread or agent, to the agent(s) have -;; occurred. Will block on failed agents. Will never return if -;; a failed agent is restarted with :clear-actions true or shutdown-agents was called." -;; [& agents] -;; ;; (io! "await in transaction" -;; ;; (when *agent* -;; ;; (throw (new Exception "Can't await in agent action"))) -;; ;; (let [latch (new java.util.concurrent.CountDownLatch (count agents)) -;; ;; count-down (fn [agent] (. latch (countDown)) agent)] -;; ;; (doseq [agent agents] -;; ;; (send agent count-down)) -;; ;; (. latch (await)))) -;; (throw "TODO: port await")) -;; -;;(defn await1 [#_clojure.lang.Agent a] -;; ;; (when (pos? (.getQueueCount a)) -;; ;; (await a)) -;; ;; a -;; (throw "TODO: port await1")) -;; -;;(defn await-for -;; "Blocks the current thread until all actions dispatched thus -;; far (from this thread or agent) to the agents have occurred, or the -;; timeout (in milliseconds) has elapsed. Returns logical false if -;; returning due to timeout, logical true otherwise." -;; [timeout-ms & agents] -;; ;; (io! "await-for in transaction" -;; ;; (when *agent* -;; ;; (throw (new Exception "Can't await in agent action"))) -;; ;; (let [latch (new java.util.concurrent.CountDownLatch (count agents)) -;; ;; count-down (fn [agent] (. latch (countDown)) agent)] -;; ;; (doseq [agent agents] -;; ;; (send agent count-down)) -;; ;; (. latch (await timeout-ms (. java.util.concurrent.TimeUnit MILLISECONDS))))) -;; (throw "TODO: port await-for")) -;; -;;(defn import -;; "import is not implemented for jank, but a var is still bound to its symbol for portability. import always throws an exception" -;; [& _] -;; (throw "import is not supported in jank, for C/C++ dependency interoperability use cpp/raw with #include, e.g. (cpp/raw \"#include \"dependency.h\")\")")) -;; -;;(defn into-array -;; "Returns an array with components set to the values in aseq. The array's -;; component type is type if provided, or the type of the first value in -;; aseq if present, or Object. All values in aseq must be compatible with -;; the component type. Class objects for the primitive types can be obtained -;; using, e.g., Integer/TYPE." -;; ([aseq] -;; ;; (clojure.lang.RT/seqToTypedArray (seq aseq)) -;; (throw "TODO: port into-array")) -;; ([type aseq] -;; ;; (clojure.lang.RT/seqToTypedArray type (seq aseq)) -;; (throw "TODO: port into-array"))) -;; -;;(defn- -;; array [& items] -;; (into-array items)) -;; -;;(defn class -;; "Returns the Class of x" -;; #_Class [#_Object x] -;; ;; (if (nil? x) x (. x (getClass))) -;; (throw "TODO: port class")) -;; -;;(defn num -;; "Coerce to Number" -;; [x] -;; ;; (. clojure.lang.Numbers (num x)) -;; (throw "TODO: port num")) -;; -;;(defn long -;; "Coerce to long" -;; [#_Number x] -;; ;; (clojure.lang.RT/longCast x) -;; (throw "TODO: port long")) -;; -;;(defn double -;; "Coerce to double" -;; [#_Number x] -;; ;; (clojure.lang.RT/doubleCast x) -;; (throw "TODO: port double")) -;; -;;(defn short -;; "Coerce to short" -;; [#_Number x] -;; ;; (clojure.lang.RT/shortCast x) -;; (throw "TODO: port short")) -;; -;;(defn byte -;; "Coerce to byte" -;; [#_Number x] -;; ;; (clojure.lang.RT/byteCast x) -;; (throw "TODO: port byte")) -;; -;;(defn char -;; "Coerce to char" -;; [x] -;; ;; (. clojure.lang.RT (charCast x)) -;; (throw "TODO: port char")) -;; -;;(defn unchecked-byte -;; "Coerce to byte. Subject to rounding or truncation." -;; [#_Number x] -;; ;; (clojure.lang.RT/uncheckedByteCast x) -;; (throw "TODO: port unchecked-byte")) -;; -;;(defn unchecked-short -;; "Coerce to short. Subject to rounding or truncation." -;; [#_Number x] -;; ;; (clojure.lang.RT/uncheckedShortCast x) -;; (throw "TODO: port unchecked-short")) -;; -;;(defn unchecked-char -;; "Coerce to char. Subject to rounding or truncation." -;; [x] -;; ;; (. clojure.lang.RT (uncheckedCharCast x)) -;; (throw "TODO: port unchecked-char")) -;; -;;(defn unchecked-int -;; "Coerce to int. Subject to rounding or truncation." -;; [#_Number x] -;; ;; (clojure.lang.RT/uncheckedIntCast x) -;; (throw "TODO: port unchecked-int")) -;; -;;(defn unchecked-long -;; "Coerce to long. Subject to rounding or truncation." -;; [#_Number x] -;; ;; (clojure.lang.RT/uncheckedLongCast x) -;; (throw "TODO: port unchecked-long")) -;; -;;(defn unchecked-float -;; "Coerce to float. Subject to rounding." -;; [#_Number x] -;; ;; (clojure.lang.RT/uncheckedFloatCast x) -;; (throw "TODO: port unchecked-float")) -;; -;;(defn unchecked-double -;; "Coerce to double. Subject to rounding." -;; [#_Number x] -;; ;; (clojure.lang.RT/uncheckedDoubleCast x) -;; (throw "TODO: port unchecked-double")) -;; -;;(defn ratio? -;; "Returns true if n is a Ratio" -;; [r] -;; (cpp/jank.runtime.is_ratio r)) -;; -;;(defn numerator -;; "Returns the numerator part of a Ratio." -;; [r] -;; (cpp/jank.runtime.numerator r)) -;; -;;(defn denominator -;; "Returns the denominator part of a Ratio." -;; [r] -;; (cpp/jank.runtime.denominator r)) -;; -;;(defn decimal? -;; "Returns true if n is a BigDecimal" -;; [n] -;; ;; (instance? BigDecimal n) -;; (cpp/jank.runtime.is_big_decimal n)) -;; -;;(defn rational? -;; "Returns true if n is a rational number" -;; [n] -;; (or (integer? n) (ratio? n) (decimal? n))) -;; -;;(defn bigint -;; "Coerce to BigInt" -;; [x] -;; ;; (cond -;; ;; (instance? clojure.lang.BigInt x) x -;; ;; (instance? BigInteger x) (clojure.lang.BigInt/fromBigInteger x) -;; ;; (decimal? x) (bigint (.toBigInteger ^BigDecimal x)) -;; ;; (float? x) (bigint (. BigDecimal valueOf (double x))) -;; ;; (ratio? x) (bigint (.bigIntegerValue ^clojure.lang.Ratio x)) -;; ;; (number? x) (clojure.lang.BigInt/valueOf (long x)) -;; ;; :else (bigint (BigInteger. x))) -;; (throw "TODO: port bigint")) -;; -;;(defn biginteger -;; "Coerce to BigInteger" -;; [x] -;; ;; (cond -;; ;; (instance? BigInteger x) x -;; ;; (instance? clojure.lang.BigInt x) (.toBigInteger ^clojure.lang.BigInt x) -;; ;; (decimal? x) (.toBigInteger ^BigDecimal x) -;; ;; (float? x) (.toBigInteger (. BigDecimal valueOf (double x))) -;; ;; (ratio? x) (.bigIntegerValue ^clojure.lang.Ratio x) -;; ;; (number? x) (BigInteger/valueOf (long x)) -;; ;; :else (BigInteger. x)) -;; (throw "TODO: port biginteger")) -;; -;;(defn bigdec -;; "Coerce to BigDecimal" -;; [x] -;; (cpp/jank.runtime.to_big_decimal x)) -;; -;;(def ^:dynamic ^:private print-initialized false) -;; -;;(defmulti print-method (fn [x writer] -;; (let [t (get (meta x) :type)] -;; (if (keyword? t) t (class x))))) -;; -;;(defmulti print-dup (fn [x writer] (class x))) -;; -;;(def ^:private #_String system-newline -;; ;; (System/getProperty "line.separator") -;; "\n") -;; -;;(defn newline -;; "Writes a platform-specific newline to *out*" -;; [] -;; ;; (. *out* (append system-newline)) -;; ;; nil -;; (throw "TODO: port newline")) -;; -;;(defn flush -;; "Flushes the output stream that is the current value of -;; *out*" -;; [] -;; ;; (. *out* (flush)) -;; ;; nil -;; (throw "TODO: port flesh")) -;; -;;(defn read -;; "Reads the next object from stream, which must be an instance of -;; java.io.PushbackReader or some derivee. stream defaults to the -;; current value of *in*. -;; -;; Opts is a persistent map with valid keys: -;; :read-cond - :allow to process reader conditionals, or -;; :preserve to keep all branches -;; :features - persistent set of feature keywords for reader conditionals -;; :eof - on eof, return value unless :eofthrow, then throw. -;; if not specified, will throw -;; -;; Note that read can execute code (controlled by *read-eval*), -;; and as such should be used only with trusted sources. -;; -;; For data structure interop use clojure.edn/read" -;; ([] -;; (read *in*)) -;; ([stream] -;; (read stream true nil)) -;; ([stream eof-error? eof-value] -;; (read stream eof-error? eof-value false)) -;; ([stream eof-error? eof-value recursive?] -;; ;; (. clojure.lang.LispReader (read stream (boolean eof-error?) eof-value recursive?)) -;; (throw "TODO: port read")) -;; ([opts stream] -;; ;; (. clojure.lang.LispReader (read stream opts)) -;; (throw "TODO: port read"))) -;; -;;(defn read+string -;; "Like read, and taking the same args. stream must be a LineNumberingPushbackReader. -;; Returns a vector containing the object read and the (whitespace-trimmed) string read." -;; ([] (read+string *in*)) -;; ([stream] (read+string stream true nil)) -;; ([stream eof-error? eof-value] (read+string stream eof-error? eof-value false)) -;; ([#_clojure.lang.LineNumberingPushbackReader stream eof-error? eof-value recursive?] -;; ;; (try -;; ;; (.captureString stream) -;; ;; (let [o (read stream eof-error? eof-value recursive?) -;; ;; s (.trim (.getString stream))] -;; ;; [o s]) -;; ;; (catch Throwable ex -;; ;; (.getString stream) -;; ;; (throw ex))) -;; (throw "TODO: port read+string")) -;; ([opts #_clojure.lang.LineNumberingPushbackReader stream] -;; ;; (try -;; ;; (.captureString stream) -;; ;; (let [o (read opts stream) -;; ;; s (.trim (.getString stream))] -;; ;; [o s]) -;; ;; (catch Throwable ex -;; ;; (.getString stream) -;; ;; (throw ex))) -;; (throw "TODO: port read+string"))) -;; -;;(defn read-line -;; "Reads the next line from stream that is the current value of *in* ." -;; [] -;; ;; (if (instance? clojure.lang.LineNumberingPushbackReader *in*) -;; ;; (.readLine ^clojure.lang.LineNumberingPushbackReader *in*) -;; ;; (.readLine ^java.io.BufferedReader *in*)) -;; (throw "TODO: port read-line")) -;; -;;(defn read-string -;; "Reads one object from the string s. Optionally include reader -;; options, as specified in read. -;; -;; Note that read-string can execute code (controlled by *read-eval*), -;; and as such should be used only with trusted sources. -;; -;; For data structure interop use clojure.edn/read-string" -;; ([s] -;; (read-string {} s)) -;; ([opts s] -;; (cpp/clojure.core_native.read_string opts s))) -;; -;;(defmacro with-open -;; "bindings => [name init ...] -;; -;; Evaluates body in a try expression with names bound to the values -;; of the inits, and a finally clause that calls (.close name) on each -;; name in reverse order." -;; [bindings & body] -;; (assert-macro-args -;; (vector? bindings) "a vector for its binding" -;; (even? (count bindings)) "an even number of forms in binding vector") -;; ;; (cond -;; ;; (= (count bindings) 0) `(do ~@body) -;; ;; (symbol? (bindings 0)) `(let ~(subvec bindings 0 2) -;; ;; (try -;; ;; (with-open ~(subvec bindings 2) ~@body) -;; ;; (finally -;; ;; (. ~(bindings 0) ~'close)))) -;; ;; :else (throw (IllegalArgumentException. -;; ;; "with-open only allows Symbols in bindings"))) -;; (throw "TODO: port with-open")) -;; -;;(defmacro memfn -;; "Expands into code that creates a fn that expects to be passed an -;; object and any args and calls the named instance method on the -;; object passing the args. Use when you want to treat a Java method as -;; a first-class fn. name may be type-hinted with the method receiver's -;; type in order to avoid reflective calls." -;; [name & args] -;; ;; (let [t (with-meta (gensym "target") -;; ;; (meta name))] -;; ;; `(fn [~t ~@args] -;; ;; (. ~t (~name ~@args)))) -;; (throw "TODO: port memfn")) -;; -;;(defn alength -;; "Returns the length of the Java array. Works on arrays of all -;; types." -;; [array] -;; ;; (. clojure.lang.RT (alength array)) -;; (throw "TODO: port alength")) -;; -;;(defn aclone -;; "Returns a clone of the Java array. Works on arrays of known -;; types." -;; [array] -;; ;; (. clojure.lang.RT (aclone array)) -;; (throw "TODO: port aclone")) -;; -;;(defn aget -;; "Returns the value at the index/indices. Works on Java arrays of all -;; types." -;; ([array idx] -;; ;; (clojure.lang.Reflector/prepRet (.getComponentType (class array)) (. Array (get array idx))) -;; (throw "TODO: port aget")) -;; ([array idx & idxs] -;; (apply aget (aget array idx) idxs))) -;; -;;(defmacro aset -;; "Sets the value at the index/indices. Returns val." -;; [array idx & more] -;; (if (= 1 (count more)) -;; ;; Simple case: (aset array index value) -;; (let [val (first more)] -;; `(do -;; (cpp/= (cpp/aget ~array ~idx) ~val) -;; ~val)) -;; ;; Nested case: (aset array idx1 idx2 & idxv) - not yet implemented -;; `(throw "TODO: Nested array indexing not yet implemented"))) -;; -;;(defmacro -;; ^{:private true} -;; def-aset [name method coerce] -;; `(defn ~name -;; {:arglists '([~'array ~'idx ~'val] [~'array ~'idx ~'idx2 & ~'idxv])} -;; ([array# idx# val#] -;; ;; (. Array (~method array# idx# (~coerce val#))) -;; ;; val# -;; (throw ~(str "TODO: port " name))) -;; ([array# idx# idx2# & idxv#] -;; (apply ~name (aget array# idx#) idx2# idxv#)))) -;; -;;(def-aset -;; ^{:doc "Sets the value at the index/indices. Works on arrays of int. Returns val."} -;; aset-int setInt int) -;; -;;(def-aset -;; ^{:doc "Sets the value at the index/indices. Works on arrays of long. Returns val."} -;; aset-long setLong long) -;; -;;(def-aset -;; ^{:doc "Sets the value at the index/indices. Works on arrays of boolean. Returns val."} -;; aset-boolean setBoolean boolean) -;; -;;(def-aset -;; ^{:doc "Sets the value at the index/indices. Works on arrays of float. Returns val."} -;; aset-float setFloat float) -;; -;;(def-aset -;; ^{:doc "Sets the value at the index/indices. Works on arrays of double. Returns val."} -;; aset-double setDouble double) -;; -;;(def-aset -;; ^{:doc "Sets the value at the index/indices. Works on arrays of short. Returns val."} -;; aset-short setShort short) -;; -;;(def-aset -;; ^{:doc "Sets the value at the index/indices. Works on arrays of byte. Returns val."} -;; aset-byte setByte byte) -;; -;;(def-aset -;; ^{:doc "Sets the value at the index/indices. Works on arrays of char. Returns val."} -;; aset-char setChar char) -;; -;;(defn make-array -;; "Creates and returns an array of instances of the specified class of -;; the specified dimension(s). Note that a class object is required. -;; Class objects can be obtained by using their name. -;; Class objects for the primitive types can be obtained using, e.g., Integer/TYPE." -;; ([#_Class type len] -;; ;; (. Array (newInstance type (int len))) -;; (throw "TODO: port make-array")) -;; ([#_Class type dim & more-dims] -;; ;; (let [dims (cons dim more-dims) -;; ;; ^"[I" dimarray (make-array (. Integer TYPE) (count dims))] -;; ;; (dotimes [i (alength dimarray)] -;; ;; (aset-int dimarray i (nth dims i))) -;; ;; (. Array (newInstance type dimarray)))) -;; (throw "TODO: port make-array"))) -;; -;;(defn to-array-2d -;; "Returns a (potentially-ragged) 2-dimensional array of Objects -;; containing the contents of coll, which can be any Collection of any -;; Collection." -;; [#_java.util.Collection coll] -;; ;; (let [ret (make-array (. Class (forName "[Ljava.lang.Object;")) (. coll (size)))] -;; ;; (loop [i 0 xs (seq coll)] -;; ;; (when xs -;; ;; (aset ret i (to-array (first xs))) -;; ;; (recur (inc i) (next xs)))) -;; ;; ret) -;; (throw "TODO: port to-array-2d")) -;; -;;(defn create-struct -;; "Returns a structure basis object." -;; [& keys] -;; ;; (. clojure.lang.PersistentStructMap (createSlotMap keys)) -;; (throw "TODO: port create-struct")) -;; -;;(defmacro defstruct -;; "Same as (def name (create-struct keys...))" -;; [name & keys] -;; `(def ~name (create-struct ~@keys))) -;; -;;(defn struct-map -;; "Returns a new structmap instance with the keys of the -;; structure-basis. keyvals may contain all, some or none of the basis -;; keys - where values are not supplied they will default to nil. -;; keyvals can also contain keys not in the basis." -;; [s & inits] -;; ;; (. clojure.lang.PersistentStructMap (create s inits)) -;; (throw "TODO: port struct-map")) -;; -;;(defn struct -;; "Returns a new structmap instance with the keys of the -;; structure-basis. vals must be supplied for basis keys in order - -;; where values are not supplied they will default to nil." -;; [s & vals] -;; ;; (. clojure.lang.PersistentStructMap (construct s vals)) -;; (throw "TODO: port struct")) -;; -;;(defn accessor -;; "Returns a fn that, given an instance of a structmap with the basis, -;; returns the value at the key. The key must be in the basis. The -;; returned function should be (slightly) more efficient than using -;; get, but such use of accessors should be limited to known -;; performance-critical areas." -;; [s key] -;; ;; (. clojure.lang.PersistentStructMap (getAccessor s key)) -;; (throw "TODO: port accessor")) -;; -;;(defn load-reader -;; "Sequentially read and evaluate the set of forms contained in the -;; stream/file" -;; [rdr] -;; ;; (. clojure.lang.Compiler (load rdr)) -;; (throw "TODO: port load-reader")) -;; -;;(defn load-string -;; "Sequentially read and evaluate the set of forms contained in the -;; string" -;; [s] -;; ;; (let [rdr (-> (java.io.StringReader. s) -;; ;; (clojure.lang.LineNumberingPushbackReader.))] -;; ;; (load-reader rdr)) -;; (throw "TODO: port load-string")) -;; -;;(defn- -;; filter-key [keyfn pred amap] -;; (loop [ret {} es (seq amap)] -;; (if es -;; (if (pred (keyfn (first es))) -;; (recur (assoc ret (key (first es)) (val (first es))) (next es)) -;; (recur ret (next es))) -;; ret))) -;; -;;(defn all-ns -;; "Returns a sequence of all namespaces." -;; [] -;; ;; (clojure.lang.Namespace/all) -;; (throw "TODO: port all-ns")) -;; -;;(defn ns-unmap -;; "Removes the mappings for the symbol from the namespace." -;; [ns sym] -;; (cpp/clojure.core_native.ns_unmap (the-ns ns) sym)) -;; -;;(defn ns-imports -;; "Returns a map of the import mappings for the namespace." -;; [ns] -;; ;; (filter-key val (partial instance? Class) (ns-map ns)) -;; (throw "TODO: port ns-imports")) -;; -;;(defn ns-interns -;; "Returns a map of the intern mappings for the namespace." -;; [ns] -;; (let [ns (the-ns ns)] -;; (filter-key val (fn [v] (and (var? v) -;; (= (ns-name ns) (-> v symbol namespace symbol)))) -;; (ns-map ns)))) -;; -;;(defn ns-refers -;; "Returns a map of the refer mappings for the namespace." -;; [ns] -;; ;; (let [ns (the-ns ns)] -;; ;; (filter-key val (fn [^clojure.lang.Var v] (and (instance? clojure.lang.Var v) -;; ;; (not= ns (.ns v)))) -;; ;; (ns-map ns))) -;; (throw "TODO: port ns-refers")) -;; -;;(defn ns-aliases -;; "Returns a map of the aliases for the namespace." -;; [ns] -;; ;; (.getAliases (the-ns ns)) -;; (throw "TODO: port ns-aliases")) -;; -;;(defn ns-unalias -;; "Removes the alias for the symbol from the namespace." -;; [ns sym] -;; (cpp/clojure.core_native.ns_unalias (the-ns ns) sym)) -;; -;;(defn var-set -;; "Sets the value in the var object to val. The var must be -;; thread-locally bound." -;; [#_clojure.lang.Var x val] -;; ;; (. x (set val)) -;; (throw "TODO: port var-set")) -;; -;;(defmacro with-local-vars -;; "varbinding=> symbol init-expr -;; -;; Executes the exprs in a context in which the symbols are bound to -;; vars with per-thread bindings to the init-exprs. The symbols refer -;; to the var objects themselves, and must be accessed with var-get and -;; var-set" -;; [name-vals-vec & body] -;; (assert-macro-args -;; (vector? name-vals-vec) "a vector for its binding" -;; (even? (count name-vals-vec)) "an even number of forms in binding vector") -;; ;; `(let [~@(interleave (take-nth 2 name-vals-vec) -;; ;; (repeat '(.. clojure.lang.Var create setDynamic)))] -;; ;; (. clojure.lang.Var (pushThreadBindings (hash-map ~@name-vals-vec))) -;; ;; (try -;; ;; (do ~@body) -;; ;; (finally (. clojure.lang.Var (popThreadBindings))))) -;; (throw "TODO: port with-local-vars")) -;; -;;(defn array-map -;; "Constructs an array-map. If any keys are equal, they are handled as -;; if by repeated uses of assoc." -;; ([] -;; ;; (. clojure.lang.PersistentArrayMap EMPTY) -;; (throw "TODO: port array-map")) -;; ([& keyvals] -;; ;; (let [ary (to-array keyvals)] -;; ;; (if (odd? (alength ary)) -;; ;; (throw (IllegalArgumentException. (str "No value supplied for key: " (last keyvals)))) -;; ;; (clojure.lang.PersistentArrayMap/createAsIfByAssoc ary))) -;; (throw "TODO: port array-map"))) -;; -;;(defn seq-to-map-for-destructuring -;; "Builds a map from a seq as described in -;; https://clojure.org/reference/special_forms#keyword-arguments" -;; [s] -;; ;; (if (next s) -;; ;; (clojure.lang.PersistentArrayMap/createAsIfByAssoc (to-array s)) -;; ;; (if (seq s) (first s) clojure.lang.PersistentArrayMap/EMPTY)) -;; (throw "TODO: port seq-to-map-for-destructuring")) -;; -;;(defmacro lazy-cat -;; "Expands to code which yields a lazy sequence of the concatenation -;; of the supplied colls. Each coll expr is not evaluated until it is -;; needed. -;; -;; (lazy-cat xs ys zs) === (concat (lazy-seq xs) (lazy-seq ys) (lazy-seq zs))" -;; [& colls] -;; `(concat ~@(map #(list `lazy-seq %) colls))) -;; -;;(defmacro with-out-str -;; "Evaluates exprs in a context in which *out* is bound to a fresh -;; StringWriter. Returns the string created by any nested printing -;; calls." -;; [& body] -;; ;; `(let [s# (new java.io.StringWriter)] -;; ;; (binding [*out* s#] -;; ;; ~@body -;; ;; (str s#))) -;; (throw "TODO: port with-out-str")) -;; -;;(defmacro with-in-str -;; "Evaluates body in a context in which *in* is bound to a fresh -;; StringReader initialized with the string s." -;; [s & body] -;; `(with-open [s# (-> (java.io.StringReader. ~s) clojure.lang.LineNumberingPushbackReader.)] -;; (binding [*in* s#] -;; ~@body))) -;; -;;(defn prn-str -;; "prn to a string, returning it" -;; [& xs] -;; ;; (with-out-str -;; ;; (apply prn xs)) -;; (throw "TODO: port prn-str")) -;; -;; -;;(defn print-str -;; "print to a string, returning it" -;; [& xs] -;; ;; (with-out-str -;; ;; (apply print xs)) -;; (throw "TODO: port print-str")) -;; -;;(defn println-str -;; "println to a string, returning it" -;; [& xs] -;; ;; (with-out-str -;; ;; (apply println xs)) -;; (throw "TODO: port println-str")) -;; -;;(defn ^:private elide-top-frames -;; [#_Throwable ex class-name] -;; ;; (let [tr (.getStackTrace ex)] -;; ;; (doto ex -;; ;; (.setStackTrace -;; ;; (when tr -;; ;; (into-array StackTraceElement -;; ;; (drop-while #(= class-name (.getClassName ^StackTraceElement %1)) tr)))))) -;; (throw "TODO: port elide-top-frames")) -;; -;;(defn test -;; "test [v] finds fn at key :test in var metadata and calls it, -;; presuming failure will throw exception" -;; [v] -;; (let [f (:test (meta v))] -;; (if f -;; (do (f) :ok) -;; :no-test))) -;; -;;(defn re-pattern -;; "Returns an instance of java.util.regex.Pattern, for use, e.g. in -;; re-matcher." -;; [s] -;; (cpp/jank.runtime.re_pattern s)) -;; -;;(defn re-matcher -;; "Returns an instance of java.util.regex.Matcher, for use, e.g. in -;; re-find." -;; [re s] -;; (cpp/jank.runtime.re_matcher re s)) -;; -;;(defn re-groups -;; "Returns the groups from the most recent match/find. If there are no -;; nested groups, returns a string of the entire match. If there are -;; nested groups, returns a vector of the groups, the first element -;; being the entire match." -;; [m] -;; (cpp/jank.runtime.re_groups m)) -;; -;;(defn re-matches -;; "Returns the match, if any, of string to pattern, using -;; java.util.regex.Matcher.matches(). Uses re-groups to return the -;; groups." -;; [re s] -;; (cpp/jank.runtime.re_matches re s)) -;; -;;(defn re-find -;; "Returns the next regex match, if any, of string to pattern, using -;; java.util.regex.Matcher.find(). Uses re-groups to return the -;; groups." -;; ([m] -;; (cpp/jank.runtime.re_find m)) -;; ([re s] -;; (let [m (re-matcher re s)] -;; (re-find m)))) -;; -;;(defn re-seq -;; "Returns a lazy sequence of successive matches of pattern in string, -;; using java.util.regex.Matcher.find(), each such match processed with -;; re-groups." -;; [re s] -;; (let [m (cpp/jank.runtime.re_matcher re s)] -;; ((fn step [] -;; (when (re-find m) -;; (cons (re-groups m) (lazy-seq (step)))))))) -;; -;;(defn rand-int -;; "Returns a random integer between 0 (inclusive) and n (exclusive)." -;; [n] (int (rand n))) -;; -;;(defn file-seq -;; "A tree seq on java.io.Files" -;; [dir] -;; ;; (tree-seq -;; ;; (fn [^java.io.File f] (. f (isDirectory))) -;; ;; (fn [^java.io.File d] (seq (. d (listFiles)))) -;; ;; dir) -;; (throw "TODO: port file-seq")) -;; -;;(defn xml-seq -;; "A tree seq on the xml elements as per xml/parse" -;; [root] -;; (tree-seq -;; (complement string?) -;; (comp seq :content) -;; root)) -;; -;;(defn special-symbol? -;; "Returns true if s names a special form" -;; [s] -;; ;; (contains? (. clojure.lang.Compiler specials) s) -;; (throw "TODO: port special-symbol?")) -;; -;;(defn max-key -;; "Returns the x for which (k x), a number, is greatest. -;; -;; If there are multiple such xs, the last one is returned." -;; ([k x] x) -;; ([k x y] (if (> (k x) (k y)) x y)) -;; ([k x y & more] -;; (let [kx (k x) ky (k y) -;; [v kv] (if (> kx ky) [x kx] [y ky])] -;; (loop [v v kv kv more more] -;; (if more -;; (let [w (first more) -;; kw (k w)] -;; (if (>= kw kv) -;; (recur w kw (next more)) -;; (recur v kv (next more)))) -;; v))))) -;; -;;(defn min-key -;; "Returns the x for which (k x), a number, is least. -;; -;; If there are multiple such xs, the last one is returned." -;; ([k x] x) -;; ([k x y] (if (< (k x) (k y)) x y)) -;; ([k x y & more] -;; (let [kx (k x) ky (k y) -;; [v kv] (if (< kx ky) [x kx] [y ky])] -;; (loop [v v kv kv more more] -;; (if more -;; (let [w (first more) -;; kw (k w)] -;; (if (<= kw kv) -;; (recur w kw (next more)) -;; (recur v kv (next more)))) -;; v))))) -;; -;;(defn replace -;; "Given a map of replacement pairs and a vector/collection, returns a -;; vector/seq with any elements = a key in smap replaced with the -;; corresponding val in smap. Returns a transducer when no collection -;; is provided." -;; ([smap] -;; (map #(if-let [e (find smap %)] (val e) %))) -;; ([smap coll] -;; (if (vector? coll) -;; (reduce (fn [v i] -;; (if-let [e (find smap (nth v i))] -;; (assoc v i (val e)) -;; v)) -;; coll (range (count coll))) -;; (map #(if-let [e (find smap %)] (val e) %) coll)))) -;; -;;(defmacro dosync -;; "Runs the exprs (in an implicit do) in a transaction that encompasses -;; exprs and any nested calls. Starts a transaction if none is already -;; running on this thread. Any uncaught exception will abort the -;; transaction and flow out of dosync. The exprs may be run more than -;; once, but any effects on Refs will be atomic." -;; [& exprs] -;; `(sync nil ~@exprs)) -;; -;;(defmacro with-precision -;; "Sets the precision and rounding mode to be used for BigDecimal operations. -;; -;; Usage: (with-precision 10 (/ 1M 3)) -;; or: (with-precision 10 :rounding HALF_DOWN (/ 1M 3)) -;; -;; The rounding mode is one of CEILING, FLOOR, HALF_UP, HALF_DOWN, -;; HALF_EVEN, UP, DOWN and UNNECESSARY; it defaults to HALF_UP." -;; [precision & exprs] -;; ;; (let [[body rm] (if (= (first exprs) :rounding) -;; ;; [(next (next exprs)) -;; ;; `((. java.math.RoundingMode ~(second exprs)))] -;; ;; [exprs nil])] -;; ;; `(binding [*math-context* (java.math.MathContext. ~precision ~@rm)] -;; ;; ~@body)) -;; (throw "TODO: port with-precision")) -;; -;;(defn- mk-bound-fn -;; [#_clojure.lang.Sorted sc test key] -;; ;; (fn [e] -;; ;; (test (.. sc comparator (compare (. sc entryKey e) key)) 0)) -;; (throw "TODO: port mk-bound-fn")) -;; -;;(defn subseq -;; "sc must be a sorted collection, test(s) one of <, <=, > or -;; >=. Returns a seq of those entries with keys ek for -;; which (test (.. sc comparator (compare ek key)) 0) is true" -;; ([#_clojure.lang.Sorted sc test key] -;; ;; (let [include (mk-bound-fn sc test key)] -;; ;; (if (#{> >=} test) -;; ;; (when-let [[e :as s] (. sc seqFrom key true)] -;; ;; (if (include e) s (next s))) -;; ;; (take-while include (. sc seq true)))) -;; (throw "TODO: port subseq")) -;; ([#_clojure.lang.Sorted sc start-test start-key end-test end-key] -;; ;; (when-let [[e :as s] (. sc seqFrom start-key true)] -;; ;; (take-while (mk-bound-fn sc end-test end-key) -;; ;; (if ((mk-bound-fn sc start-test start-key) e) s (next s)))) -;; (throw "TODO: port subseq"))) -;; -;;(defn rsubseq -;; "sc must be a sorted collection, test(s) one of <, <=, > or -;; >=. Returns a reverse seq of those entries with keys ek for -;; which (test (.. sc comparator (compare ek key)) 0) is true" -;; ([#_clojure.lang.Sorted sc test key] -;; ;; (let [include (mk-bound-fn sc test key)] -;; ;; (if (#{< <=} test) -;; ;; (when-let [[e :as s] (. sc seqFrom key false)] -;; ;; (if (include e) s (next s))) -;; ;; (take-while include (. sc seq false)))) -;; (throw "TODO: port rsubseq")) -;; ([#_clojure.lang.Sorted sc start-test start-key end-test end-key] -;; ;; (when-let [[e :as s] (. sc seqFrom end-key false)] -;; ;; (take-while (mk-bound-fn sc start-test start-key) -;; ;; (if ((mk-bound-fn sc end-test end-key) e) s (next s)))) -;; (throw "TODO: port rsubseq"))) -;; -;;(defn add-classpath -;; "DEPRECATED -;; -;; Adds the url (String or URL object) to the classpath per -;; URLClassLoader.addURL" -;; [url] -;; (println "WARNING: add-classpath is deprecated") -;; ;; (clojure.lang.RT/addURL url) -;; (throw "TODO: port add-classpath")) -;; -;;(defn mix-collection-hash -;; "Mix final collection hash for ordered or unordered collections. -;; hash-basis is the combined collection hash, count is the number -;; of elements included in the basis. Note this is the hash code -;; consistent with =, different from .hashCode. -;; See http://clojure.org/data_structures#hash for full algorithms." -;; #_long -;; [#_long hash-basis #_long count] -;; ;; (clojure.lang.Murmur3/mixCollHash hash-basis count) -;; (throw "TODO: port mix-collection-hash")) -;; -;;(defn hash-ordered-coll -;; "Returns the hash code, consistent with =, for an external ordered -;; collection implementing Iterable. -;; See http://clojure.org/data_structures#hash for full algorithms." -;; #_long -;; [coll] -;; ;; (clojure.lang.Murmur3/hashOrdered coll) -;; (throw "TODO: port hash-ordered-coll")) -;; -;;(defn hash-unordered-coll -;; "Returns the hash code, consistent with =, for an external unordered -;; collection implementing Iterable. For maps, the iterator should -;; return map entries whose hash is computed as -;; (hash-ordered-coll [k v]). -;; See http://clojure.org/data_structures#hash for full algorithms." -;; [coll] -;; (cpp/clojure.core_native.hash_unordered coll)) -;; -;;(defmacro definline -;; "Experimental - like defmacro, except defines a named function whose -;; body is the expansion, calls to which may be expanded inline as if -;; it were a macro. Cannot be used with variadic (&) args." -;; [name & decl] -;; (let [[pre-args [args expr]] (split-with (comp not vector?) decl)] -;; `(do -;; (defn ~name ~@pre-args ~args ~(apply (eval (list `fn args expr)) args)) -;; (alter-meta! (var ~name) assoc :inline (fn ~name ~args ~expr)) -;; (var ~name)))) -;; -;;(defmacro amap -;; "Maps an expression across an array a, using an index named idx, and -;; return value named ret, initialized to a clone of a, then setting -;; each element of ret to the evaluation of expr, returning the new -;; array ret." -;; [a idx ret expr] -;; `(let [a# ~a l# (alength a#) -;; ~ret (aclone a#)] -;; (loop [~idx 0] -;; (if (< ~idx l#) -;; (do -;; (aset ~ret ~idx ~expr) -;; (recur (unchecked-inc ~idx))) -;; ~ret)))) -;; -;;(defmacro areduce -;; "Reduces an expression across an array a, using an index named idx, -;; and return value named ret, initialized to init, setting ret to the -;; evaluation of expr at each step, returning ret." -;; [a idx ret init expr] -;; `(let [a# ~a l# (alength a#)] -;; (loop [~idx 0 ~ret ~init] -;; (if (< ~idx l#) -;; (recur (unchecked-inc-int ~idx) ~expr) -;; ~ret)))) -;; -;;(defn float-array -;; "Creates an array of floats" -;; ([size-or-seq] -;; ;; (. clojure.lang.Numbers float_array size-or-seq) -;; (throw "TODO: port float-array")) -;; ([size init-val-or-seq] -;; ;; (. clojure.lang.Numbers float_array size init-val-or-seq) -;; (throw "TODO: port float-array") )) -;; -;;(defn boolean-array -;; "Creates an array of booleans" -;; ([size-or-seq] -;; ;; (. clojure.lang.Numbers boolean_array size-or-seq) -;; (throw "TODO: port boolean-array")) -;; ([size init-val-or-seq] -;; ;; (. clojure.lang.Numbers boolean_array size init-val-or-seq) -;; (throw "TODO: port boolean-array"))) -;; -;;(defn byte-array -;; "Creates an array of bytes" -;; ([size-or-seq] -;; ;; (. clojure.lang.Numbers byte_array size-or-seq) -;; (throw "TODO: port byte-array")) -;; ([size init-val-or-seq] -;; ;; (. clojure.lang.Numbers byte_array size init-val-or-seq) -;; (throw "TODO: port byte-array"))) -;; -;;(defn char-array -;; "Creates an array of chars" -;; ([size-or-seq] -;; ;; (. clojure.lang.Numbers char_array size-or-seq) -;; (throw "TODO: port char-array")) -;; ([size init-val-or-seq] -;; ;; (. clojure.lang.Numbers char_array size init-val-or-seq) -;; (throw "TODO: port char-array"))) -;; -;;(defn short-array -;; "Creates an array of shorts" -;; ([size-or-seq] -;; ;; (. clojure.lang.Numbers short_array size-or-seq) -;; (throw "TODO: port short-array")) -;; ([size init-val-or-seq] -;; ;; (. clojure.lang.Numbers short_array size init-val-or-seq) -;; (throw "TODO: port short-array"))) -;; -;;(defn double-array -;; "Creates an array of doubles" -;; ([size-or-seq] -;; ;; (. clojure.lang.Numbers double_array size-or-seq) -;; (throw "TODO: port double-array")) -;; ([size init-val-or-seq] -;; ;; (. clojure.lang.Numbers double_array size init-val-or-seq) -;; (throw "TODO: port double-array"))) -;; -;;(defn object-array -;; "Creates an array of objects" -;; ([size-or-seq] -;; ;; (. clojure.lang.RT object_array size-or-seq) -;; (throw "TODO: port object-array"))) -;; -;;(defn int-array -;; "Creates an array of ints" -;; ([size-or-seq] -;; ;; (. clojure.lang.Numbers int_array size-or-seq) -;; (throw "TODO: port int-array")) -;; ([size init-val-or-seq] -;; ;; (. clojure.lang.Numbers int_array size init-val-or-seq) -;; (throw "TODO: port int-array"))) -;; -;;(defn long-array -;; "Creates an array of longs" -;; ([size-or-seq] -;; ;; (. clojure.lang.Numbers long_array size-or-seq) -;; (throw "TODO: port long-array")) -;; ([size init-val-or-seq] -;; ;; (. clojure.lang.Numbers long_array size init-val-or-seq) -;; (throw "TODO: port long-array"))) -;; -;;;; definline doesn't work without eval -;; -;;;; (definline booleans -;;;; "Casts to boolean[]" -;;;; [xs] -;;;; ;; `(. clojure.lang.Numbers booleans ~xs) -;;;; (throw "TODO: port")) -;; -;;;; (definline bytes -;;;; "Casts to bytes[]" -;;;; [xs] -;;;; ;; `(. clojure.lang.Numbers bytes ~xs) -;;;; (throw "TODO: port")) -;; -;;;; (definline chars -;;;; "Casts to chars[]" -;;;; [xs] -;;;; ;; `(. clojure.lang.Numbers chars ~xs) -;;;; (throw "TODO: port")) -;; -;;;; (definline shorts -;;;; "Casts to shorts[]" -;;;; [xs] -;;;; ;; `(. clojure.lang.Numbers shorts ~xs) -;;;; (throw "TODO: port")) -;; -;;;; (definline floats -;;;; "Casts to float[]" -;;;; [xs] -;;;; ;; `(. clojure.lang.Numbers floats ~xs) -;;;; (throw "TODO: port")) -;; -;;;; (definline ints -;;;; "Casts to int[]" -;;;; [xs] -;;;; ;; `(. clojure.lang.Numbers ints ~xs) -;;;; (throw "TODO: port")) -;; -;;;; (definline doubles -;;;; "Casts to double[]" -;;;; [xs] -;;;; ;; `(. clojure.lang.Numbers doubles ~xs) -;;;; (throw "TODO: port")) -;; -;;;; (definline longs -;;;; "Casts to long[]" -;;;; [xs] -;;;; ;; `(. clojure.lang.Numbers longs ~xs) -;;;; (throw "TODO: port")) -;; -;;(defn bytes? -;; "Return true if x is a byte array" -;; [x] -;; ;; (if (nil? x) -;; ;; false -;; ;; (-> x class .getComponentType (= Byte/TYPE))) -;; (throw "TODO: port bytes?")) -;; -;;(defn seque -;; "Creates a queued seq on another (presumably lazy) seq s. The queued -;; seq will produce a concrete seq in the background, and can get up to -;; n items ahead of the consumer. n-or-q can be an integer n buffer -;; size, or an instance of java.util.concurrent BlockingQueue. Note -;; that reading from a seque can block if the reader gets ahead of the -;; producer." -;; ([s] (seque 100 s)) -;; ([n-or-q s] -;; ;; (let [^BlockingQueue q (if (instance? BlockingQueue n-or-q) -;; ;; n-or-q -;; ;; (LinkedBlockingQueue. (int n-or-q))) -;; ;; NIL (Object.) ;nil sentinel since LBQ doesn't support nils -;; ;; agt (agent (lazy-seq s)) ; never start with nil; that signifies we've already put eos -;; ;; log-error (fn [q e] -;; ;; (if (.offer q q) -;; ;; (throw e) -;; ;; e)) -;; ;; fill (fn [s] -;; ;; (when s -;; ;; (if (instance? Exception s) ; we failed to .offer an error earlier -;; ;; (log-error q s) -;; ;; (try -;; ;; (loop [[x & xs :as s] (seq s)] -;; ;; (if s -;; ;; (if (.offer q (if (nil? x) NIL x)) -;; ;; (recur xs) -;; ;; s) -;; ;; (when-not (.offer q q) ; q itself is eos sentinel -;; ;; ()))) ; empty seq, not nil, so we know to put eos next time -;; ;; (catch Exception e -;; ;; (log-error q e)))))) -;; ;; drain (fn drain [] -;; ;; (lazy-seq -;; ;; (let [x (.take q)] -;; ;; (if (identical? x q) ;q itself is eos sentinel -;; ;; (do @agt nil) ;touch agent just to propagate errors -;; ;; (do -;; ;; (send-off agt fill) -;; ;; (release-pending-sends) -;; ;; (cons (if (identical? x NIL) nil x) (drain)))))))] -;; ;; (send-off agt fill) -;; ;; (drain)) -;; (throw "TODO: port seque"))) -;; -;;(defn class? -;; "Returns true if x is an instance of Class" -;; [x] -;; ;; (instance? Class x) -;; (throw "TODO: port class?")) -;; -;;(defn- is-annotation? [c] -;; ;; (and (class? c) -;; ;; (.isAssignableFrom java.lang.annotation.Annotation c)) -;; (throw "TODO: port is-annotation?")) -;; -;;(defn- is-runtime-annotation? [#_Class c] -;; ;; (boolean -;; ;; (and (is-annotation? c) -;; ;; (when-let [^java.lang.annotation.Retention r -;; ;; (.getAnnotation c java.lang.annotation.Retention)] -;; ;; (= (.value r) java.lang.annotation.RetentionPolicy/RUNTIME)))) -;; (throw "TODO: port is-runtime-annotation?")) -;; -;;(defn- descriptor [#_Class c] -;; ;; (clojure.asm.Type/getDescriptor c) -;; (throw "TODO: port descriptor")) -;; -;;(declare process-annotation) -;; -;;(defn- add-annotation [#_clojure.asm.AnnotationVisitor av name v] -;; ;; (cond -;; ;; (vector? v) (let [avec (.visitArray av name)] -;; ;; (doseq [vval v] -;; ;; (add-annotation avec "value" vval)) -;; ;; (.visitEnd avec)) -;; ;; (symbol? v) (let [ev (eval v)] -;; ;; (cond -;; ;; (instance? java.lang.Enum ev) -;; ;; (.visitEnum av name (descriptor (class ev)) (str ev)) -;; ;; (class? ev) (.visit av name (clojure.asm.Type/getType ev)) -;; ;; :else (throw (IllegalArgumentException. -;; ;; (str "Unsupported annotation value: " v " of class " (class ev)))))) -;; ;; (seq? v) (let [[nested nv] v -;; ;; c (resolve nested) -;; ;; nav (.visitAnnotation av name (descriptor c))] -;; ;; (process-annotation nav nv) -;; ;; (.visitEnd nav)) -;; ;; :else (.visit av name v)) -;; (throw "TODO: port add-annotation")) -;; -;;(defn- process-annotation [av v] -;; (if (map? v) -;; (doseq [[k v] v] -;; (add-annotation av (name k) v)) -;; (add-annotation av "value" v))) -;; -;;(defn- add-annotations -;; ([visitor m] (add-annotations visitor m nil)) -;; ([visitor m i] -;; ;; (doseq [[k v] m] -;; ;; (when (symbol? k) -;; ;; (when-let [c (resolve k)] -;; ;; (when (is-annotation? c) -;; ;; ;this is known duck/reflective as no common base of ASM Visitors -;; ;; (let [av (if i -;; ;; (.visitParameterAnnotation visitor i (descriptor c) -;; ;; (is-runtime-annotation? c)) -;; ;; (.visitAnnotation visitor (descriptor c) -;; ;; (is-runtime-annotation? c)))] -;; ;; (process-annotation av v) -;; ;; (.visitEnd av)))))) -;; (throw "TODO: port add-annotations"))) -;; -;;(defn bases -;; "Returns the immediate superclass and direct interfaces of c, if any" -;; [#_Class c] -;; ;; (when c -;; ;; (let [i (seq (.getInterfaces c)) -;; ;; s (.getSuperclass c)] -;; ;; (if s (cons s i) i))) -;; (throw "TODO: port bases")) -;; -;;(defn supers -;; "Returns the immediate and indirect superclasses and interfaces of c, if any" -;; [#_Class class] -;; (loop [ret (set (bases class)) cs ret] -;; (if (seq cs) -;; (let [c (first cs) bs (bases c)] -;; (recur (into ret bs) (into (disj cs c) bs))) -;; (not-empty ret)))) -;; -;; -;;(defn resultset-seq -;; "Creates and returns a lazy sequence of structmaps corresponding to -;; the rows in the java.sql.ResultSet rs" -;; [#_java.sql.ResultSet rs] -;; ;; (let [rsmeta (. rs (getMetaData)) -;; ;; idxs (range 1 (inc (. rsmeta (getColumnCount)))) -;; ;; keys (map (comp keyword #(.toLowerCase ^String %)) -;; ;; (map (fn [i] (. rsmeta (getColumnLabel i))) idxs)) -;; ;; check-keys -;; ;; (or (apply distinct? keys) -;; ;; (throw (Exception. "ResultSet must have unique column labels"))) -;; ;; row-struct (apply create-struct keys) -;; ;; row-values (fn [] (map (fn [^Integer i] (. rs (getObject i))) idxs)) -;; ;; rows (fn thisfn [] -;; ;; (when (. rs (next)) -;; ;; (cons (apply struct row-struct (row-values)) (lazy-seq (thisfn)))))] -;; ;; (rows)) -;; (throw "TODO: port resultset-seq")) -;; -;;(defn iterator-seq -;; "Returns a seq on a java.util.Iterator. Note that most collections -;; providing iterators implement Iterable and thus support seq directly. -;; Seqs cache values, thus iterator-seq should not be used on any -;; iterator that repeatedly returns the same mutable object." -;; [iter] -;; ;; (clojure.lang.RT/chunkIteratorSeq iter) -;; (throw "TODO: port iterator-seq")) -;; -;;(defn enumeration-seq -;; "Returns a seq on a java.util.Enumeration" -;; [e] -;; ;; (clojure.lang.EnumerationSeq/create e) -;; (throw "TODO: port enumeration-seq")) -;; -;;(defn format -;; "Formats a string using java.lang.String.format, see java.util.Formatter for format -;; string syntax" -;; #_String [fmt & args] -;; ;; (String/format fmt (to-array args)) -;; (throw "TODO: port format")) -;; -;;(defn printf -;; "Prints formatted output, as per format" -;; [fmt & args] -;; (print (apply format fmt args))) -;; -;;(declare gen-class) -;; -;;(defmacro with-loading-context [& body] -;; ;; `((fn loading# [] -;; ;; (. clojure.lang.Var (pushThreadBindings {clojure.lang.Compiler/LOADER -;; ;; (.getClassLoader (.getClass ^Object loading#))})) -;; ;; (try -;; ;; (do ~@body) -;; ;; (finally -;; ;; (. clojure.lang.Var (popThreadBindings)))))) -;; (throw "TODO: port with-loading-context")) -;; -;;(defonce -;; ^{:private true -;; :dynamic true -;; :doc "True while a verbose load is pending"} -;; *loading-verbosely* false) -;; -;;(defn- root-directory -;; "Returns the root resource path for a lib" -;; [lib] -;; ;; (let [d (root-resource lib)] -;; ;; (subs d 0 (.lastIndexOf d "/"))) -;; (throw "TODO: port root-resource")) -;; -;;(defn- serialized-require -;; "Like 'require', but serializes loading. -;; Interim function preferred over 'require' for known asynchronous loads. -;; Future changes may make these equivalent." -;; [& args] -;; ;; (locking clojure.lang.RT/REQUIRE_LOCK -;; ;; (apply require args)) -;; (throw "TODO: port serialized-require")) -;; -;;(defn requiring-resolve -;; "Resolves namespace-qualified sym per 'resolve'. If initial resolve -;;fails, attempts to require sym's namespace and retries." -;; [sym] -;; ;; (if (qualified-symbol? sym) -;; ;; (or (resolve sym) -;; ;; (do (-> sym namespace symbol serialized-require) -;; ;; (resolve sym))) -;; ;; (throw (IllegalArgumentException. (str "Not a qualified symbol: " sym)))) -;; (throw "TODO: port requiring-resolve")) -;; -;;(defn loaded-libs -;; "Returns a sorted set of symbols naming the currently loaded libs" -;; [] @*loaded-libs*) -;; -;;(defn sorted? -;; "Returns true if coll implements Sorted" -;; [coll] -;; (cpp/jank.runtime.is_sorted coll)) -;; -;;(defn counted? -;; "Returns true if coll implements count in constant time" -;; [coll] -;; (cpp/jank.runtime.is_counted coll)) -;; -;;(defn reversible? -;; "Returns true if coll implements Reversible" -;; [coll] -;; ;; (instance? clojure.lang.Reversible coll) -;; (throw "TODO: port reversible?")) -;; -;;(defn indexed? -;; "Return true if coll implements Indexed, indicating efficient lookup by index" -;; [coll] -;; ;; (instance? clojure.lang.Indexed coll) -;; (throw "TODO: port indexed?")) -;; -;;(def ^:dynamic -;; ^{:doc "bound in a repl thread to the most recent value printed"} -;; *1) -;; -;;(def ^:dynamic -;; ^{:doc "bound in a repl thread to the second most recent value printed"} -;; *2) -;; -;;(def ^:dynamic -;; ^{:doc "bound in a repl thread to the third most recent value printed"} -;; *3) -;; -;;(def ^:dynamic -;; ^{:doc "bound in a repl thread to the most recent exception caught by the repl"} -;; *e) -;; -;;(def ^:dynamic -;; ^{:doc "Bound to true in a repl thread"} -;; *repl* false) -;; -;;(defn trampoline -;; "trampoline can be used to convert algorithms requiring mutual -;; recursion without stack consumption. Calls f with supplied args, if -;; any. If f returns a fn, calls that fn with no arguments, and -;; continues to repeat, until the return value is not a fn, then -;; returns that non-fn value. Note that if you want to return a fn as a -;; final value, you must wrap it in some data structure and unpack it -;; after trampoline returns." -;; ([f] -;; (let [ret (f)] -;; (if (fn? ret) -;; (recur ret) -;; ret))) -;; ([f & args] -;; (trampoline #(apply f args)))) -;; -;;(defmacro while -;; "Repeatedly executes body while test expression is true. Presumes -;; some side-effect will cause test to become false/nil. Returns nil" -;; [test & body] -;; `(loop [] -;; (when ~test -;; ~@body -;; (recur)))) -;; -;;(defn memoize -;; "Returns a memoized version of a referentially transparent function. The -;; memoized version of the function keeps a cache of the mapping from arguments -;; to results and, when calls with the same arguments are repeated often, has -;; higher performance at the expense of higher memory use." -;; [f] -;; (let [mem (atom {})] -;; (fn [& args] -;; (if-let [e (find @mem args)] -;; (val e) -;; (let [ret (apply f args)] -;; (swap! mem assoc args ret) -;; ret))))) -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; var documentation ;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;(defmacro add-doc-and-meta {:private true} [name docstring meta] -;; `(alter-meta! (var ~name) merge (assoc ~meta :doc ~docstring))) -;; -;;;; (add-doc-and-meta *file* -;;;; "The path of the file being evaluated, as a String. -;; -;;;; When there is no file, e.g. in the REPL, the value is not defined." -;;;; {}) -;; -;;;; (add-doc-and-meta *command-line-args* -;;;; "A sequence of the supplied command line arguments, or nil if -;;;; none were supplied" -;;;; {}) -;; -;;;; (add-doc-and-meta *warn-on-reflection* -;;;; "When set to true, the compiler will emit warnings when reflection is -;;;; needed to resolve Java method calls or field accesses. -;; -;;;; Defaults to false." -;;;; {}) -;; -;;;; (add-doc-and-meta *compile-path* -;;;; "Specifies the directory where 'compile' will write out .class -;;;; files. This directory must be in the classpath for 'compile' to -;;;; work. -;; -;;;; Defaults to \"classes\"" -;;;; {}) -;; -;;;; (add-doc-and-meta *compile-files* -;;;; "Set to true when compiling files, false otherwise." -;;;; {}) -;; -;;;; (add-doc-and-meta *unchecked-math* -;;;; "While bound to true, compilations of +, -, *, inc, dec and the -;;;; coercions will be done without overflow checks. While bound -;;;; to :warn-on-boxed, same behavior as true, and a warning is emitted -;;;; when compilation uses boxed math. Default: false." -;;;; {}) -;; -;;;; (add-doc-and-meta *compiler-options* -;;;; "A map of keys to options. -;;;; Note, when binding dynamically make sure to merge with previous value. -;;;; Supported options: -;;;; :elide-meta - a collection of metadata keys to elide during compilation. -;;;; :disable-locals-clearing - set to true to disable clearing, useful for using a debugger -;;;; :direct-linking - set to true to use direct static invocation of functions, rather than vars -;;;; Note that call sites compiled with direct linking will not be affected by var redefinition. -;;;; Use ^:redef (or ^:dynamic) on a var to prevent direct linking and allow redefinition. -;;;; See https://clojure.org/reference/compilation for more information." -;;;; {}) -;; -;;;; (add-doc-and-meta *in* -;;;; "A java.io.Reader object representing standard input for read operations. -;; -;;;; Defaults to System/in, wrapped in a LineNumberingPushbackReader" -;;;; {}) -;; -;;;; (add-doc-and-meta *err* -;;;; "A java.io.Writer object representing standard error for print operations. -;; -;;;; Defaults to System/err, wrapped in a PrintWriter" -;;;; {}) -;; -;;;; (add-doc-and-meta *flush-on-newline* -;;;; "When set to true, output will be flushed whenever a newline is printed. -;; -;;;; Defaults to true." -;;;; {}) -;; -;;;; (add-doc-and-meta *print-meta* -;;;; "If set to logical true, when printing an object, its metadata will also -;;;; be printed in a form that can be read back by the reader. -;; -;;;; Defaults to false." -;;;; {}) -;; -;;;; (add-doc-and-meta *print-dup* -;;;; "When set to logical true, objects will be printed in a way that preserves -;;;; their type when read in later. -;; -;;;; Defaults to false." -;;;; {}) -;; -;;;; (add-doc-and-meta *print-readably* -;;;; "When set to logical false, strings and characters will be printed with -;;;; non-alphanumeric characters converted to the appropriate escape sequences. -;; -;;;; Defaults to true" -;;;; {}) -;; -;;;; (add-doc-and-meta *read-eval* -;;;; "Defaults to true (or value specified by system property, see below) -;;;; ***This setting implies that the full power of the reader is in play, -;;;; including syntax that can cause code to execute. It should never be -;;;; used with untrusted sources. See also: clojure.edn/read.*** -;; -;;;; When set to logical false in the thread-local binding, -;;;; the eval reader (#=) and record/type literal syntax are disabled in read/load. -;;;; Example (will fail): (binding [*read-eval* false] (read-string \"#=(* 2 21)\")) -;; -;;;; The default binding can be controlled by the system property -;;;; 'clojure.read.eval' System properties can be set on the command line -;;;; like this: -;; -;;;; java -Dclojure.read.eval=false ... -;; -;;;; The system property can also be set to 'unknown' via -;;;; -Dclojure.read.eval=unknown, in which case the default binding -;;;; is :unknown and all reads will fail in contexts where *read-eval* -;;;; has not been explicitly bound to either true or false. This setting -;;;; can be a useful diagnostic tool to ensure that all of your reads -;;;; occur in considered contexts. You can also accomplish this in a -;;;; particular scope by binding *read-eval* to :unknown -;;;; " -;;;; {}) -;; -;;;; (add-doc-and-meta *assert* -;;;; "When set to logical false, 'assert' will omit assertion checks in -;;;; compiled code. Defaults to true." -;;;; {}) -;; -;;(defn future? -;; "Returns true if x is a future" -;; [x] -;; ;; (instance? java.util.concurrent.Future x) -;; (throw "TODO: port future?")) -;; -;;(defn future-done? -;; "Returns true if future f is done" -;; [#_java.util.concurrent.Future f] -;; ;; (.isDone f) -;; (throw "TODO: port future-done?")) -;; -;;(defmacro letfn -;; "fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+) -;; -;; Takes a vector of function specs and a body, and generates a set of -;; bindings of functions to their names. All of the names are available -;; in all of the definitions of the functions, as well as the body." -;; {:forms '[(letfn [fnspecs*] exprs*)], -;; :special-form true} -;; [fnspecs & body] -;; `(letfn* ~(vec (interleave (map first fnspecs) -;; (map #(cons `fn %) fnspecs))) -;; ~@body)) -;; -;;(defn stream-reduce! -;; "Works like reduce but takes a java.util.stream.BaseStream as its source. -;; Honors 'reduced', is a terminal operation on the stream" -;; ([f #_java.util.stream.BaseStream s] -;; ;; (clojure.core.protocols/iterator-reduce! (.iterator s) f) -;; (throw "TODO: port stream-reduce!")) -;; ([f init #_java.util.stream.BaseStream s] -;; ;; (clojure.core.protocols/iterator-reduce! (.iterator s) f init) -;; (throw "TODO: port stream-reduce!"))) -;; -;;(defn stream-seq! -;; "Takes a java.util.stream.BaseStream instance s and returns a seq of its -;; contents. This is a terminal operation on the stream." -;; [#_java.util.stream.BaseStream stream] -;; ;; (iterator-seq (.iterator stream)) -;; (throw "TODO: port stream-seq!")) -;; -;;(defn stream-transduce! -;; "Works like transduce but takes a java.util.stream.BaseStream as its source. -;; This is a terminal operation on the stream." -;; ([xform f #_java.util.stream.BaseStream stream] -;; (stream-transduce! xform f (f) stream)) -;; ([xform f init #_java.util.stream.BaseStream stream] -;; (let [f (xform f) -;; ret (stream-reduce! f init stream)] -;; (f ret)))) -;; -;;(defn stream-into! -;; "Returns a new coll consisting of coll with all of the items of the -;; stream conjoined. This is a terminal operation on the stream." -;; ([to #_java.util.stream.BaseStream stream] -;; ;; (if (instance? clojure.lang.IEditableCollection to) -;; ;; (with-meta (persistent! (stream-reduce! conj! (transient to) stream)) (meta to)) -;; ;; (stream-reduce! conj to stream)) -;; (throw "TODO: port stream-into!")) -;; ([to xform #_java.util.stream.BaseStream stream] -;; ;; (if (instance? clojure.lang.IEditableCollection to) -;; ;; (with-meta (persistent! (stream-transduce! xform conj! (transient to) stream)) (meta to)) -;; ;; (stream-transduce! xform conj to stream)) -;; (throw "TODO: port stream-into!"))) -;; -;; -;;(defmacro ^:private when-class [class-name & body] -;; ;; `(try -;; ;; (Class/forName ^String ~class-name) -;; ;; ~@body -;; ;; (catch ClassNotFoundException _#)) -;; (throw "TODO: port when-class")) -;; -;;;; (defprotocol Inst -;;;; (inst-ms* [inst])) -;; -;;;; (extend-protocol Inst -;;;; java.util.Date -;;;; (inst-ms* [inst] (.getTime ^java.util.Date inst))) -;; -;;(defn inst-ms -;; "Return the number of milliseconds since January 1, 1970, 00:00:00 GMT" -;; [inst] -;; (cpp/jank.runtime.inst_ms inst)) -;; -;;(defn inst? -;; "Return true if x satisfies Inst" -;; [x] -;; (cpp/jank.runtime.is_inst x)) -;; -;;;; (extend-protocol clojure.core/Inst -;;;; java.time.Instant -;;;; (inst-ms* [inst] (.toEpochMilli ^java.time.Instant inst))) -;; -;;(defn uuid? -;; "Return true if x is a java.util.UUID" -;; [x] -;; (cpp/jank.runtime.is_uuid x)) -;; -;;(defn random-uuid -;; "Returns a pseudo-randomly generated java.util.UUID instance (i.e. type 4). -;; -;; See: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID--" -;; [] -;; (cpp/jank.runtime.random_uuid)) -;; -;;;; (extend-protocol clojure.core.protocols/IKVReduce -;;;; nil -;;;; (kv-reduce -;;;; [_ f init] -;;;; init) -;; -;;;; ;;slow path default -;;;; java.lang.Object -;;;; (kv-reduce -;;;; [amap f init] -;;;; (reduce (fn [ret ^java.util.Map$Entry me] -;;;; (f ret -;;;; (.getKey me) -;;;; (.getValue me))) -;;;; init -;;;; amap)) -;; -;;;; clojure.lang.IKVReduce -;;;; (kv-reduce -;;;; [amap f init] -;;;; (.kvreduce amap f init))) -;; -;;(defn reduce-kv -;; "Reduces an associative collection. f should be a function of 3 -;; arguments. Returns the result of applying f to init, the first key -;; and the first value in coll, then applying f to that result and the -;; 2nd key and value, etc. If coll contains no entries, returns init -;; and f is not called. Note that reduce-kv is supported on vectors, -;; where the keys will be the ordinals." -;; ([f init coll] -;; ;; (clojure.core.protocols/kv-reduce coll f init) -;; (reduce (fn [s [k v]] (f s k v)) init coll))) -;; -;;(defn- normalize-slurp-opts -;; [opts] -;; (if (string? (first opts)) -;; (do -;; (println "WARNING: (slurp f enc) is deprecated, use (slurp f :encoding enc).") -;; [:encoding (first opts)]) -;; opts)) -;; -;;(defn slurp -;; "Opens a reader on f and reads all its contents, returning a string. -;; See clojure.java.io/reader for a complete list of supported arguments." -;; ([f & opts] -;; (let [opts (normalize-slurp-opts opts) -;; fname (cpp/cast (cpp/type "char const*") f) -;; file (cpp/std.ifstream. fname)] -;; (if-not (cpp/.is_open file) -;; (throw (str f " (No such file or directory)")) -;; (let [size (cpp/std.filesystem.file_size fname) -;; out (cpp/std.string. size (cpp/char 0))] -;; (cpp/.read file (cpp/& (cpp/.front out)) size) -;; out))))) -;; -;;(defn spit -;; "Opposite of slurp. Opens f with writer, writes content, then -;; closes f. Options passed to clojure.java.io/writer." -;; [f content & options] -;; (let [file (cpp/std.ofstream.)] -;; (cpp/.open file (cpp/cast (cpp/type "char const*") f)) -;; (cpp/<< file (cpp/cast (cpp/type "char const*") content)) -;; (cpp/.close file) -;; nil)) -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; futures (needs proxy);;;;;;;;;;;;;;;;;; -;;(defn future-call -;; "Takes a function of no args and yields a future object that will -;; invoke the function in another thread, and will cache the result and -;; return it on all subsequent calls to deref/@. If the computation has -;; not yet finished, calls to deref/@ will block, unless the variant -;; of deref with timeout is used. See also - realized?." -;; [f] -;; ;; (let [f (binding-conveyor-fn f) -;; ;; fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)] -;; ;; (reify -;; ;; clojure.lang.IDeref -;; ;; (deref [_] (deref-future fut)) -;; ;; clojure.lang.IBlockingDeref -;; ;; (deref -;; ;; [_ timeout-ms timeout-val] -;; ;; (deref-future fut timeout-ms timeout-val)) -;; ;; clojure.lang.IPending -;; ;; (isRealized [_] (.isDone fut)) -;; ;; java.util.concurrent.Future -;; ;; (get [_] (.get fut)) -;; ;; (get [_ timeout unit] (.get fut timeout unit)) -;; ;; (isCancelled [_] (.isCancelled fut)) -;; ;; (isDone [_] (.isDone fut)) -;; ;; (cancel [_ interrupt?] (.cancel fut interrupt?)))) -;; (throw "TODO: port future-call")) -;; -;;(defmacro future -;; "Takes a body of expressions and yields a future object that will -;; invoke the body in another thread, and will cache the result and -;; return it on all subsequent calls to deref/@. If the computation has -;; not yet finished, calls to deref/@ will block, unless the variant of -;; deref with timeout is used. See also - realized?." -;; [& body] -;; ;; `(future-call (^{:once true} fn* [] ~@body)) -;; (throw "TODO: port future")) -;; -;;(defn future-cancel -;; "Cancels the future, if possible." -;; [#_java.util.concurrent.Future f] -;; ;; (.cancel f true) -;; (throw "TODO: port future-cancel")) -;; -;;(defn future-cancelled? -;; "Returns true if future f is cancelled" -;; [#_java.util.concurrent.Future f] -;; ;; (.isCancelled f) -;; (throw "TODO: port future-cancelled?")) -;; -;;(defn pmap -;; "Like map, except f is applied in parallel. Semi-lazy in that the -;; parallel computation stays ahead of the consumption, but doesn't -;; realize the entire result unless required. Only useful for -;; computationally intensive functions where the time of f dominates -;; the coordination overhead." -;; ([f coll] -;; ;; (let [n (+ 2 (.. Runtime getRuntime availableProcessors)) -;; ;; rets (map #(future (f %)) coll) -;; ;; step (fn step [[x & xs :as vs] fs] -;; ;; (lazy-seq -;; ;; (if-let [s (seq fs)] -;; ;; (cons (deref x) (step xs (rest s))) -;; ;; (map deref vs))))] -;; ;; (step rets (drop n rets))) -;; (throw "TODO: port pmap")) -;; ([f coll & colls] -;; ;; (let [step (fn step [cs] -;; ;; (lazy-seq -;; ;; (let [ss (map seq cs)] -;; ;; (when (every? identity ss) -;; ;; (cons (map first ss) (step (map rest ss)))))))] -;; ;; (pmap #(apply f %) (step (cons coll colls)))) -;; (throw "TODO: port pmap"))) -;; -;; -;;(defn pcalls -;; "Executes the no-arg fns in parallel, returning a lazy sequence of -;; their values" -;; [& fns] (pmap #(%) fns)) -;; -;;(defmacro pvalues -;; "Returns a lazy sequence of the values of the exprs, which are -;; evaluated in parallel" -;; [& exprs] -;; `(pcalls ~@(map #(list `fn [] %) exprs))) -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; clojure version number ;;;;;;;;;;;;;;;;;;;;;; -;; -;;;; (let [^java.util.Properties -;;;; properties (with-open [version-stream (.getResourceAsStream -;;;; (clojure.lang.RT/baseLoader) -;;;; "clojure/version.properties")] -;;;; (doto (new java.util.Properties) -;;;; (.load version-stream))) -;;;; version-string (.getProperty properties "version") -;;;; [_ major minor incremental qualifier snapshot] -;;;; (re-matches -;;;; #"(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9_]+))?(?:-(SNAPSHOT))?" -;;;; version-string) -;;;; clojure-version {:major (Integer/valueOf ^String major) -;;;; :minor (Integer/valueOf ^String minor) -;;;; :incremental (Integer/valueOf ^String incremental) -;;;; :qualifier (if (= qualifier "SNAPSHOT") nil qualifier)}] -;;;; (def ^:dynamic *clojure-version* -;;;; (if (.contains version-string "SNAPSHOT") -;;;; (clojure.lang.RT/assoc clojure-version :interim true) -;;;; clojure-version))) -;; -;;;; (add-doc-and-meta *clojure-version* -;;;; "The version info for Clojure core, as a map containing :major :minor -;;;; :incremental and :qualifier keys. Feature releases may increment -;;;; :minor and/or :major, bugfix releases will increment :incremental. -;;;; Possible values of :qualifier include \"GA\", \"SNAPSHOT\", \"RC-x\" \"BETA-x\"" -;;;; {:added "1.0"}) -;; -;;(defn clojure-version -;; "Returns clojure version as a printable string." -;; [] -;; (cpp/clojure.core_native.jank_version)) -;; -;;(defn promise -;; "Returns a promise object that can be read with deref/@, and set, -;; once only, with deliver. Calls to deref/@ prior to delivery will -;; block, unless the variant of deref with timeout is used. All -;; subsequent derefs will return the same delivered value without -;; blocking. See also - realized?." -;; [] -;; ;; (let [d (java.util.concurrent.CountDownLatch. 1) -;; ;; v (atom d)] -;; ;; (reify -;; ;; clojure.lang.IDeref -;; ;; (deref [_] (.await d) @v) -;; ;; clojure.lang.IBlockingDeref -;; ;; (deref -;; ;; [_ timeout-ms timeout-val] -;; ;; (if (.await d timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS) -;; ;; @v -;; ;; timeout-val)) -;; ;; clojure.lang.IPending -;; ;; (isRealized [this] -;; ;; (zero? (.getCount d))) -;; ;; clojure.lang.IFn -;; ;; (invoke -;; ;; [this x] -;; ;; (when (and (pos? (.getCount d)) -;; ;; (compare-and-set! v d x)) -;; ;; (.countDown d) -;; ;; this)))) -;; (throw "TODO: port promise")) -;; -;;(defn deliver -;; "Delivers the supplied value to the promise, releasing any pending -;; derefs. A subsequent call to deliver on a promise will have no effect." -;; [promise val] (promise val)) -;; -;;(defn rand-nth -;; "Return a random element of the (sequential) collection. Will have -;; the same performance characteristics as nth for the given -;; collection." -;; [coll] -;; (nth coll (rand-int (count coll)))) -;; -;;(defn splitv-at -;; "Returns a vector of [(into [] (take n) coll) (drop n coll)]" -;; [n coll] -;; [(into [] (take n) coll) (drop n coll)]) -;; -;;(defn partitionv -;; "Returns a lazy sequence of vectors of n items each, at offsets step -;; apart. If step is not supplied, defaults to n, i.e. the partitions -;; do not overlap. If a pad collection is supplied, use its elements as -;; necessary to complete last partition upto n items. In case there are -;; not enough padding elements, return a partition with less than n items." -;; ([n coll] -;; (partitionv n n coll)) -;; ([n step coll] -;; (lazy-seq -;; (when-let [s (seq coll)] -;; (let [p (into [] (take n) s)] -;; (when (= n (count p)) -;; (cons p (partitionv n step (nthrest s step)))))))) -;; ([n step pad coll] -;; (lazy-seq -;; (when-let [s (seq coll)] -;; (let [p (into [] (take n) s)] -;; (if (= n (count p)) -;; (cons p (partitionv n step pad (nthrest s step))) -;; (list (into [] (take n) (concat p pad))))))))) -;; -;;(defn partitionv-all -;; "Returns a lazy sequence of vector partitions, but may include -;; partitions with fewer than n items at the end. -;; Returns a stateful transducer when no collection is provided." -;; ([n] -;; (partition-all n)) -;; ([n coll] -;; (partitionv-all n n coll)) -;; ([n step coll] -;; (lazy-seq -;; (when-let [s (seq coll)] -;; (let [seg (into [] (take n) coll)] -;; (cons seg (partitionv-all n step (drop step s)))))))) -;; -;;(defn shuffle -;; "Return a random permutation of coll" -;; [coll] -;; (cpp/jank.runtime.shuffle coll)) -;; -;;(defn bounded-count -;; "If coll is counted? returns its count, else will count at most the first n -;; elements of coll using its seq" -;; [n coll] -;; (if (counted? coll) -;; (count coll) -;; (loop [i 0 s (seq coll)] -;; (if (and s (< i n)) -;; (recur (inc i) (next s)) -;; i)))) -;; -;;(defn bounded-count -;; "If coll is counted? returns its count, else will count at most the first n -;; elements of coll using its seq" -;; [n coll] -;; (if (counted? coll) -;; (count coll) -;; (loop [i 0 s (seq coll)] -;; (if (and s (< i n)) -;; (recur (inc i) (next s)) -;; i)))) -;; -;;(defn- ^{:dynamic true} assert-valid-fdecl -;; "A good fdecl looks like (([a] ...) ([a b] ...)) near the end of defn." -;; [fdecl] -;; (when (empty? fdecl) (throw "Parameter declaration missing")) -;; (let [argdecls (map -;; #(if (seq? %) -;; (first %) -;; (throw (if (seq? (first fdecl)) -;; (str "Invalid signature \"" -;; % -;; "\" should be a list") -;; (str "Parameter declaration \"" -;; % -;; "\" should be a vector")))) -;; fdecl) -;; bad-args (seq (remove #(vector? %) argdecls))] -;; (when bad-args -;; (throw (str "Parameter declaration \"" (first bad-args) -;; "\" should be a vector"))))) -;; -;;(defn realized? -;; "Returns true if a value has been produced for a promise, delay, future or lazy sequence." -;; [#_clojure.lang.IPending x] -;; ;; (.isRealized x) -;; (throw "TODO: port realized?")) -;; -;;(defn random-sample -;; "Returns items from coll with random probability of prob (0.0 - -;; 1.0). Returns a transducer when no collection is provided." -;; ([prob] -;; (filter (fn [_] (< (rand) prob)))) -;; ([prob coll] -;; (filter (fn [_] (< (rand) prob)) coll))) -;; -;;;; (deftype Eduction [xform coll] -;;;; Iterable -;;;; (iterator [_] -;;;; (clojure.lang.TransformerIterator/create xform (clojure.lang.RT/iter coll))) -;; -;;;; clojure.lang.IReduceInit -;;;; (reduce [_ f init] -;;;; ;; NB (completing f) isolates completion of inner rf from outer rf -;;;; (transduce xform (completing f) init coll)) -;; -;;;; clojure.lang.Sequential) -;; -;;;; (defn eduction -;;;; "Returns a reducible/iterable application of the transducers -;;;; to the items in coll. Transducers are applied in order as if -;;;; combined with comp. Note that these applications will be -;;;; performed every time reduce/iterator is called." -;;;; [& xforms] -;;;; (Eduction. (apply comp (butlast xforms)) (last xforms))) -;; -;;;; (defmethod print-method Eduction [c, ^Writer w] -;;;; (if *print-readably* -;;;; (do -;;;; (print-sequential "(" pr-on " " ")" c w)) -;;;; (print-object c w))) -;; -;;(defn iteration -;; "Creates a seqable/reducible via repeated calls to step, -;; a function of some (continuation token) 'k'. The first call to step -;; will be passed initk, returning 'ret'. Iff (somef ret) is true, -;; (vf ret) will be included in the iteration, else iteration will -;; terminate and vf/kf will not be called. If (kf ret) is non-nil it -;; will be passed to the next step call, else iteration will terminate. -;; -;; This can be used e.g. to consume APIs that return paginated or batched data. -;; -;; step - (possibly impure) fn of 'k' -> 'ret' -;; -;; :somef - fn of 'ret' -> logical true/false, default 'some?' -;; :vf - fn of 'ret' -> 'v', a value produced by the iteration, default 'identity' -;; :kf - fn of 'ret' -> 'next-k' or nil (signaling 'do not continue'), default 'identity' -;; :initk - the first value passed to step, default 'nil' -;; -;; It is presumed that step with non-initk is unreproducible/non-idempotent. -;; If step with initk is unreproducible it is on the consumer to not consume twice." -;; [step & {:keys [somef vf kf initk] -;; :or {vf identity -;; kf identity -;; somef some? -;; initk nil}}] -;; ;; (reify -;; ;; clojure.lang.Seqable -;; ;; (seq [_] -;; ;; ((fn next [ret] -;; ;; (when (somef ret) -;; ;; (cons (vf ret) -;; ;; (when-some [k (kf ret)] -;; ;; (lazy-seq (next (step k))))))) -;; ;; (step initk))) -;; ;; clojure.lang.IReduceInit -;; ;; (reduce [_ rf init] -;; ;; (loop [acc init -;; ;; ret (step initk)] -;; ;; (if (somef ret) -;; ;; (let [acc (rf acc (vf ret))] -;; ;; (if (reduced? acc) -;; ;; @acc -;; ;; (if-some [k (kf ret)] -;; ;; (recur acc (step k)) -;; ;; acc))) -;; ;; acc)))) -;; (throw "TODO: port iteration")) -;; -;;(defn tagged-literal? -;; "Return true if the value is the data representation of a tagged literal" -;; [value] -;; (cpp/jank.runtime.is_tagged_literal value)) -;; -;;(defn tagged-literal -;; "Construct a data representation of a tagged literal from a -;; tag symbol and a form." -;; [tag form] -;; (cpp/jank.runtime.tagged_literal tag form)) -;; -;;(defn reader-conditional? -;; "Return true if the value is the data representation of a reader conditional" -;; [value] -;; ;; (instance? clojure.lang.ReaderConditional value) -;; (throw "TODO: port reader-conditional?")) -;; -;;(defn reader-conditional -;; "Construct a data representation of a reader conditional. -;; If true, splicing? indicates read-cond-splicing." -;; [form #_Boolean splicing?] -;; ;; (clojure.lang.ReaderConditional/create form splicing?) -;; (throw "TODO: port reader-conditional")) -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; data readers ;;;;;;;;;;;;;;;;;; -;; -;;(def default-data-readers -;; "Default map of data reader functions provided by Clojure. May be -;; overridden by binding *data-readers*." -;; (merge -;; ;; {'uuid #'clojure.uuid/default-uuid-reader} -;; ;; (when-class "java.sql.Timestamp" -;; ;; {'inst #'clojure.instant/read-instant-date}) -;; )) -;; -;;(def ^:dynamic *data-readers* -;; "Map from reader tag symbols to data reader Vars. -;; -;; When Clojure starts, it searches for files named 'data_readers.clj' -;; and 'data_readers.cljc' at the root of the classpath. Each such file -;; must contain a literal map of symbols, like this: -;; -;; {foo/bar my.project.foo/bar -;; foo/baz my.project/baz} -;; -;; The first symbol in each pair is a tag that will be recognized by -;; the Clojure reader. The second symbol in the pair is the -;; fully-qualified name of a Var which will be invoked by the reader to -;; parse the form following the tag. For example, given the -;; data_readers.clj file above, the Clojure reader would parse this -;; form: -;; -;; #foo/bar [1 2 3] -;; -;; by invoking the Var #'my.project.foo/bar on the vector [1 2 3]. The -;; data reader function is invoked on the form AFTER it has been read -;; as a normal Clojure data structure by the reader. -;; -;; Reader tags without namespace qualifiers are reserved for -;; Clojure. Default reader tags are defined in -;; clojure.core/default-data-readers but may be overridden in -;; data_readers.clj, data_readers.cljc, or by rebinding this Var." -;; {}) -;; -;;(def ^:dynamic *default-data-reader-fn* -;; "When no data reader is found for a tag and *default-data-reader-fn* -;; is non-nil, it will be called with two arguments, -;; the tag and the value. If *default-data-reader-fn* is nil (the -;; default), an exception will be thrown for the unknown tag." -;; nil) -;; -;;(defn- data-reader-urls [] -;; ;; (let [cl (.. Thread currentThread getContextClassLoader)] -;; ;; (concat -;; ;; (enumeration-seq (.getResources cl "data_readers.clj")) -;; ;; (enumeration-seq (.getResources cl "data_readers.cljc")))) -;; (throw "TODO: port data-reader-urls")) -;; -;;(defn- data-reader-var [sym] -;; (intern (create-ns (symbol (namespace sym))) -;; (symbol (name sym)))) -;; -;;(defn- load-data-reader-file [mappings #_java.net.URL url] -;; ;; (with-open [rdr (clojure.lang.LineNumberingPushbackReader. -;; ;; (java.io.InputStreamReader. -;; ;; (.openStream url) "UTF-8"))] -;; ;; (binding [*file* (.getFile url)] -;; ;; (let [read-opts (if (.endsWith (.getPath url) "cljc") -;; ;; {:eof nil :read-cond :allow} -;; ;; {:eof nil}) -;; ;; new-mappings (read read-opts rdr)] -;; ;; (when (not (map? new-mappings)) -;; ;; (throw (ex-info (str "Not a valid data-reader map") -;; ;; {:url url}))) -;; ;; (reduce -;; ;; (fn [m [k v]] -;; ;; (when (not (symbol? k)) -;; ;; (throw (ex-info (str "Invalid form in data-reader file") -;; ;; {:url url -;; ;; :form k}))) -;; ;; (let [v-var (data-reader-var v)] -;; ;; (when (and (contains? mappings k) -;; ;; (not= (mappings k) v-var)) -;; ;; (throw (ex-info "Conflicting data-reader mapping" -;; ;; {:url url -;; ;; :conflict k -;; ;; :mappings m}))) -;; ;; (assoc m k v-var))) -;; ;; mappings -;; ;; new-mappings)))) -;; (throw "TODO: port load-data-reader-file")) -;; -;;(defn- load-data-readers [] -;; ;; (alter-var-root #'*data-readers* -;; ;; (fn [mappings] -;; ;; (reduce load-data-reader-file -;; ;; mappings (data-reader-urls)))) -;; (throw "TODO: port load-data-readers")) -;; -;;;; (try -;;;; (load-data-readers) -;;;; (catch #_Throwable t -;;;; (.printStackTrace t) -;;;; (throw t))) -;; -;;(defonce ^:private tapset (atom #{})) -;; -;;;; (defonce ^:private ^java.util.concurrent.ArrayBlockingQueue tapq (java.util.concurrent.ArrayBlockingQueue. 1024)) -;; -;;(defonce ^:private tap-loop -;; ;; (delay -;; ;; (doto (Thread. -;; ;; #(let [t (.take tapq) -;; ;; x (if (identical? ::tap-nil t) nil t) -;; ;; taps @tapset] -;; ;; (doseq [tap taps] -;; ;; (try -;; ;; (tap x) -;; ;; (catch Throwable ex))) -;; ;; (recur)) -;; ;; "clojure.core/tap-loop") -;; ;; (.setDaemon true) -;; ;; (.start))) -;; nil) -;; -;;(defn add-tap -;; "adds f, a fn of one argument, to the tap set. This function will be called with anything sent via tap>. -;; This function may (briefly) block (e.g. for streams), and will never impede calls to tap>, -;; but blocking indefinitely may cause tap values to be dropped. -;; Remember f in order to remove-tap" -;; [f] -;; (force tap-loop) -;; (swap! tapset conj f) -;; nil) -;; -;;(defn remove-tap -;; "Remove f from the tap set." -;; [f] -;; (swap! tapset disj f) -;; nil) -;; -;;(defn tap> -;; "sends x to any taps. Will not block. Returns true if there was room in the queue, -;; false if not (dropped)." -;; [x] -;; (force tap-loop) -;; ;; (.offer tapq (if (nil? x) ::tap-nil x)) -;; (throw "TODO: port tap>")) -;; -;;(defn update-vals -;; "m f => {k (f v) ...} -;; -;; Given a map m and a function f of 1-argument, returns a new map where the keys of m -;; are mapped to result of applying f to the corresponding values of m." -;; [m f] -;; (with-meta -;; (persistent! -;; (reduce-kv (fn [acc k v] (assoc! acc k (f v))) -;; (if (transientable? m) -;; (transient m) -;; (transient {})) -;; m)) -;; (meta m))) -;; -;;(defn update-keys -;; "m f => {(f k) v ...} -;; -;; Given a map m and a function f of 1-argument, returns a new map whose -;; keys are the result of applying f to the keys of m, mapped to the -;; corresponding values of m. -;; f must return a unique key for each key of m, else the behavior is undefined." -;; [m f] -;; (let [ret (persistent! -;; (reduce-kv (fn [acc k v] (assoc! acc (f k) v)) -;; (transient {}) -;; m))] -;; (with-meta ret (meta m)))) -;; -;;(defn- parsing-err -;; "Construct message for parsing for non-string parsing error" -;; [val] -;; (str "Expected string, got " (if (nil? val) "nil" (type val)))) -;; -;;(defn parse-long -;; "Parse string of decimal digits with optional leading -/+ and return a -;; Long value, or nil if parse fails" -;; [s] -;; (cpp/jank.runtime.parse_long s)) -;; -;;(defn parse-double -;; "Parse string with floating point components and return a Double value, -;; or nil if parse fails. -;; -;; Grammar: https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#valueOf-java.lang.String-" -;; [s] -;; (cpp/jank.runtime.parse_double s)) -;; -;;(defn parse-uuid -;; "Parse a string representing a UUID and return a java.util.UUID instance, -;; or nil if parse fails. -;; -;; Grammar: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#toString--" -;; [s] -;; (cpp/jank.runtime.parse_uuid s)) -;; -;;(defn parse-boolean -;; "Parse strings \"true\" or \"false\" and return a boolean, or nil if invalid" -;; [s] -;; (if (string? s) -;; (case s -;; "true" true -;; "false" false -;; nil) -;; (throw (parsing-err s)))) -;; -;;(defn NaN? -;; "Returns true if num is NaN, else false" -;; [num] -;; (cpp/jank.runtime.is_nan num)) -;; -;;(defn infinite? -;; "Returns true if num is negative or positive infinity, else false" -;; [num] -;; (cpp/jank.runtime.is_infinite num)) +; The full `apply` will be defined below, but it requires more helpers to support +; all of its arities. This version of apply* is used by the parser for syntax quoting. +; This allows us to use syntax quoting sooner and also have more easily inlinable +; syntax quoting code, since this version of apply is lighter than the full version. +(def ^:private apply* + (fn* apply* [source args] + (cpp/jank.runtime.apply_to source args))) + +(def ^{:macro true} let + (fn* let [&form &env & decl] + `(let* ~@decl))) + +(def ^{:macro true} loop + (fn* loop [&form &env & decl] + `(loop* ~@decl))) + +(def ^{:macro true} fn + (fn* fn [&form &env & decl] + (with-meta `(fn* ~@decl) (meta &form)))) + +(def = + "Equality. Returns true if x equals y, false if not. It also works + for nil and compares numbers and collections in a type-independent + manner. Clojure's immutable data structures define equals() (and + thus =) as a value, not an identity, comparison." + (fn* = + ([x] true) + ([x y] + (cpp/jank.runtime.equal x y)) + ([x y & more] + (if (cpp/jank.runtime.equal x y) + (if (next more) + (recur y (first more) (next more)) + (cpp/jank.runtime.equal y (first more))) + false)))) + +(def == + "Returns non-nil if nums all have the equivalent + value (type-independent), otherwise false" + (fn* == + ([x] true) + ([x y] + (cpp/jank.runtime.is_equiv x y)) + ([x y & more] + (if (cpp/jank.runtime.is_equiv x y) + (if (next more) + (recur y (first more) (next more)) + (cpp/jank.runtime.is_equiv y (first more))) + false)))) + +(def ^:private sigs + (fn* [fdecl] + (let* [asig (fn* asig [fdecl] + (let* [arglist (first fdecl) + ;elide implicit macro args + arglist (if (= '&form (first arglist)) + (subvec arglist 2 (count arglist)) + arglist) + body (next fdecl)] + (if (map? (first body)) + (if (next body) + (with-meta arglist (conj (if (meta arglist) + (meta arglist) + {}) + (first body))) + arglist) + arglist)))] + (if (seq? (first fdecl)) + (loop* [ret [] + fdecls fdecl] + (if fdecls + (recur (conj ret (asig (first fdecls))) (next fdecls)) + (seq ret))) + (list (asig fdecl)))))) + +; Macros. +(def ^{:macro true + :doc "Same as (def name (fn [params* ] exprs*)) or (def + name (fn ([params* ] exprs*)+)) with any doc-string or attrs added + to the var metadata. prepost-map defines a map with optional keys + :pre and :post that contain collections of pre or post conditions."} + defn + (fn* defn [&form &env name & fdecl] + ;; Note: Cannot delegate this check to def because of the call to (with-meta name ..) + (if (not (symbol? name)) + (throw "First argument to defn must be a symbol")) + (let* [m (if (string? (first fdecl)) + {:doc (first fdecl)} + {}) + fdecl (if (string? (first fdecl)) + (next fdecl) + fdecl) + m (if (map? (first fdecl)) + (conj m (first fdecl)) + m) + fdecl (if (map? (first fdecl)) + (next fdecl) + fdecl) + fdecl (if (vector? (first fdecl)) + (list fdecl) + fdecl) + m (if (map? (last fdecl)) + (conj m (last fdecl)) + m) + fdecl (if (map? (last fdecl)) + (butlast fdecl) + fdecl) + m (conj {:arglists (list 'quote (sigs fdecl))} m) + m (let* [inline (:inline m) + ifn (first inline) + iname (second inline)] + ;; same as: (if (and (= 'fn ifn) (not (symbol? iname))) ...) + (if (if (= 'fn ifn) + (if (symbol? iname) + false + true)) + ;; inserts the same fn name to the inline fn if it does not have one + (assoc m :inline (cons ifn (cons (symbol (str iname "__inliner")) + (next inline)))) + m)) + m (conj (if (meta name) (meta name) {}) m)] + `(def ~(with-meta name m) + ~(with-meta `(fn ~name ~@fdecl) {:rettag (:tag m)}))))) + +(defn macroexpand-1 + "If form represents a macro form, returns its expansion, + else returns form." + [form] + (cpp/jank.runtime.macroexpand1 form)) +(defn macroexpand + "Repeatedly calls macroexpand-1 on form until it no longer + represents a macro form, then returns it. Note neither + macroexpand-1 nor macroexpand expand macros in subforms." + [form] + (cpp/jank.runtime.macroexpand form)) + +(defn gensym + "Returns a new symbol with a unique name. If a prefix string is + supplied, the name is prefix# where # is some unique number. If + prefix is not supplied, the prefix is 'G__'." + ([] + (cpp/jank.runtime.gensym "G__")) + ([prefix-string] + (cpp/jank.runtime.gensym prefix-string))) + +(defn + ^{:macro true + :doc "Like defn, but the resulting function name is declared as a + macro and will be used as a macro by the compiler when it is + called."} + defmacro + [&form &env name & args] + (let [prefix (loop [p (list name) args args] + (let [f (first args)] + (if (string? f) + (recur (cons f p) (next args)) + (if (map? f) + (recur (cons f p) (next args)) + p)))) + fdecl (loop [fd args] + (if (string? (first fd)) + (recur (next fd)) + (if (map? (first fd)) + (recur (next fd)) + fd))) + fdecl (if (vector? (first fdecl)) + (list fdecl) + fdecl) + add-implicit-args (fn [fd] + (let [args (first fd)] + (cons (vec (cons '&form (cons '&env args))) (next fd)))) + add-args (fn [acc ds] + (if (nil? ds) + acc + (let [d (first ds)] + (if (map? d) + (conj acc d) + (recur (conj acc (add-implicit-args d)) (next ds)))))) + fdecl (seq (add-args [] fdecl)) + decl (loop [p prefix d fdecl] + (if p + (recur (next p) (cons (first p) d)) + d))] + (list 'do + (cons `defn decl) + (list `reset-meta! (list 'var name) (list 'assoc + (list 'meta (list 'var name)) + :macro + true)) + (list 'var name)))) + +(defmacro defn- + "Same as defn, yielding non-public def." + {:added "1.0"} + [name & decls] + (cons `defn (cons (with-meta name (assoc (meta name) :private true)) decls))) + +(defmacro when + "Evaluates test. If logical true, evaluates body in an implicit do." + [condition & body] + (list 'if condition + (cons 'do body) + nil)) + +(defmacro when-not + "Evaluates test. If logical false, evaluates body in an implicit do." + [condition & body] + (list 'if (list 'clojure.core/not condition) + (cons 'do body) + nil)) + +(defmacro cond + "Takes a set of test/expr pairs. It evaluates each test one at a + time. If a test returns logical true, cond evaluates and returns + the value of the corresponding expr and doesn't evaluate any of the + other tests or exprs. (cond) returns nil." + [& clauses] + (when clauses + (list 'if (first clauses) + (if (next clauses) + (second clauses) + (let [err "cond requires an even number of forms"] + (list 'throw (list 'clojure.core/ex-info "invalid cond" {:err err})))) + (cons 'clojure.core/cond (next (next clauses)))))) + +(defmacro or + "Evaluates exprs one at a time, from left to right. If a form + returns a logical true value, or returns that value and doesn't + evaluate any of the other expressions, otherwise it returns the + value of the last expression. (or) returns nil." + ([] + nil) + ([x] + x) + ([x & more] + (let [x-res (gensym)] + (list `let [x-res x] + (list 'if x-res + x-res + (cons `or more)))))) + +(defmacro and + "Evaluates exprs one at a time, from left to right. If a form + returns logical false (nil or false), and returns that value and + doesn't evaluate any of the other expressions, otherwise it returns + the value of the last expr. (and) returns true." + ([] + true) + ([x] + x) + ([x & more] + (let [x-res (gensym)] + (list `let [x-res x] + (list 'if x-res + (cons `and more) + x-res))))) + +(defmacro assert + "Evaluates expr and throws an exception if it does not evaluate to + logical true." + ([x] + (when *assert* + (list `when-not x + (list 'throw (list `ex-info + "assertion failed" + {:assertion (pr-str x)}))))) + ([x message] + (when *assert* + (list `when-not x + (list 'throw (list `ex-info + "assertion failed" + {:assertion (pr-str x) + :message message})))))) + +(defmacro comment + "Ignores body, yields nil" + [& body]) + +;; Transients. +(defn- transientable? + "Returns a whether the collection can be made transient." + [coll] + (cpp/jank.runtime.is_transientable coll)) + +(defn transient + "Returns a new, transient version of the collection, in constant time." + [coll] + (cpp/jank.runtime.transient coll)) + +(defn persistent! + "Returns a new, persistent version of the transient collection, in + constant time. The transient collection cannot be used after this + call, any such use will throw an exception." + [coll] + (cpp/jank.runtime.persistent coll)) + +(defn conj! + "Adds x to the transient collection, and return coll. The 'addition' + may happen at different 'places' depending on the concrete type." + ([] + (transient [])) + ([coll] + coll) + ([coll x] + (cpp/jank.runtime.conj_in_place coll x))) + +(defn assoc! + "When applied to a transient map, adds mapping of key(s) to + val(s). When applied to a transient vector, sets the val at index. + Note - index must be <= (count vector). Returns coll." + ([coll k v] + (cpp/jank.runtime.assoc_in_place coll k v)) + ([coll k v & kvs] + (let [ret (assoc! coll k v)] + (if kvs + (recur ret (first kvs) (second kvs) (nnext kvs)) + ret)))) + +(defn dissoc! + "Returns a transient map that doesn't contain a mapping for key(s)." + ([coll k] + (cpp/jank.runtime.dissoc_in_place coll k)) + ([coll k & ks] + (let [ret (dissoc! coll k)] + (if ks + (recur ret (first ks) (next ks)) + ret)))) + +(defn pop! + "Removes the last item from a transient vector. If + the collection is empty, throws an exception. Returns coll" + [coll] + (cpp/jank.runtime.pop_in_place coll)) + +(defn disj! + "disj[oin]. Returns a transient set of the same (hashed/sorted) type, that + does not contain key(s)." + ([set] set) + ([set elem] + (cpp/jank.runtime.dissoc_in_place set elem)) + ([set elem & elems] + (let [ret (disj! set elem)] + (if elems + (recur ret (first elems) (next elems)) + ret)))) + +;; Functions. +(defn- spread + [arglist] + (cond + (nil? arglist) nil + (nil? (next arglist)) (seq (first arglist)) + :else (cons (first arglist) (spread (next arglist))))) + +(defn list* + "Creates a new seq containing the items prepended to the rest, the + last of which will be treated as a sequence." + ([args] + (seq args)) + ([a args] + (cons a args)) + ([a b args] + (cons a (cons b args))) + ([a b c args] + (cons a (cons b (cons c args)))) + ([a b c d & more] + (cons a (cons b (cons c (cons d (spread more))))))) + +(defn apply + "Applies fn f to the argument list formed by prepending intervening arguments to args." + ([f args] + (cpp/jank.runtime.apply_to f args)) + ([f x args] + (cpp/jank.runtime.apply_to f (list* x args))) + ([f x y args] + (cpp/jank.runtime.apply_to f (list* x y args))) + ([f x y z args] + (cpp/jank.runtime.apply_to f (list* x y z args))) + ([f a b c d & args] + (cpp/jank.runtime.apply_to f (cons a (cons b (cons c (cons d (spread args)))))))) + +(defn constantly + "Returns a function that takes any number of arguments and returns x." + [x] + (fn [& args] + x)) + +(defn identity + "Returns its argument." + [x] + x) + +(defn complement + "Takes a fn f and returns a fn that takes the same arguments as f, + has the same effects, if any, and returns the opposite truth value." + [f] + (fn + ([] (not (f))) + ([x] (not (f x))) + ([x y] (not (f x y))) + ([x y & zs] (not (apply f x y zs))))) + +; Utils. +(defn deref + "Also reader macro: @ref/@agent/@var/@atom/@delay/@future/@promise. Within a transaction, + returns the in-transaction-value of ref, else returns the + most-recently-committed value of ref. When applied to a var, agent + or atom, returns its current state. When applied to a delay, forces + it if not already forced. When applied to a future, will block if + computation not complete. When applied to a promise, will block + until a value is delivered. The variant taking a timeout can be + used for blocking references (futures and promises), and will return + timeout-val if the timeout (in milliseconds) is reached before a + value is available. See also - realized?." + ([ref] + (cpp/jank.runtime.deref ref)) + ; TODO: Blocking. + ([ref timeout-ms timeout-val] + ;(if (instance? clojure.lang.IBlockingDeref ref) + ; (.deref ^clojure.lang.IBlockingDeref ref timeout-ms timeout-val) + ; (deref-future ref timeout-ms timeout-val)) + )) + +(defn reduced + "Wraps x in a way such that a reduce will terminate with the value x" + [x] + (cpp/jank.runtime.reduced x)) + +(defn reduced? + "Returns true if x is the result of a call to reduced" + [x] + (cpp/jank.runtime.is_reduced x)) + +(defn ensure-reduced + "If x is already reduced?, returns it, else returns (reduced x)" + [x] + (if (reduced? x) + x + (reduced x))) + +(defn unreduced + "If x is reduced?, returns (deref x), else returns x" + [x] + (if (reduced? x) + (deref x) + x)) + +(defn reduce + "f should be a function of 2 arguments. If val is not supplied, + returns the result of applying f to the first 2 items in coll, then + applying f to that result and the 3rd item, etc. If coll contains no + items, f must accept no arguments as well, and reduce returns the + result of calling f with no arguments. If coll has only 1 item, it + is returned and f is not called. If val is supplied, returns the + result of applying f to val and the first item in coll, then + applying f to that result and the 2nd item, etc. If coll contains no + items, returns val and f is not called." + ([f coll] + (let [s (seq coll)] + (if s + (reduce f (first s) (next s)) + (f)))) + ([f init coll] + ; TODO: Chunking support. + (cpp/jank.runtime.reduce f init coll))) + +(defn completing + "Takes a reducing function f of 2 args and returns a fn suitable for + transduce by adding an arity-1 signature that calls cf (default - + identity) on the result argument." + ([f] (completing f identity)) + ([f cf] + (fn + ([] (f)) + ([x] (cf x)) + ([x y] (f x y))))) + +(defn transduce + "reduce with a transformation of rf (xf). If init is not + supplied, (rf) will be called to produce it. f should be a reducing + step function that accepts both 1 and 2 arguments, if it accepts + only 2 you can add the arity-1 with 'completing'. Returns the result + of applying (the transformed) xf to init and the first item in coll, + then applying xf to that result and the 2nd item, etc. If coll + contains no items, returns init and rf is not called. Note that + certain transforms may inject or skip items." + ([xform rf coll] + (transduce xform rf (rf) coll)) + ([xform rf init coll] + (let [f (xform rf) + ret (reduce f init coll)] + (f ret)))) + +;; TODO: private +(defn preserving-reduced + [rf] + #(let [ret (rf %1 %2)] + (if (reduced? ret) + (reduced ret) + ret))) + +(defn cat + "A transducer which concatenates the contents of each input, which must be a + collection, into the reduction." + [rf] + (let [rrf (preserving-reduced rf)] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] + (reduce rrf result input))))) + +(defn run! + "Runs the supplied procedure (via reduce), for purposes of side + effects, on successive items in the collection. Returns nil" + [proc coll] + (reduce #(proc %2) nil coll) + nil) + +(defn comp + "Takes a set of functions and returns a fn that is the composition + of those fns. The returned fn takes a variable number of args, + applies the rightmost of fns to the args, the next + fn (right-to-left) to the result, etc." + ([] identity) + ([f] f) + ([f g] + (let [a 1] (fn + ([] (f (g))) + ([x] (f (g x))) + ([x y] (f (g x y))) + ([x y z] (f (g x y z))) + ([x y z & args] (f (apply g x y z args)))))) + ([f g & fs] + (reduce comp (list* f g fs)))) + +(defn peek + "For a list or queue, same as first, for a vector, same as, but much + more efficient than, last. If the collection is empty, returns nil." + [coll] + (cpp/jank.runtime.peek coll)) + +(defn pop + "For a list or queue, returns a new list/queue without the first + item, for a vector, returns a new vector without the last item. If + the collection is empty, throws an exception. Note - not the same + as next/butlast." + [coll] + (cpp/jank.runtime.pop coll)) + +(defn vary-meta + "Returns an object of the same type and value as obj, with + (apply f (meta obj) args) as its metadata." + [o f & args] + (with-meta o (apply f (meta o) args))) + +(defn alter-meta! + "Atomically sets the metadata for a namespace/var/ref/agent/atom to be: + + (apply f its-current-meta args) + + f must be free of side-effects" + [o f & args] + ; TODO: Atomics. + (reset-meta! o (apply f (meta o) args))) + +;; Atoms. +(defn atom + "Creates and returns an Atom with an initial value of x and zero or + more options (in any order): + + :meta metadata-map + + :validator validate-fn + + If metadata-map is supplied, it will become the metadata on the + atom. validate-fn must be nil or a side-effect-free fn of one + argument, which will be passed the intended new state on any state + change. If the new state is unacceptable, the validate-fn should + return false or throw an exception." + ([x] + (cpp/jank.runtime.atom x)) + ; TODO: Validators. + #_([x & options] + (setup-reference (atom x) options))) + +(defn swap! + "Atomically swaps the value of atom to be: + (apply f current-value-of-atom args). Note that f may be called + multiple times, and thus should be free of side effects. Returns + the value that was swapped in." + ([atom f] + (cpp/jank.runtime.swap_atom atom f)) + ([atom f x] + (cpp/jank.runtime.swap_atom atom f x)) + ([atom f x y] + (cpp/jank.runtime.swap_atom atom f x y)) + ([atom f x y & args] + (cpp/jank.runtime.swap_atom atom f x y args))) + +(defn swap-vals! + "Atomically swaps the value of atom to be: + (apply f current-value-of-atom args). Note that f may be called + multiple times, and thus should be free of side effects. + Returns [old new], the value of the atom before and after the swap." + ([atom f] + (cpp/jank.runtime.swap_vals atom f)) + ([atom f x] + (cpp/jank.runtime.swap_vals atom f x)) + ([atom f x y] + (cpp/jank.runtime.swap_vals atom f x y)) + ([atom f x y & args] + (cpp/jank.runtime.swap_vals atom f x y args))) + +(defn compare-and-set! + "Atomically sets the value of atom to newval if and only if the + current value of the atom is identical to oldval. Returns true if + set happened, else false" + [atom oldval newval] + (cpp/jank.runtime.compare_and_set atom oldval newval)) + +(defn reset! + "Sets the value of atom to newval without regard for the + current value. Returns newval." + [atom newval] + (cpp/jank.runtime.reset atom newval)) + +(defn reset-vals! + "Sets the value of atom to newval. Returns [old new], the value of the + atom before and after the reset." + [atom newval] + (cpp/jank.runtime.reset_vals atom newval)) + +;; Volatiles. +(defn volatile! + "Creates and returns a volatile with an initial value of val." + [val] + (cpp/jank.runtime.volatile_ val)) + +(defn vreset! + "Sets the value of volatile to newval without regard for the + current value. Returns newval." + [vol newval] + (cpp/jank.runtime.vreset vol newval)) + +; TODO: In Clojure, this is a macro (for perf reasons). +(defn vswap! + "Non-atomically swaps the value of the volatile as if: + (apply f current-value-of-vol args). Returns the value that + was swapped in." + ([vol f] + (cpp/jank.runtime.vswap vol f)) + ([vol f & args] + (cpp/jank.runtime.vswap vol f args))) + +(defn volatile? + "Returns true if x is a volatile." + [x] + (cpp/jank.runtime.is_volatile x)) + +(defn- delay* [f] (cpp/clojure.core_native.delay f)) + +(defmacro delay + "Takes a body of expressions and yields a Delay object that will + invoke the body only the first time it is forced (with force or deref/@), and + will cache the result and return it on all subsequent force + calls. See also - realized?" + [& body] + (list `delay* (cons `fn (cons '[] body)))) + +(defn force + "If x is a Delay, returns the (possibly cached) value of its expression, else returns x" + [x] + (cpp/jank.runtime.force x)) + +;; Primitives. +;;; Arithmetic. +(defn + ^{:arities {2 {:supports-unboxed-input? true + :unboxed-output? true}}} + + + ([] + 0) + ([x] + x) + ([l r] + (cpp/jank.runtime.add l r)) + ([l r & args] + (let [res (cpp/jank.runtime.add l r)] + (if (empty? args) + res + (recur res (first args) (next args)))))) + +(defn + ^{:arities {2 {:supports-unboxed-input? true + :unboxed-output? true}}} + - + ([x] + (- 0 x)) + ([l r] + (cpp/jank.runtime.sub l r)) + ([l r & args] + (let [res (cpp/jank.runtime.sub l r)] + (if (empty? args) + res + (recur res (first args) (next args)))))) + +(defn + ^{:arities {2 {:supports-unboxed-input? true + :unboxed-output? true}}} + * + ([] + 1) + ([x] + x) + ([l r] + (cpp/jank.runtime.mul l r)) + ([l r & args] + (let [res (cpp/jank.runtime.mul l r)] + (if (empty? args) + res + (recur res (first args) (next args)))))) + +(defn + ^{:arities {2 {:supports-unboxed-input? true + :unboxed-output? true}}} + / + ([x] + (/ 1 x)) + ([l r] + (cpp/jank.runtime.div l r)) + ([l r & args] + (let [res (cpp/jank.runtime.div l r)] + (if (empty? args) + res + (recur res (first args) (next args)))))) + +;; Bit operations. +; TODO: Unboxing and inlining for these. +(defn bit-not + "Bitwise complement" + [x] + (cpp/jank.runtime.bit_not x)) + +(defn bit-and + "Bitwise and" + ([x y] + (cpp/jank.runtime.bit_and x y)) + ([x y & more] + (reduce bit-and (bit-and x y) more))) + +(defn bit-or + "Bitwise or" + ([x y] + (cpp/jank.runtime.bit_or x y)) + ([x y & more] + (reduce bit-or (bit-or x y) more))) + +(defn bit-xor + "Bitwise exclusive or" + ([x y] + (cpp/jank.runtime.bit_xor x y)) + ([x y & more] + (reduce bit-xor (bit-xor x y) more))) + +(defn bit-and-not + "Bitwise and with complement" + ([x y] + (cpp/jank.runtime.bit_and_not x y)) + ([x y & more] + (reduce bit-and-not (bit-and-not x y) more))) + +(defn bit-clear + "Clear bit at index n" + [x n] + (cpp/jank.runtime.bit_clear x n)) + +(defn bit-set + "Set bit at index n" + [x n] + (cpp/jank.runtime.bit_set x n)) + +(defn bit-flip + "Flip bit at index n" + [x n] + (cpp/jank.runtime.bit_flip x n)) + +(defn bit-test + "Test bit at index n" + [x n] + (cpp/jank.runtime.bit_test x n)) + +(defn bit-shift-left + "Bitwise shift left" + [x n] + (cpp/jank.runtime.bit_shift_left x n)) + +(defn bit-shift-right + "Bitwise shift right" + [x n] + (cpp/jank.runtime.bit_shift_right x n)) + +(defn unsigned-bit-shift-right + "Bitwise shift right, without sign-extension." + [x n] + (cpp/jank.runtime.bit_unsigned_shift_right x n)) + +(defn not= + ([x] + false) + ([x y] + (not (= x y))) + ([x y & more] + (not (apply = x y more)))) + +(defn + ^{:arities {2 {:supports-unboxed-input? true + :unboxed-output? true}}} + < + ([x] + true) + ([l r] + (cpp/jank.runtime.lt l r)) + ([l r & args] + (if (cpp/jank.runtime.lt l r) + (if (next args) + (recur r (first args) (next args)) + (cpp/jank.runtime.lt r (first args))) + false))) + +(defn + ^{:arities {2 {:supports-unboxed-input? true + :unboxed-output? true}}} + <= + ([x] + true) + ([l r] + (cpp/jank.runtime.lte l r)) + ([l r & args] + (if (cpp/jank.runtime.lte l r) + (if (next args) + (recur r (first args) (next args)) + (cpp/jank.runtime.lte r (first args))) + false))) + +(defn + ^{:arities {2 {:supports-unboxed-input? true + :unboxed-output? true}}} + > + ([x] + true) + ([l r] + (cpp/jank.runtime.lt r l)) + ([l r & args] + (if (cpp/jank.runtime.lt r l) + (if (next args) + (recur r (first args) (next args)) + (cpp/jank.runtime.lt (first args) r)) + false))) + +(defn + ^{:arities {2 {:supports-unboxed-input? true + :unboxed-output? true}}} + >= + ([x] + true) + ([l r] + (cpp/jank.runtime.lte r l)) + ([l r & args] + (if (cpp/jank.runtime.lte r l) + (if (next args) + (recur r (first args) (next args)) + (cpp/jank.runtime.lte (first args) r)) + false))) + +(defn + ^{:arities {2 {:supports-unboxed-input? true + :unboxed-output? true}}} + min + ([x] + x) + ([l r] + (cpp/jank.runtime.min l r)) + ([l r & args] + (let [res (cpp/jank.runtime.min l r)] + (if (empty? args) + res + (recur res (first args) (next args)))))) + +(defn + ^{:arities {2 {:supports-unboxed-input? true + :unboxed-output? true}}} + max + ([x] + x) + ([l r] + (cpp/jank.runtime.max l r)) + ([l r & args] + (let [res (cpp/jank.runtime.max l r)] + (if (empty? args) + res + (recur res (first args) (next args)))))) + +(defn inc + "Returns a number one greater than num. Does not auto-promote + longs, will throw on overflow. See also: inc'" + [x] + (cpp/jank.runtime.inc x)) +(defn dec + "Returns a number one less than num. Does not auto-promote + longs, will throw on overflow. See also: dec" + [x] + (cpp/jank.runtime.dec x)) + +(defn pos? + "Returns true if num is greater than zero, else false" + [num] + (cpp/jank.runtime.is_pos num)) +(defn neg? + "Returns true if num is less than zero, else false" + [num] + (cpp/jank.runtime.is_neg num)) +(defn zero? + "Returns true if num is zero, else false" + [num] + (cpp/jank.runtime.is_zero num)) + +(defn rem + "Returns the remainder of dividing numerator by denominator." + [num div] + (cpp/jank.runtime.rem num div)) +(defn quot + "quot[ient] of dividing numerator by denominator." + [num div] + (cpp/jank.runtime.quot num div)) + +(defn mod + "Modulus of num and div. Truncates toward negative infinity." + [num div] + (let [m (rem num div)] + (if (or (zero? m) (= (pos? num) (pos? div))) + m + (+ m div)))) + +;; Numbers. +(defn integer? + "Returns true if n is an integer" + [n] + (cpp/jank.runtime.is_integer n)) +(defn float? + "Returns true if n is a floating point number" + [n] + (cpp/jank.runtime.is_real n)) +(defn boolean? + "Returns true if x is a boolean" + [x] + (cpp/jank.runtime.is_boolean x)) +(defn number? + "Returns true if x is a number" + [x] + (cpp/jank.runtime.is_number x)) + +(defn even? + "Returns true if n is even, throws an exception if n is not an integer" + [n] + (cpp/jank.runtime.is_even n)) +(defn odd? + "Returns true if n is odd, throws an exception if n is not an integer" + [n] + (cpp/jank.runtime.is_odd n)) + +;; Random. +(defn rand + "Returns a random floating point number between 0 (inclusive) and + n (default 1) (exclusive)." + ([] + (cpp/jank.runtime.rand)) + ([n] + (* (rand) n))) + +;; Strings. +(defn subs + "Returns the substring of s beginning at start inclusive, and ending + at end (defaults to length of string), exclusive." + ([s start] + (cpp/jank.runtime.subs s start)) + ([s start end] + (cpp/jank.runtime.subs s start end))) + +;; Sequences (again). +(defn sequential? + "Returns true if coll implements sequential" + [coll] + (cpp/jank.runtime.is_sequential coll)) + +(defn reverse + "Returns a seq of the items in coll in reverse order. Not lazy." + [coll] + (reduce conj '() coll)) + +(defn every? + "Returns true if (pred x) is logical true for every x in coll, else false." + [pred coll] + (cond + (nil? (seq coll)) true + (pred (first coll)) (recur pred (next coll)) + :else false)) + +(defn vector + "Creates a new vector containing the args." + ([] + []) + ([a] + [a]) + ([a b] + [a b]) + ([a b c] + [a b c]) + ([a b c d] + [a b c d]) + ([a b c d e] + [a b c d e]) + ([a b c d e f] + [a b c d e f]) + ([a b c d e f & args] + ; TODO: LazilyPersistentVector + (vec (concat* [a b c d e f] args)))) + +(defn- lazy-seq* [o] (cpp/clojure.core_native.lazy_seq o)) + +(defmacro lazy-seq + "Takes a body of expressions that returns an ISeq or nil, and yields + a Seqable object that will invoke the body only the first time seq + is called, and will cache the result and return it on all subsequent + seq calls. See also - realized?" + [& body] + (list `lazy-seq* (list* `fn `lazy-seq# [] body))) + +(defn chunk-buffer + [capacity] + (cpp/jank.runtime.chunk_buffer capacity)) + +(defn chunk-append + [b x] + (cpp/jank.runtime.chunk_append b x)) + +(defn chunk + [b] + (cpp/jank.runtime.chunk b)) + +(defn chunk-first + [s] + (cpp/jank.runtime.chunk_first s)) + +(defn chunk-next + [s] + (cpp/jank.runtime.chunk_next s)) + +(defn chunk-rest + [s] + (cpp/jank.runtime.chunk_rest s)) + +(defn chunk-cons [chunk rest] + (if (empty? chunk) + rest + (cpp/jank.runtime.chunk_cons chunk rest))) + +(defn chunked-seq? + [s] + (cpp/jank.runtime.is_chunked_seq s)) + +; TODO: Support more bindings +; TODO: Support `for` functionality +(defmacro doseq + "Repeatedly executes body (presumably for side-effects) with + bindings and filtering as provided by `for`. Does not retain + the head of the sequence. Returns nil." + [bindings & body] + (let [arg (first bindings) + s (second bindings)] + (list 'clojure.core/reduce (concat* (list 'clojure.core/fn ['_ arg]) + body + [nil]) + nil + s))) + +(defn concat + "Returns a lazy seq representing the concatenation of the elements in the supplied colls." + ([] (lazy-seq nil)) + ([x] (lazy-seq x)) + ([x y] + (lazy-seq + (let [s (seq x)] + (if s + (if (chunked-seq? s) + (chunk-cons (chunk-first s) (concat (chunk-rest s) y)) + (cons (first s) (concat (rest s) y))) + y)))) + ([x y & zs] + (let [cat* (fn cat* [xys zs] + (lazy-seq + (let [xys (seq xys)] + (if xys + (if (chunked-seq? xys) + (chunk-cons (chunk-first xys) + (cat* (chunk-rest xys) zs)) + (cons (first xys) (cat* (rest xys) zs))) + (when zs + (cat* (first zs) (next zs)))))))] + (cat* (concat x y) zs)))) + +(defn juxt + "Takes a set of functions and returns a fn that is the juxtaposition + of those fns. The returned fn takes a variable number of args, and + returns a vector containing the result of applying each fn to the + args (left-to-right). + ((juxt a b c) x) => [(a x) (b x) (c x)]" + ([f] + (fn + ([] [(f)]) + ([x] [(f x)]) + ([x y] [(f x y)]) + ([x y z] [(f x y z)]) + ([x y z & args] [(apply f x y z args)]))) + ([f g] + (fn + ([] [(f) (g)]) + ([x] [(f x) (g x)]) + ([x y] [(f x y) (g x y)]) + ([x y z] [(f x y z) (g x y z)]) + ([x y z & args] [(apply f x y z args) (apply g x y z args)]))) + ([f g h] + (fn + ([] [(f) (g) (h)]) + ([x] [(f x) (g x) (h x)]) + ([x y] [(f x y) (g x y) (h x y)]) + ([x y z] [(f x y z) (g x y z) (h x y z)]) + ([x y z & args] [(apply f x y z args) (apply g x y z args) (apply h x y z args)]))) + ([f g h & fs] + (let [fs (list* f g h fs)] + (fn + ([] (reduce #(conj %1 (%2)) [] fs)) + ([x] (reduce #(conj %1 (%2 x)) [] fs)) + ([x y] (reduce #(conj %1 (%2 x y)) [] fs)) + ([x y z] (reduce #(conj %1 (%2 x y z)) [] fs)) + ([x y z & args] (reduce #(conj %1 (apply %2 x y z args)) [] fs)))))) + +(defn partial + "Takes a function f and fewer than the normal arguments to f, and + returns a fn that takes a variable number of additional args. When + called, the returned function calls f with args + additional args." + ([f] f) + ([f arg1] + (fn + ([] (f arg1)) + ([x] (f arg1 x)) + ([x y] (f arg1 x y)) + ([x y z] (f arg1 x y z)) + ([x y z & args] (apply f arg1 x y z args)))) + ([f arg1 arg2] + (fn + ([] (f arg1 arg2)) + ([x] (f arg1 arg2 x)) + ([x y] (f arg1 arg2 x y)) + ([x y z] (f arg1 arg2 x y z)) + ([x y z & args] (apply f arg1 arg2 x y z args)))) + ([f arg1 arg2 arg3] + (fn + ([] (f arg1 arg2 arg3)) + ([x] (f arg1 arg2 arg3 x)) + ([x y] (f arg1 arg2 arg3 x y)) + ([x y z] (f arg1 arg2 arg3 x y z)) + ([x y z & args] (apply f arg1 arg2 arg3 x y z args)))) + ([f arg1 arg2 arg3 & more] + (fn [& args] (apply f arg1 arg2 arg3 (concat more args))))) + +(defn fnil + "Takes a function f, and returns a function that calls f, replacing + a nil first argument to f with the supplied value x. Higher arity + versions can replace arguments in the second and third + positions (y, z). Note that the function f can take any number of + arguments, not just the one(s) being nil-patched." + ([f x] + (fn + ([a] (f (if (nil? a) x a))) + ([a b] (f (if (nil? a) x a) b)) + ([a b c] (f (if (nil? a) x a) b c)) + ([a b c & ds] (apply f (if (nil? a) x a) b c ds)))) + ([f x y] + (fn + ([a b] (f (if (nil? a) x a) (if (nil? b) y b))) + ([a b c] (f (if (nil? a) x a) (if (nil? b) y b) c)) + ([a b c & ds] (apply f (if (nil? a) x a) (if (nil? b) y b) c ds)))) + ([f x y z] + (fn + ([a b] (f (if (nil? a) x a) (if (nil? b) y b))) + ([a b c] (f (if (nil? a) x a) (if (nil? b) y b) (if (nil? c) z c))) + ([a b c & ds] (apply f (if (nil? a) x a) (if (nil? b) y b) (if (nil? c) z c) ds))))) + +(defn some + "Returns the first logical true value of (pred x) for any x in coll, + else nil. One common idiom is to use a set as pred, for example + this will return :fred if :fred is in the sequence, otherwise nil: + (some #{:fred} coll)" + [pred coll] + (let [s (seq coll)] + (when s + (or (pred (first s)) (recur pred (next s)))))) + + +(defn every-pred + "Takes a set of predicates and returns a function f that returns true if all of its + composing predicates return a logical true value against all of its arguments, else it returns + false. Note that f is short-circuiting in that it will stop execution on the first + argument that triggers a logical false result against the original predicates." + ([p] + (fn ep1 + ([] true) + ([x] (boolean (p x))) + ([x y] (boolean (and (p x) (p y)))) + ([x y z] (boolean (and (p x) (p y) (p z)))) + ([x y z & args] (boolean (and (ep1 x y z) + (every? p args)))))) + ([p1 p2] + (fn ep2 + ([] true) + ([x] (boolean (and (p1 x) (p2 x)))) + ([x y] (boolean (and (p1 x) (p1 y) (p2 x) (p2 y)))) + ([x y z] (boolean (and (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z)))) + ([x y z & args] (boolean (and (ep2 x y z) + (every? #(and (p1 %) (p2 %)) args)))))) + ([p1 p2 p3] + (fn ep3 + ([] true) + ([x] (boolean (and (p1 x) (p2 x) (p3 x)))) + ([x y] (boolean (and (p1 x) (p1 y) (p2 x) (p2 y) (p3 x) (p3 y)))) + ([x y z] (boolean (and (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z) (p3 x) (p3 y) (p3 z)))) + ([x y z & args] (boolean (and (ep3 x y z) + (every? #(and (p1 %) (p2 %) (p3 %)) args)))))) + ([p1 p2 p3 & ps] + (let [ps (list* p1 p2 p3 ps)] + (fn epn + ([] true) + ([x] (every? #(% x) ps)) + ([x y] (every? #(and (% x) (% y)) ps)) + ([x y z] (every? #(and (% x) (% y) (% z)) ps)) + ([x y z & args] (boolean (and (epn x y z) + (every? #(every? % args) ps)))))))) + +(defn some-fn + "Takes a set of predicates and returns a function f that returns the first logical true value + returned by one of its composing predicates against any of its arguments, else it returns + logical false. Note that f is short-circuiting in that it will stop execution on the first + argument that triggers a logical true result against the original predicates." + ([p] + (fn sp1 + ([] nil) + ([x] (p x)) + ([x y] (or (p x) (p y))) + ([x y z] (or (p x) (p y) (p z))) + ([x y z & args] (or (sp1 x y z) + (some p args))))) + ([p1 p2] + (fn sp2 + ([] nil) + ([x] (or (p1 x) (p2 x))) + ([x y] (or (p1 x) (p1 y) (p2 x) (p2 y))) + ([x y z] (or (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z))) + ([x y z & args] (or (sp2 x y z) + (some #(or (p1 %) (p2 %)) args))))) + ([p1 p2 p3] + (fn sp3 + ([] nil) + ([x] (or (p1 x) (p2 x) (p3 x))) + ([x y] (or (p1 x) (p1 y) (p2 x) (p2 y) (p3 x) (p3 y))) + ([x y z] (or (p1 x) (p1 y) (p1 z) (p2 x) (p2 y) (p2 z) (p3 x) (p3 y) (p3 z))) + ([x y z & args] (or (sp3 x y z) + (some #(or (p1 %) (p2 %) (p3 %)) args))))) + ([p1 p2 p3 & ps] + (let [ps (list* p1 p2 p3 ps)] + (fn spn + ([] nil) + ([x] (some #(% x) ps)) + ([x y] (some #(or (% x) (% y)) ps)) + ([x y z] (some #(or (% x) (% y) (% z)) ps)) + ([x y z & args] (or (spn x y z) + (some #(some % args) ps))))))) + + +(defn not-any? [pred coll] + (not (some pred coll))) + +(defmacro -> + "Threads the expr through the forms. Inserts x as the + second item in the first form, making a list of it if it is not a + list already. If there are more forms, inserts the first form as the + second item in second form, etc." + [x & forms] + (loop* [x x + forms forms] + (if forms + (let [form (first forms) + threaded (if (seq? form) + (with-meta `(~(first form) ~x ~@(next form)) (meta form)) + (list form x))] + (recur threaded (next forms))) + x))) + +(defmacro ->> + "Threads the expr through the forms. Inserts x as the + last item in the first form, making a list of it if it is not a + list already. If there are more forms, inserts the first form as the + last item in second form, etc." + [x & forms] + (loop* [x x + forms forms] + (if forms + (let [form (first forms) + threaded (if (seq? form) + (with-meta `(~(first form) ~@(next form) ~x) (meta form)) + (list form x))] + (recur threaded (next forms))) + x))) + +;; Maps. +(defn key + "Returns the key of the map entry." + [e] + (first e)) + +(defn val + "Returns the value in the map entry." + [e] + (second e)) + +(defn keys + "Returns a sequence of the map's keys, in the same order as (seq map)." + [m] + ; TODO: Use a proper key seq instead. + (reduce (fn [acc kv] + (conj acc (first kv))) + [] + m)) + +(defn vals + "Returns a sequence of the map's values, in the same order as (seq map)." + [m] + ; TODO: Use a proper val seq instead. + (reduce (fn [acc kv] + (conj acc (second kv))) + [] + m)) + +(defn get + "Returns the value mapped to key, not-found or nil if key not present + in associative collection, set, string, array, or ILookup instance." + ([map key] + (cpp/jank.runtime.get map key)) + ([map key not-found] + (cpp/jank.runtime.get map key not-found))) +(defn get-in + "Returns the value in a nested associative structure, + where ks is a sequence of keys. Returns nil if the key + is not present, or the not-found value if supplied." + ([m ks] + (cpp/jank.runtime.get_in m ks)) + ([m ks not-found] + (cpp/jank.runtime.get_in m ks not-found))) + +(defn dissoc + "dissoc[iate]. Returns a new map of the same (hashed/sorted) type, + that does not contain a mapping for key(s)." + ([m] + m) + ([m k] + (cpp/jank.runtime.dissoc m k)) + ([m k & ks] + (let* [ret (dissoc m k)] + (if ks + (recur ret (first ks) (next ks)) + ret)))) + +(defn contains? + "Returns true if key is present in the given collection, otherwise + returns false. Note that for numerically indexed collections like + vectors and Java arrays, this tests if the numeric key is within the + range of indexes. 'contains?' operates constant or logarithmic time; + it will not perform a linear search for a value. See also 'some'." + [coll key] + (cpp/jank.runtime.contains coll key)) + +(defn find + "Returns the map entry for key, or nil if key not present." + [map key] + (cpp/jank.runtime.find map key)) + +(defn select-keys + "Returns a map containing only those entries in map whose key is in keys" + [m ks] + (reduce (fn [acc k] + (let [e (find m k)] + (if e + (conj acc e) + acc))) + {} + ks)) + +(defn zipmap + "Returns a map with the keys mapped to the corresponding vals." + [keys vals] + (loop* [map (transient (hash-map)) + ks (seq keys) + vs (seq vals)] + (if (and ks vs) + (recur (assoc! map (first ks) (first vs)) + (next ks) + (next vs)) + (persistent! map)))) + +;; Sets. +(defn hash-set + "Returns a new hash set with supplied keys. Any equal keys are + handled as if by repeated uses of conj." + ([] (cpp/jank.runtime.obj.persistent_hash_set.empty)) + ([& keys] + (cpp/jank.runtime.obj.persistent_hash_set.create_from_seq keys))) + +(defn sorted-set + "Returns a new sorted set with supplied keys. Any equal keys are + handled as if by repeated uses of conj." + ([] (cpp/jank.runtime.obj.persistent_sorted_set.empty)) + ([& keys] + (cpp/jank.runtime.obj.persistent_sorted_set.create_from_seq keys))) + +(defn sorted-set-by + "Returns a new sorted set with supplied keys, using the supplied + comparator. Any equal keys are handled as if by repeated uses of + conj." + ([comparator & keys] + (throw "not yet implemented: sorted-set-by"))) + +(defn disj + "disj[oin]. Returns a new set of the same (hashed/sorted) type, that + does not contain key(s)." + ([set] + set) + ([set key] + (cpp/jank.runtime.disj set key)) + ([set key & ks] + (let* [res (disj set key)] + (if (empty? ks) + res + (recur res (first ks) (next ks)))))) + +(defn set? + "Returns true if x implements IPersistentSet" + [x] + (cpp/jank.runtime.is_set x)) + +(defn set + "Returns a set of the distinct elements of coll." + [coll] + (if (set? coll) + (with-meta coll nil) + (persistent! (reduce (fn [acc e] + (conj! acc e)) + (transient #{}) + coll)))) + +;; Other. +(defn hash + "Returns the hash code of its argument. Note this is the hash code + consistent with =, and thus is different than .hashCode for Integer, + Short, Byte and Clojure collections." + [o] + (cpp/jank.runtime.to_hash o)) + +(defn- named? + [x] + (cpp/jank.runtime.is_named x)) + +(defn name + "Returns the name String of a string, symbol or keyword." + [x] + (cpp/jank.runtime.name x)) + +(defn namespace + "Returns the namespace String of a symbol or keyword, or nil if not present." + [x] + (cpp/jank.runtime.namespace_ x)) + +;; Sequences. +; This is defined to be lazy later on. +(defn drop + ([n coll] + (let [step (fn [n acc] + (let [s (seq acc)] + (if (and (pos? n) s) + (recur (dec n) (rest s)) + acc)))] + (step n coll)))) + +;; Vars. +(defn var? + "Returns true if v is a var." + [x] + (cpp/clojure.core_native.is_var x)) + +(defn var-get + "Gets the value in the var object." + [x] + (cpp/clojure.core_native.var_get x)) + +(defn alter-var-root + "Atomically alters the root binding of var v by applying f to its + current value plus any args" + [v f & args] + (cpp/clojure.core_native.alter_var_root v f args)) + +(defn bound? + "Returns true if all of the vars provided as arguments have any bound value, root or thread-local. + Implies that deref'ing the provided vars will succeed. Returns true if no vars are provided." + [& vars] + (every? #(cpp/clojure.core_native.is_var_bound %) vars)) + +(defn thread-bound? + "Returns true if all of the vars provided as arguments have thread-local bindings. + Implies that set!'ing the provided vars will succeed. Returns true if no vars are provided." + [& vars] + (every? #(cpp/clojure.core_native.is_var_thread_bound %) vars)) + +(defmacro ^:private assert-macro-args + [& pairs] + (list 'do + (list 'clojure.core/when-not (first pairs) + ; TODO: No need for ex-info, if we had a simpler exception type + (list 'throw (list 'clojure.core/ex-info + (list 'clojure.core/str + '&form + " requires " + (second pairs) + " in " + 'clojure.core/*ns* + ":" + (:line (meta '&form))) + {}))) + (let [more (next (next pairs))] + (when more + (list* 'clojure.core/assert-macro-args more))))) + +(defmacro if-let + "bindings => binding-form test + + If test is true, evaluates then with binding-form bound to the value of + test, if not, yields else" + ([bindings then] + `(if-let ~bindings ~then nil)) + ([bindings then else & oldform] + (assert-macro-args + (vector? bindings) "a vector for its binding" + (nil? oldform) "1 or 2 forms after binding vector" + (= 2 (count bindings)) "exactly 2 forms in binding vector") + (let [form (get bindings 0) + tst (get bindings 1)] + `(let [temp# ~tst] + (if temp# + (let [~form temp#] + ~then) + ~else))))) + +(defmacro when-let + "bindings => binding-form test + + When test is true, evaluates body with binding-form bound to the value of test" + [bindings & body] + (assert-macro-args + (vector? bindings) "a vector for its binding" + (= 2 (count bindings)) "exactly 2 forms in binding vector") + (let [form (get bindings 0) + tst (get bindings 1)] + `(let [temp# ~tst] + (when temp# + (let [~form temp#] + ~@body))))) + +(defmacro if-some + "bindings => binding-form test + + If test is not nil, evaluates then with binding-form bound to the + value of test, if not, yields else" + ([bindings then] + `(if-some ~bindings ~then nil)) + ([bindings then else & oldform] + (assert-macro-args + (vector? bindings) "a vector for its binding" + (nil? oldform) "1 or 2 forms after binding vector" + (= 2 (count bindings)) "exactly 2 forms in binding vector") + (let [form (get bindings 0) tst (get bindings 1)] + `(let [temp# ~tst] + (if (nil? temp#) + ~else + (let [~form temp#] + ~then)))))) + +(defmacro when-some + "bindings => binding-form test + + When test is not nil, evaluates body with binding-form bound to the + value of test" + [bindings & body] + (assert-macro-args + (vector? bindings) "a vector for its binding" + (= 2 (count bindings)) "exactly 2 forms in binding vector") + (let [form (get bindings 0) + tst (get bindings 1)] + `(let [temp# ~tst] + (if (nil? temp#) + nil + (let [~form temp#] + ~@body))))) + +(defmacro dotimes + "bindings => name n + + Repeatedly executes body (presumably for side-effects) with name + bound to integers from 0 through n-1." + [bindings & body] + (assert-macro-args + (vector? bindings) "a vector for its binding" + (= 2 (count bindings)) "exactly 2 forms in binding vector") + (let [i (first bindings) + n (second bindings)] + `(let [n# (int ~n)] + (loop [~i 0] + (when (< ~i n#) + ~@body + ; TODO: unchecked-inc + (recur (inc ~i))))))) + +(defn push-thread-bindings + "WARNING: This is a low-level function. Prefer high-level macros like + binding where ever possible. + + Takes a map of Var/value pairs. Binds each Var to the associated value for + the current thread. Each call *MUST* be accompanied by a matching call to + pop-thread-bindings wrapped in a try-finally! + + (push-thread-bindings bindings) + (try + ... + (finally + (pop-thread-bindings)))" + [bindings] + (cpp/jank.runtime.push_thread_bindings bindings)) + +(defn pop-thread-bindings + "Pop one set of bindings pushed with push-binding before. It is an error to + pop bindings without pushing before." + [] + (cpp/jank.runtime.pop_thread_bindings)) + +(defn get-thread-bindings + "Get a map with the Var/value pairs which is currently in effect for the + current thread." + [] + (cpp/jank.runtime.get_thread_bindings)) + +(defmacro binding + "binding => var-symbol init-expr + + Creates new bindings for the (already-existing) vars, with the + supplied initial values, executes the exprs in an implicit do, then + re-establishes the bindings that existed before. The new bindings + are made in parallel (unlike let); all init-exprs are evaluated + before the vars are bound to their new values." + [bindings & body] + (assert-macro-args + (vector? bindings) "a vector for its binding" + (even? (count bindings)) "an even number of forms in binding vector") + (let [->var-pairs (fn ->var-pairs [var-vals] + (loop [ret [] + vvs (seq var-vals)] + (if vvs + (recur (conj (conj ret `(var ~(first vvs))) (second vvs)) + (next (next vvs))) + (seq ret))))] + `(do + (push-thread-bindings (hash-map ~@(->var-pairs bindings))) + (try + (do ~@body) + (finally + (pop-thread-bindings)))))) + +;; Keywords. +(defn keyword? + "Return true if x is a Keyword" + [x] + (cpp/jank.runtime.is_keyword x)) +(defn simple-keyword? + "Return true if x is a keyword without a namespace" + [x] + (cpp/jank.runtime.is_simple_keyword x)) +(defn qualified-keyword? + "Return true if x is a keyword with a namespace" + [x] + (cpp/jank.runtime.is_qualified_keyword x)) + +(defn keyword + "Returns a Keyword with the given namespace and name. Do not use : + in the keyword strings, it will be added automatically." + ([name] + (cond + (keyword? name) name + (symbol? name) (cpp/jank.runtime.keyword nil (str name)) + (string? name) (cpp/jank.runtime.keyword nil name))) + ([ns name] + (cpp/jank.runtime.keyword ns name))) + +(defn ident? + "Returns true if x is a symbol or keyword" + [x] + (or (keyword? x) (symbol? x))) + +(defn simple-ident? + "Returns true if x is a symbol or keyword without a namespace" + [x] + (and (ident? x) (nil? (namespace x)))) + +(defn qualified-ident? + "Returns true if x is a symbol or keyword with a namespace" + [x] + (boolean (and (ident? x) (namespace x) true))) + +;; Sequences. +(defn iterate + "Returns a lazy (infinite!) sequence of x, (f x), (f (f x)) etc. + f must be free of side-effects" + [fn x] + (cpp/jank.runtime.iterate fn x)) + +(defn range + "Returns a lazy seq of nums from start (inclusive) to end + (exclusive), by step, where start defaults to 0, step to 1, and end to + infinity. When step is equal to 0, returns an infinite sequence of + start. When start is equal to end, returns empty list." + ([] + (iterate inc 0)) + ([end] + (if (integer? end) + (cpp/jank.runtime.obj.integer_range.create end) + (cpp/jank.runtime.obj.range.create end))) + ([start end] + (if (and (integer? start) (integer? end)) + (cpp/jank.runtime.obj.integer_range.create start end) + (cpp/jank.runtime.obj.range.create start end))) + ([start end step] + (if (and (integer? start) (integer? end) (integer? step)) + (cpp/jank.runtime.obj.integer_range.create start end step) + (cpp/jank.runtime.obj.range.create start end step)))) + +(defn nth + "Returns the value at the index. get returns nil if index out of + bounds, nth throws an exception unless not-found is supplied. nth + also works for strings, Java arrays, regex Matchers and Lists, and, + in O(n) time, for sequences." + ([coll index] + (cpp/jank.runtime.nth coll index)) + ([coll index not-found] + (cpp/jank.runtime.nth coll index not-found))) + +(defn nthnext + "Returns the nth next of coll, (seq coll) when n is 0." + [coll n] + ;; TODO add support for IDrop + (loop [n n xs (seq coll)] + (if (and xs (pos? n)) + (recur (dec n) (next xs)) + xs))) + +(defn nthrest + "Returns the nth rest of coll, coll when n is 0." + [coll n] + ;; TODO add support for IDrop + (if (pos? n) + (if-let [xs (seq coll)] + (recur (rest xs) (dec n)) + (or (seq coll) ())) + coll)) + +(defn take-nth + "Returns a lazy seq of every nth item in coll. Returns a stateful + transducer when no collection is provided." + ([n] + (fn [rf] + (let [iv (volatile! -1)] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] + (let [i (vswap! iv inc)] + (if (zero? (rem i n)) + (rf result input) + result))))))) + ([n coll] + (lazy-seq + (when-let [s (seq coll)] + (cons (first s) (take-nth n (drop n s))))))) + +(defn map + "Returns a lazy sequence consisting of the result of applying f to + the set of first items of each coll, followed by applying f to the + set of second items in each coll, until any one of the colls is + exhausted. Any remaining items in other colls are ignored. Function + f should accept number-of-colls arguments. Returns a transducer when + no collection is provided." + ([f] + (fn [rf] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] + (rf result (f input))) + ([result input & inputs] + (rf result (apply f input inputs)))))) + ([f coll] + (lazy-seq + (when-let [s (seq coll)] + (if (chunked-seq? s) + (let [c (chunk-first s) + size (int (count c)) + b (chunk-buffer size)] + (dotimes [i size] + (chunk-append b (f (nth c i)))) + (chunk-cons (chunk b) (map f (chunk-rest s)))) + (cons (f (first s)) (map f (rest s))))))) + ([f c1 c2] + (lazy-seq + (let [s1 (seq c1) + s2 (seq c2)] + (when (and s1 s2) + (cons (f (first s1) (first s2)) + (map f (rest s1) (rest s2))))))) + ([f c1 c2 c3] + (lazy-seq + (let [s1 (seq c1) + s2 (seq c2) + s3 (seq c3)] + (when (and s1 s2 s3) + (cons (f (first s1) (first s2) (first s3)) + (map f (rest s1) (rest s2) (rest s3))))))) + ([f c1 c2 c3 & colls] + (let [step (fn step [cs] + (lazy-seq + (let [ss (map seq cs)] + (when (every? identity ss) + (cons (map first ss) (step (map rest ss)))))))] + (map #(apply f %) (step (conj colls c3 c2 c1)))))) + +(defmacro doto + "Evaluates x then calls all of the methods and functions with the + value of x supplied at the front of the given arguments. The forms + are evaluated in order. Returns x." + [x & forms] + (let [gx (gensym)] + `(let [~gx ~x] + ~@(map (fn [f] + (with-meta + (if (seq? f) + `(~(first f) ~gx ~@(next f)) + `(~f ~gx)) + (meta f))) + forms) + ~gx))) + +(defn map-indexed + "Returns a lazy sequence consisting of the result of applying f to 0 + and the first item of coll, followed by applying f to 1 and the second + item in coll, etc, until coll is exhausted. Thus function f should + accept 2 arguments, index and item. Returns a stateful transducer when + no collection is provided." + ([f] + (fn [rf] + (let [i (volatile! -1)] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] + (rf result (f (vswap! i inc) input))))))) + ([f coll] + (let [mapi (fn mapi [idx coll] + (lazy-seq + (when-let [s (seq coll)] + (if (chunked-seq? s) + (let [c (chunk-first s) + size (int (count c)) + b (chunk-buffer size)] + (dotimes [i size] + (chunk-append b (f (+ idx i) (nth c i)))) + (chunk-cons (chunk b) (mapi (+ idx size) (chunk-rest s)))) + (cons (f idx (first s)) (mapi (inc idx) (rest s)))))))] + (mapi 0 coll)))) + +(defn keep + "Returns a lazy sequence of the non-nil results of (f item). Note, + this means false return values will be included. f must be free of + side-effects. Returns a transducer when no collection is provided." + ([f] + (fn [rf] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] + (let [v (f input)] + (if (nil? v) + result + (rf result v))))))) + ([f coll] + (lazy-seq + (when-let [s (seq coll)] + (if (chunked-seq? s) + (let [c (chunk-first s) + size (count c) + b (chunk-buffer size)] + (dotimes [i size] + (let [x (f (nth c i))] + (when-not (nil? x) + (chunk-append b x)))) + (chunk-cons (chunk b) (keep f (chunk-rest s)))) + (let [x (f (first s))] + (if (nil? x) + (keep f (rest s)) + (cons x (keep f (rest s)))))))))) + +(defn keep-indexed + "Returns a lazy sequence of the non-nil results of (f index item). Note, + this means false return values will be included. f must be free of + side-effects. Returns a stateful transducer when no collection is + provided." + ([f] + (fn [rf] + (let [iv (volatile! -1)] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] + (let [i (vswap! iv inc) + v (f i input)] + (if (nil? v) + result + (rf result v)))))))) + ([f coll] + (let [keepi (fn keepi [idx coll] + (lazy-seq + (when-let [s (seq coll)] + (if (chunked-seq? s) + (let [c (chunk-first s) + size (count c) + b (chunk-buffer size)] + (dotimes [i size] + (let [x (f (+ idx i) (nth c i))] + (when-not (nil? x) + (chunk-append b x)))) + (chunk-cons (chunk b) (keepi (+ idx size) (chunk-rest s)))) + (let [x (f idx (first s))] + (if (nil? x) + (keepi (inc idx) (rest s)) + (cons x (keepi (inc idx) (rest s)))))))))] + (keepi 0 coll)))) + +(defn take + "Returns a lazy sequence of the first n items in coll, or all items if + there are fewer than n. Returns a stateful transducer when + no collection is provided." + ([n] + (fn [rf] + (let [nv (volatile! n)] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] + (let [n (deref nv) + nn (vswap! nv dec) + result (if (pos? n) + (rf result input) + result)] + (if (not (pos? nn)) + (ensure-reduced result) + result))))))) + ([n coll] + (lazy-seq + (when (pos? n) + (when-let [s (seq coll)] + (cons (first s) (take (dec n) (rest s)))))))) + +(defn repeatedly + "Takes a function of no args, presumably with side effects, and + returns an infinite (or length n if supplied) lazy sequence of calls + to it" + ([f] (lazy-seq (cons (f) (repeatedly f)))) + ([n f] (take n (repeatedly f)))) + +(defn take-while + "Returns a lazy sequence of successive items from coll while + (pred item) returns logical true. pred must be free of side-effects. + Returns a transducer when no collection is provided" + ([pred] + (fn [rf] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] + (if (pred input) + (rf result input) + (reduced result)))))) + ([pred coll] + (lazy-seq + (when-let [s (seq coll)] + (when (pred (first s)) + (cons (first s) (take-while pred (rest s)))))))) + +(defn drop + "Returns a lazy sequence of all but the first n items in coll. + Returns a stateful transducer when no collection is provided." + ([n] + (fn [rf] + (let [nv (volatile! n)] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] + (let [n (deref nv)] + (vswap! nv dec) + (if (pos? n) + result + (rf result input)))))))) + ([n coll] + (let [step (fn [n coll] + (let [s (seq coll)] + (if (and (pos? n) s) + (recur (dec n) (rest s)) + s)))] + (lazy-seq (step n coll))))) + +(defn drop-last + "Return a lazy sequence of all but the last n (default 1) items in coll" + ([coll] (drop-last 1 coll)) + ([n coll] (map (fn [x _] x) coll (drop n coll)))) + +(defn drop-while + "Returns a lazy sequence of the items in coll starting from the + first item for which (pred item) returns logical false. Returns a + stateful transducer when no collection is provided." + ([pred] + (fn [rf] + (let [dv (volatile! true)] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] + (let [drop? (deref dv)] + (if (and drop? (pred input)) + result + (do + (vreset! dv nil) + (rf result input))))))))) + ([pred coll] + (let [step (fn [pred coll] + (let [s (seq coll)] + (if (and s (pred (first s))) + (recur pred (rest s)) + s)))] + (lazy-seq (step pred coll))))) + +(defn cycle + "Returns a lazy (infinite!) sequence of repetitions of the items in coll." + [coll] + ; TODO: Custom cycle object + (lazy-seq (concat coll (cycle coll)))) + +(defn repeat + "Returns a lazy (infinite!, or length n if supplied) sequence of val." + ([x] + (cpp/jank.runtime.obj.repeat.create x)) + ([n x] + (cpp/jank.runtime.obj.repeat.create n x))) + +(defn split-at + "Returns a vector of [(take n coll) (drop n coll)]" + [n coll] + [(take n coll) (drop n coll)]) + +(defn split-with + "Returns a vector of [(take-while pred coll) (drop-while pred coll)]" + [pred coll] + [(take-while pred coll) (drop-while pred coll)]) + +(defn interleave + "Returns a lazy seq of the first item in each coll, then the second etc." + ([] ()) + ([c1] (lazy-seq c1)) + ([c1 c2] + (lazy-seq + (let [s1 (seq c1) s2 (seq c2)] + (when (and s1 s2) + (cons (first s1) (cons (first s2) + (interleave (rest s1) (rest s2)))))))) + ([c1 c2 & colls] + (lazy-seq + (let [ss (map seq (conj colls c2 c1))] + (when (every? identity ss) + (concat (map first ss) (apply interleave (map rest ss)))))))) + +(defn interpose + "Returns a lazy seq of the elements of coll separated by sep. + Returns a stateful transducer when no collection is provided." + ([sep] + (fn [rf] + (let [started (volatile! false)] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] + (if (deref started) + (let [sepr (rf result sep)] + (if (reduced? sepr) + sepr + (rf sepr input))) + (do + (vreset! started true) + (rf result input)))))))) + ([sep coll] + (drop 1 (interleave (repeat sep) coll)))) + +(defn dorun + "When lazy sequences are produced via functions that have side + effects, any effects other than those needed to produce the first + element in the seq do not occur until the seq is consumed. dorun can + be used to force any effects. Walks through the successive nexts of + the seq, does not retain the head and returns nil." + ([coll] + (when-let [s (seq coll)] + (recur (next s)))) + ([n coll] + (when (and (seq coll) (pos? n)) + (recur (dec n) (next coll))))) + +(defn doall + "When lazy sequences are produced via functions that have side + effects, any effects other than those needed to produce the first + element in the seq do not occur until the seq is consumed. doall can + be used to force any effects. Walks through the successive nexts of + the seq, retains the head and returns it, thus causing the entire + seq to reside in memory at one time." + ([coll] + (dorun coll) + coll) + ([n coll] + (dorun n coll) + coll)) + +(defn partition + "Returns a lazy sequence of lists of n items each, at offsets step + apart. If step is not supplied, defaults to n, i.e. the partitions + do not overlap. If a pad collection is supplied, use its elements as + necessary to complete last partition upto n items. In case there are + not enough padding elements, return a partition with less than n items." + ([n coll] + (partition n n coll)) + ([n step coll] + (lazy-seq + (when-let [s (seq coll)] + (let [p (doall (take n s))] + (when (= n (count p)) + (cons p (partition n step (nthrest s step)))))))) + ([n step pad coll] + (lazy-seq + (when-let [s (seq coll)] + (let [p (doall (take n s))] + (if (= n (count p)) + (cons p (partition n step pad (nthrest s step))) + (list (take n (concat p pad))))))))) + +(defn partition-all + "Returns a lazy sequence of lists like partition, but may include + partitions with fewer than n items at the end. Returns a stateful + transducer when no collection is provided." + ([n] + (fn [rf] + ;; OPTIMIZE: jvm clojure uses an array here for perf + (let [part (volatile! [])] + (fn + ([] (rf)) + ([result] + (let [p (deref part) + result (if (empty? p) + result + (unreduced (rf result p)))] + (rf result))) + ([result input] + (let [p (vswap! part conj input)] + (if (= n (count p)) + (do (vreset! part []) + (rf result p)) + result))))))) + ([n coll] + (partition-all n n coll)) + ([n step coll] + (lazy-seq + (when-let [s (seq coll)] + (let [seg (doall (take n s))] + (cons seg (partition-all n step (nthrest s step)))))))) + +(defn partition-by + "Applies f to each value in coll, splitting it each time f returns a + new value. Returns a lazy seq of partitions. Returns a stateful + transducer when no collection is provided." + ([f] + (fn [rf] + ;; OPTIMIZE: jvm clojure uses an array here for perf + (let [vv (volatile! []) + pv (volatile! ::none)] + (fn + ([] (rf)) + ([result] + (let [v (deref vv) + result (if (empty? v) + result + (unreduced (rf result v)))] + (rf result))) + ([result input] + (let [pval (deref pv) + val (f input)] + (vreset! pv val) + (if (or (identical? pval ::none) + (= val pval)) + (do + (vswap! vv conj input) + result) + (let [v (deref vv) + ret (rf result v)] + (when-not (reduced? ret) + (vreset! vv [input])) + ret)))))))) + ([f coll] + (lazy-seq + (when-let [s (seq coll)] + (let [fst (first s) + fv (f fst) + run (cons fst (take-while #(= fv (f %)) (next s)))] + (cons run (partition-by f (lazy-seq (drop (count run) s))))))))) + +(defn frequencies + "Returns a map from distinct items in coll to the number of times + they appear." + [coll] + (persistent! + (reduce + (fn [counts x] + (assoc! counts x (inc (get counts x 0)))) + (transient {}) + coll))) + +(defn group-by + "Returns a map of the elements of coll keyed by the result of + f on each element. The value at each key will be a vector of the + corresponding elements, in the order they appeared in coll." + [f coll] + (persistent! + (reduce + (fn [ret x] + (let [k (f x)] + (assoc! ret k (conj (get ret k []) x)))) + (transient {}) + coll))) + +(defn reductions + "Returns a lazy seq of the intermediate values of the reduction (as + per reduce) of coll by f, starting with init." + ([f coll] + (lazy-seq + (if-let [s (seq coll)] + (reductions f (first s) (rest s)) + (list (f))))) + ([f init coll] + (if (reduced? init) + (list (deref init)) + (cons init + (lazy-seq + (when-let [s (seq coll)] + (reductions f (f init (first s)) (rest s)))))))) + +(defn into + "Returns a new coll consisting of to-coll with all of the items of + from-coll conjoined. A transducer may be supplied." + ([] []) + ([to] to) + ([to from] + (if (transientable? to) + (with-meta (persistent! (reduce conj! (transient to) from)) (meta to)) + (reduce conj to from))) + ([to xform from] + (if (transientable? to) + (with-meta (persistent! (transduce xform conj! (transient to) from)) (meta to)) + (transduce xform conj to from)))) + +; Redefine let and loop with destructuring. +(defn destructure + [bindings] + (let [bents (partition 2 bindings) + pb (fn pb [bvec b v] + (let [pvec + (fn pvec [bvec b val] + (let [gvec (gensym "vec") + gseq (gensym "seq") + gfirst (gensym "first") + has-rest (some #{'&} b)] + (loop [ret (let [ret (conj bvec gvec val)] + (if has-rest + (conj ret gseq (list `seq gvec)) + ret)) + n 0 + bs b + seen-rest? false] + (if (seq bs) + (let [firstb (first bs)] + (cond + (= firstb '&) (recur (pb ret (second bs) gseq) + n + (nnext bs) + true) + (= firstb :as) (pb ret (second bs) gvec) + :else (if seen-rest? + (throw "Unsupported binding form, only :as can follow & parameter") + (recur (pb (if has-rest + (conj ret + gfirst `(first ~gseq) + gseq `(next ~gseq)) + ret) + firstb + (if has-rest + gfirst + (list `nth gvec n nil))) + (inc n) + (next bs) + seen-rest?)))) + ret)))) + pmap + (fn pmap [bvec b v] + (let [gmap (gensym "map") + defaults (:or b)] + (loop [ret (-> bvec + (conj gmap) (conj v) + (conj gmap) (conj `(if (seq? ~gmap) + (if (next ~gmap) + (into {} ~gmap) + (if (seq ~gmap) + (first ~gmap) + {})) + ~gmap)) + ((fn pmap#ret [ret] + (if (:as b) + (conj ret (:as b) gmap) + ret)))) + bes (let [transforms + (reduce + (fn pmap#transforms [transforms mk] + (if (keyword? mk) + (let [mkns (namespace mk) + mkn (name mk)] + (cond (= mkn "keys") (assoc transforms mk #(keyword (or mkns (namespace %)) (name %))) + (= mkn "syms") (assoc transforms mk #(list `quote (symbol (or mkns (namespace %)) (name %)))) + (= mkn "strs") (assoc transforms mk str) + :else transforms)) + transforms)) + {} + (keys b))] + (reduce + (fn pmap#bes [bes entry] + (reduce #(assoc %1 %2 ((val entry) %2)) + (dissoc bes (key entry)) + ((key entry) bes))) + (dissoc b :as :or) + transforms))] + (if (seq bes) + (let [bb (key (first bes)) + bk (val (first bes)) + local (if (named? bb) + (with-meta (symbol nil (name bb)) (meta bb)) + bb) + bv (if (contains? defaults local) + (list `get gmap bk (defaults local)) + (list `get gmap bk))] + (recur (if (ident? bb) + (-> ret (conj local bv)) + (pb ret bb bv)) + (next bes))) + ret))))] + (cond + (symbol? b) (-> bvec (conj b) (conj v)) + (vector? b) (pvec bvec b v) + (map? b) (pmap bvec b v) + :else (throw (str "Unsupported binding form: " b))))) + process-entry (fn process-entry [bvec b] + (pb bvec (first b) (second b)))] + (if (every? symbol? (map first bents)) + bindings + (reduce process-entry [] bents)))) + +(defmacro let + "binding => binding-form init-expr + binding-form => name, or destructuring-form + destructuring-form => map-destructure-form, or seq-destructure-form + + Evaluates the exprs in a lexical context in which the symbols in + the binding-forms are bound to their respective init-exprs or parts + therein. + + See https://clojure.org/reference/special_forms#binding-forms for + more information about destructuring." + [bindings & body] + (assert-macro-args + (vector? bindings) "a vector for its binding" + (even? (count bindings)) "an even number of forms in binding vector") + `(let* ~(destructure bindings) ~@body)) + +(defn maybe-destructured + {:private true} + [params body] + (if (every? symbol? params) + (cons params body) + (loop [params params + new-params (with-meta [] (meta params)) + lets []] + (if params + (if (symbol? (first params)) + (recur (next params) (conj new-params (first params)) lets) + (let [gparam (gensym "p__")] + (recur (next params) (conj new-params gparam) + (-> lets (conj (first params)) (conj gparam))))) + `(~new-params + (let ~lets + ~@body)))))) + +(defmacro fn + "params => positional-params*, or positional-params* & rest-param + positional-param => binding-form + rest-param => binding-form + binding-form => name, or destructuring-form + + Defines a function. + + See https://clojure.org/reference/special_forms#fn for more information" + [& sigs] + (let [name (if (symbol? (first sigs)) (first sigs) nil) + sigs (if name (next sigs) sigs) + sigs (if (vector? (first sigs)) + (list sigs) + (if (seq? (first sigs)) + sigs + ; Assume single arity syntax + (throw (if (seq sigs) + (str "Parameter declaration " + (first sigs) + " should be a vector") + (str "Parameter declaration missing"))))) + psig (fn* [sig] + ; Ensure correct type before destructuring sig + (when (not (seq? sig)) + (throw (str "Invalid signature " sig + " should be a list"))) + (let [[params & body] sig + _ (when (not (vector? params)) + (throw (if (seq? (first sigs)) + (str "Parameter declaration " params + " should be a vector") + (str "Invalid signature " sig + " should be a list")))) + conds (when (and (next body) (map? (first body))) + (first body)) + body (if conds (next body) body) + conds (or conds (meta params)) + pre (:pre conds) + post (:post conds) + body (if post + `((let [~'% ~(if (< 1 (count body)) + `(do ~@body) + (first body))] + ~@(map (fn* [c] + `(assert ~c)) post) + ~'%)) + body) + body (if pre + (concat (map (fn* [c] + `(assert ~c)) pre) + body) + body)] + (maybe-destructured params body))) + new-sigs (map psig sigs)] + (with-meta + (if name + `(fn* ~name ~@new-sigs) + `(fn* ~@new-sigs)) + (meta &form)))) + +(defmacro loop + "Evaluates the exprs in a lexical context in which the symbols in + the binding-forms are bound to their respective init-exprs or parts + therein. Acts as a recur target." + [all-bindings & body] + (assert-macro-args + (vector? all-bindings) "a vector for its binding" + (even? (count all-bindings)) "an even number of forms in binding vector") + (let [db (destructure all-bindings)] + (if (= db all-bindings) + `(loop* ~all-bindings ~@body) + (let [values (take-nth 2 (drop 1 all-bindings)) + bindings (take-nth 2 all-bindings) + syms (map (fn [b] + (if (symbol? b) + b + (gensym))) + bindings) + final-bindings (reduce (fn [ret [b v g]] + (if (symbol? b) + (conj ret g v) + (conj ret g v b g))) + [] + (map vector bindings values syms))] + `(let ~final-bindings + (loop* ~(vec (interleave syms syms)) + (let ~(vec (interleave bindings syms)) + ~@body))))))) + +(defmacro for + "List comprehension. Takes a vector of one or more + binding-form/collection-expr pairs, each followed by zero or more + modifiers, and yields a lazy sequence of evaluations of expr. + Collections are iterated in a nested fashion, rightmost fastest, + and nested coll-exprs can refer to bindings created in prior + binding-forms. Supported modifiers are: :let [binding-form expr ...], + :while test, :when test. + + (take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))" + [seq-exprs body-expr] + (assert-macro-args + (vector? seq-exprs) "a vector for its binding" + (even? (count seq-exprs)) "an even number of forms in binding vector") + (let [to-groups (fn [seq-exprs] + (reduce (fn [groups [k v]] + (if (keyword? k) + (conj (pop groups) (conj (peek groups) [k v])) + (conj groups [k v]))) + [] (partition 2 seq-exprs))) + err (fn [& msg] (throw (apply str msg))) + emit-bind (fn emit-bind [[[bind expr & mod-pairs] + & [[_ next-expr] :as next-groups]]] + (let [giter (gensym "iter__") + gxs (gensym "s__") + do-mod (fn do-mod [[[k v :as pair] & etc]] + (cond + (= k :let) `(let ~v ~(do-mod etc)) + (= k :while) `(when ~v ~(do-mod etc)) + (= k :when) `(if ~v + ~(do-mod etc) + (recur (rest ~gxs))) + (keyword? k) (err "Invalid 'for' keyword " k) + next-groups + `(let [iterys# ~(emit-bind next-groups) + fs# (seq (iterys# ~next-expr))] + (if fs# + (concat fs# (~giter (rest ~gxs))) + (recur (rest ~gxs)))) + :else (do + `(cons ~body-expr + (~giter (rest ~gxs))))))] + (if next-groups + ; not the inner-most loop + `(fn ~giter [~gxs] + (lazy-seq + (loop [~gxs ~gxs] + (when-first [~bind ~gxs] + ~(do-mod mod-pairs))))) + ; inner-most loop + (let [gi (gensym "i__") + gb (gensym "b__") + do-cmod (fn do-cmod [[[k v :as pair] & etc]] + (cond + (= k :let) `(let ~v ~(do-cmod etc)) + (= k :while) `(when ~v ~(do-cmod etc)) + (= k :when) `(if ~v + ~(do-cmod etc) + (recur + ; TODO: unchecked-inc + (inc ~gi))) + (keyword? k) + (err "Invalid 'for' keyword " k) + :else + `(do (chunk-append ~gb ~body-expr) + ; TODO: unchecked-inc + (recur (inc ~gi)))))] + `(fn ~giter [~gxs] + (lazy-seq + (loop [~gxs ~gxs] + (when-let [~gxs (seq ~gxs)] + (if (chunked-seq? ~gxs) + (let [c# (chunk-first ~gxs) + size# (int (count c#)) + ~gb (chunk-buffer size#)] + (if (loop [~gi (int 0)] + (if (< ~gi size#) + (let [~bind (nth c# ~gi)] + ~(do-cmod mod-pairs)) + true)) + (chunk-cons + (chunk ~gb) + (~giter (chunk-rest ~gxs))) + (chunk-cons (chunk ~gb) nil))) + (let [~bind (first ~gxs)] + ~(do-mod mod-pairs)))))))))))] + `(let [iter# ~(emit-bind (to-groups seq-exprs))] + (iter# ~(second seq-exprs))))) + +(defn not-empty + "If coll is empty, returns nil, else coll" + [coll] + (when (seq coll) + coll)) + +(defn get-in + "Returns the value in a nested associative structure, + where ks is a sequence of keys. Returns nil if the key + is not present, or the not-found value if supplied." + ([m ks] + (reduce get m ks)) + ([m ks not-found] + (loop [m m + ks (seq ks)] + (if ks + (let [m (get m (first ks) ::none)] + (if (identical? ::none m) + not-found + (recur m (next ks)))) + m)))) + +(defn assoc-in + "Associates a value in a nested associative structure, where ks is a + sequence of keys and v is the new value and returns a new nested structure. + If any levels do not exist, hash-maps will be created." + [m [k & ks] v] + (if ks + (assoc m k (assoc-in (get m k) ks v)) + (assoc m k v))) + +(defn update-in + "'Updates' a value in a nested associative structure, where ks is a + sequence of keys and f is a function that will take the old value + and any supplied args and return the new value, and returns a new + nested structure. If any levels do not exist, hash-maps will be + created." + [m ks f & args] + (let [up (fn up [m ks f args] + (let [[k & ks] ks] + (if ks + (assoc m k (up (get m k) ks f args)) + (assoc m k (apply f (get m k) args)))))] + (up m ks f args))) + +(defn update + "'Updates' a value in an associative structure, where k is a + key and f is a function that will take the old value + and any supplied args and return the new value, and returns a new + structure. If the key does not exist, nil is passed as the old value." + ([m k f] + (assoc m k (f (get m k)))) + ([m k f x] + (assoc m k (f (get m k) x))) + ([m k f x y] + (assoc m k (f (get m k) x y))) + ([m k f x y z] + (assoc m k (f (get m k) x y z))) + ([m k f x y z & more] + (assoc m k (apply f (get m k) x y z more)))) + +(defmacro when-first + "bindings => x xs + + Roughly the same as (when (seq xs) (let [x (first xs)] body)) but xs is evaluated only once" + [bindings & body] + (assert-macro-args + (vector? bindings) "a vector for its binding" + (= 2 (count bindings)) "exactly 2 forms in binding vector") + (let [[x xs] bindings] + `(when-let [xs# (seq ~xs)] + (let [~x (first xs#)] + ~@body)))) + +(defn take-last + "Returns a seq of the last n items in coll. Depending on the type + of coll may be no better than linear time. For vectors, see also subvec." + [n coll] + (loop [s (seq coll) + lead (seq (drop n coll))] + (if lead + (recur (next s) (next lead)) + s))) + +(defn mapv + "Returns a vector consisting of the result of applying f to the + set of first items of each coll, followed by applying f to the set + of second items in each coll, until any one of the colls is + exhausted. Any remaining items in other colls are ignored. Function + f should accept number-of-colls arguments." + ([f coll] + (-> (reduce (fn [v o] + (conj! v (f o))) + (transient []) + coll) + persistent!)) + ([f c1 c2] + (into [] (map f c1 c2))) + ([f c1 c2 c3] + (into [] (map f c1 c2 c3))) + ([f c1 c2 c3 & colls] + (into [] (apply map f c1 c2 c3 colls)))) + +(defn filterv + "Returns a vector of the items in coll for which + (pred item) returns logical true. pred must be free of side-effects." + [pred coll] + (-> (reduce (fn [v o] + (if (pred o) + (conj! v o) + v)) + (transient []) + coll) + persistent!)) + +(defn mapcat + "Returns the result of applying concat to the result of applying map + to f and colls. Thus function f should return a collection. Returns + a transducer when no collections are provided" + ([f] (comp (map f) cat)) + ; TODO: Variadic. + ([f coll] + (apply concat (map f coll)))) + +(defn tree-seq + "Returns a lazy sequence of the nodes in a tree, via a depth-first walk. + branch? must be a fn of one arg that returns true if passed a node + that can have children (but may not). children must be a fn of one + arg that returns a sequence of the children. Will only be called on + nodes for which branch? returns true. Root is the root node of the + tree." + [branch? children root] + (let [walk (fn walk [node] + (lazy-seq + (cons node + (when (branch? node) + (mapcat walk (children node))))))] + (walk root))) + +(defn distinct + "Returns a lazy sequence of the elements of coll with duplicates removed. + Returns a stateful transducer when no collection is provided." + ([] + (fn [rf] + (let [seen (volatile! #{})] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] + (if (contains? (deref seen) input) + result + (do (vswap! seen conj input) + (rf result input)))))))) + ([coll] + (let [step (fn step [xs seen] + (lazy-seq + ((fn [[f :as xs] seen] + (when-let [s (seq xs)] + (if (contains? seen f) + (recur (rest s) seen) + (cons f (step (rest s) (conj seen f)))))) + xs seen)))] + (step coll #{})))) + +(defn distinct? + "Returns true if no two of the arguments are =" + ([x] true) + ([x y] (not (= x y))) + ([x y & more] + (if (not= x y) + (loop [s #{x y} + [x & etc :as xs] more] + (if xs + (if (contains? s x) + false + (recur (conj s x) etc)) + true)) + false))) + +(defn filter + "Returns a lazy sequence of the items in coll for which + (pred item) returns logical true. pred must be free of side-effects. + Returns a transducer when no collection is provided." + ([pred] + (fn [rf] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] + (if (pred input) + (rf result input) + result))))) + ([pred coll] + (lazy-seq + (when-let [s (seq coll)] + (if (chunked-seq? s) + (let [c (chunk-first s) + size (count c) + b (chunk-buffer size)] + (dotimes [i size] + (let [v (nth c i)] + (when (pred v) + (chunk-append b v)))) + (chunk-cons (chunk b) (filter pred (chunk-rest s)))) + (let [f (first s) r (rest s)] + (if (pred f) + (cons f (filter pred r)) + (filter pred r)))))))) + +(defn flatten + "Takes any nested combination of sequential things (lists, vectors, + etc.) and returns their contents as a single, flat lazy sequence. + (flatten nil) returns an empty sequence." + [x] + (filter (complement sequential?) + (rest (tree-seq sequential? seq x)))) + +(defn remove + "Returns a lazy sequence of the items in coll for which + (pred item) returns logical false. pred must be free of side-effects. + Returns a transducer when no collection is provided." + ([pred] + (filter (complement pred))) + ([pred coll] + (filter (complement pred) coll))) + +(defn dedupe + "Returns a lazy sequence removing consecutive duplicates in coll. + Returns a transducer when no collection is provided." + ([] + (fn [rf] + (let [pv (volatile! ::none)] + (fn + ([] (rf)) + ([result] (rf result)) + ([result input] + (let [prior (deref pv)] + (vreset! pv input) + (if (= prior input) + result + (rf result input)))))))) + ([coll] + (let [step (fn step [prior xs] + (lazy-seq + (when-some [[x & more] (seq xs)] + (if (= x prior) + (step prior more) + (cons x (step x more))))))] + (step ::none coll)))) + +(defmacro condp + "Takes a binary predicate, an expression, and a set of clauses. + Each clause can take the form of either: + + test-expr result-expr + + test-expr :>> result-fn + + Note :>> is an ordinary keyword. + + For each clause, (pred test-expr expr) is evaluated. If it returns + logical true, the clause is a match. If a binary clause matches, the + result-expr is returned, if a ternary clause matches, its result-fn, + which must be a unary function, is called with the result of the + predicate as its argument, the result of that call being the return + value of condp. A single default expression can follow the clauses, + and its value will be returned if no clause matches. If no default + expression is provided and no clause matches, an + IllegalArgumentException is thrown." + [pred expr & clauses] + (let [gpred (gensym "pred__") + gexpr (gensym "expr__") + emit (fn emit [pred expr args] + (let [[[a b c :as clause] more] + (split-at (if (= :>> (second args)) 3 2) args) + n (count clause)] + (cond + (= 0 n) `(throw (str "No matching clause: " ~expr)) + (= 1 n) a + (= 2 n) `(if (~pred ~a ~expr) + ~b + ~(emit pred expr more)) + :else `(if-let [p# (~pred ~a ~expr)] + (~c p#) + ~(emit pred expr more)))))] + `(let [~gpred ~pred + ~gexpr ~expr] + ~(emit gpred gexpr clauses)))) + +(defmacro cond-> + "Takes an expression and a set of test/form pairs. Threads expr (via ->) + through each form for which the corresponding test + expression is true. Note that, unlike cond branching, cond-> threading does + not short circuit after the first true test expression." + [expr & clauses] + (assert (even? (count clauses))) + (let [g (gensym) + steps (map (fn [test+step] + (let [test (first test+step) + step (second test+step)] + `(if ~test + (-> ~g ~step) + ~g))) + (partition 2 clauses))] + `(let [~g ~expr + ~@(interleave (repeat g) (butlast steps))] + ~(if (empty? steps) + g + (last steps))))) + +(defmacro cond->> + "Takes an expression and a set of test/form pairs. Threads expr (via ->>) + through each form for which the corresponding test expression + is true. Note that, unlike cond branching, cond->> threading does not short circuit + after the first true test expression." + [expr & clauses] + (assert (even? (count clauses))) + (let [g (gensym) + steps (map (fn [[test step]] `(if ~test (->> ~g ~step) ~g)) + (partition 2 clauses))] + `(let [~g ~expr + ~@(interleave (repeat g) (butlast steps))] + ~(if (empty? steps) + g + (last steps))))) + +(defmacro as-> + "Binds name to expr, evaluates the first form in the lexical context + of that binding, then binds name to that result, repeating for each + successive form, returning the result of the last form." + [expr name & forms] + `(let [~name ~expr + ~@(interleave (repeat name) (butlast forms))] + ~(if (empty? forms) + name + (last forms)))) + +(defmacro some-> + "When expr is not nil, threads it into the first form (via ->), + and when that result is not nil, through the next etc" + [expr & forms] + (let [g (gensym) + steps (map (fn [step] `(if (nil? ~g) nil (-> ~g ~step))) + forms)] + `(let [~g ~expr + ~@(interleave (repeat g) (butlast steps))] + ~(if (empty? steps) + g + (last steps))))) + +(defmacro some->> + "When expr is not nil, threads it into the first form (via ->>), + and when that result is not nil, through the next etc" + [expr & forms] + (let [g (gensym) + steps (map (fn [step] `(if (nil? ~g) nil (->> ~g ~step))) + forms)] + `(let [~g ~expr + ~@(interleave (repeat g) (butlast steps))] + ~(if (empty? steps) + g + (last steps))))) + +;; Functions. +(defn ifn? + "Returns true if x implements IFn. Note that many data structures + (e.g. sets and maps) implement IFn" + [x] + (cpp/jank.runtime.is_callable x)) +(defn fn? + "Returns true if x implements Fn, i.e. is an object created via fn." + [x] + (cpp/clojure.core_native.is_fn x)) + +;; Multimethods. +(defn- check-valid-options + "Throws an exception if the given option map contains keys not listed + as valid, else returns nil." + [options & valid-keys] + (when (seq (apply disj (apply hash-set (keys options)) valid-keys)) + (throw (apply str "Only these options are valid: " + (first valid-keys) + (map #(str ", " %) (rest valid-keys)))))) + +(defn- multi-fn? + [x] + (cpp/clojure.core_native.is_multi_fn x)) + +(defn- multi-fn* + [name dispatch_fn default hierarchy] + (cpp/clojure.core_native.multi_fn name dispatch_fn default hierarchy)) + +(def global-hierarchy) + +(defmacro defmulti + "Creates a new multimethod with the associated dispatch function. + The docstring and attr-map are optional. + + Options are key-value pairs and may be one of: + + :default + + The default dispatch value, defaults to :default + + :hierarchy + + The value used for hierarchical dispatch (e.g. ::square is-a ::shape) + + Hierarchies are type-like relationships that do not depend upon type + inheritance. By default Clojure's multimethods dispatch off of a + global hierarchy map. However, a hierarchy relationship can be + created with the derive function used to augment the root ancestor + created with make-hierarchy. + + Multimethods expect the value of the hierarchy option to be supplied as + a reference type e.g. a var (i.e. via the Var-quote dispatch macro #' + or the var special form)." + [mm-name & options] + (let [docstring (if (string? (first options)) + (first options) + nil) + options (if (string? (first options)) + (next options) + options) + m (if (map? (first options)) + (first options) + {}) + options (if (map? (first options)) + (next options) + options) + dispatch-fn (first options) + options (next options) + m (if docstring + (assoc m :doc docstring) + m) + m (if (meta mm-name) + (conj (meta mm-name) m) + m) + mm-name (with-meta mm-name m)] + (let [options (apply hash-map options) + default (get options :default :default) + hierarchy (get options :hierarchy #'global-hierarchy)] + (check-valid-options options :default :hierarchy) + ; TODO: This returns nil, due to an issue with let*. Why? + `(let [v# (def ~mm-name)] + (when-not (multi-fn? (deref v#)) + (def ~mm-name (multi-fn* '~(symbol *ns* mm-name) ~dispatch-fn ~default ~hierarchy))))))) + +(defn- defmethod* + [multifn dispatch-val f] + (cpp/clojure.core_native.defmethod multifn dispatch-val f)) + +(defmacro defmethod + "Creates and installs a new method of multimethod associated with dispatch-value. " + [multifn dispatch-val & fn-tail] + `(defmethod* ~multifn ~dispatch-val (fn ~@fn-tail))) + +(defn remove-all-methods + "Removes all of the methods of multimethod." + [multifn] + (cpp/clojure.core_native.remove_all_methods multifn)) + +(defn remove-method + "Removes the method of multimethod associated with dispatch-value." + [multifn dispatch-val] + (cpp/clojure.core_native.remove_method multifn dispatch-val)) + +(defn prefer-method + "Causes the multimethod to prefer matches of dispatch-val-x over dispatch-val-y + when there is a conflict" + [multifn dispatch-val-x dispatch-val-y] + (cpp/clojure.core_native.prefer_method multifn dispatch-val-x dispatch-val-y)) + +(defn methods + "Given a multimethod, returns a map of dispatch values -> dispatch fns" + [multifn] + (cpp/clojure.core_native.methods multifn)) + +(defn get-method + "Given a multimethod and a dispatch value, returns the dispatch fn + that would apply to that value, or nil if none apply and no default" + [multifn dispatch-val] + (cpp/clojure.core_native.get_method multifn dispatch-val)) + +(defn prefers + "Given a multimethod, returns a map of preferred value -> set of other values" + [multifn] + (cpp/clojure.core_native.prefers multifn)) + +;; Hierarchies. +(defn make-hierarchy + "Creates a hierarchy object for use with derive, isa? etc." + [] + {:parents {} + :descendants {} + :ancestors {}}) + +(def ^:private global-hierarchy (make-hierarchy)) + +(defn isa? + "Returns true if (= child parent), or child is directly or indirectly derived from + parent, either via a Java type inheritance relationship or a + relationship established via derive. h must be a hierarchy obtained + from make-hierarchy, if not supplied defaults to the global + hierarchy" + ([child parent] + (isa? global-hierarchy child parent)) + ([h child parent] + (or (= child parent) + (contains? (get (:ancestors h) child) parent) + (and (vector? parent) (vector? child) + (= (count parent) (count child)) + (loop [ret true + i 0] + (if (or (not ret) (= i (count parent))) + ret + (recur (isa? h (get child i) (get parent i)) (inc i)))))))) + +(defn parents + "Returns the immediate parents of tag, either via a Java type + inheritance relationship or a relationship established via derive. h + must be a hierarchy obtained from make-hierarchy, if not supplied + defaults to the global hierarchy" + ([tag] + (parents global-hierarchy tag)) + ([h tag] + (not-empty (get (:parents h) tag)))) + +(defn ancestors + "Returns the immediate and indirect parents of tag, either via a Java type + inheritance relationship or a relationship established via derive. h + must be a hierarchy obtained from make-hierarchy, if not supplied + defaults to the global hierarchy" + ([tag] + (ancestors global-hierarchy tag)) + ([h tag] + (not-empty (get (:ancestors h) tag)))) + +(defn descendants + "Returns the immediate and indirect children of tag, through a + relationship established via derive. h must be a hierarchy obtained + from make-hierarchy, if not supplied defaults to the global + hierarchy. Note: does not work on Java type inheritance + relationships." + ([tag] + (descendants global-hierarchy tag)) + ([h tag] + (not-empty (get (:descendants h) tag)))) + +(defn derive + "Establishes a parent/child relationship between parent and + tag. Parent must be a namespace-qualified symbol or keyword and + child can be either a namespace-qualified symbol or keyword or a + class. h must be a hierarchy obtained from make-hierarchy, if not + supplied defaults to, and modifies, the global hierarchy." + ([tag parent] + (assert (namespace parent)) + (assert (and (named? tag) (namespace tag))) + (alter-var-root #'global-hierarchy derive tag parent) + nil) + ([h tag parent] + (assert (not= tag parent)) + (assert (named? tag)) + (assert (named? parent)) + (let [tp (:parents h) + td (:descendants h) + ta (:ancestors h) + tf (fn [m source sources target targets] + (reduce (fn [ret k] + (assoc ret + k + (reduce conj + (get targets k #{}) + (cons target (targets target))))) + m + (cons source (sources source))))] + (or + (when-not (contains? (tp tag) parent) + (when (contains? (ta tag) parent) + (throw (str tag " already has " parent " as ancestor"))) + (when (contains? (ta parent) tag) + (throw (str "Cyclic derivation: " parent " has " tag " as ancestor"))) + {:parents (assoc (:parents h) tag (conj (get tp tag #{}) parent)) + :ancestors (tf (:ancestors h) tag td parent ta) + :descendants (tf (:descendants h) parent ta tag td)}) + h)))) + +(defn underive + "Removes a parent/child relationship between parent and + tag. h must be a hierarchy obtained from make-hierarchy, if not + supplied defaults to, and modifies, the global hierarchy." + ([tag parent] + (alter-var-root #'global-hierarchy underive tag parent) nil) + ([h tag parent] + (let [parent-map (:parents h) + child-parents (if (parent-map tag) + (disj (parent-map tag) parent) + #{}) + new-parents (if (not-empty child-parents) + (assoc parent-map tag child-parents) + (dissoc parent-map tag)) + deriv-seq (flatten (map #(cons (key %) (interpose (key %) (val %))) + (seq new-parents)))] + (if (contains? (parent-map tag) parent) + (reduce #(apply derive %1 %2) + (make-hierarchy) + (partition 2 deriv-seq)) + h)))) + +(defmacro defonce + "defs name to have the root value of the expr iff the named var has no root value, + else expr is unevaluated" + [name expr] + `(let [v# (def ~name)] + (when-not (bound? v#) + (def ~name ~expr)))) + +;; Case. +(def ^:private max-mask-bits 13) +(def ^:private max-switch-table-size (bit-shift-left 1 max-mask-bits)) + +(defn- i64? [n] + (and (integer? n) + (>= n (cpp/value "std::numeric_limits::min()")) + (<= n (cpp/value "std::numeric_limits::max()")))) + +(defn- i32? [n] + (and (integer? n) + (>= n (cpp/value "std::numeric_limits::min()")) + (<= n (cpp/value "std::numeric_limits::max()")))) + +(defn- shift-mask [shift mask x] + (-> x (bit-shift-right shift) (bit-and mask))) + +(defn- case-hash + "Returns the input if it is within the range of a 32-bit signed integer, otherwise returns the hash of the + input. The native hash returns a int32 int so this is to make sure that (case-hash (case-hash x)) == (case-hash x). + A key may be hashed more than once and we need to make sure its value does not change in later hashing." + [input] + (if (i32? input) + input + (hash input))) + +(defn- maybe-min-hash + "Takes a collection of hashes and returns [shift mask] or nil if none found" + [hashes] + (first + (filter + (fn [[s m]] + (apply distinct? (map #(shift-mask s m %) hashes))) + (for [mask + (map #(dec (bit-shift-left 1 %)) (range 1 (inc max-mask-bits))) + shift + (range 0 31)] + [shift mask])))) + +(defn- case-map-with-check + "Transforms a sequence of test constants and their corresponding branch expressions + into a sorted map for consumption by `case*`. This version is used when no hash collisions + are detected (i.e. the skip-check set is empty). + + Returns a sorted map where each key is the transformed test constant and each value is a `condp` form + that checks the original expression against the test constant before selecting the branch." + [expr-sym default case-f test-f tests thens] + (into (sorted-map) + (zipmap (map case-f tests) + (map + (fn [key then] + (let [key + (if (symbol? key) + (list 'quote key) + key)] + `(condp = ~expr-sym ~key ~then + ~default))) + (map test-f tests) + thens)))) + +(defn- case-map-collison-merged + "Transforms a sequence of test constants and their corresponding branch expressions + into a sorted map for consumption by `case*`. + + This version is selected when hash collisions have been detected (i.e. the skip-check set is nonempty) + and resolved (typically via merging in `merge-hash-collisions`). In these cases, the branch expressions + have already been pre-wrapped in `condp` forms to handle multiple colliding constants. Therefore, no additional + wrapping is needed here-the transformed test constants are mapped directly to their corresponding branch expressions. + + Returns a sorted map mapping each transformed test constant directly to its branch expression." + [case-f test-f tests thens] + (into (sorted-map) + (zipmap (map case-f tests) thens))) + +(defn- case-map + [expr-sym default case-f test-f tests thens skip-check] + (if (empty? skip-check) + (case-map-with-check expr-sym default case-f test-f tests thens) + (case-map-collison-merged case-f test-f tests thens))) + +(defn- fits-table? + "Returns true if the collection of ints can fit within the + max-table-switch-size, false otherwise." + [ints] + (< (- (apply max (seq ints)) (apply min (seq ints))) max-switch-table-size)) + +(defn- prep-ints + "Takes a sequence of int-sized test constants and a corresponding sequence of + then expressions. Returns a tuple of [shift mask case-map] where + case-map is a map of int case values to [test then] tuples" + [expr-sym default tests thens] + (if (fits-table? tests) + ; compact case ints, no shift-mask + [0 0 (case-map expr-sym default int int tests thens #{})] + (let [[shift mask] (or (maybe-min-hash (map int tests)) [0 0])] + (if (zero? mask) + ; sparse case ints, no shift-mask + [0 0 (case-map expr-sym default int int tests thens #{})] + ; compact case ints, with shift-mask + [shift + mask + (case-map expr-sym default #(shift-mask shift mask (int %)) int tests thens #{})])))) + +(defn- merge-hash-collisions + "Takes a case expression, default expression, and a sequence of test constants + and a corresponding sequence of then expressions. Returns a tuple of + [tests thens skip-check-set] where no tests have the same hash. Each set of + input test constants with the same hash is replaced with a single test + constant (the case int), and their respective thens are combined into: + (condp = expr + test-1 then-1 + ... + test-n then-n + default). + The skip-check is a set of case ints for which post-switch equivalence + checking must not be done (the cases holding the above condp thens)." + [expr-sym default tests thens] + (let [buckets + (loop [m {} + ks tests + vs thens] + (if (and ks vs) + (recur + (update m (case-hash (first ks)) (fnil conj []) [(first ks) (first vs)]) + (next ks) (next vs)) + m)) + assoc-multi + (fn [m h bucket] + (let [testexprs + (mapcat (fn [kv] [(list 'quote (first kv)) (second kv)]) bucket) + expr + `(condp = ~expr-sym ~@testexprs ~default)] + (assoc m h expr))) + hmap + (reduce + (fn [m [h bucket]] + (if (== 1 (count bucket)) + (assoc m (ffirst bucket) (second (first bucket))) + (assoc-multi m h bucket))) + {} buckets) + skip-check + (->> buckets + (filter #(< 1 (count (second %)))) + (map first) + (into #{}))] + [(keys hmap) (vals hmap) skip-check])) + +(defn- prep-hashes + "Takes a sequence of test constants and a corresponding sequence of then + expressions. Returns a tuple of [shift mask case-map] + where case-map is a map of int case values to [test then] tuples." + [expr-sym default tests thens skip-check] + (let [hashes (into #{} (map case-hash tests))] + (if (== (count tests) (count hashes)) + (if (fits-table? hashes) + ; compact case ints, no shift-mask + [0 0 + (case-map expr-sym default case-hash identity tests thens skip-check)] + (let [[shift mask] (or (maybe-min-hash hashes) [0 0])] + (if (zero? mask) + ; sparse case ints, no shift-mask + [0 0 + (case-map expr-sym default case-hash identity tests thens skip-check)] + ; compact case ints, with shift-mask + [shift mask + (case-map expr-sym default #(shift-mask shift mask (case-hash %)) identity tests thens skip-check)]))) + ; resolve hash collisions and try again + (let [[tests thens skip-check] + (merge-hash-collisions expr-sym default tests thens) + [shift mask case-map] + (prep-hashes expr-sym default tests thens skip-check) + skip-check + (if (zero? mask) + skip-check + (into #{} (map #(shift-mask shift mask %) skip-check)))] + [shift mask case-map])))) + +(defmacro case + "Takes an expression, and a set of clauses. + + Each clause can take the form of either: + + test-constant result-expr + + (test-constant1 ... test-constantN) result-expr + + The test-constants are not evaluated. They must be compile-time + literals, and need not be quoted. If the expression is equal to a + test-constant, the corresponding result-expr is returned. A single + default expression can follow the clauses, and its value will be + returned if no clause matches. If no default expression is provided + and no clause matches, an IllegalArgumentException is thrown. + + Unlike cond and condp, case does a constant-time dispatch, the + clauses are not considered sequentially. All manner of constant + expressions are acceptable in case, including numbers, strings, + symbols, keywords, and (Clojure) composites thereof. Note that since + lists are used to group multiple constants that map to the same + expression, a vector can be used to match a list if needed. The + test-constants need not be all of the same type." + {:added "1.2"} + + [e & clauses] + (let [ge + (gensym) + default + (if (odd? (count clauses)) + (last clauses) + `(throw (str "No matching clause: " ~ge)))] + (if (> 2 (count clauses)) + `(let [~ge ~e] ~default) + (let [pairs + (partition 2 clauses) + assoc-test + (fn assoc-test [m test expr] + (if (contains? m test) + (throw (str "Duplicate case test constant: " test)) + (assoc m test expr))) + pairs + (reduce + (fn [m [test expr]] + (if (seq? test) + (reduce #(assoc-test %1 %2 expr) m test) + (assoc-test m test expr))) + {} pairs) + tests + (keys pairs) + thens + (vals pairs) + mode + (cond + (every? i64? tests) + :ints + + (every? keyword? tests) + :identity + + :else + :hashes)] + (condp = mode + :ints + (let [[shift mask imap] (prep-ints ge default tests thens)] + `(let [~ge ~e] (case* ~ge ~shift ~mask ~default ~imap))) + :hashes + (let [[shift mask imap] + (prep-hashes ge default tests thens #{})] + `(let [~ge ~e] + (case* ~ge ~shift ~mask ~default ~imap))) + :identity + (let [[shift mask imap] + (prep-hashes ge default tests thens #{})] + `(let [~ge ~e] + (case* ~ge ~shift ~mask ~default ~imap)))))))) + +;; Miscellaneous. +; TODO: jank.core +(defn- sleep [ms] + (cpp/clojure.core_native.sleep ms)) +(defn- current-time [] + (cpp/clojure.core_native.current_time)) + +(defmacro time + "Evaluates expr and prints the time it took. Returns the value of expr." + [expr] + `(let [start# (current-time) + ret# ~expr + end# (current-time)] + (println (str "Elapsed time: " (/ (- end# start#) 1000000.0) " ms")) + ret#)) + +(defn with-redefs-fn + "Temporarily redefines Vars during a call to func. Each val of + binding-map will replace the root value of its key which must be + a Var. After func is called with no args, the root values of all + the Vars will be set back to their old values. These temporary + changes will be visible in all threads. Useful for mocking out + functions during testing." + [binding-map fun] + (let [root-bind (fn root-bind [m] + (doseq [kv m] + (cpp/clojure.core_native.var_bind_root (first kv) (second kv)))) + old-vals (zipmap (keys binding-map) + (map #(cpp/clojure.core_native.var_get_root %) (keys binding-map)))] + (try + (root-bind binding-map) + (fun) + (finally + (root-bind old-vals))))) + +(defmacro with-redefs + "binding => var-symbol temp-value-expr + + Temporarily redefines Vars while executing the body. The + temp-value-exprs will be evaluated and each resulting value will + replace in parallel the root value of its Var. After the body is + executed, the root values of all the Vars will be set back to their + old values. These temporary changes will be visible in all threads. + Useful for mocking out functions during testing." + [bindings & body] + (list `with-redefs-fn + (zipmap (map (fn [v] + (list 'var v)) + (take-nth 2 bindings)) + (take-nth 2 (next bindings))) + (list* `fn [] + body))) + +;; Namespaces. +(defn in-ns + "Sets *ns* to the namespace named by the symbol, creating it if needed." + [name] + (cpp/clojure.core_native.in_ns name)) + +(defn create-ns + "Create a new namespace named by the symbol if one doesn't already + exist, returns it or the already-existing namespace of the same + name." + [sym] + (cpp/clojure.core_native.intern_ns sym)) + + +(defn find-ns + "Returns the namespace named by the symbol or nil if it doesn't exist." + [sym] + (cpp/clojure.core_native.find_ns sym)) + +(defn find-var + "Returns the global var named by the namespace-qualified symbol, or + nil if no var with that name." + [sym] + (cpp/clojure.core_native.find_var sym)) + +(defn remove-ns + "Removes the namespace named by the symbol. Use with caution. + Cannot be used to remove the clojure namespace." + [sym] + (cpp/clojure.core_native.remove_ns sym)) + +(defn the-ns + "If passed a namespace, returns it. Else, when passed a symbol, + returns the namespace named by it, throwing an exception if not + found." + [ns-or-sym] + (if (cpp/clojure.core_native.is_ns ns-or-sym) + ns-or-sym + (let [found (find-ns ns-or-sym)] + (if (nil? found) + (throw (ex-info :not-an-ns-or-sym {:value ns-or-sym})) + found)))) + +(defn ns-name + "Returns the name of the namespace, a symbol." + [ns-sym] + (let [ns (the-ns ns-sym)] + (cpp/clojure.core_native.ns_name ns))) + +(defn ns-map + "Returns a map of all the mappings for the namespace." + [ns-sym] + (let [ns (the-ns ns-sym)] + (cpp/clojure.core_native.ns_map ns))) + +(defn ns-publics + "Returns a map of the public intern mappings for the namespace." + [ns-sym] + (let [ns (the-ns ns-sym)] + ; TODO: It may be faster to start with the whole map and dissoc. + ; TODO: Good use case for transients. + (reduce (fn [acc kv] + (let [k (first kv) + v (second kv)] + ; TODO: Check for visibility. + (if (var? v) + (if (= ns (cpp/clojure.core_native.var_ns v)) + (assoc acc k v) + acc) + acc))) + {} + (ns-map ns)))) + +(defn ns-resolve + "Returns the var to which a symbol will be resolved in the + namespace (unless found in the environment), else nil. Note that + if the symbol is fully qualified, the var to which it resolves + need not be present in the namespace." + ([ns sym] + (ns-resolve ns nil sym)) + ([ns env sym] + (when-not (contains? env sym) + (cpp/clojure.core_native.ns_resolve (the-ns ns) sym)))) + +(defn resolve + "Same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)" + ([sym] + (ns-resolve *ns* sym)) + ([env sym] + (ns-resolve *ns* env sym))) + +(defn- libspec? [x] + (or (symbol? x) + (and (vector? x) + (or (nil? (second x)) + (keyword? (second x)))))) + +(defn- prependss [x coll] + (if (symbol? x) + (cons x coll) + (concat x coll))) + +(defn- root-resource [lib] + (str "/" (name lib))) + +(defn- throw-if [pred msg] + (when pred + (throw (ex-info :assertion-failure {:msg msg})))) + +(defn alias + "Add an alias in the current namespace to another + namespace. Arguments are two symbols: the alias to be used, and + the symbolic name of the target namespace. Use :as in the ns macro in preference + to calling this directly." + [alias ns-sym] + (let [ns-obj (the-ns ns-sym)] + (cpp/clojure.core_native.alias *ns* ns-obj alias))) + +(defn refer + "refers to all public vars of ns, subject to filters. + filters can include at most one each of: + + :exclude list-of-symbols + :only list-of-symbols + :rename map-of-fromsymbol-tosymbol + + For each public interned var in the namespace named by the symbol, + adds a mapping from the name of the var to the var to the current + namespace. Throws an exception if name is already mapped to + something else in the current namespace. Filters can be used to + select a subset, via inclusion or exclusion, or to provide a mapping + to a symbol different from the var's name, in order to prevent + clashes. Use :use in the ns macro in preference to calling this directly." + [ns-sym & filters] + (let [ns (find-ns ns-sym) + _ (when (nil? ns) + (throw (ex-info :unknown-namespace {:value ns-sym}))) + filters (apply hash-map filters) + rename (or (:rename filters) {}) + exclude? (set (:exclude filters)) + sym->var (ns-publics ns) + to-refer (if (= :all (get filters :refer)) + (keys sym->var) + (or (get filters :refer) (get filters :only) (keys sym->var)))] + ; TODO: Loop + (reduce (fn [acc sym] + (when (not (exclude? sym)) + (let [v (get sym->var sym) + sym (rename sym sym)] + (when (nil? v) + (throw (ex-info :var-does-not-exist {:value sym}))) + (cpp/clojure.core_native.refer *ns* sym v)))) + nil + to-refer))) + +;; TODO: Should be a ref instead of atom +(defonce + ^{:private true + :dynamic true + :doc "An atom holding a sorted set of symbols representing loaded libs"} + *loaded-libs* (atom (sorted-set))) + +(defonce + ^{:private true + :dynamic true + :doc "A stack of paths currently being loaded by this thread"} + *pending-paths* ()) + +(defn- check-cyclic-dependency + "Detects and rejects non-trivial cyclic load dependencies. The + exception message shows the dependency chain with the cycle + highlighted. Ignores the trivial case of a file attempting to load + itself because that can occur when a gen-class'd class loads its + implementation." + [path] + (when (some #{path} (rest *pending-paths*)) + (let [pending (map #(if (= % path) (str "[ " % " ]") %) + (cons path *pending-paths*)) + chain (apply str (interpose "->" pending))] + (throw-if true (str "Cyclic load dependency: " chain))))) + +(defn load + "Loads Clojure code from resources in the module path. A path is interpreted as + module-path-relative if it begins with a slash or relative to the root + directory for the current namespace otherwise." + [& paths] + (doseq [path paths] + (check-cyclic-dependency path) + (when-not (= path (first *pending-paths*)) + (binding [*pending-paths* (conj *pending-paths* path)] + (clojure.core-native/load-module path))))) + +(defn- load-one + "Loads a lib given its name. If `need-ns?`, ensures that the associated + namespace exists after loading. If `require?`, records the load so any + duplicate loads can be skipped." + [lib need-ns? require?] + (load (root-resource lib)) + (throw-if (and need-ns? (not (find-ns lib))) + (str "namespace " lib " not found after loading " (root-resource lib))) + (when require? + (swap! *loaded-libs* conj lib))) + +(defn- load-all + "Loads a lib given its name and forces a load of any libs it directly or + indirectly loads. If need-ns?, ensures that the associated namespace + exists after loading. If require?, records the load so any duplicate loads + can be skipped." + [lib need-ns? require?] + (swap! *loaded-libs* #(reduce conj %1 %2) + (binding [*loaded-libs* (atom (sorted-set))] + (load-one lib need-ns? require?) + @*loaded-libs*))) + +(defn- load-lib + "Loads a lib with options" + [lib & options] + (let [opts (apply hash-map options) + ; TODO: Map destructuring. + as (:as opts) + reload (:reload opts) + reload-all (:reload-all opts) + require (:require opts) + use (:use opts) + verbose (:verbose opts) + as-alias (:as-alias opts) + loaded? (contains? @*loaded-libs* lib) + need-ns? (or as use) + load (cond reload-all load-all + reload load-one + (not loaded?) (cond need-ns? load-one + as-alias (fn [lib _need _require] + (create-ns lib)) + :else load-one)) + + filter-opts (select-keys opts [:exclude :only :rename :refer]) + undefined-on-entry? (not (find-ns lib))] + (if load + (try + (load lib need-ns? require) + (catch e + (when undefined-on-entry? + (remove-ns lib)) + (throw e))) + (throw-if (and need-ns? (not (find-ns lib))) + (str "namespace " lib " not found"))) + (when as + (alias as lib)) + (when as-alias + (alias as-alias lib)) + (when (or use (:refer filter-opts)) + (apply refer lib (mapcat seq filter-opts))))) + +(defn- load-libs + "Loads libs, interpreting libspecs, prefix lists, and flags for + forwarding to load-lib" + [& args] + (let [flags (filter keyword? args) + opts (interleave flags (repeat true)) + args (remove keyword? args)] + (let [supported #{:as :reload :reload-all :require :use :verbose :refer :as-alias} + unsupported (seq (remove supported flags))] + (throw-if unsupported + (str "Unsupported option(s) supplied: " unsupported))) + (throw-if (not (seq args)) "Nothing specified to load") + (doseq [arg args] + (throw-if (not (libspec? arg)) (str "not a libspec: " arg)) + (apply load-lib (prependss arg opts))))) + +(defn compile + "Compiles the namespace named by the symbol lib into a set of + classfiles. The source for the lib must be in a proper + module-path-relative directory. The output files will go into the + directory specified by *compile-path*, and that directory too must + be in the module path." + [path] + (cpp/clojure.core_native.compile path)) + +(defn require + "Loads libs, skipping any that are already loaded. Each argument is + either a libspec that identifies a lib, a prefix list that identifies + multiple libs whose names share a common prefix, or a flag that modifies + how all the identified libs are loaded. Use :require in the ns macro + in preference to calling this directly. + + Libs + + A 'lib' is a named set of resources in module path whose contents define a + library of Clojure code. Lib names are symbols and each lib is associated + with a Clojure namespace and a Java package that share its name. A lib's + name also locates its root directory within module path using Java's + package name to module path-relative path mapping. All resources in a lib + should be contained in the directory structure under its root directory. + All definitions a lib makes should be in its associated namespace. + + 'require loads a lib by loading its root resource. The root resource path + is derived from the lib name in the following manner: + Consider a lib named by the symbol 'x.y.z; it has the root directory + /x/y/, and its root resource is /x/y/z.clj, or + /x/y/z.cljc if /x/y/z.clj does not exist. The + root resource should contain code to create the lib's + namespace (usually by using the ns macro) and load any additional + lib resources. + + Libspecs + + A libspec is a lib name or a vector containing a lib name followed by + options expressed as sequential keywords and arguments. + + Recognized options: + :as takes a symbol as its argument and makes that symbol an alias to the + lib's namespace in the current namespace. + :as-alias takes a symbol as its argument and aliases like :as, however + the lib will not be loaded. If the lib has not been loaded, a new + empty namespace will be created (as with create-ns). + :refer takes a list of symbols to refer from the namespace or the :all + keyword to bring in all public vars. + + Prefix Lists + + It's common for Clojure code to depend on several libs whose names have + the same prefix. When specifying libs, prefix lists can be used to reduce + repetition. A prefix list contains the shared prefix followed by libspecs + with the shared prefix removed from the lib names. After removing the + prefix, the names that remain must not contain any periods. + + Flags + + A flag is a keyword. + Recognized flags: :reload, :reload-all, :verbose + :reload forces loading of all the identified libs even if they are + already loaded (has no effect on libspecs using :as-alias) + :reload-all implies :reload and also forces loading of all libs that the + identified libs directly or indirectly load via require or use + (has no effect on libspecs using :as-alias) + :verbose triggers printing information about each load, alias, and refer + + Example: + + The following would load the libraries clojure.zip and clojure.set + abbreviated as 's'. + + (require '(clojure zip [set :as s]))" + [& args] + (apply load-libs :require args)) + +(defn use + "Like 'require, but also refers to each lib's namespace using + clojure.core/refer. Use :use in the ns macro in preference to calling + this directly. + + 'use accepts additional options in libspecs: :exclude, :only, :rename. + The arguments and semantics for :exclude, :only, and :rename are the same + as those documented for clojure.core/refer." + [& args] + (apply load-libs :require :use args)) + +(defmacro ns + "Sets *ns* to the namespace named by name (unevaluated), creating it + if needed. References can be zero or more of: (:refer-clojure ...) + (:require ...) (:use ...) (:load ...) + with the syntax of refer-clojure/require/use/load respectively." + [name & references] + (let [process-reference (fn [reference] + (let [kname (first reference) + args (rest reference)] + (cons (symbol "clojure.core" (clojure.core/name kname)) + (map (fn [a] + (list 'quote a)) + args)))) + refer-full-clojure? (not-any? (fn [ref] + (= :refer-clojure (first ref))) + references)] + `(do + (clojure.core/in-ns '~name) + ; TODO: with-loading-context + (do ; with-loading-context + ~@(when (and (not= name 'clojure.core) refer-full-clojure?) + `((clojure.core/refer '~'clojure.core))) + ~@(map process-reference references)) + (if (= '~name '~'clojure.core) + nil + (do (swap! @#'*loaded-libs* conj '~name) nil))))) + +(defmacro refer-clojure + "Same as (refer 'clojure.core )" + [& filters] + `(clojure.core/refer '~'clojure.core ~@filters)) + +(defn intern + "Finds or creates a var named by the symbol name in the namespace + ns (which can be a symbol or a namespace), setting its root binding + to val if supplied. The namespace must exist. The var will adopt any + metadata from the name symbol. Returns the var." + ([ns name] + (let [v (cpp/clojure.core_native.intern_var + (cpp/jank.runtime.to_qualified_symbol + (the-ns ns) name))] + (when (meta name) (cpp/jank.runtime.reset_meta v (meta name))) + v)) + ([ns name val] + (let [v (cpp/clojure.core_native.intern_var + (cpp/jank.runtime.to_qualified_symbol + (the-ns ns) name))] + (cpp/clojure.core_native.var_bind_root v val) + (when (meta name) (cpp/jank.runtime.reset_meta v (meta name))) + v))) + +(defn nfirst + "Same as (next (first x))" + [x] + (next (first x))) + +(defn fnext + "Same as (first (next x))" + [x] + (first (next x))) + +(defn instance? + "Evaluates x and tests if it is an instance of the class + c. Returns true or false" + [c x] + ;; (. c (isInstance x)) + (throw "TODO: port instance?")) + +(def ^{:private true :dynamic true} + assert-valid-fdecl (fn [fdecl])) + +(defn to-array + "Returns an array of Objects containing the contents of coll, which + can be any Collection. Maps to java.util.Collection.toArray()." + [coll] + ;; (. clojure.lang.RT (toArray coll)) + (throw "TODO: port to-array")) + +(defn cast + "Throws a ClassCastException if x is not a c, else returns x." + [c x] + ;; (. c (cast x)) + (throw "TODO: port cast")) + +(defn sorted-map-by + "keyval => key val + Returns a new sorted map with supplied mappings, using the supplied + comparator. If any keys are equal, they are handled as if by + repeated uses of assoc." + ([comparator & keyvals] + ;; (clojure.lang.PersistentTreeMap/create comparator keyvals) + (throw "TODO: port sorted-map-by"))) + +(defn any? + "Returns true given any argument." + [x] true) + +(defn find-keyword + "Returns a Keyword with the given namespace and name if one already + exists. This function will not intern a new keyword. If the keyword + has not already been interned, it will return nil. Do not use : + in the keyword strings, it will be added automatically." + ([name] + ;; (cond (keyword? name) name + ;; (symbol? name) (clojure.lang.Keyword/find ^clojure.lang.Symbol name) + ;; (string? name) (clojure.lang.Keyword/find ^String name)) + (throw "TODO: port find-keyword")) + ([ns name] + ;; (clojure.lang.Keyword/find ns name) + (throw "TODO: port find-keyword"))) + +(defn delay? + "returns true if x is a Delay created with delay" + [x] + ;; (instance? clojure.lang.Delay x) + (throw "TODO: port delay?")) + +(defmacro if-not + "Evaluates test. If logical false, evaluates and returns then expr, + otherwise else expr, if supplied, else nil." + ([test then] `(if-not ~test ~then nil)) + ([test then else] + `(if (not ~test) ~then ~else))) + +(defn compare + "Comparator. Returns a negative number, zero, or a positive number + when x is logically 'less than', 'equal to', or 'greater than' + y. Same as Java x.compareTo(y) except it also works for nil, and + compares numbers and collections in a type-independent manner. x + must implement Comparable" + [x y] + (cpp/jank.runtime.compare x y)) + +(defn inc' + "Returns a number one greater than num. Supports arbitrary precision. + See also: inc" + [x] + ;; (. clojure.lang.Numbers (incP x)) + (throw "TODO: port inc'")) + +;; ;;math stuff +;; (defn ^:private nary-inline +;; ([op] (nary-inline op op)) +;; ([op unchecked-op] +;; (fn +;; ([x] (let [op (if *unchecked-math* unchecked-op op)] +;; `(. clojure.lang.Numbers (~op ~x)))) +;; ([x y] (let [op (if *unchecked-math* unchecked-op op)] +;; `(. clojure.lang.Numbers (~op ~x ~y)))) +;; ([x y & more] +;; (let [op (if *unchecked-math* unchecked-op op)] +;; (reduce1 +;; (fn [a b] `(. clojure.lang.Numbers (~op ~a ~b))) +;; `(. clojure.lang.Numbers (~op ~x ~y)) more)))))) + +;; (defn ^:private >1? [n] (clojure.lang.Numbers/gt n 1)) + +;; (defn ^:private >0? [n] (clojure.lang.Numbers/gt n 0)) + +(defn +' + "Returns the sum of nums. (+') returns 0. Supports arbitrary precision. + See also: +" + ([] 0) + ([x] + ;; (cast Number x) + (throw "TODO: port +'")) + ([x y] + ;; (. clojure.lang.Numbers (addP x y)) + (throw "TODO: port +'")) + ([x y & more] + (reduce +' (+' x y) more))) + +(defn *' + "Returns the product of nums. (*') returns 1. Supports arbitrary precision. + See also: *" + ([] 1) + ([x] + ;; (cast Number x) + (throw "TODO: port *'")) + ([x y] + ;; (. clojure.lang.Numbers (multiplyP x y)) + (throw "TODO: port *'")) + ([x y & more] + (reduce *' (*' x y) more))) + +(defn -' + "If no ys are supplied, returns the negation of x, else subtracts + the ys from x and returns the result. Supports arbitrary precision. + See also: -" + ([x] + ;; (. clojure.lang.Numbers (minusP x)) + (throw "TODO: port -'")) + ([x y] + ;; (. clojure.lang.Numbers (minusP x y)) + (throw "TODO: port -'")) + ([x y & more] + (reduce -' (-' x y) more))) + +(defn abs + "Returns the absolute value of a. + If a is Long/MIN_VALUE => Long/MIN_VALUE + If a is a double and zero => +0.0 + If a is a double and ##Inf or ##-Inf => ##Inf + If a is a double and ##NaN => ##NaN" + [a] + (cpp/jank.runtime.abs a)) + +(defn dec' + "Returns a number one less than num. Supports arbitrary precision. + See also: dec" + [x] + ;; (. clojure.lang.Numbers (decP x)) + (throw "TODO: port dec'")) + +(defn unchecked-inc-int + "Returns a number one greater than x, an int. + Note - uses a primitive operator subject to overflow." + [x] + ;; (. clojure.lang.Numbers (unchecked_int_inc x)) + (throw "TODO: port unchecked-inc-int")) + +(defn unchecked-inc + "Returns a number one greater than x, a long. + Note - uses a primitive operator subject to overflow." + [x] + ;; (. clojure.lang.Numbers (unchecked_inc x)) + (throw "TODO: port unchecked-inc")) + +(defn unchecked-dec-int + "Returns a number one less than x, an int. + Note - uses a primitive operator subject to overflow." + [x] + ;; (. clojure.lang.Numbers (unchecked_int_dec x)) + (throw "TODO: port unchecked-dec-int")) + +(defn unchecked-dec + "Returns a number one less than x, a long. + Note - uses a primitive operator subject to overflow." + [x] + ;; (. clojure.lang.Numbers (unchecked_dec x)) + (throw "TODO: port unchecked-dec")) + +(defn unchecked-negate-int + "Returns the negation of x, an int. + Note - uses a primitive operator subject to overflow." + [x] + ;; (. clojure.lang.Numbers (unchecked_int_negate x)) + (throw "TODO: port unchecked-negate-int")) + +(defn unchecked-negate + "Returns the negation of x, a long. + Note - uses a primitive operator subject to overflow." + [x] + ;; (. clojure.lang.Numbers (unchecked_minus x)) + (throw "TODO: port unchecked-negate")) + +(defn unchecked-add-int + "Returns the sum of x and y, both int. + Note - uses a primitive operator subject to overflow." + [x y] + ;; (. clojure.lang.Numbers (unchecked_int_add x y)) + (throw "TODO: port unchecked-add-int")) + +(defn unchecked-add + "Returns the sum of x and y, both long. + Note - uses a primitive operator subject to overflow." + [x y] + ;; (. clojure.lang.Numbers (unchecked_add x y)) + (throw "TODO: port unchecked-add")) + +(defn unchecked-subtract-int + "Returns the difference of x and y, both int. + Note - uses a primitive operator subject to overflow." + [x y] + ;; (. clojure.lang.Numbers (unchecked_int_subtract x y)) + (throw "TODO: port unchecked-subtract-int")) + +(defn unchecked-subtract + "Returns the difference of x and y, both long. + Note - uses a primitive operator subject to overflow." + [x y] + ;; (. clojure.lang.Numbers (unchecked_minus x y)) + (throw "TODO: port unchecked-subtract")) + +(defn unchecked-multiply-int + "Returns the product of x and y, both int. + Note - uses a primitive operator subject to overflow." + [x y] + ;; (. clojure.lang.Numbers (unchecked_int_multiply x y)) + (throw "TODO: port unchecked-multiply-int")) + +(defn unchecked-multiply + "Returns the product of x and y, both long. + Note - uses a primitive operator subject to overflow." + [x y] + ;; (. clojure.lang.Numbers (unchecked_multiply x y)) + (throw "TODO: port unchecked-multiply")) + +(defn unchecked-divide-int + "Returns the division of x by y, both int. + Note - uses a primitive operator subject to truncation." + [x y] + ;; (. clojure.lang.Numbers (unchecked_int_divide x y)) + (throw "TODO: port unchecked-divide-int")) + +(defn unchecked-remainder-int + "Returns the remainder of division of x by y, both int. + Note - uses a primitive operator subject to truncation." + [x y] + ;; (. clojure.lang.Numbers (unchecked_int_remainder x y)) + (throw "TODO: port unchecked-remainder-int")) + +(defn rationalize + "returns the rational value of num" + [num] + ;; (. clojure.lang.Numbers (rationalize num)) + (throw "TODO: port rationalize")) + +(defn int? + "Return true if x is a fixed precision integer" + [x] + (integer? x)) + +(defn pos-int? + "Return true if x is a positive fixed precision integer" + [x] (and (int? x) + (pos? x))) + +(defn neg-int? + "Return true if x is a negative fixed precision integer" + [x] (and (int? x) + (neg? x))) + +(defn nat-int? + "Return true if x is a non-negative fixed precision integer" + [x] (and (int? x) + (not (neg? x)))) + +(defn double? + "Return true if x is a Double" + [x] + (float? x)) + +;;map stuff + +(defn map-entry? + "Return true if x is a map entry" + [x] + (and (vector? x) + (== 2 (count x)))) + +(defn rseq + "Returns, in constant time, a seq of the items in rev (which + can be a vector or sorted-map), in reverse order. If rev is empty returns nil" + [#_clojure.lang.Reversible rev] + ;; (. rev (rseq)) + (throw "TODO: port rseq")) + +(defmacro locking + "Executes exprs in an implicit do, while holding the monitor of x. + Will release the monitor of x in all circumstances." + [x & body] + `(let [lockee# ~x] + (try + (let [locklocal# lockee#] + (monitor-enter locklocal#) + (try + (do ~@body) + (finally + (monitor-exit locklocal#))))))) + +;; (defmacro .. +;; "form => fieldName-symbol or (instanceMethodName-symbol args*) + +;; Expands into a member access (.) of the first member on the first +;; argument, followed by the next member on the result, etc. For +;; instance: + +;; (.. System (getProperties) (get \"os.name\")) + +;; expands to: + +;; (. (. System (getProperties)) (get \"os.name\")) + +;; but is easier to write, read, and understand." +;; ([x form] +;; ;; `(. ~x ~form) +;; (throw "TODO: port")) +;; ([x form & more] +;; ;; `(.. (. ~x ~form) ~@more)) +;; (throw "TODO: port")) + + +;;;;;;;;; var stuff + +(defn with-bindings* + "Takes a map of Var/value pairs. Installs for the given Vars the associated + values as thread-local bindings. Then calls f with the supplied arguments. + Pops the installed bindings after f returned. Returns whatever f returns." + [binding-map f & args] + (push-thread-bindings (if (= "persistent_array_map" (type binding-map)) + (into (hash-map) binding-map) + binding-map)) + (try + (apply f args) + (finally + (pop-thread-bindings)))) + +(defmacro with-bindings + "Takes a map of Var/value pairs. Installs for the given Vars the associated + values as thread-local bindings. Then executes body. Pops the installed + bindings after body was evaluated. Returns the value of body." + [binding-map & body] + `(with-bindings* ~binding-map (fn [] ~@body))) + +(defn bound-fn* + "Returns a function, which will install the same bindings in effect as in + the thread at the time bound-fn* was called and then call f with any given + arguments. This may be used to define a helper function which runs on a + different thread, but needs the same bindings in place." + [f] + (let [bindings (get-thread-bindings)] + (fn [& args] + (apply with-bindings* bindings f args)))) + +(defmacro bound-fn + "Returns a function defined by the given fntail, which will install the + same bindings in effect as in the thread at the time bound-fn was called. + This may be used to define a helper function which runs on a different + thread, but needs the same bindings in place." + [& fntail] + `(bound-fn* (fn ~@fntail))) + +(defn- binding-conveyor-fn + [f] + ;; (let [frame (clojure.lang.Var/cloneThreadBindingFrame)] + ;; (fn + ;; ([] + ;; (clojure.lang.Var/resetThreadBindingFrame frame) + ;; (f)) + ;; ([x] + ;; (clojure.lang.Var/resetThreadBindingFrame frame) + ;; (f x)) + ;; ([x y] + ;; (clojure.lang.Var/resetThreadBindingFrame frame) + ;; (f x y)) + ;; ([x y z] + ;; (clojure.lang.Var/resetThreadBindingFrame frame) + ;; (f x y z)) + ;; ([x y z & args] + ;; (clojure.lang.Var/resetThreadBindingFrame frame) + ;; (apply f x y z args)))) + (throw "TODO: port binding-conveyor-fn")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Refs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defn- + setup-reference [#_clojure.lang.ARef r options] + ;; (let [opts (apply hash-map options)] + ;; (when (:meta opts) + ;; (.resetMeta r (:meta opts))) + ;; (when (:validator opts) + ;; (.setValidator r (:validator opts))) + ;; r) + (throw "TODO: port setup-reference")) + +(defn agent + "Creates and returns an agent with an initial value of state and + zero or more options (in any order): + + :meta metadata-map + + :validator validate-fn + + :error-handler handler-fn + + :error-mode mode-keyword + + If metadata-map is supplied, it will become the metadata on the + agent. validate-fn must be nil or a side-effect-free fn of one + argument, which will be passed the intended new state on any state + change. If the new state is unacceptable, the validate-fn should + return false or throw an exception. handler-fn is called if an + action throws an exception or if validate-fn rejects a new state -- + see set-error-handler! for details. The mode-keyword may be either + :continue (the default if an error-handler is given) or :fail (the + default if no error-handler is given) -- see set-error-mode! for + details." + ([state & options] + ;; (let [a (new clojure.lang.Agent state) + ;; opts (apply hash-map options)] + ;; (setup-reference a options) + ;; (when (:error-handler opts) + ;; (.setErrorHandler a (:error-handler opts))) + ;; (.setErrorMode a (or (:error-mode opts) + ;; (if (:error-handler opts) :continue :fail))) + ;; a) + (throw "TODO: port agent"))) + +(defn set-agent-send-executor! + "Sets the ExecutorService to be used by send" + [executor] + ;; (set! clojure.lang.Agent/pooledExecutor executor) + (throw "TODO: port set-agent-send-executor!")) + +(defn set-agent-send-off-executor! + "Sets the ExecutorService to be used by send-off" + [executor] + ;; (set! clojure.lang.Agent/soloExecutor executor) + (throw "TODO: port set-agent-send-off-executor!")) + +(defn send-via + "Dispatch an action to an agent. Returns the agent immediately. + Subsequently, in a thread supplied by executor, the state of the agent + will be set to the value of: + + (apply action-fn state-of-agent args)" + [executor #_clojure.lang.Agent a f & args] + ;; (.dispatch a (binding [*agent* a] (binding-conveyor-fn f)) args executor) + (throw "TODO: port send-via")) + +(defn send + "Dispatch an action to an agent. Returns the agent immediately. + Subsequently, in a thread from a thread pool, the state of the agent + will be set to the value of: + + (apply action-fn state-of-agent args)" + [#_clojure.lang.Agent a f & args] + ;; (apply send-via clojure.lang.Agent/pooledExecutor a f args) + (throw "TODO: port send")) + +(defn send-off + "Dispatch a potentially blocking action to an agent. Returns the + agent immediately. Subsequently, in a separate thread, the state of + the agent will be set to the value of: + + (apply action-fn state-of-agent args)" + [#_clojure.lang.Agent a f & args] + ;; (apply send-via clojure.lang.Agent/soloExecutor a f args) + (throw "TODO: port send-off")) + +(defn release-pending-sends + "Normally, actions sent directly or indirectly during another action + are held until the action completes (changes the agent's + state). This function can be used to dispatch any pending sent + actions immediately. This has no impact on actions sent during a + transaction, which are still held until commit. If no action is + occurring, does nothing. Returns the number of actions dispatched." + [] + ;; (clojure.lang.Agent/releasePendingSends) + (throw "TODO: port release-pending-sends")) + +(defn add-watch + "Adds a watch function to an agent/atom/var/ref reference. The watch + fn must be a fn of 4 args: a key, the reference, its old-state, its + new-state. Whenever the reference's state might have been changed, + any registered watches will have their functions called. The watch fn + will be called synchronously, on the agent's thread if an agent, + before any pending sends if agent or ref. Note that an atom's or + ref's state may have changed again prior to the fn call, so use + old/new-state rather than derefing the reference. Note also that watch + fns may be called from multiple threads simultaneously. Var watchers + are triggered only by root binding changes, not thread-local + set!s. Keys must be unique per reference, and can be used to remove + the watch with remove-watch, but are otherwise considered opaque by + the watch mechanism." + [reference key f] + (cpp/jank.runtime.add_watch reference key f)) + +(defn remove-watch + "Removes a watch (set by add-watch) from a reference" + [reference key] + (cpp/jank.runtime.remove_watch reference key)) + +(defn agent-error + "Returns the exception thrown during an asynchronous action of the + agent if the agent is failed. Returns nil if the agent is not + failed." + [#_clojure.lang.Agent a] + ;; (.getError a) + (throw "TODO: port agent-error")) + +(defn restart-agent + "When an agent is failed, changes the agent state to new-state and + then un-fails the agent so that sends are allowed again. If + a :clear-actions true option is given, any actions queued on the + agent that were being held while it was failed will be discarded, + otherwise those held actions will proceed. The new-state must pass + the validator if any, or restart will throw an exception and the + agent will remain failed with its old state and error. Watchers, if + any, will NOT be notified of the new state. Throws an exception if + the agent is not failed." + [#_clojure.lang.Agent a, new-state & options] + ;; (let [opts (apply hash-map options)] + ;; (.restart a new-state (if (:clear-actions opts) true false))) + (throw "TODO: port restart-agent")) + +(defn set-error-handler! + "Sets the error-handler of agent a to handler-fn. If an action + being run by the agent throws an exception or doesn't pass the + validator fn, handler-fn will be called with two arguments: the + agent and the exception." + [#_clojure.lang.Agent a, handler-fn] + ;; (.setErrorHandler a handler-fn) + (throw "TODO: port set-error-handler!")) + +(defn error-handler + "Returns the error-handler of agent a, or nil if there is none. + See set-error-handler!" + [#_clojure.lang.Agent a] + ;; (.getErrorHandler a) + (throw "TODO: port error-handler")) + +(defn set-error-mode! + "Sets the error-mode of agent a to mode-keyword, which must be + either :fail or :continue. If an action being run by the agent + throws an exception or doesn't pass the validator fn, an + error-handler may be called (see set-error-handler!), after which, + if the mode is :continue, the agent will continue as if neither the + action that caused the error nor the error itself ever happened. + + If the mode is :fail, the agent will become failed and will stop + accepting new 'send' and 'send-off' actions, and any previously + queued actions will be held until a 'restart-agent'. Deref will + still work, returning the state of the agent before the error." + [#_clojure.lang.Agent a, mode-keyword] + ;; (.setErrorMode a mode-keyword) + (throw "TODO: port set-error-mode!")) + +(defn error-mode + "Returns the error-mode of agent a. See set-error-mode!" + [#_clojure.lang.Agent a] + ;; (.getErrorMode a) + (throw "TODO: port error-mode")) + +(defn agent-errors + "DEPRECATED: Use 'agent-error' instead. + Returns a sequence of the exceptions thrown during asynchronous + actions of the agent." + [a] + (when-let [e (agent-error a)] + (list e))) + +(defn clear-agent-errors + "DEPRECATED: Use 'restart-agent' instead. + Clears any exceptions thrown during asynchronous actions of the + agent, allowing subsequent actions to occur." + [#_clojure.lang.Agent a] + ;; (restart-agent a (.deref a)) + (throw "TODO: port clear-agent-errors")) + +(defn shutdown-agents + "Initiates a shutdown of the thread pools that back the agent + system. Running actions will complete, but no new actions will be + accepted" + [] + ;; (. clojure.lang.Agent shutdown) + (throw "TODO: port shutdown-agents")) + +(defn ref + "Creates and returns a Ref with an initial value of x and zero or + more options (in any order): + + :meta metadata-map + + :validator validate-fn + + :min-history (default 0) + :max-history (default 10) + + If metadata-map is supplied, it will become the metadata on the + ref. validate-fn must be nil or a side-effect-free fn of one + argument, which will be passed the intended new state on any state + change. If the new state is unacceptable, the validate-fn should + return false or throw an exception. validate-fn will be called on + transaction commit, when all refs have their final values. + + Normally refs accumulate history dynamically as needed to deal with + read demands. If you know in advance you will need history you can + set :min-history to ensure it will be available when first needed (instead + of after a read fault). History is limited, and the limit can be set + with :max-history." + ([x] + ;; (new clojure.lang.Ref x) + (throw "TODO: port ref")) + ([x & options] + ;; (let [r ^clojure.lang.Ref (setup-reference (ref x) options) + ;; opts (apply hash-map options)] + ;; (when (:max-history opts) + ;; (.setMaxHistory r (:max-history opts))) + ;; (when (:min-history opts) + ;; (.setMinHistory r (:min-history opts))) + ;; r) + (throw "TODO: port ref"))) + +(defn- deref-future + ([#_java.util.concurrent.Future fut] + ;; (.get fut) + (throw "TODO: port deref-future")) + ([#_java.util.concurrent.Future fut timeout-ms timeout-val] + ;; (try (.get fut timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS) + ;; (catch java.util.concurrent.TimeoutException e + ;; timeout-val)) + (throw "TODO: port deref-future"))) + +(defn set-validator! + "Sets the validator-fn for a var/ref/agent/atom. validator-fn must be nil or a + side-effect-free fn of one argument, which will be passed the intended + new state on any state change. If the new state is unacceptable, the + validator-fn should return false or throw an exception. If the current state (root + value if var) is not acceptable to the new validator, an exception + will be thrown and the validator will not be changed." + [#_clojure.lang.IRef iref validator-fn] + ;; (. iref (setValidator validator-fn)) + (throw "TODO: port set-validator!")) + +(defn get-validator + "Gets the validator-fn for a var/ref/agent/atom." + [#_clojure.lang.IRef iref] + ;; (. iref (getValidator)) + (throw "TODO: port get-validator")) + +(defn commute + "Must be called in a transaction. Sets the in-transaction-value of + ref to: + + (apply fun in-transaction-value-of-ref args) + + and returns the in-transaction-value of ref. + + At the commit point of the transaction, sets the value of ref to be: + + (apply fun most-recently-committed-value-of-ref args) + + Thus fun should be commutative, or, failing that, you must accept + last-one-in-wins behavior. commute allows for more concurrency than + ref-set." + [#_clojure.lang.Ref ref fun & args] + ;; (. ref (commute fun args)) + (throw "TODO: port commute")) + +(defn alter + "Must be called in a transaction. Sets the in-transaction-value of + ref to: + + (apply fun in-transaction-value-of-ref args) + + and returns the in-transaction-value of ref." + [#_clojure.lang.Ref ref fun & args] + ;; (. ref (alter fun args)) + (throw "TODO: port alter")) + +(defn ref-set + "Must be called in a transaction. Sets the value of ref. + Returns val." + [#_clojure.lang.Ref ref val] + ;; (. ref (set val)) + (throw "TODO: port ref-set")) + +(defn ref-history-count + "Returns the history count of a ref" + [#_clojure.lang.Ref ref] + ;; (.getHistoryCount ref) + (throw "TODO: port ref-history-count")) + +(defn ref-min-history + "Gets the min-history of a ref, or sets it and returns the ref" + ([#_clojure.lang.Ref ref] + ;; (.getMinHistory ref) + (throw "TODO: port ref-min-history")) + ([#_clojure.lang.Ref ref n] + ;; (.setMinHistory ref n) + (throw "TODO: port ref-min-history"))) + +(defn ref-max-history + "Gets the max-history of a ref, or sets it and returns the ref" + ([#_clojure.lang.Ref ref] + ;; (.getMaxHistory ref) + (throw "TODO: port ref-max-history")) + ([#_clojure.lang.Ref ref n] + ;; (.setMaxHistory ref n) + (throw "TODO: port ref-max-history"))) + +(defn ensure + "Must be called in a transaction. Protects the ref from modification + by other transactions. Returns the in-transaction-value of + ref. Allows for more concurrency than (ref-set ref @ref)" + [#_clojure.lang.Ref ref] + ;; (. ref (touch)) + ;; (. ref (deref)) + (throw "TODO: port ensure")) + +(defmacro sync + "transaction-flags => TBD, pass nil for now + + Runs the exprs (in an implicit do) in a transaction that encompasses + exprs and any nested calls. Starts a transaction if none is already + running on this thread. Any uncaught exception will abort the + transaction and flow out of sync. The exprs may be run more than + once, but any effects on Refs will be atomic." + [flags-ignored-for-now & body] + ;; `(. clojure.lang.LockingTransaction + ;; (runInTransaction (fn [] ~@body))) + (throw "TODO: port sync")) + +(defmacro io! + "If an io! block occurs in a transaction, throws an + IllegalStateException, else runs body in an implicit do. If the + first expression in body is a literal string, will use that as the + exception message." + [& body] + ;; (let [message (when (string? (first body)) (first body)) + ;; body (if message (next body) body)] + ;; `(if (clojure.lang.LockingTransaction/isRunning) + ;; (throw (new IllegalStateException ~(or message "I/O in transaction"))) + ;; (do ~@body))) + (throw "TODO: port io!")) + +;;;;;;;;;;;;;;;;;;; sequence fns ;;;;;;;;;;;;;;;;;;;;;;; + +(defn sequence + "Coerces coll to a (possibly empty) sequence, if it is not already + one. Will not force a lazy seq. (sequence nil) yields (), When a + transducer is supplied, returns a lazy sequence of applications of + the transform to the items in coll(s), i.e. to the set of first + items of each coll, followed by the set of second + items in each coll, until any one of the colls is exhausted. Any + remaining items in other colls are ignored. The transform should accept + number-of-colls arguments" + ([coll] + (if (seq? coll) coll + (or (seq coll) ()))) + ([xform coll] + ;; (or (clojure.lang.RT/chunkIteratorSeq + ;; (clojure.lang.TransformerIterator/create xform (clojure.lang.RT/iter coll))) + ;; ()) + (throw "TODO: port sequence")) + ([xform coll & colls] + ;; (or (clojure.lang.RT/chunkIteratorSeq + ;; (clojure.lang.TransformerIterator/createMulti + ;; xform + ;; (map #(clojure.lang.RT/iter %) (cons coll colls)))) + ;; ()) + (throw "TODO: port sequence"))) + +(defn not-every? + "Returns false if (pred x) is logical true for every x in + coll, else true." + [pred coll] + (not (every? pred coll))) + +(defmacro declare + "defs the supplied var names with no bindings, useful for making forward declarations." + [& names] `(do ~@(map #(list 'def (vary-meta % assoc :declared true)) names))) + +(defn replicate + "DEPRECATED: Use 'repeat' instead. + Returns a lazy seq of n xs." + [n x] (take n (repeat x))) + +(defn merge + "Returns a map that consists of the rest of the maps conj-ed onto + the first. If a key occurs in more than one map, the mapping from + the latter (left-to-right) will be the mapping in the result." + [& maps] + (when (some identity maps) + (reduce #(conj (or %1 {}) %2) maps))) + +(defn merge-with + "Returns a map that consists of the rest of the maps conj-ed onto + the first. If a key occurs in more than one map, the mapping(s) + from the latter (left-to-right) will be combined with the mapping in + the result by calling (f val-in-result val-in-latter)." + [f & maps] + (when (some identity maps) + (let [merge-entry (fn [m e] + (let [k (key e) v (val e)] + (if (contains? m k) + (assoc m k (f (get m k) v)) + (assoc m k v)))) + merge2 (fn [m1 m2] + (reduce merge-entry (or m1 {}) (seq m2)))] + (reduce merge2 maps)))) + +(defn line-seq + "Returns the lines of text from rdr as a lazy sequence of strings. + rdr must implement java.io.BufferedReader." + [#_java.io.BufferedReader rdr] + ;; (when-let [line (.readLine rdr)] + ;; (cons line (lazy-seq (line-seq rdr)))) + (throw "TODO: port line-seq")) + +(defn comparator + "Returns an implementation of java.util.Comparator based upon pred." + [pred] + (fn [x y] + (cond (pred x y) -1 (pred y x) 1 :else 0))) + +(defn sort + "Returns a sorted sequence of the items in coll. If no comparator is + supplied, uses compare. comparator must implement + java.util.Comparator. Guaranteed to be stable: equal elements will + not be reordered. If coll is a Java array, it will be modified. To + avoid this, sort a copy of the array." + [coll] + (cpp/jank.runtime.sort coll)) + +(defn sort-by + "Returns a sorted sequence of the items in coll, where the sort + order is determined by comparing (keyfn item). If no comparator is + supplied, uses compare. comparator must implement + java.util.Comparator. Guaranteed to be stable: equal elements will + not be reordered. If coll is a Java array, it will be modified. To + avoid this, sort a copy of the array." + ([keyfn coll] + (sort-by keyfn compare coll)) + ([keyfn #_java.util.Comparator comp coll] + ;; (sort (fn [x y] (. comp (compare (keyfn x) (keyfn y)))) coll) + (throw "TODO: port sort-by"))) + +;; evaluation + +(defn eval + "Evaluates the form data structure (not text!) and returns the result." + [form] + (cpp/clojure.core_native.eval form)) + +(defn await + "Blocks the current thread (indefinitely!) until all actions + dispatched thus far, from this thread or agent, to the agent(s) have + occurred. Will block on failed agents. Will never return if + a failed agent is restarted with :clear-actions true or shutdown-agents was called." + [& agents] + ;; (io! "await in transaction" + ;; (when *agent* + ;; (throw (new Exception "Can't await in agent action"))) + ;; (let [latch (new java.util.concurrent.CountDownLatch (count agents)) + ;; count-down (fn [agent] (. latch (countDown)) agent)] + ;; (doseq [agent agents] + ;; (send agent count-down)) + ;; (. latch (await)))) + (throw "TODO: port await")) + +(defn await1 [#_clojure.lang.Agent a] + ;; (when (pos? (.getQueueCount a)) + ;; (await a)) + ;; a + (throw "TODO: port await1")) + +(defn await-for + "Blocks the current thread until all actions dispatched thus + far (from this thread or agent) to the agents have occurred, or the + timeout (in milliseconds) has elapsed. Returns logical false if + returning due to timeout, logical true otherwise." + [timeout-ms & agents] + ;; (io! "await-for in transaction" + ;; (when *agent* + ;; (throw (new Exception "Can't await in agent action"))) + ;; (let [latch (new java.util.concurrent.CountDownLatch (count agents)) + ;; count-down (fn [agent] (. latch (countDown)) agent)] + ;; (doseq [agent agents] + ;; (send agent count-down)) + ;; (. latch (await timeout-ms (. java.util.concurrent.TimeUnit MILLISECONDS))))) + (throw "TODO: port await-for")) + +(defn import + "import is not implemented for jank, but a var is still bound to its symbol for portability. import always throws an exception" + [& _] + (throw "import is not supported in jank, for C/C++ dependency interoperability use cpp/raw with #include, e.g. (cpp/raw \"#include \"dependency.h\")\")")) + +(defn into-array + "Returns an array with components set to the values in aseq. The array's + component type is type if provided, or the type of the first value in + aseq if present, or Object. All values in aseq must be compatible with + the component type. Class objects for the primitive types can be obtained + using, e.g., Integer/TYPE." + ([aseq] + ;; (clojure.lang.RT/seqToTypedArray (seq aseq)) + (throw "TODO: port into-array")) + ([type aseq] + ;; (clojure.lang.RT/seqToTypedArray type (seq aseq)) + (throw "TODO: port into-array"))) + +(defn- + array [& items] + (into-array items)) + +(defn class + "Returns the Class of x" + #_Class [#_Object x] + ;; (if (nil? x) x (. x (getClass))) + (throw "TODO: port class")) + +(defn num + "Coerce to Number" + [x] + ;; (. clojure.lang.Numbers (num x)) + (throw "TODO: port num")) + +(defn long + "Coerce to long" + [#_Number x] + ;; (clojure.lang.RT/longCast x) + (throw "TODO: port long")) + +(defn double + "Coerce to double" + [#_Number x] + ;; (clojure.lang.RT/doubleCast x) + (throw "TODO: port double")) + +(defn short + "Coerce to short" + [#_Number x] + ;; (clojure.lang.RT/shortCast x) + (throw "TODO: port short")) + +(defn byte + "Coerce to byte" + [#_Number x] + ;; (clojure.lang.RT/byteCast x) + (throw "TODO: port byte")) + +(defn char + "Coerce to char" + [x] + ;; (. clojure.lang.RT (charCast x)) + (throw "TODO: port char")) + +(defn unchecked-byte + "Coerce to byte. Subject to rounding or truncation." + [#_Number x] + ;; (clojure.lang.RT/uncheckedByteCast x) + (throw "TODO: port unchecked-byte")) + +(defn unchecked-short + "Coerce to short. Subject to rounding or truncation." + [#_Number x] + ;; (clojure.lang.RT/uncheckedShortCast x) + (throw "TODO: port unchecked-short")) + +(defn unchecked-char + "Coerce to char. Subject to rounding or truncation." + [x] + ;; (. clojure.lang.RT (uncheckedCharCast x)) + (throw "TODO: port unchecked-char")) + +(defn unchecked-int + "Coerce to int. Subject to rounding or truncation." + [#_Number x] + ;; (clojure.lang.RT/uncheckedIntCast x) + (throw "TODO: port unchecked-int")) + +(defn unchecked-long + "Coerce to long. Subject to rounding or truncation." + [#_Number x] + ;; (clojure.lang.RT/uncheckedLongCast x) + (throw "TODO: port unchecked-long")) + +(defn unchecked-float + "Coerce to float. Subject to rounding." + [#_Number x] + ;; (clojure.lang.RT/uncheckedFloatCast x) + (throw "TODO: port unchecked-float")) + +(defn unchecked-double + "Coerce to double. Subject to rounding." + [#_Number x] + ;; (clojure.lang.RT/uncheckedDoubleCast x) + (throw "TODO: port unchecked-double")) + +(defn ratio? + "Returns true if n is a Ratio" + [r] + (cpp/jank.runtime.is_ratio r)) + +(defn numerator + "Returns the numerator part of a Ratio." + [r] + (cpp/jank.runtime.numerator r)) + +(defn denominator + "Returns the denominator part of a Ratio." + [r] + (cpp/jank.runtime.denominator r)) + +(defn decimal? + "Returns true if n is a BigDecimal" + [n] + ;; (instance? BigDecimal n) + (cpp/jank.runtime.is_big_decimal n)) + +(defn rational? + "Returns true if n is a rational number" + [n] + (or (integer? n) (ratio? n) (decimal? n))) + +(defn bigint + "Coerce to BigInt" + [x] + ;; (cond + ;; (instance? clojure.lang.BigInt x) x + ;; (instance? BigInteger x) (clojure.lang.BigInt/fromBigInteger x) + ;; (decimal? x) (bigint (.toBigInteger ^BigDecimal x)) + ;; (float? x) (bigint (. BigDecimal valueOf (double x))) + ;; (ratio? x) (bigint (.bigIntegerValue ^clojure.lang.Ratio x)) + ;; (number? x) (clojure.lang.BigInt/valueOf (long x)) + ;; :else (bigint (BigInteger. x))) + (throw "TODO: port bigint")) + +(defn biginteger + "Coerce to BigInteger" + [x] + ;; (cond + ;; (instance? BigInteger x) x + ;; (instance? clojure.lang.BigInt x) (.toBigInteger ^clojure.lang.BigInt x) + ;; (decimal? x) (.toBigInteger ^BigDecimal x) + ;; (float? x) (.toBigInteger (. BigDecimal valueOf (double x))) + ;; (ratio? x) (.bigIntegerValue ^clojure.lang.Ratio x) + ;; (number? x) (BigInteger/valueOf (long x)) + ;; :else (BigInteger. x)) + (throw "TODO: port biginteger")) + +(defn bigdec + "Coerce to BigDecimal" + [x] + (cpp/jank.runtime.to_big_decimal x)) + +(def ^:dynamic ^:private print-initialized false) + +(defmulti print-method (fn [x writer] + (let [t (get (meta x) :type)] + (if (keyword? t) t (class x))))) + +(defmulti print-dup (fn [x writer] (class x))) + +(def ^:private #_String system-newline + ;; (System/getProperty "line.separator") + "\n") + +(defn newline + "Writes a platform-specific newline to *out*" + [] + ;; (. *out* (append system-newline)) + ;; nil + (throw "TODO: port newline")) + +(defn flush + "Flushes the output stream that is the current value of + *out*" + [] + ;; (. *out* (flush)) + ;; nil + (throw "TODO: port flesh")) + +(defn read + "Reads the next object from stream, which must be an instance of + java.io.PushbackReader or some derivee. stream defaults to the + current value of *in*. + + Opts is a persistent map with valid keys: + :read-cond - :allow to process reader conditionals, or + :preserve to keep all branches + :features - persistent set of feature keywords for reader conditionals + :eof - on eof, return value unless :eofthrow, then throw. + if not specified, will throw + + Note that read can execute code (controlled by *read-eval*), + and as such should be used only with trusted sources. + + For data structure interop use clojure.edn/read" + ([] + (read *in*)) + ([stream] + (read stream true nil)) + ([stream eof-error? eof-value] + (read stream eof-error? eof-value false)) + ([stream eof-error? eof-value recursive?] + ;; (. clojure.lang.LispReader (read stream (boolean eof-error?) eof-value recursive?)) + (throw "TODO: port read")) + ([opts stream] + ;; (. clojure.lang.LispReader (read stream opts)) + (throw "TODO: port read"))) + +(defn read+string + "Like read, and taking the same args. stream must be a LineNumberingPushbackReader. + Returns a vector containing the object read and the (whitespace-trimmed) string read." + ([] (read+string *in*)) + ([stream] (read+string stream true nil)) + ([stream eof-error? eof-value] (read+string stream eof-error? eof-value false)) + ([#_clojure.lang.LineNumberingPushbackReader stream eof-error? eof-value recursive?] + ;; (try + ;; (.captureString stream) + ;; (let [o (read stream eof-error? eof-value recursive?) + ;; s (.trim (.getString stream))] + ;; [o s]) + ;; (catch Throwable ex + ;; (.getString stream) + ;; (throw ex))) + (throw "TODO: port read+string")) + ([opts #_clojure.lang.LineNumberingPushbackReader stream] + ;; (try + ;; (.captureString stream) + ;; (let [o (read opts stream) + ;; s (.trim (.getString stream))] + ;; [o s]) + ;; (catch Throwable ex + ;; (.getString stream) + ;; (throw ex))) + (throw "TODO: port read+string"))) + +(defn read-line + "Reads the next line from stream that is the current value of *in* ." + [] + ;; (if (instance? clojure.lang.LineNumberingPushbackReader *in*) + ;; (.readLine ^clojure.lang.LineNumberingPushbackReader *in*) + ;; (.readLine ^java.io.BufferedReader *in*)) + (throw "TODO: port read-line")) + +(defn read-string + "Reads one object from the string s. Optionally include reader + options, as specified in read. + + Note that read-string can execute code (controlled by *read-eval*), + and as such should be used only with trusted sources. + + For data structure interop use clojure.edn/read-string" + ([s] + (read-string {} s)) + ([opts s] + (cpp/clojure.core_native.read_string opts s))) + +(defmacro with-open + "bindings => [name init ...] + + Evaluates body in a try expression with names bound to the values + of the inits, and a finally clause that calls (.close name) on each + name in reverse order." + [bindings & body] + (assert-macro-args + (vector? bindings) "a vector for its binding" + (even? (count bindings)) "an even number of forms in binding vector") + ;; (cond + ;; (= (count bindings) 0) `(do ~@body) + ;; (symbol? (bindings 0)) `(let ~(subvec bindings 0 2) + ;; (try + ;; (with-open ~(subvec bindings 2) ~@body) + ;; (finally + ;; (. ~(bindings 0) ~'close)))) + ;; :else (throw (IllegalArgumentException. + ;; "with-open only allows Symbols in bindings"))) + (throw "TODO: port with-open")) + +(defmacro memfn + "Expands into code that creates a fn that expects to be passed an + object and any args and calls the named instance method on the + object passing the args. Use when you want to treat a Java method as + a first-class fn. name may be type-hinted with the method receiver's + type in order to avoid reflective calls." + [name & args] + ;; (let [t (with-meta (gensym "target") + ;; (meta name))] + ;; `(fn [~t ~@args] + ;; (. ~t (~name ~@args)))) + (throw "TODO: port memfn")) + +(defn alength + "Returns the length of the Java array. Works on arrays of all + types." + [array] + ;; (. clojure.lang.RT (alength array)) + (throw "TODO: port alength")) + +(defn aclone + "Returns a clone of the Java array. Works on arrays of known + types." + [array] + ;; (. clojure.lang.RT (aclone array)) + (throw "TODO: port aclone")) + +(defn aget + "Returns the value at the index/indices. Works on Java arrays of all + types." + ([array idx] + ;; (clojure.lang.Reflector/prepRet (.getComponentType (class array)) (. Array (get array idx))) + (throw "TODO: port aget")) + ([array idx & idxs] + (apply aget (aget array idx) idxs))) + +(defmacro aset + "Sets the value at the index/indices. Returns val." + [array idx & more] + (if (= 1 (count more)) + ;; Simple case: (aset array index value) + (let [val (first more)] + `(do + (cpp/= (cpp/aget ~array ~idx) ~val) + ~val)) + ;; Nested case: (aset array idx1 idx2 & idxv) - not yet implemented + `(throw "TODO: Nested array indexing not yet implemented"))) + +(defmacro + ^{:private true} + def-aset [name method coerce] + `(defn ~name + {:arglists '([~'array ~'idx ~'val] [~'array ~'idx ~'idx2 & ~'idxv])} + ([array# idx# val#] + ;; (. Array (~method array# idx# (~coerce val#))) + ;; val# + (throw ~(str "TODO: port " name))) + ([array# idx# idx2# & idxv#] + (apply ~name (aget array# idx#) idx2# idxv#)))) + +(def-aset + ^{:doc "Sets the value at the index/indices. Works on arrays of int. Returns val."} + aset-int setInt int) + +(def-aset + ^{:doc "Sets the value at the index/indices. Works on arrays of long. Returns val."} + aset-long setLong long) + +(def-aset + ^{:doc "Sets the value at the index/indices. Works on arrays of boolean. Returns val."} + aset-boolean setBoolean boolean) + +(def-aset + ^{:doc "Sets the value at the index/indices. Works on arrays of float. Returns val."} + aset-float setFloat float) + +(def-aset + ^{:doc "Sets the value at the index/indices. Works on arrays of double. Returns val."} + aset-double setDouble double) + +(def-aset + ^{:doc "Sets the value at the index/indices. Works on arrays of short. Returns val."} + aset-short setShort short) + +(def-aset + ^{:doc "Sets the value at the index/indices. Works on arrays of byte. Returns val."} + aset-byte setByte byte) + +(def-aset + ^{:doc "Sets the value at the index/indices. Works on arrays of char. Returns val."} + aset-char setChar char) + +(defn make-array + "Creates and returns an array of instances of the specified class of + the specified dimension(s). Note that a class object is required. + Class objects can be obtained by using their name. + Class objects for the primitive types can be obtained using, e.g., Integer/TYPE." + ([#_Class type len] + ;; (. Array (newInstance type (int len))) + (throw "TODO: port make-array")) + ([#_Class type dim & more-dims] + ;; (let [dims (cons dim more-dims) + ;; ^"[I" dimarray (make-array (. Integer TYPE) (count dims))] + ;; (dotimes [i (alength dimarray)] + ;; (aset-int dimarray i (nth dims i))) + ;; (. Array (newInstance type dimarray)))) + (throw "TODO: port make-array"))) + +(defn to-array-2d + "Returns a (potentially-ragged) 2-dimensional array of Objects + containing the contents of coll, which can be any Collection of any + Collection." + [#_java.util.Collection coll] + ;; (let [ret (make-array (. Class (forName "[Ljava.lang.Object;")) (. coll (size)))] + ;; (loop [i 0 xs (seq coll)] + ;; (when xs + ;; (aset ret i (to-array (first xs))) + ;; (recur (inc i) (next xs)))) + ;; ret) + (throw "TODO: port to-array-2d")) + +(defn create-struct + "Returns a structure basis object." + [& keys] + ;; (. clojure.lang.PersistentStructMap (createSlotMap keys)) + (throw "TODO: port create-struct")) + +(defmacro defstruct + "Same as (def name (create-struct keys...))" + [name & keys] + `(def ~name (create-struct ~@keys))) + +(defn struct-map + "Returns a new structmap instance with the keys of the + structure-basis. keyvals may contain all, some or none of the basis + keys - where values are not supplied they will default to nil. + keyvals can also contain keys not in the basis." + [s & inits] + ;; (. clojure.lang.PersistentStructMap (create s inits)) + (throw "TODO: port struct-map")) + +(defn struct + "Returns a new structmap instance with the keys of the + structure-basis. vals must be supplied for basis keys in order - + where values are not supplied they will default to nil." + [s & vals] + ;; (. clojure.lang.PersistentStructMap (construct s vals)) + (throw "TODO: port struct")) + +(defn accessor + "Returns a fn that, given an instance of a structmap with the basis, + returns the value at the key. The key must be in the basis. The + returned function should be (slightly) more efficient than using + get, but such use of accessors should be limited to known + performance-critical areas." + [s key] + ;; (. clojure.lang.PersistentStructMap (getAccessor s key)) + (throw "TODO: port accessor")) + +(defn load-reader + "Sequentially read and evaluate the set of forms contained in the + stream/file" + [rdr] + ;; (. clojure.lang.Compiler (load rdr)) + (throw "TODO: port load-reader")) + +(defn load-string + "Sequentially read and evaluate the set of forms contained in the + string" + [s] + ;; (let [rdr (-> (java.io.StringReader. s) + ;; (clojure.lang.LineNumberingPushbackReader.))] + ;; (load-reader rdr)) + (throw "TODO: port load-string")) + +(defn- + filter-key [keyfn pred amap] + (loop [ret {} es (seq amap)] + (if es + (if (pred (keyfn (first es))) + (recur (assoc ret (key (first es)) (val (first es))) (next es)) + (recur ret (next es))) + ret))) + +(defn all-ns + "Returns a sequence of all namespaces." + [] + ;; (clojure.lang.Namespace/all) + (throw "TODO: port all-ns")) + +(defn ns-unmap + "Removes the mappings for the symbol from the namespace." + [ns sym] + (cpp/clojure.core_native.ns_unmap (the-ns ns) sym)) + +(defn ns-imports + "Returns a map of the import mappings for the namespace." + [ns] + ;; (filter-key val (partial instance? Class) (ns-map ns)) + (throw "TODO: port ns-imports")) + +(defn ns-interns + "Returns a map of the intern mappings for the namespace." + [ns] + (let [ns (the-ns ns)] + (filter-key val (fn [v] (and (var? v) + (= (ns-name ns) (-> v symbol namespace symbol)))) + (ns-map ns)))) + +(defn ns-refers + "Returns a map of the refer mappings for the namespace." + [ns] + ;; (let [ns (the-ns ns)] + ;; (filter-key val (fn [^clojure.lang.Var v] (and (instance? clojure.lang.Var v) + ;; (not= ns (.ns v)))) + ;; (ns-map ns))) + (throw "TODO: port ns-refers")) + +(defn ns-aliases + "Returns a map of the aliases for the namespace." + [ns] + ;; (.getAliases (the-ns ns)) + (throw "TODO: port ns-aliases")) + +(defn ns-unalias + "Removes the alias for the symbol from the namespace." + [ns sym] + (cpp/clojure.core_native.ns_unalias (the-ns ns) sym)) + +(defn var-set + "Sets the value in the var object to val. The var must be + thread-locally bound." + [#_clojure.lang.Var x val] + ;; (. x (set val)) + (throw "TODO: port var-set")) + +(defmacro with-local-vars + "varbinding=> symbol init-expr + + Executes the exprs in a context in which the symbols are bound to + vars with per-thread bindings to the init-exprs. The symbols refer + to the var objects themselves, and must be accessed with var-get and + var-set" + [name-vals-vec & body] + (assert-macro-args + (vector? name-vals-vec) "a vector for its binding" + (even? (count name-vals-vec)) "an even number of forms in binding vector") + ;; `(let [~@(interleave (take-nth 2 name-vals-vec) + ;; (repeat '(.. clojure.lang.Var create setDynamic)))] + ;; (. clojure.lang.Var (pushThreadBindings (hash-map ~@name-vals-vec))) + ;; (try + ;; (do ~@body) + ;; (finally (. clojure.lang.Var (popThreadBindings))))) + (throw "TODO: port with-local-vars")) + +(defn array-map + "Constructs an array-map. If any keys are equal, they are handled as + if by repeated uses of assoc." + ([] + ;; (. clojure.lang.PersistentArrayMap EMPTY) + (throw "TODO: port array-map")) + ([& keyvals] + ;; (let [ary (to-array keyvals)] + ;; (if (odd? (alength ary)) + ;; (throw (IllegalArgumentException. (str "No value supplied for key: " (last keyvals)))) + ;; (clojure.lang.PersistentArrayMap/createAsIfByAssoc ary))) + (throw "TODO: port array-map"))) + +(defn seq-to-map-for-destructuring + "Builds a map from a seq as described in + https://clojure.org/reference/special_forms#keyword-arguments" + [s] + ;; (if (next s) + ;; (clojure.lang.PersistentArrayMap/createAsIfByAssoc (to-array s)) + ;; (if (seq s) (first s) clojure.lang.PersistentArrayMap/EMPTY)) + (throw "TODO: port seq-to-map-for-destructuring")) + +(defmacro lazy-cat + "Expands to code which yields a lazy sequence of the concatenation + of the supplied colls. Each coll expr is not evaluated until it is + needed. + + (lazy-cat xs ys zs) === (concat (lazy-seq xs) (lazy-seq ys) (lazy-seq zs))" + [& colls] + `(concat ~@(map #(list `lazy-seq %) colls))) + +(defmacro with-out-str + "Evaluates exprs in a context in which *out* is bound to a fresh + StringWriter. Returns the string created by any nested printing + calls." + [& body] + ;; `(let [s# (new java.io.StringWriter)] + ;; (binding [*out* s#] + ;; ~@body + ;; (str s#))) + (throw "TODO: port with-out-str")) + +(defmacro with-in-str + "Evaluates body in a context in which *in* is bound to a fresh + StringReader initialized with the string s." + [s & body] + `(with-open [s# (-> (java.io.StringReader. ~s) clojure.lang.LineNumberingPushbackReader.)] + (binding [*in* s#] + ~@body))) + +(defn prn-str + "prn to a string, returning it" + [& xs] + ;; (with-out-str + ;; (apply prn xs)) + (throw "TODO: port prn-str")) + + +(defn print-str + "print to a string, returning it" + [& xs] + ;; (with-out-str + ;; (apply print xs)) + (throw "TODO: port print-str")) + +(defn println-str + "println to a string, returning it" + [& xs] + ;; (with-out-str + ;; (apply println xs)) + (throw "TODO: port println-str")) + +(defn ^:private elide-top-frames + [#_Throwable ex class-name] + ;; (let [tr (.getStackTrace ex)] + ;; (doto ex + ;; (.setStackTrace + ;; (when tr + ;; (into-array StackTraceElement + ;; (drop-while #(= class-name (.getClassName ^StackTraceElement %1)) tr)))))) + (throw "TODO: port elide-top-frames")) + +(defn test + "test [v] finds fn at key :test in var metadata and calls it, + presuming failure will throw exception" + [v] + (let [f (:test (meta v))] + (if f + (do (f) :ok) + :no-test))) + +(defn re-pattern + "Returns an instance of java.util.regex.Pattern, for use, e.g. in + re-matcher." + [s] + (cpp/jank.runtime.re_pattern s)) + +(defn re-matcher + "Returns an instance of java.util.regex.Matcher, for use, e.g. in + re-find." + [re s] + (cpp/jank.runtime.re_matcher re s)) + +(defn re-groups + "Returns the groups from the most recent match/find. If there are no + nested groups, returns a string of the entire match. If there are + nested groups, returns a vector of the groups, the first element + being the entire match." + [m] + (cpp/jank.runtime.re_groups m)) + +(defn re-matches + "Returns the match, if any, of string to pattern, using + java.util.regex.Matcher.matches(). Uses re-groups to return the + groups." + [re s] + (cpp/jank.runtime.re_matches re s)) + +(defn re-find + "Returns the next regex match, if any, of string to pattern, using + java.util.regex.Matcher.find(). Uses re-groups to return the + groups." + ([m] + (cpp/jank.runtime.re_find m)) + ([re s] + (let [m (re-matcher re s)] + (re-find m)))) + +(defn re-seq + "Returns a lazy sequence of successive matches of pattern in string, + using java.util.regex.Matcher.find(), each such match processed with + re-groups." + [re s] + (let [m (cpp/jank.runtime.re_matcher re s)] + ((fn step [] + (when (re-find m) + (cons (re-groups m) (lazy-seq (step)))))))) + +(defn rand-int + "Returns a random integer between 0 (inclusive) and n (exclusive)." + [n] (int (rand n))) + +(defn file-seq + "A tree seq on java.io.Files" + [dir] + ;; (tree-seq + ;; (fn [^java.io.File f] (. f (isDirectory))) + ;; (fn [^java.io.File d] (seq (. d (listFiles)))) + ;; dir) + (throw "TODO: port file-seq")) + +(defn xml-seq + "A tree seq on the xml elements as per xml/parse" + [root] + (tree-seq + (complement string?) + (comp seq :content) + root)) + +(defn special-symbol? + "Returns true if s names a special form" + [s] + ;; (contains? (. clojure.lang.Compiler specials) s) + (throw "TODO: port special-symbol?")) + +(defn max-key + "Returns the x for which (k x), a number, is greatest. + + If there are multiple such xs, the last one is returned." + ([k x] x) + ([k x y] (if (> (k x) (k y)) x y)) + ([k x y & more] + (let [kx (k x) ky (k y) + [v kv] (if (> kx ky) [x kx] [y ky])] + (loop [v v kv kv more more] + (if more + (let [w (first more) + kw (k w)] + (if (>= kw kv) + (recur w kw (next more)) + (recur v kv (next more)))) + v))))) + +(defn min-key + "Returns the x for which (k x), a number, is least. + + If there are multiple such xs, the last one is returned." + ([k x] x) + ([k x y] (if (< (k x) (k y)) x y)) + ([k x y & more] + (let [kx (k x) ky (k y) + [v kv] (if (< kx ky) [x kx] [y ky])] + (loop [v v kv kv more more] + (if more + (let [w (first more) + kw (k w)] + (if (<= kw kv) + (recur w kw (next more)) + (recur v kv (next more)))) + v))))) + +(defn replace + "Given a map of replacement pairs and a vector/collection, returns a + vector/seq with any elements = a key in smap replaced with the + corresponding val in smap. Returns a transducer when no collection + is provided." + ([smap] + (map #(if-let [e (find smap %)] (val e) %))) + ([smap coll] + (if (vector? coll) + (reduce (fn [v i] + (if-let [e (find smap (nth v i))] + (assoc v i (val e)) + v)) + coll (range (count coll))) + (map #(if-let [e (find smap %)] (val e) %) coll)))) + +(defmacro dosync + "Runs the exprs (in an implicit do) in a transaction that encompasses + exprs and any nested calls. Starts a transaction if none is already + running on this thread. Any uncaught exception will abort the + transaction and flow out of dosync. The exprs may be run more than + once, but any effects on Refs will be atomic." + [& exprs] + `(sync nil ~@exprs)) + +(defmacro with-precision + "Sets the precision and rounding mode to be used for BigDecimal operations. + + Usage: (with-precision 10 (/ 1M 3)) + or: (with-precision 10 :rounding HALF_DOWN (/ 1M 3)) + + The rounding mode is one of CEILING, FLOOR, HALF_UP, HALF_DOWN, + HALF_EVEN, UP, DOWN and UNNECESSARY; it defaults to HALF_UP." + [precision & exprs] + ;; (let [[body rm] (if (= (first exprs) :rounding) + ;; [(next (next exprs)) + ;; `((. java.math.RoundingMode ~(second exprs)))] + ;; [exprs nil])] + ;; `(binding [*math-context* (java.math.MathContext. ~precision ~@rm)] + ;; ~@body)) + (throw "TODO: port with-precision")) + +(defn- mk-bound-fn + [#_clojure.lang.Sorted sc test key] + ;; (fn [e] + ;; (test (.. sc comparator (compare (. sc entryKey e) key)) 0)) + (throw "TODO: port mk-bound-fn")) + +(defn subseq + "sc must be a sorted collection, test(s) one of <, <=, > or + >=. Returns a seq of those entries with keys ek for + which (test (.. sc comparator (compare ek key)) 0) is true" + ([#_clojure.lang.Sorted sc test key] + ;; (let [include (mk-bound-fn sc test key)] + ;; (if (#{> >=} test) + ;; (when-let [[e :as s] (. sc seqFrom key true)] + ;; (if (include e) s (next s))) + ;; (take-while include (. sc seq true)))) + (throw "TODO: port subseq")) + ([#_clojure.lang.Sorted sc start-test start-key end-test end-key] + ;; (when-let [[e :as s] (. sc seqFrom start-key true)] + ;; (take-while (mk-bound-fn sc end-test end-key) + ;; (if ((mk-bound-fn sc start-test start-key) e) s (next s)))) + (throw "TODO: port subseq"))) + +(defn rsubseq + "sc must be a sorted collection, test(s) one of <, <=, > or + >=. Returns a reverse seq of those entries with keys ek for + which (test (.. sc comparator (compare ek key)) 0) is true" + ([#_clojure.lang.Sorted sc test key] + ;; (let [include (mk-bound-fn sc test key)] + ;; (if (#{< <=} test) + ;; (when-let [[e :as s] (. sc seqFrom key false)] + ;; (if (include e) s (next s))) + ;; (take-while include (. sc seq false)))) + (throw "TODO: port rsubseq")) + ([#_clojure.lang.Sorted sc start-test start-key end-test end-key] + ;; (when-let [[e :as s] (. sc seqFrom end-key false)] + ;; (take-while (mk-bound-fn sc start-test start-key) + ;; (if ((mk-bound-fn sc end-test end-key) e) s (next s)))) + (throw "TODO: port rsubseq"))) + +(defn add-classpath + "DEPRECATED + + Adds the url (String or URL object) to the classpath per + URLClassLoader.addURL" + [url] + (println "WARNING: add-classpath is deprecated") + ;; (clojure.lang.RT/addURL url) + (throw "TODO: port add-classpath")) + +(defn mix-collection-hash + "Mix final collection hash for ordered or unordered collections. + hash-basis is the combined collection hash, count is the number + of elements included in the basis. Note this is the hash code + consistent with =, different from .hashCode. + See http://clojure.org/data_structures#hash for full algorithms." + #_long + [#_long hash-basis #_long count] + ;; (clojure.lang.Murmur3/mixCollHash hash-basis count) + (throw "TODO: port mix-collection-hash")) + +(defn hash-ordered-coll + "Returns the hash code, consistent with =, for an external ordered + collection implementing Iterable. + See http://clojure.org/data_structures#hash for full algorithms." + #_long + [coll] + ;; (clojure.lang.Murmur3/hashOrdered coll) + (throw "TODO: port hash-ordered-coll")) + +(defn hash-unordered-coll + "Returns the hash code, consistent with =, for an external unordered + collection implementing Iterable. For maps, the iterator should + return map entries whose hash is computed as + (hash-ordered-coll [k v]). + See http://clojure.org/data_structures#hash for full algorithms." + [coll] + (cpp/clojure.core_native.hash_unordered coll)) + +(defmacro definline + "Experimental - like defmacro, except defines a named function whose + body is the expansion, calls to which may be expanded inline as if + it were a macro. Cannot be used with variadic (&) args." + [name & decl] + (let [[pre-args [args expr]] (split-with (comp not vector?) decl)] + `(do + (defn ~name ~@pre-args ~args ~(apply (eval (list `fn args expr)) args)) + (alter-meta! (var ~name) assoc :inline (fn ~name ~args ~expr)) + (var ~name)))) + +(defmacro amap + "Maps an expression across an array a, using an index named idx, and + return value named ret, initialized to a clone of a, then setting + each element of ret to the evaluation of expr, returning the new + array ret." + [a idx ret expr] + `(let [a# ~a l# (alength a#) + ~ret (aclone a#)] + (loop [~idx 0] + (if (< ~idx l#) + (do + (aset ~ret ~idx ~expr) + (recur (unchecked-inc ~idx))) + ~ret)))) + +(defmacro areduce + "Reduces an expression across an array a, using an index named idx, + and return value named ret, initialized to init, setting ret to the + evaluation of expr at each step, returning ret." + [a idx ret init expr] + `(let [a# ~a l# (alength a#)] + (loop [~idx 0 ~ret ~init] + (if (< ~idx l#) + (recur (unchecked-inc-int ~idx) ~expr) + ~ret)))) + +(defn float-array + "Creates an array of floats" + ([size-or-seq] + ;; (. clojure.lang.Numbers float_array size-or-seq) + (throw "TODO: port float-array")) + ([size init-val-or-seq] + ;; (. clojure.lang.Numbers float_array size init-val-or-seq) + (throw "TODO: port float-array") )) + +(defn boolean-array + "Creates an array of booleans" + ([size-or-seq] + ;; (. clojure.lang.Numbers boolean_array size-or-seq) + (throw "TODO: port boolean-array")) + ([size init-val-or-seq] + ;; (. clojure.lang.Numbers boolean_array size init-val-or-seq) + (throw "TODO: port boolean-array"))) + +(defn byte-array + "Creates an array of bytes" + ([size-or-seq] + ;; (. clojure.lang.Numbers byte_array size-or-seq) + (throw "TODO: port byte-array")) + ([size init-val-or-seq] + ;; (. clojure.lang.Numbers byte_array size init-val-or-seq) + (throw "TODO: port byte-array"))) + +(defn char-array + "Creates an array of chars" + ([size-or-seq] + ;; (. clojure.lang.Numbers char_array size-or-seq) + (throw "TODO: port char-array")) + ([size init-val-or-seq] + ;; (. clojure.lang.Numbers char_array size init-val-or-seq) + (throw "TODO: port char-array"))) + +(defn short-array + "Creates an array of shorts" + ([size-or-seq] + ;; (. clojure.lang.Numbers short_array size-or-seq) + (throw "TODO: port short-array")) + ([size init-val-or-seq] + ;; (. clojure.lang.Numbers short_array size init-val-or-seq) + (throw "TODO: port short-array"))) + +(defn double-array + "Creates an array of doubles" + ([size-or-seq] + ;; (. clojure.lang.Numbers double_array size-or-seq) + (throw "TODO: port double-array")) + ([size init-val-or-seq] + ;; (. clojure.lang.Numbers double_array size init-val-or-seq) + (throw "TODO: port double-array"))) + +(defn object-array + "Creates an array of objects" + ([size-or-seq] + ;; (. clojure.lang.RT object_array size-or-seq) + (throw "TODO: port object-array"))) + +(defn int-array + "Creates an array of ints" + ([size-or-seq] + ;; (. clojure.lang.Numbers int_array size-or-seq) + (throw "TODO: port int-array")) + ([size init-val-or-seq] + ;; (. clojure.lang.Numbers int_array size init-val-or-seq) + (throw "TODO: port int-array"))) + +(defn long-array + "Creates an array of longs" + ([size-or-seq] + ;; (. clojure.lang.Numbers long_array size-or-seq) + (throw "TODO: port long-array")) + ([size init-val-or-seq] + ;; (. clojure.lang.Numbers long_array size init-val-or-seq) + (throw "TODO: port long-array"))) + +;; definline doesn't work without eval + +;; (definline booleans +;; "Casts to boolean[]" +;; [xs] +;; ;; `(. clojure.lang.Numbers booleans ~xs) +;; (throw "TODO: port")) + +;; (definline bytes +;; "Casts to bytes[]" +;; [xs] +;; ;; `(. clojure.lang.Numbers bytes ~xs) +;; (throw "TODO: port")) + +;; (definline chars +;; "Casts to chars[]" +;; [xs] +;; ;; `(. clojure.lang.Numbers chars ~xs) +;; (throw "TODO: port")) + +;; (definline shorts +;; "Casts to shorts[]" +;; [xs] +;; ;; `(. clojure.lang.Numbers shorts ~xs) +;; (throw "TODO: port")) + +;; (definline floats +;; "Casts to float[]" +;; [xs] +;; ;; `(. clojure.lang.Numbers floats ~xs) +;; (throw "TODO: port")) + +;; (definline ints +;; "Casts to int[]" +;; [xs] +;; ;; `(. clojure.lang.Numbers ints ~xs) +;; (throw "TODO: port")) + +;; (definline doubles +;; "Casts to double[]" +;; [xs] +;; ;; `(. clojure.lang.Numbers doubles ~xs) +;; (throw "TODO: port")) + +;; (definline longs +;; "Casts to long[]" +;; [xs] +;; ;; `(. clojure.lang.Numbers longs ~xs) +;; (throw "TODO: port")) + +(defn bytes? + "Return true if x is a byte array" + [x] + ;; (if (nil? x) + ;; false + ;; (-> x class .getComponentType (= Byte/TYPE))) + (throw "TODO: port bytes?")) + +(defn seque + "Creates a queued seq on another (presumably lazy) seq s. The queued + seq will produce a concrete seq in the background, and can get up to + n items ahead of the consumer. n-or-q can be an integer n buffer + size, or an instance of java.util.concurrent BlockingQueue. Note + that reading from a seque can block if the reader gets ahead of the + producer." + ([s] (seque 100 s)) + ([n-or-q s] + ;; (let [^BlockingQueue q (if (instance? BlockingQueue n-or-q) + ;; n-or-q + ;; (LinkedBlockingQueue. (int n-or-q))) + ;; NIL (Object.) ;nil sentinel since LBQ doesn't support nils + ;; agt (agent (lazy-seq s)) ; never start with nil; that signifies we've already put eos + ;; log-error (fn [q e] + ;; (if (.offer q q) + ;; (throw e) + ;; e)) + ;; fill (fn [s] + ;; (when s + ;; (if (instance? Exception s) ; we failed to .offer an error earlier + ;; (log-error q s) + ;; (try + ;; (loop [[x & xs :as s] (seq s)] + ;; (if s + ;; (if (.offer q (if (nil? x) NIL x)) + ;; (recur xs) + ;; s) + ;; (when-not (.offer q q) ; q itself is eos sentinel + ;; ()))) ; empty seq, not nil, so we know to put eos next time + ;; (catch Exception e + ;; (log-error q e)))))) + ;; drain (fn drain [] + ;; (lazy-seq + ;; (let [x (.take q)] + ;; (if (identical? x q) ;q itself is eos sentinel + ;; (do @agt nil) ;touch agent just to propagate errors + ;; (do + ;; (send-off agt fill) + ;; (release-pending-sends) + ;; (cons (if (identical? x NIL) nil x) (drain)))))))] + ;; (send-off agt fill) + ;; (drain)) + (throw "TODO: port seque"))) + +(defn class? + "Returns true if x is an instance of Class" + [x] + ;; (instance? Class x) + (throw "TODO: port class?")) + +(defn- is-annotation? [c] + ;; (and (class? c) + ;; (.isAssignableFrom java.lang.annotation.Annotation c)) + (throw "TODO: port is-annotation?")) + +(defn- is-runtime-annotation? [#_Class c] + ;; (boolean + ;; (and (is-annotation? c) + ;; (when-let [^java.lang.annotation.Retention r + ;; (.getAnnotation c java.lang.annotation.Retention)] + ;; (= (.value r) java.lang.annotation.RetentionPolicy/RUNTIME)))) + (throw "TODO: port is-runtime-annotation?")) + +(defn- descriptor [#_Class c] + ;; (clojure.asm.Type/getDescriptor c) + (throw "TODO: port descriptor")) + +(declare process-annotation) + +(defn- add-annotation [#_clojure.asm.AnnotationVisitor av name v] + ;; (cond + ;; (vector? v) (let [avec (.visitArray av name)] + ;; (doseq [vval v] + ;; (add-annotation avec "value" vval)) + ;; (.visitEnd avec)) + ;; (symbol? v) (let [ev (eval v)] + ;; (cond + ;; (instance? java.lang.Enum ev) + ;; (.visitEnum av name (descriptor (class ev)) (str ev)) + ;; (class? ev) (.visit av name (clojure.asm.Type/getType ev)) + ;; :else (throw (IllegalArgumentException. + ;; (str "Unsupported annotation value: " v " of class " (class ev)))))) + ;; (seq? v) (let [[nested nv] v + ;; c (resolve nested) + ;; nav (.visitAnnotation av name (descriptor c))] + ;; (process-annotation nav nv) + ;; (.visitEnd nav)) + ;; :else (.visit av name v)) + (throw "TODO: port add-annotation")) + +(defn- process-annotation [av v] + (if (map? v) + (doseq [[k v] v] + (add-annotation av (name k) v)) + (add-annotation av "value" v))) + +(defn- add-annotations + ([visitor m] (add-annotations visitor m nil)) + ([visitor m i] + ;; (doseq [[k v] m] + ;; (when (symbol? k) + ;; (when-let [c (resolve k)] + ;; (when (is-annotation? c) + ;; ;this is known duck/reflective as no common base of ASM Visitors + ;; (let [av (if i + ;; (.visitParameterAnnotation visitor i (descriptor c) + ;; (is-runtime-annotation? c)) + ;; (.visitAnnotation visitor (descriptor c) + ;; (is-runtime-annotation? c)))] + ;; (process-annotation av v) + ;; (.visitEnd av)))))) + (throw "TODO: port add-annotations"))) + +(defn bases + "Returns the immediate superclass and direct interfaces of c, if any" + [#_Class c] + ;; (when c + ;; (let [i (seq (.getInterfaces c)) + ;; s (.getSuperclass c)] + ;; (if s (cons s i) i))) + (throw "TODO: port bases")) + +(defn supers + "Returns the immediate and indirect superclasses and interfaces of c, if any" + [#_Class class] + (loop [ret (set (bases class)) cs ret] + (if (seq cs) + (let [c (first cs) bs (bases c)] + (recur (into ret bs) (into (disj cs c) bs))) + (not-empty ret)))) + + +(defn resultset-seq + "Creates and returns a lazy sequence of structmaps corresponding to + the rows in the java.sql.ResultSet rs" + [#_java.sql.ResultSet rs] + ;; (let [rsmeta (. rs (getMetaData)) + ;; idxs (range 1 (inc (. rsmeta (getColumnCount)))) + ;; keys (map (comp keyword #(.toLowerCase ^String %)) + ;; (map (fn [i] (. rsmeta (getColumnLabel i))) idxs)) + ;; check-keys + ;; (or (apply distinct? keys) + ;; (throw (Exception. "ResultSet must have unique column labels"))) + ;; row-struct (apply create-struct keys) + ;; row-values (fn [] (map (fn [^Integer i] (. rs (getObject i))) idxs)) + ;; rows (fn thisfn [] + ;; (when (. rs (next)) + ;; (cons (apply struct row-struct (row-values)) (lazy-seq (thisfn)))))] + ;; (rows)) + (throw "TODO: port resultset-seq")) + +(defn iterator-seq + "Returns a seq on a java.util.Iterator. Note that most collections + providing iterators implement Iterable and thus support seq directly. + Seqs cache values, thus iterator-seq should not be used on any + iterator that repeatedly returns the same mutable object." + [iter] + ;; (clojure.lang.RT/chunkIteratorSeq iter) + (throw "TODO: port iterator-seq")) + +(defn enumeration-seq + "Returns a seq on a java.util.Enumeration" + [e] + ;; (clojure.lang.EnumerationSeq/create e) + (throw "TODO: port enumeration-seq")) + +(defn format + "Formats a string using java.lang.String.format, see java.util.Formatter for format + string syntax" + #_String [fmt & args] + ;; (String/format fmt (to-array args)) + (throw "TODO: port format")) + +(defn printf + "Prints formatted output, as per format" + [fmt & args] + (print (apply format fmt args))) + +(declare gen-class) + +(defmacro with-loading-context [& body] + ;; `((fn loading# [] + ;; (. clojure.lang.Var (pushThreadBindings {clojure.lang.Compiler/LOADER + ;; (.getClassLoader (.getClass ^Object loading#))})) + ;; (try + ;; (do ~@body) + ;; (finally + ;; (. clojure.lang.Var (popThreadBindings)))))) + (throw "TODO: port with-loading-context")) + +(defonce + ^{:private true + :dynamic true + :doc "True while a verbose load is pending"} + *loading-verbosely* false) + +(defn- root-directory + "Returns the root resource path for a lib" + [lib] + ;; (let [d (root-resource lib)] + ;; (subs d 0 (.lastIndexOf d "/"))) + (throw "TODO: port root-resource")) + +(defn- serialized-require + "Like 'require', but serializes loading. + Interim function preferred over 'require' for known asynchronous loads. + Future changes may make these equivalent." + [& args] + ;; (locking clojure.lang.RT/REQUIRE_LOCK + ;; (apply require args)) + (throw "TODO: port serialized-require")) + +(defn requiring-resolve + "Resolves namespace-qualified sym per 'resolve'. If initial resolve +fails, attempts to require sym's namespace and retries." + [sym] + ;; (if (qualified-symbol? sym) + ;; (or (resolve sym) + ;; (do (-> sym namespace symbol serialized-require) + ;; (resolve sym))) + ;; (throw (IllegalArgumentException. (str "Not a qualified symbol: " sym)))) + (throw "TODO: port requiring-resolve")) + +(defn loaded-libs + "Returns a sorted set of symbols naming the currently loaded libs" + [] @*loaded-libs*) + +(defn sorted? + "Returns true if coll implements Sorted" + [coll] + (cpp/jank.runtime.is_sorted coll)) + +(defn counted? + "Returns true if coll implements count in constant time" + [coll] + (cpp/jank.runtime.is_counted coll)) + +(defn reversible? + "Returns true if coll implements Reversible" + [coll] + ;; (instance? clojure.lang.Reversible coll) + (throw "TODO: port reversible?")) + +(defn indexed? + "Return true if coll implements Indexed, indicating efficient lookup by index" + [coll] + ;; (instance? clojure.lang.Indexed coll) + (throw "TODO: port indexed?")) + +(def ^:dynamic + ^{:doc "bound in a repl thread to the most recent value printed"} + *1) + +(def ^:dynamic + ^{:doc "bound in a repl thread to the second most recent value printed"} + *2) + +(def ^:dynamic + ^{:doc "bound in a repl thread to the third most recent value printed"} + *3) + +(def ^:dynamic + ^{:doc "bound in a repl thread to the most recent exception caught by the repl"} + *e) + +(def ^:dynamic + ^{:doc "Bound to true in a repl thread"} + *repl* false) + +(defn trampoline + "trampoline can be used to convert algorithms requiring mutual + recursion without stack consumption. Calls f with supplied args, if + any. If f returns a fn, calls that fn with no arguments, and + continues to repeat, until the return value is not a fn, then + returns that non-fn value. Note that if you want to return a fn as a + final value, you must wrap it in some data structure and unpack it + after trampoline returns." + ([f] + (let [ret (f)] + (if (fn? ret) + (recur ret) + ret))) + ([f & args] + (trampoline #(apply f args)))) + +(defmacro while + "Repeatedly executes body while test expression is true. Presumes + some side-effect will cause test to become false/nil. Returns nil" + [test & body] + `(loop [] + (when ~test + ~@body + (recur)))) + +(defn memoize + "Returns a memoized version of a referentially transparent function. The + memoized version of the function keeps a cache of the mapping from arguments + to results and, when calls with the same arguments are repeated often, has + higher performance at the expense of higher memory use." + [f] + (let [mem (atom {})] + (fn [& args] + (if-let [e (find @mem args)] + (val e) + (let [ret (apply f args)] + (swap! mem assoc args ret) + ret))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; var documentation ;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defmacro add-doc-and-meta {:private true} [name docstring meta] + `(alter-meta! (var ~name) merge (assoc ~meta :doc ~docstring))) + +;; (add-doc-and-meta *file* +;; "The path of the file being evaluated, as a String. + +;; When there is no file, e.g. in the REPL, the value is not defined." +;; {}) + +;; (add-doc-and-meta *command-line-args* +;; "A sequence of the supplied command line arguments, or nil if +;; none were supplied" +;; {}) + +;; (add-doc-and-meta *warn-on-reflection* +;; "When set to true, the compiler will emit warnings when reflection is +;; needed to resolve Java method calls or field accesses. + +;; Defaults to false." +;; {}) + +;; (add-doc-and-meta *compile-path* +;; "Specifies the directory where 'compile' will write out .class +;; files. This directory must be in the classpath for 'compile' to +;; work. + +;; Defaults to \"classes\"" +;; {}) + +;; (add-doc-and-meta *compile-files* +;; "Set to true when compiling files, false otherwise." +;; {}) + +;; (add-doc-and-meta *unchecked-math* +;; "While bound to true, compilations of +, -, *, inc, dec and the +;; coercions will be done without overflow checks. While bound +;; to :warn-on-boxed, same behavior as true, and a warning is emitted +;; when compilation uses boxed math. Default: false." +;; {}) + +;; (add-doc-and-meta *compiler-options* +;; "A map of keys to options. +;; Note, when binding dynamically make sure to merge with previous value. +;; Supported options: +;; :elide-meta - a collection of metadata keys to elide during compilation. +;; :disable-locals-clearing - set to true to disable clearing, useful for using a debugger +;; :direct-linking - set to true to use direct static invocation of functions, rather than vars +;; Note that call sites compiled with direct linking will not be affected by var redefinition. +;; Use ^:redef (or ^:dynamic) on a var to prevent direct linking and allow redefinition. +;; See https://clojure.org/reference/compilation for more information." +;; {}) + +;; (add-doc-and-meta *in* +;; "A java.io.Reader object representing standard input for read operations. + +;; Defaults to System/in, wrapped in a LineNumberingPushbackReader" +;; {}) + +;; (add-doc-and-meta *err* +;; "A java.io.Writer object representing standard error for print operations. + +;; Defaults to System/err, wrapped in a PrintWriter" +;; {}) + +;; (add-doc-and-meta *flush-on-newline* +;; "When set to true, output will be flushed whenever a newline is printed. + +;; Defaults to true." +;; {}) + +;; (add-doc-and-meta *print-meta* +;; "If set to logical true, when printing an object, its metadata will also +;; be printed in a form that can be read back by the reader. + +;; Defaults to false." +;; {}) + +;; (add-doc-and-meta *print-dup* +;; "When set to logical true, objects will be printed in a way that preserves +;; their type when read in later. + +;; Defaults to false." +;; {}) + +;; (add-doc-and-meta *print-readably* +;; "When set to logical false, strings and characters will be printed with +;; non-alphanumeric characters converted to the appropriate escape sequences. + +;; Defaults to true" +;; {}) + +;; (add-doc-and-meta *read-eval* +;; "Defaults to true (or value specified by system property, see below) +;; ***This setting implies that the full power of the reader is in play, +;; including syntax that can cause code to execute. It should never be +;; used with untrusted sources. See also: clojure.edn/read.*** + +;; When set to logical false in the thread-local binding, +;; the eval reader (#=) and record/type literal syntax are disabled in read/load. +;; Example (will fail): (binding [*read-eval* false] (read-string \"#=(* 2 21)\")) + +;; The default binding can be controlled by the system property +;; 'clojure.read.eval' System properties can be set on the command line +;; like this: + +;; java -Dclojure.read.eval=false ... + +;; The system property can also be set to 'unknown' via +;; -Dclojure.read.eval=unknown, in which case the default binding +;; is :unknown and all reads will fail in contexts where *read-eval* +;; has not been explicitly bound to either true or false. This setting +;; can be a useful diagnostic tool to ensure that all of your reads +;; occur in considered contexts. You can also accomplish this in a +;; particular scope by binding *read-eval* to :unknown +;; " +;; {}) + +;; (add-doc-and-meta *assert* +;; "When set to logical false, 'assert' will omit assertion checks in +;; compiled code. Defaults to true." +;; {}) + +(defn future? + "Returns true if x is a future" + [x] + ;; (instance? java.util.concurrent.Future x) + (throw "TODO: port future?")) + +(defn future-done? + "Returns true if future f is done" + [#_java.util.concurrent.Future f] + ;; (.isDone f) + (throw "TODO: port future-done?")) + +(defmacro letfn + "fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+) + + Takes a vector of function specs and a body, and generates a set of + bindings of functions to their names. All of the names are available + in all of the definitions of the functions, as well as the body." + {:forms '[(letfn [fnspecs*] exprs*)], + :special-form true} + [fnspecs & body] + `(letfn* ~(vec (interleave (map first fnspecs) + (map #(cons `fn %) fnspecs))) + ~@body)) + +(defn stream-reduce! + "Works like reduce but takes a java.util.stream.BaseStream as its source. + Honors 'reduced', is a terminal operation on the stream" + ([f #_java.util.stream.BaseStream s] + ;; (clojure.core.protocols/iterator-reduce! (.iterator s) f) + (throw "TODO: port stream-reduce!")) + ([f init #_java.util.stream.BaseStream s] + ;; (clojure.core.protocols/iterator-reduce! (.iterator s) f init) + (throw "TODO: port stream-reduce!"))) + +(defn stream-seq! + "Takes a java.util.stream.BaseStream instance s and returns a seq of its + contents. This is a terminal operation on the stream." + [#_java.util.stream.BaseStream stream] + ;; (iterator-seq (.iterator stream)) + (throw "TODO: port stream-seq!")) + +(defn stream-transduce! + "Works like transduce but takes a java.util.stream.BaseStream as its source. + This is a terminal operation on the stream." + ([xform f #_java.util.stream.BaseStream stream] + (stream-transduce! xform f (f) stream)) + ([xform f init #_java.util.stream.BaseStream stream] + (let [f (xform f) + ret (stream-reduce! f init stream)] + (f ret)))) + +(defn stream-into! + "Returns a new coll consisting of coll with all of the items of the + stream conjoined. This is a terminal operation on the stream." + ([to #_java.util.stream.BaseStream stream] + ;; (if (instance? clojure.lang.IEditableCollection to) + ;; (with-meta (persistent! (stream-reduce! conj! (transient to) stream)) (meta to)) + ;; (stream-reduce! conj to stream)) + (throw "TODO: port stream-into!")) + ([to xform #_java.util.stream.BaseStream stream] + ;; (if (instance? clojure.lang.IEditableCollection to) + ;; (with-meta (persistent! (stream-transduce! xform conj! (transient to) stream)) (meta to)) + ;; (stream-transduce! xform conj to stream)) + (throw "TODO: port stream-into!"))) + + +(defmacro ^:private when-class [class-name & body] + ;; `(try + ;; (Class/forName ^String ~class-name) + ;; ~@body + ;; (catch ClassNotFoundException _#)) + (throw "TODO: port when-class")) + +;; (defprotocol Inst +;; (inst-ms* [inst])) + +;; (extend-protocol Inst +;; java.util.Date +;; (inst-ms* [inst] (.getTime ^java.util.Date inst))) + +(defn inst-ms + "Return the number of milliseconds since January 1, 1970, 00:00:00 GMT" + [inst] + (cpp/jank.runtime.inst_ms inst)) + +(defn inst? + "Return true if x satisfies Inst" + [x] + (cpp/jank.runtime.is_inst x)) + +;; (extend-protocol clojure.core/Inst +;; java.time.Instant +;; (inst-ms* [inst] (.toEpochMilli ^java.time.Instant inst))) + +(defn uuid? + "Return true if x is a java.util.UUID" + [x] + (cpp/jank.runtime.is_uuid x)) + +(defn random-uuid + "Returns a pseudo-randomly generated java.util.UUID instance (i.e. type 4). + + See: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#randomUUID--" + [] + (cpp/jank.runtime.random_uuid)) + +;; (extend-protocol clojure.core.protocols/IKVReduce +;; nil +;; (kv-reduce +;; [_ f init] +;; init) + +;; ;;slow path default +;; java.lang.Object +;; (kv-reduce +;; [amap f init] +;; (reduce (fn [ret ^java.util.Map$Entry me] +;; (f ret +;; (.getKey me) +;; (.getValue me))) +;; init +;; amap)) + +;; clojure.lang.IKVReduce +;; (kv-reduce +;; [amap f init] +;; (.kvreduce amap f init))) + +(defn reduce-kv + "Reduces an associative collection. f should be a function of 3 + arguments. Returns the result of applying f to init, the first key + and the first value in coll, then applying f to that result and the + 2nd key and value, etc. If coll contains no entries, returns init + and f is not called. Note that reduce-kv is supported on vectors, + where the keys will be the ordinals." + ([f init coll] + ;; (clojure.core.protocols/kv-reduce coll f init) + (reduce (fn [s [k v]] (f s k v)) init coll))) + +(defn- normalize-slurp-opts + [opts] + (if (string? (first opts)) + (do + (println "WARNING: (slurp f enc) is deprecated, use (slurp f :encoding enc).") + [:encoding (first opts)]) + opts)) + +(defn slurp + "Opens a reader on f and reads all its contents, returning a string. + See clojure.java.io/reader for a complete list of supported arguments." + ([f & opts] + (let [opts (normalize-slurp-opts opts) + fname (cpp/cast (cpp/type "char const*") f) + file (cpp/std.ifstream. fname)] + (if-not (cpp/.is_open file) + (throw (str f " (No such file or directory)")) + (let [size (cpp/std.filesystem.file_size fname) + out (cpp/std.string. size (cpp/char 0))] + (cpp/.read file (cpp/& (cpp/.front out)) size) + out))))) + +(defn spit + "Opposite of slurp. Opens f with writer, writes content, then + closes f. Options passed to clojure.java.io/writer." + [f content & options] + (let [file (cpp/std.ofstream.)] + (cpp/.open file (cpp/cast (cpp/type "char const*") f)) + (cpp/<< file (cpp/cast (cpp/type "char const*") content)) + (cpp/.close file) + nil)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; futures (needs proxy);;;;;;;;;;;;;;;;;; +(defn future-call + "Takes a function of no args and yields a future object that will + invoke the function in another thread, and will cache the result and + return it on all subsequent calls to deref/@. If the computation has + not yet finished, calls to deref/@ will block, unless the variant + of deref with timeout is used. See also - realized?." + [f] + ;; (let [f (binding-conveyor-fn f) + ;; fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)] + ;; (reify + ;; clojure.lang.IDeref + ;; (deref [_] (deref-future fut)) + ;; clojure.lang.IBlockingDeref + ;; (deref + ;; [_ timeout-ms timeout-val] + ;; (deref-future fut timeout-ms timeout-val)) + ;; clojure.lang.IPending + ;; (isRealized [_] (.isDone fut)) + ;; java.util.concurrent.Future + ;; (get [_] (.get fut)) + ;; (get [_ timeout unit] (.get fut timeout unit)) + ;; (isCancelled [_] (.isCancelled fut)) + ;; (isDone [_] (.isDone fut)) + ;; (cancel [_ interrupt?] (.cancel fut interrupt?)))) + (throw "TODO: port future-call")) + +(defmacro future + "Takes a body of expressions and yields a future object that will + invoke the body in another thread, and will cache the result and + return it on all subsequent calls to deref/@. If the computation has + not yet finished, calls to deref/@ will block, unless the variant of + deref with timeout is used. See also - realized?." + [& body] + ;; `(future-call (^{:once true} fn* [] ~@body)) + (throw "TODO: port future")) + +(defn future-cancel + "Cancels the future, if possible." + [#_java.util.concurrent.Future f] + ;; (.cancel f true) + (throw "TODO: port future-cancel")) + +(defn future-cancelled? + "Returns true if future f is cancelled" + [#_java.util.concurrent.Future f] + ;; (.isCancelled f) + (throw "TODO: port future-cancelled?")) + +(defn pmap + "Like map, except f is applied in parallel. Semi-lazy in that the + parallel computation stays ahead of the consumption, but doesn't + realize the entire result unless required. Only useful for + computationally intensive functions where the time of f dominates + the coordination overhead." + ([f coll] + ;; (let [n (+ 2 (.. Runtime getRuntime availableProcessors)) + ;; rets (map #(future (f %)) coll) + ;; step (fn step [[x & xs :as vs] fs] + ;; (lazy-seq + ;; (if-let [s (seq fs)] + ;; (cons (deref x) (step xs (rest s))) + ;; (map deref vs))))] + ;; (step rets (drop n rets))) + (throw "TODO: port pmap")) + ([f coll & colls] + ;; (let [step (fn step [cs] + ;; (lazy-seq + ;; (let [ss (map seq cs)] + ;; (when (every? identity ss) + ;; (cons (map first ss) (step (map rest ss)))))))] + ;; (pmap #(apply f %) (step (cons coll colls)))) + (throw "TODO: port pmap"))) + + +(defn pcalls + "Executes the no-arg fns in parallel, returning a lazy sequence of + their values" + [& fns] (pmap #(%) fns)) + +(defmacro pvalues + "Returns a lazy sequence of the values of the exprs, which are + evaluated in parallel" + [& exprs] + `(pcalls ~@(map #(list `fn [] %) exprs))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; clojure version number ;;;;;;;;;;;;;;;;;;;;;; + +;; (let [^java.util.Properties +;; properties (with-open [version-stream (.getResourceAsStream +;; (clojure.lang.RT/baseLoader) +;; "clojure/version.properties")] +;; (doto (new java.util.Properties) +;; (.load version-stream))) +;; version-string (.getProperty properties "version") +;; [_ major minor incremental qualifier snapshot] +;; (re-matches +;; #"(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9_]+))?(?:-(SNAPSHOT))?" +;; version-string) +;; clojure-version {:major (Integer/valueOf ^String major) +;; :minor (Integer/valueOf ^String minor) +;; :incremental (Integer/valueOf ^String incremental) +;; :qualifier (if (= qualifier "SNAPSHOT") nil qualifier)}] +;; (def ^:dynamic *clojure-version* +;; (if (.contains version-string "SNAPSHOT") +;; (clojure.lang.RT/assoc clojure-version :interim true) +;; clojure-version))) + +;; (add-doc-and-meta *clojure-version* +;; "The version info for Clojure core, as a map containing :major :minor +;; :incremental and :qualifier keys. Feature releases may increment +;; :minor and/or :major, bugfix releases will increment :incremental. +;; Possible values of :qualifier include \"GA\", \"SNAPSHOT\", \"RC-x\" \"BETA-x\"" +;; {:added "1.0"}) + +(defn clojure-version + "Returns clojure version as a printable string." + [] + (cpp/clojure.core_native.jank_version)) + +(defn promise + "Returns a promise object that can be read with deref/@, and set, + once only, with deliver. Calls to deref/@ prior to delivery will + block, unless the variant of deref with timeout is used. All + subsequent derefs will return the same delivered value without + blocking. See also - realized?." + [] + ;; (let [d (java.util.concurrent.CountDownLatch. 1) + ;; v (atom d)] + ;; (reify + ;; clojure.lang.IDeref + ;; (deref [_] (.await d) @v) + ;; clojure.lang.IBlockingDeref + ;; (deref + ;; [_ timeout-ms timeout-val] + ;; (if (.await d timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS) + ;; @v + ;; timeout-val)) + ;; clojure.lang.IPending + ;; (isRealized [this] + ;; (zero? (.getCount d))) + ;; clojure.lang.IFn + ;; (invoke + ;; [this x] + ;; (when (and (pos? (.getCount d)) + ;; (compare-and-set! v d x)) + ;; (.countDown d) + ;; this)))) + (throw "TODO: port promise")) + +(defn deliver + "Delivers the supplied value to the promise, releasing any pending + derefs. A subsequent call to deliver on a promise will have no effect." + [promise val] (promise val)) + +(defn rand-nth + "Return a random element of the (sequential) collection. Will have + the same performance characteristics as nth for the given + collection." + [coll] + (nth coll (rand-int (count coll)))) + +(defn splitv-at + "Returns a vector of [(into [] (take n) coll) (drop n coll)]" + [n coll] + [(into [] (take n) coll) (drop n coll)]) + +(defn partitionv + "Returns a lazy sequence of vectors of n items each, at offsets step + apart. If step is not supplied, defaults to n, i.e. the partitions + do not overlap. If a pad collection is supplied, use its elements as + necessary to complete last partition upto n items. In case there are + not enough padding elements, return a partition with less than n items." + ([n coll] + (partitionv n n coll)) + ([n step coll] + (lazy-seq + (when-let [s (seq coll)] + (let [p (into [] (take n) s)] + (when (= n (count p)) + (cons p (partitionv n step (nthrest s step)))))))) + ([n step pad coll] + (lazy-seq + (when-let [s (seq coll)] + (let [p (into [] (take n) s)] + (if (= n (count p)) + (cons p (partitionv n step pad (nthrest s step))) + (list (into [] (take n) (concat p pad))))))))) + +(defn partitionv-all + "Returns a lazy sequence of vector partitions, but may include + partitions with fewer than n items at the end. + Returns a stateful transducer when no collection is provided." + ([n] + (partition-all n)) + ([n coll] + (partitionv-all n n coll)) + ([n step coll] + (lazy-seq + (when-let [s (seq coll)] + (let [seg (into [] (take n) coll)] + (cons seg (partitionv-all n step (drop step s)))))))) + +(defn shuffle + "Return a random permutation of coll" + [coll] + (cpp/jank.runtime.shuffle coll)) + +(defn bounded-count + "If coll is counted? returns its count, else will count at most the first n + elements of coll using its seq" + [n coll] + (if (counted? coll) + (count coll) + (loop [i 0 s (seq coll)] + (if (and s (< i n)) + (recur (inc i) (next s)) + i)))) + +(defn bounded-count + "If coll is counted? returns its count, else will count at most the first n + elements of coll using its seq" + [n coll] + (if (counted? coll) + (count coll) + (loop [i 0 s (seq coll)] + (if (and s (< i n)) + (recur (inc i) (next s)) + i)))) + +(defn- ^{:dynamic true} assert-valid-fdecl + "A good fdecl looks like (([a] ...) ([a b] ...)) near the end of defn." + [fdecl] + (when (empty? fdecl) (throw "Parameter declaration missing")) + (let [argdecls (map + #(if (seq? %) + (first %) + (throw (if (seq? (first fdecl)) + (str "Invalid signature \"" + % + "\" should be a list") + (str "Parameter declaration \"" + % + "\" should be a vector")))) + fdecl) + bad-args (seq (remove #(vector? %) argdecls))] + (when bad-args + (throw (str "Parameter declaration \"" (first bad-args) + "\" should be a vector"))))) + +(defn realized? + "Returns true if a value has been produced for a promise, delay, future or lazy sequence." + [#_clojure.lang.IPending x] + ;; (.isRealized x) + (throw "TODO: port realized?")) + +(defn random-sample + "Returns items from coll with random probability of prob (0.0 - + 1.0). Returns a transducer when no collection is provided." + ([prob] + (filter (fn [_] (< (rand) prob)))) + ([prob coll] + (filter (fn [_] (< (rand) prob)) coll))) + +;; (deftype Eduction [xform coll] +;; Iterable +;; (iterator [_] +;; (clojure.lang.TransformerIterator/create xform (clojure.lang.RT/iter coll))) + +;; clojure.lang.IReduceInit +;; (reduce [_ f init] +;; ;; NB (completing f) isolates completion of inner rf from outer rf +;; (transduce xform (completing f) init coll)) + +;; clojure.lang.Sequential) + +;; (defn eduction +;; "Returns a reducible/iterable application of the transducers +;; to the items in coll. Transducers are applied in order as if +;; combined with comp. Note that these applications will be +;; performed every time reduce/iterator is called." +;; [& xforms] +;; (Eduction. (apply comp (butlast xforms)) (last xforms))) + +;; (defmethod print-method Eduction [c, ^Writer w] +;; (if *print-readably* +;; (do +;; (print-sequential "(" pr-on " " ")" c w)) +;; (print-object c w))) + +(defn iteration + "Creates a seqable/reducible via repeated calls to step, + a function of some (continuation token) 'k'. The first call to step + will be passed initk, returning 'ret'. Iff (somef ret) is true, + (vf ret) will be included in the iteration, else iteration will + terminate and vf/kf will not be called. If (kf ret) is non-nil it + will be passed to the next step call, else iteration will terminate. + + This can be used e.g. to consume APIs that return paginated or batched data. + + step - (possibly impure) fn of 'k' -> 'ret' + + :somef - fn of 'ret' -> logical true/false, default 'some?' + :vf - fn of 'ret' -> 'v', a value produced by the iteration, default 'identity' + :kf - fn of 'ret' -> 'next-k' or nil (signaling 'do not continue'), default 'identity' + :initk - the first value passed to step, default 'nil' + + It is presumed that step with non-initk is unreproducible/non-idempotent. + If step with initk is unreproducible it is on the consumer to not consume twice." + [step & {:keys [somef vf kf initk] + :or {vf identity + kf identity + somef some? + initk nil}}] + ;; (reify + ;; clojure.lang.Seqable + ;; (seq [_] + ;; ((fn next [ret] + ;; (when (somef ret) + ;; (cons (vf ret) + ;; (when-some [k (kf ret)] + ;; (lazy-seq (next (step k))))))) + ;; (step initk))) + ;; clojure.lang.IReduceInit + ;; (reduce [_ rf init] + ;; (loop [acc init + ;; ret (step initk)] + ;; (if (somef ret) + ;; (let [acc (rf acc (vf ret))] + ;; (if (reduced? acc) + ;; @acc + ;; (if-some [k (kf ret)] + ;; (recur acc (step k)) + ;; acc))) + ;; acc)))) + (throw "TODO: port iteration")) + +(defn tagged-literal? + "Return true if the value is the data representation of a tagged literal" + [value] + (cpp/jank.runtime.is_tagged_literal value)) + +(defn tagged-literal + "Construct a data representation of a tagged literal from a + tag symbol and a form." + [tag form] + (cpp/jank.runtime.tagged_literal tag form)) + +(defn reader-conditional? + "Return true if the value is the data representation of a reader conditional" + [value] + ;; (instance? clojure.lang.ReaderConditional value) + (throw "TODO: port reader-conditional?")) + +(defn reader-conditional + "Construct a data representation of a reader conditional. + If true, splicing? indicates read-cond-splicing." + [form #_Boolean splicing?] + ;; (clojure.lang.ReaderConditional/create form splicing?) + (throw "TODO: port reader-conditional")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; data readers ;;;;;;;;;;;;;;;;;; + +(def default-data-readers + "Default map of data reader functions provided by Clojure. May be + overridden by binding *data-readers*." + (merge + ;; {'uuid #'clojure.uuid/default-uuid-reader} + ;; (when-class "java.sql.Timestamp" + ;; {'inst #'clojure.instant/read-instant-date}) + )) + +(def ^:dynamic *data-readers* + "Map from reader tag symbols to data reader Vars. + + When Clojure starts, it searches for files named 'data_readers.clj' + and 'data_readers.cljc' at the root of the classpath. Each such file + must contain a literal map of symbols, like this: + + {foo/bar my.project.foo/bar + foo/baz my.project/baz} + + The first symbol in each pair is a tag that will be recognized by + the Clojure reader. The second symbol in the pair is the + fully-qualified name of a Var which will be invoked by the reader to + parse the form following the tag. For example, given the + data_readers.clj file above, the Clojure reader would parse this + form: + + #foo/bar [1 2 3] + + by invoking the Var #'my.project.foo/bar on the vector [1 2 3]. The + data reader function is invoked on the form AFTER it has been read + as a normal Clojure data structure by the reader. + + Reader tags without namespace qualifiers are reserved for + Clojure. Default reader tags are defined in + clojure.core/default-data-readers but may be overridden in + data_readers.clj, data_readers.cljc, or by rebinding this Var." + {}) + +(def ^:dynamic *default-data-reader-fn* + "When no data reader is found for a tag and *default-data-reader-fn* + is non-nil, it will be called with two arguments, + the tag and the value. If *default-data-reader-fn* is nil (the + default), an exception will be thrown for the unknown tag." + nil) + +(defn- data-reader-urls [] + ;; (let [cl (.. Thread currentThread getContextClassLoader)] + ;; (concat + ;; (enumeration-seq (.getResources cl "data_readers.clj")) + ;; (enumeration-seq (.getResources cl "data_readers.cljc")))) + (throw "TODO: port data-reader-urls")) + +(defn- data-reader-var [sym] + (intern (create-ns (symbol (namespace sym))) + (symbol (name sym)))) + +(defn- load-data-reader-file [mappings #_java.net.URL url] + ;; (with-open [rdr (clojure.lang.LineNumberingPushbackReader. + ;; (java.io.InputStreamReader. + ;; (.openStream url) "UTF-8"))] + ;; (binding [*file* (.getFile url)] + ;; (let [read-opts (if (.endsWith (.getPath url) "cljc") + ;; {:eof nil :read-cond :allow} + ;; {:eof nil}) + ;; new-mappings (read read-opts rdr)] + ;; (when (not (map? new-mappings)) + ;; (throw (ex-info (str "Not a valid data-reader map") + ;; {:url url}))) + ;; (reduce + ;; (fn [m [k v]] + ;; (when (not (symbol? k)) + ;; (throw (ex-info (str "Invalid form in data-reader file") + ;; {:url url + ;; :form k}))) + ;; (let [v-var (data-reader-var v)] + ;; (when (and (contains? mappings k) + ;; (not= (mappings k) v-var)) + ;; (throw (ex-info "Conflicting data-reader mapping" + ;; {:url url + ;; :conflict k + ;; :mappings m}))) + ;; (assoc m k v-var))) + ;; mappings + ;; new-mappings)))) + (throw "TODO: port load-data-reader-file")) + +(defn- load-data-readers [] + ;; (alter-var-root #'*data-readers* + ;; (fn [mappings] + ;; (reduce load-data-reader-file + ;; mappings (data-reader-urls)))) + (throw "TODO: port load-data-readers")) + +;; (try +;; (load-data-readers) +;; (catch #_Throwable t +;; (.printStackTrace t) +;; (throw t))) + +(defonce ^:private tapset (atom #{})) + +;; (defonce ^:private ^java.util.concurrent.ArrayBlockingQueue tapq (java.util.concurrent.ArrayBlockingQueue. 1024)) + +(defonce ^:private tap-loop + ;; (delay + ;; (doto (Thread. + ;; #(let [t (.take tapq) + ;; x (if (identical? ::tap-nil t) nil t) + ;; taps @tapset] + ;; (doseq [tap taps] + ;; (try + ;; (tap x) + ;; (catch Throwable ex))) + ;; (recur)) + ;; "clojure.core/tap-loop") + ;; (.setDaemon true) + ;; (.start))) + nil) + +(defn add-tap + "adds f, a fn of one argument, to the tap set. This function will be called with anything sent via tap>. + This function may (briefly) block (e.g. for streams), and will never impede calls to tap>, + but blocking indefinitely may cause tap values to be dropped. + Remember f in order to remove-tap" + [f] + (force tap-loop) + (swap! tapset conj f) + nil) + +(defn remove-tap + "Remove f from the tap set." + [f] + (swap! tapset disj f) + nil) + +(defn tap> + "sends x to any taps. Will not block. Returns true if there was room in the queue, + false if not (dropped)." + [x] + (force tap-loop) + ;; (.offer tapq (if (nil? x) ::tap-nil x)) + (throw "TODO: port tap>")) + +(defn update-vals + "m f => {k (f v) ...} + + Given a map m and a function f of 1-argument, returns a new map where the keys of m + are mapped to result of applying f to the corresponding values of m." + [m f] + (with-meta + (persistent! + (reduce-kv (fn [acc k v] (assoc! acc k (f v))) + (if (transientable? m) + (transient m) + (transient {})) + m)) + (meta m))) + +(defn update-keys + "m f => {(f k) v ...} + + Given a map m and a function f of 1-argument, returns a new map whose + keys are the result of applying f to the keys of m, mapped to the + corresponding values of m. + f must return a unique key for each key of m, else the behavior is undefined." + [m f] + (let [ret (persistent! + (reduce-kv (fn [acc k v] (assoc! acc (f k) v)) + (transient {}) + m))] + (with-meta ret (meta m)))) + +(defn- parsing-err + "Construct message for parsing for non-string parsing error" + [val] + (str "Expected string, got " (if (nil? val) "nil" (type val)))) + +(defn parse-long + "Parse string of decimal digits with optional leading -/+ and return a + Long value, or nil if parse fails" + [s] + (cpp/jank.runtime.parse_long s)) + +(defn parse-double + "Parse string with floating point components and return a Double value, + or nil if parse fails. + + Grammar: https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#valueOf-java.lang.String-" + [s] + (cpp/jank.runtime.parse_double s)) + +(defn parse-uuid + "Parse a string representing a UUID and return a java.util.UUID instance, + or nil if parse fails. + + Grammar: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#toString--" + [s] + (cpp/jank.runtime.parse_uuid s)) + +(defn parse-boolean + "Parse strings \"true\" or \"false\" and return a boolean, or nil if invalid" + [s] + (if (string? s) + (case s + "true" true + "false" false + nil) + (throw (parsing-err s)))) + +(defn NaN? + "Returns true if num is NaN, else false" + [num] + (cpp/jank.runtime.is_nan num)) + +(defn infinite? + "Returns true if num is negative or positive infinity, else false" + [num] + (cpp/jank.runtime.is_infinite num)) From 938a7e7a359c8c782313c21ef6e2056421f3c0d3 Mon Sep 17 00:00:00 2001 From: jeaye Date: Mon, 8 Dec 2025 12:12:27 -0800 Subject: [PATCH 072/122] Remove some more object* --- .../include/cpp/jank/runtime/convert/builtin.hpp | 8 ++++---- compiler+runtime/src/cpp/jank/runtime/module/loader.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp b/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp index 3d59df5b3..21e20bb64 100644 --- a/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp @@ -44,22 +44,22 @@ namespace jank::runtime requires(jtl::is_any_same) struct convert { - static object *into_object(T t) + static object_ref into_object(T t) { return const_cast(t); } - static object *into_object(object_ref const t) + static object_ref into_object(object_ref const t) { return t.erase(); } - static object *from_object(T t) + static object_ref from_object(T t) { return const_cast(t); } - static object *from_object(object_ref const t) + static object_ref from_object(object_ref const t) { return t.erase(); } diff --git a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp index 1abdcd973..3ea237e1f 100644 --- a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp @@ -1055,7 +1055,7 @@ namespace jank::runtime::module * What if load function is already loaded/defined? The llvm::Interpreter::Execute will fail. */ auto const load_function_name{ module_to_load_function(module) }; auto const load{ __rt_ctx->jit_prc.find_symbol(load_function_name).expect_ok() }; - reinterpret_cast(load)(); + reinterpret_cast(load)(); return ok(); } From 25d5dc877a77836b1f7515eca65c188b38b57b2c Mon Sep 17 00:00:00 2001 From: jeaye Date: Mon, 8 Dec 2025 13:03:52 -0800 Subject: [PATCH 073/122] Fix array map buffer overflow --- .../include/cpp/jank/runtime/detail/native_array_map.hpp | 1 + .../src/cpp/jank/runtime/detail/native_array_map.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp b/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp index f6577be43..f9aaaaea6 100644 --- a/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp @@ -30,6 +30,7 @@ namespace jank::runtime::detail template >> native_array_map(in_place_unique, jtl::ref const kvs, L const l) : data{ std::move(kvs.data) } + , cap{ static_cast(l) } , length{ static_cast(l) } { } diff --git a/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp b/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp index 2a7c43820..9f69cb8e3 100644 --- a/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp @@ -335,7 +335,7 @@ namespace jank::runtime::detail native_array_map native_array_map::clone() const { native_array_map ret{ *this }; - ret.data = new object_ref[length]; + ret.data = new object_ref[cap]; for(usize i{}; i < length; ++i) { ret.data[i] = data[i]; From 38293e5088e1f8494728ef420ec58f0f4664c833 Mon Sep 17 00:00:00 2001 From: jeaye Date: Mon, 8 Dec 2025 13:48:45 -0800 Subject: [PATCH 074/122] Get arc working for phase 2 --- compiler+runtime/CMakeLists.txt | 2 ++ .../include/cpp/jank/runtime/context.hpp | 4 +--- .../src/cpp/jank/environment/check_health.cpp | 2 +- compiler+runtime/src/cpp/jank/runtime/context.cpp | 14 +++++++------- compiler+runtime/src/cpp/jank/runtime/var.cpp | 2 +- compiler+runtime/src/cpp/main.cpp | 2 +- ray.jank | 10 +++++++++- 7 files changed, 22 insertions(+), 14 deletions(-) diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index b7abaff36..c71b83df9 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -92,6 +92,8 @@ set( set( jank_common_compiler_flags -std=gnu++20 + # https://groups.google.com/g/llvm-dev/c/W-OweiAjDcU?pli=1 + -femulated-tls -DIMMER_TAGGED_NODE=0 -DHAVE_CXX14=1 -DCPPINTEROP_USE_REPL -DFOLLY_HAVE_JEMALLOC=0 -DFOLLY_HAVE_TCMALLOC=0 -DFOLLY_ASSUME_NO_JEMALLOC=1 -DFOLLY_ASSUME_NO_TCMALLOC=1 diff --git a/compiler+runtime/include/cpp/jank/runtime/context.hpp b/compiler+runtime/include/cpp/jank/runtime/context.hpp index 95d1c8578..ad084965d 100644 --- a/compiler+runtime/include/cpp/jank/runtime/context.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/context.hpp @@ -162,9 +162,7 @@ namespace jank::runtime /* Hold onto the CLI Options for use at runtime */ util::cli::options opts; - /* XXX: We can't use thread_local here, due to bdwgc not supporting it. */ - static native_unordered_map> - thread_binding_frames; + static thread_local native_list thread_binding_frames; /* This must go last, since it'll try to access other bits in the runtime context during * its initialization and we need them to be ready. */ diff --git a/compiler+runtime/src/cpp/jank/environment/check_health.cpp b/compiler+runtime/src/cpp/jank/environment/check_health.cpp index 8bd1f8cfb..68a894154 100644 --- a/compiler+runtime/src/cpp/jank/environment/check_health.cpp +++ b/compiler+runtime/src/cpp/jank/environment/check_health.cpp @@ -25,7 +25,7 @@ #include #ifdef JANK_PHASE_2 -extern "C" jank_object_ref jank_load_clojure_core(); +void jank_load_clojure_core(); #endif namespace jank::environment diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 27db98825..dd59d14c1 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -35,7 +35,7 @@ namespace jank::runtime { /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ - decltype(context::thread_binding_frames) context::thread_binding_frames{}; + thread_local decltype(context::thread_binding_frames) context::thread_binding_frames{}; /* NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) */ context *__rt_ctx{}; @@ -721,7 +721,7 @@ namespace jank::runtime jtl::string_result context::push_thread_bindings() { auto bindings(obj::persistent_hash_map::empty()); - auto &tbfs(thread_binding_frames[std::this_thread::get_id()]); + auto &tbfs(thread_binding_frames); if(!tbfs.empty()) { bindings = tbfs.front().bindings; @@ -750,8 +750,8 @@ namespace jank::runtime context::push_thread_bindings(obj::persistent_hash_map_ref const bindings) { thread_binding_frame frame{ obj::persistent_hash_map::empty() }; - auto const &thread_id(std::this_thread::get_id()); - auto &tbfs(thread_binding_frames[thread_id]); + auto &tbfs(thread_binding_frames); + auto const thread_id{ std::this_thread::get_id() }; if(!tbfs.empty()) { frame.bindings = tbfs.front().bindings; @@ -792,7 +792,7 @@ namespace jank::runtime jtl::string_result context::pop_thread_bindings() { - auto &tbfs(thread_binding_frames[std::this_thread::get_id()]); + auto &tbfs(thread_binding_frames); if(tbfs.empty()) { return err("Mismatched thread binding pop"); @@ -805,7 +805,7 @@ namespace jank::runtime obj::persistent_hash_map_ref context::get_thread_bindings() const { - auto const &tbfs(thread_binding_frames[std::this_thread::get_id()]); + auto const &tbfs(thread_binding_frames); if(tbfs.empty()) { return obj::persistent_hash_map::empty(); @@ -815,7 +815,7 @@ namespace jank::runtime jtl::option context::current_thread_binding_frame() { - auto &tbfs(thread_binding_frames[std::this_thread::get_id()]); + auto &tbfs(thread_binding_frames); if(tbfs.empty()) { return none; diff --git a/compiler+runtime/src/cpp/jank/runtime/var.cpp b/compiler+runtime/src/cpp/jank/runtime/var.cpp index 5cf87dc38..e00daf26d 100644 --- a/compiler+runtime/src/cpp/jank/runtime/var.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/var.cpp @@ -156,7 +156,7 @@ namespace jank::runtime return {}; } - auto &tbfs(runtime::context::thread_binding_frames[std::this_thread::get_id()]); + auto &tbfs(runtime::context::thread_binding_frames); if(tbfs.empty()) { return {}; diff --git a/compiler+runtime/src/cpp/main.cpp b/compiler+runtime/src/cpp/main.cpp index 5236985fa..922a389c8 100644 --- a/compiler+runtime/src/cpp/main.cpp +++ b/compiler+runtime/src/cpp/main.cpp @@ -32,7 +32,7 @@ #include #ifdef JANK_PHASE_2 -extern "C" jank_object_ref jank_load_clojure_core(); +void jank_load_clojure_core(); #endif namespace jank diff --git a/ray.jank b/ray.jank index 22afb109c..425f72851 100644 --- a/ray.jank +++ b/ray.jank @@ -348,5 +348,13 @@ (println "meow")))) -;(jank.perf/benchmark {:label "ray"} (-main)) +; macOS +; -- main +; +; -- ref counting - non-atomic - no weak refs +; | ms/op | op/s | err% | total | benchmark +; |--------------------:|--------------------:|--------:|----------:|:---------- +; | 109.99 | 9.09 | 0.3% | 26.67 | `ray` + +(jank.perf/benchmark {:label "ray"} (-main)) ;(-main) From 7be9c0ecdc47c81229c3a0ba8debcfd730b2b187 Mon Sep 17 00:00:00 2001 From: jeaye Date: Mon, 8 Dec 2025 14:45:38 -0800 Subject: [PATCH 075/122] Make object count atomic --- .../include/cpp/jank/runtime/object.hpp | 11 +++++- .../src/cpp/jank/runtime/object.cpp | 38 ++++++++++++++++++- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/runtime/object.hpp b/compiler+runtime/include/cpp/jank/runtime/object.hpp index f5678aa3b..ab2e64d8b 100644 --- a/compiler+runtime/include/cpp/jank/runtime/object.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/object.hpp @@ -243,12 +243,19 @@ namespace jank::runtime struct object { + object() = default; + object(object const &) noexcept; + object(object &&) noexcept; + object(object_type) noexcept; + void retain(); void release(); + object &operator=(object const &) noexcept; + object &operator=(object &&) noexcept; + object_type type{}; - /* TODO: Atomic. */ - i32 ref_count{}; + std::atomic ref_count{}; }; namespace obj diff --git a/compiler+runtime/src/cpp/jank/runtime/object.cpp b/compiler+runtime/src/cpp/jank/runtime/object.cpp index dcdee8bc8..0811ec89a 100644 --- a/compiler+runtime/src/cpp/jank/runtime/object.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/object.cpp @@ -6,6 +6,21 @@ namespace jank::runtime { + object::object(object const &rhs) noexcept + : type{ rhs.type } + { + } + + object::object(object &&rhs) noexcept + : type{ rhs.type } + { + } + + object::object(object_type const type) noexcept + : type{ type } + { + } + void object::retain() { ++ref_count; @@ -16,9 +31,8 @@ namespace jank::runtime void object::release() { jank_debug_assert(ref_count > 0); - --ref_count; //util::println("release {} type {} count {}", this, object_type_str(type), ref_count); - if(ref_count == 0) + if(--ref_count == 0) { visit_object( [](auto const typed_this) { @@ -30,6 +44,26 @@ namespace jank::runtime } } + object &object::operator=(object const &rhs) noexcept + { + if(this == &rhs) + { + return *this; + } + type = rhs.type; + return *this; + } + + object &object::operator=(object &&rhs) noexcept + { + if(this == &rhs) + { + return *this; + } + type = rhs.type; + return *this; + } + bool very_equal_to::operator()(object_ref const lhs, object_ref const rhs) const noexcept { if(lhs->type != rhs->type) From c4bef9fd8b37999a346e19d29faf4bdd08476ae8 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 9 Dec 2025 16:29:01 -0800 Subject: [PATCH 076/122] Fix letfn cppgen and ratio test --- compiler+runtime/src/cpp/jank/analyze/processor.cpp | 4 ++-- compiler+runtime/src/cpp/jank/codegen/processor.cpp | 4 ++-- compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index 70693f98d..f9bb4856a 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -1790,7 +1790,7 @@ namespace jank::analyze { auto const s(runtime::expect_object(first_elem)); name = s->name; - unique_name = __rt_ctx->unique_namespaced_string(name); + unique_name = __rt_ctx->unique_string(name); if(length < 3) { return error::analyze_invalid_fn("This function is missing its parameter vector.", @@ -1802,7 +1802,7 @@ namespace jank::analyze } else { - name = __rt_ctx->unique_namespaced_string("fn"); + name = __rt_ctx->unique_string("fn"); unique_name = name; } diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 6142a1674..c391c287d 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -498,8 +498,8 @@ namespace jank::codegen compilation_target const target) : root_fn{ expr } , module{ module } - , target{ target } /* The normal unique name is fully namespaced, which we don't need. */ - , struct_name{ runtime::munge(runtime::__rt_ctx->unique_string(root_fn->name)) } + , target{ target } + , struct_name{ runtime::munge(root_fn->unique_name) } { assert(root_fn->frame.data); } diff --git a/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp b/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp index 2fb7c3dc2..cae9f1790 100644 --- a/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp +++ b/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp @@ -25,8 +25,8 @@ namespace jank::runtime } SUBCASE("Valid ratio object_ref ctor") { - auto const num_ptr{ make_box(4).erase() }; - auto const denom_ptr{ make_box(6).erase() }; + auto const num_ptr{ make_box(4) }; + auto const denom_ptr{ make_box(6) }; obj::ratio_data const ratio{ num_ptr, denom_ptr }; CHECK_EQ(ratio.numerator, 2); CHECK_EQ(ratio.denominator, 3); From 92188abe53ca93d21483f91d75e45ac746b3cd6a Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 11 Dec 2025 14:32:52 -0800 Subject: [PATCH 077/122] Fix health check, C API, and AOT --- .../include/cpp/clojure/core_native.hpp | 2 +- .../include/cpp/jank/compiler_native.hpp | 4 +- compiler+runtime/include/cpp/jtl/result.hpp | 6 ++ .../src/cpp/clojure/core_native.cpp | 4 +- .../src/cpp/jank/aot/processor.cpp | 12 ++- compiler+runtime/src/cpp/jank/c_api.cpp | 80 +++++++++++-------- .../src/cpp/jank/compiler_native.cpp | 4 +- .../src/cpp/jank/environment/check_health.cpp | 4 +- .../clojure-test-suite/clojure-test-suite | 2 +- 9 files changed, 65 insertions(+), 53 deletions(-) diff --git a/compiler+runtime/include/cpp/clojure/core_native.hpp b/compiler+runtime/include/cpp/clojure/core_native.hpp index df25efae8..d284b3a27 100644 --- a/compiler+runtime/include/cpp/clojure/core_native.hpp +++ b/compiler+runtime/include/cpp/clojure/core_native.hpp @@ -3,7 +3,7 @@ #include #include -extern "C" jank_object_ref jank_load_clojure_core_native(); +void jank_load_clojure_core_native(); namespace clojure::core_native { diff --git a/compiler+runtime/include/cpp/jank/compiler_native.hpp b/compiler+runtime/include/cpp/jank/compiler_native.hpp index 079db5e25..929f26468 100644 --- a/compiler+runtime/include/cpp/jank/compiler_native.hpp +++ b/compiler+runtime/include/cpp/jank/compiler_native.hpp @@ -1,5 +1,3 @@ #pragma once -#include - -extern "C" jank_object_ref jank_load_jank_compiler_native(); +void jank_load_jank_compiler_native(); diff --git a/compiler+runtime/include/cpp/jtl/result.hpp b/compiler+runtime/include/cpp/jtl/result.hpp index 946ff95d5..3fbd9d5ef 100644 --- a/compiler+runtime/include/cpp/jtl/result.hpp +++ b/compiler+runtime/include/cpp/jtl/result.hpp @@ -155,6 +155,12 @@ namespace jtl detail::panic(*this); } + constexpr R &expect_ok() + { + assert_ok(); + return std::get(data); + } + constexpr R const &expect_ok() const { assert_ok(); diff --git a/compiler+runtime/src/cpp/clojure/core_native.cpp b/compiler+runtime/src/cpp/clojure/core_native.cpp index 71bee7c3f..d237fc487 100644 --- a/compiler+runtime/src/cpp/clojure/core_native.cpp +++ b/compiler+runtime/src/cpp/clojure/core_native.cpp @@ -298,7 +298,7 @@ namespace clojure::core_native } } -extern "C" jank_object_ref jank_load_clojure_core_native() +void jank_load_clojure_core_native() { using namespace jank; using namespace jank::runtime; @@ -848,6 +848,4 @@ extern "C" jank_object_ref jank_load_clojure_core_native() }; intern_fn_obj("repeat", fn); } - - return jank_nil().erase(); } diff --git a/compiler+runtime/src/cpp/jank/aot/processor.cpp b/compiler+runtime/src/cpp/jank/aot/processor.cpp index 737e7d1a8..932657655 100644 --- a/compiler+runtime/src/cpp/jank/aot/processor.cpp +++ b/compiler+runtime/src/cpp/jank/aot/processor.cpp @@ -42,9 +42,9 @@ extern "C" int jank_init_with_pch(int const argc, char const * const pch_data, jank_usize pch_size, int (*fn)(int const, char const ** const)); -extern "C" jank_object_ref jank_load_clojure_core_native(); -extern "C" jank_object_ref jank_load_clojure_core(); -extern "C" jank_object_ref jank_load_jank_compiler_native(); +void jank_load_clojure_core_native(); +void jank_load_clojure_core(); +void jank_load_jank_compiler_native(); extern "C" jank_object_ref jank_var_intern_c(char const *, char const *); extern "C" jank_object_ref jank_deref(jank_object_ref); extern "C" jank_object_ref jank_call2(jank_object_ref, jank_object_ref, jank_object_ref); @@ -55,9 +55,7 @@ extern "C" jank_object_ref jank_parse_command_line_args(int, char const **); auto const modules_rlocked{ __rt_ctx->loaded_modules_in_order.rlock() }; for(auto const &it : *modules_rlocked) { - util::format_to(sb, - R"(extern "C" jank_object_ref {}();)", - module::module_to_load_function(it)); + util::format_to(sb, R"(void {}();)", module::module_to_load_function(it)); sb("\n"); } @@ -126,7 +124,7 @@ int main(int argc, const char** argv) if(main_var.is_nil()) { return error::aot_unresolved_main(util::format( - "The entrypoint of the program is expected to be #'{}/-main, but this var is missing.", + "The entrypoint of the program is expected to be #'{}/-main, but this var was not found.", module)); } diff --git a/compiler+runtime/src/cpp/jank/c_api.cpp b/compiler+runtime/src/cpp/jank/c_api.cpp index 535a36692..438ddc46f 100644 --- a/compiler+runtime/src/cpp/jank/c_api.cpp +++ b/compiler+runtime/src/cpp/jank/c_api.cpp @@ -54,18 +54,18 @@ extern "C" jank_object_ref jank_eval(jank_object_ref const s) { auto const s_obj(try_object(reinterpret_cast(s))); - return __rt_ctx->eval_string(s_obj->data).erase(); + return __rt_ctx->eval_string(s_obj->data).retain().erase(); } jank_object_ref jank_read_string(jank_object_ref const s) { auto const s_obj(try_object(reinterpret_cast(s))); - return __rt_ctx->read_string(s_obj->data).erase(); + return __rt_ctx->read_string(s_obj->data).retain().erase(); } jank_object_ref jank_read_string_c(char const * const s) { - return __rt_ctx->read_string(s).erase(); + return __rt_ctx->read_string(s).retain().erase(); } jank_object_ref jank_ns_intern(jank_object_ref const sym) @@ -91,53 +91,56 @@ extern "C" __rt_ctx->intern_ns(ns_obj->data); auto const name_obj(try_object(reinterpret_cast(name))); - return __rt_ctx->intern_var(ns_obj->data, name_obj->data).expect_ok().erase(); + return __rt_ctx->intern_var(ns_obj->data, name_obj->data).expect_ok().retain().erase(); } jank_object_ref jank_var_intern_c(char const * const ns, char const * const name) { __rt_ctx->intern_ns(ns); - return __rt_ctx->intern_var(ns, name).expect_ok().erase(); + return __rt_ctx->intern_var(ns, name).expect_ok().retain().erase(); } jank_object_ref jank_var_bind_root(jank_object_ref const var, jank_object_ref const val) { auto const var_obj(try_object(reinterpret_cast(var))); auto const val_obj(reinterpret_cast(val)); - return var_obj->bind_root(val_obj).erase(); + return var_obj->bind_root(val_obj).retain().erase(); } jank_object_ref jank_var_set_dynamic(jank_object_ref const var, jank_object_ref const dynamic) { auto const var_obj(try_object(reinterpret_cast(var))); auto const dynamic_obj(reinterpret_cast(dynamic)); - return var_obj->set_dynamic(truthy(dynamic_obj)).erase(); + return var_obj->set_dynamic(truthy(dynamic_obj)).retain().erase(); } jank_object_ref jank_keyword_intern(jank_object_ref const ns, jank_object_ref const name) { auto const ns_obj(reinterpret_cast(ns)); auto const name_obj(reinterpret_cast(name)); - return __rt_ctx->intern_keyword(to_string(ns_obj), to_string(name_obj)).expect_ok().erase(); + return __rt_ctx->intern_keyword(to_string(ns_obj), to_string(name_obj)) + .expect_ok() + .retain() + .erase(); } jank_object_ref jank_deref(jank_object_ref const o) { auto const o_obj(reinterpret_cast(o)); - return deref(o_obj).erase(); + return deref(o_obj).retain().erase(); } jank_object_ref jank_call0(jank_object_ref const f) { auto const f_obj(reinterpret_cast(f)); - return dynamic_call(f_obj).erase(); + return dynamic_call(f_obj).retain().erase(); } jank_object_ref jank_call1(jank_object_ref const f, jank_object_ref const a1) { auto const f_obj(reinterpret_cast(f)); auto const a1_obj(reinterpret_cast(a1)); - return dynamic_call(f_obj, a1_obj).erase(); + return dynamic_call(f_obj, a1_obj).retain().erase(); } jank_object_ref @@ -146,7 +149,7 @@ extern "C" auto const f_obj(reinterpret_cast(f)); auto const a1_obj(reinterpret_cast(a1)); auto const a2_obj(reinterpret_cast(a2)); - return dynamic_call(f_obj, a1_obj, a2_obj).erase(); + return dynamic_call(f_obj, a1_obj, a2_obj).retain().erase(); } jank_object_ref jank_call3(jank_object_ref const f, @@ -158,7 +161,7 @@ extern "C" auto const a1_obj(reinterpret_cast(a1)); auto const a2_obj(reinterpret_cast(a2)); auto const a3_obj(reinterpret_cast(a3)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj).erase(); + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj).retain().erase(); } jank_object_ref jank_call4(jank_object_ref const f, @@ -172,7 +175,7 @@ extern "C" auto const a2_obj(reinterpret_cast(a2)); auto const a3_obj(reinterpret_cast(a3)); auto const a4_obj(reinterpret_cast(a4)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj).erase(); + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj).retain().erase(); } jank_object_ref jank_call5(jank_object_ref const f, @@ -188,7 +191,7 @@ extern "C" auto const a3_obj(reinterpret_cast(a3)); auto const a4_obj(reinterpret_cast(a4)); auto const a5_obj(reinterpret_cast(a5)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj).erase(); + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj).retain().erase(); } jank_object_ref jank_call6(jank_object_ref const f, @@ -206,7 +209,7 @@ extern "C" auto const a4_obj(reinterpret_cast(a4)); auto const a5_obj(reinterpret_cast(a5)); auto const a6_obj(reinterpret_cast(a6)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj).erase(); + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj).retain().erase(); } jank_object_ref jank_call7(jank_object_ref const f, @@ -226,7 +229,9 @@ extern "C" auto const a5_obj(reinterpret_cast(a5)); auto const a6_obj(reinterpret_cast(a6)); auto const a7_obj(reinterpret_cast(a7)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj, a7_obj).erase(); + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj, a7_obj) + .retain() + .erase(); } jank_object_ref jank_call8(jank_object_ref const f, @@ -249,6 +254,7 @@ extern "C" auto const a7_obj(reinterpret_cast(a7)); auto const a8_obj(reinterpret_cast(a8)); return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj, a7_obj, a8_obj) + .retain() .erase(); } @@ -283,6 +289,7 @@ extern "C" a7_obj, a8_obj, a9_obj) + .retain() .erase(); } @@ -320,6 +327,7 @@ extern "C" a8_obj, a9_obj, a10_obj) + .retain() .erase(); } @@ -360,6 +368,7 @@ extern "C" a9_obj, a10_obj, try_object(rest_obj)) + .retain() .erase(); } @@ -370,34 +379,34 @@ extern "C" jank_object_ref jank_const_true() { - return jank_true.erase(); + return jank_true.retain().erase(); } jank_object_ref jank_const_false() { - return jank_false.erase(); + return jank_false.retain().erase(); } jank_object_ref jank_integer_create(jank_i64 const i) { - return make_box(i).erase(); + return make_box(i).retain().erase(); } jank_object_ref jank_big_integer_create(char const * const s) { jank_assert(s); - return make_box(s).erase(); + return make_box(s).retain().erase(); } jank_object_ref jank_big_decimal_create(char const * const s) { jank_assert(s); - return make_box(s).erase(); + return make_box(s).retain().erase(); } jank_object_ref jank_real_create(jank_f64 const r) { - return make_box(r).erase(); + return make_box(r).retain().erase(); } jank_object_ref @@ -405,44 +414,47 @@ extern "C" { return make_box(runtime::obj::ratio_data(reinterpret_cast(numerator), reinterpret_cast(denominator))) + .retain() .erase(); } jank_object_ref jank_string_create(char const *s) { jank_debug_assert(s); - return make_box(s).erase(); + return make_box(s).retain().erase(); } jank_object_ref jank_symbol_create(jank_object_ref const ns, jank_object_ref const name) { auto const ns_obj(reinterpret_cast(ns)); auto const name_obj(reinterpret_cast(name)); - return make_box(ns_obj, name_obj).erase(); + return make_box(ns_obj, name_obj).retain().erase(); } jank_object_ref jank_character_create(char const *s) { jank_debug_assert(s); - return make_box(read::parse::get_char_from_literal(s).unwrap()).erase(); + return make_box(read::parse::get_char_from_literal(s).unwrap()) + .retain() + .erase(); } jank_object_ref jank_regex_create(char const *s) { jank_debug_assert(s); - return make_box(s).erase(); + return make_box(s).retain().erase(); } jank_object_ref jank_uuid_create(char const *s) { jank_debug_assert(s); - return make_box(s).erase(); + return make_box(s).retain().erase(); } jank_object_ref jank_inst_create(char const *s) { jank_debug_assert(s); - return make_box(s).erase(); + return make_box(s).retain().erase(); } jank_object_ref jank_list_create(jank_u64 const size, ...) @@ -462,7 +474,7 @@ extern "C" va_end(args); runtime::detail::native_persistent_list const npl{ v.rbegin(), v.rend() }; - return make_box(std::move(npl)).erase(); + return make_box(std::move(npl)).retain().erase(); } jank_object_ref jank_vector_create(jank_u64 const size, ...) @@ -480,7 +492,7 @@ extern "C" } va_end(args); - return trans.to_persistent().erase(); + return trans.to_persistent().retain().erase(); } /* TODO: Meta for maps, vectors, sets, symbols, and fns. */ @@ -502,7 +514,7 @@ extern "C" } va_end(args); - return trans.to_persistent().erase(); + return trans.to_persistent().retain().erase(); } jank_object_ref jank_set_create(u64 const size, ...) @@ -520,7 +532,7 @@ extern "C" } va_end(args); - return trans.to_persistent().erase(); + return trans.to_persistent().retain().erase(); } jank_object_ref jank_box(char const * const type, void const * const o) @@ -1069,6 +1081,6 @@ extern "C" trans.conj_in_place(make_box(arg)); } - return trans.to_persistent().erase(); + return trans.to_persistent().retain().erase(); } } diff --git a/compiler+runtime/src/cpp/jank/compiler_native.cpp b/compiler+runtime/src/cpp/jank/compiler_native.cpp index db0a94f7d..a18aad6e1 100644 --- a/compiler+runtime/src/cpp/jank/compiler_native.cpp +++ b/compiler+runtime/src/cpp/jank/compiler_native.cpp @@ -50,7 +50,7 @@ namespace jank::compiler_native } } -extern "C" jank_object_ref jank_load_jank_compiler_native() +void jank_load_jank_compiler_native() { using namespace jank; using namespace jank::runtime; @@ -65,6 +65,4 @@ extern "C" jank_object_ref jank_load_jank_compiler_native() make_box(obj::symbol{ __rt_ctx->current_ns()->to_string(), name }.to_string()))))); }); intern_fn("native-source", &compiler_native::native_source); - - return jank_nil().erase(); } diff --git a/compiler+runtime/src/cpp/jank/environment/check_health.cpp b/compiler+runtime/src/cpp/jank/environment/check_health.cpp index 68a894154..b7e7f16a4 100644 --- a/compiler+runtime/src/cpp/jank/environment/check_health.cpp +++ b/compiler+runtime/src/cpp/jank/environment/check_health.cpp @@ -322,6 +322,8 @@ namespace jank::environment terminal_style::reset); } + /* This is disabled until IR gen supports ref counting OR we switch back to using a GC. */ + [[maybe_unused]] static jtl::immutable_string check_ir_jit() { bool error{}; @@ -500,7 +502,7 @@ namespace jank::environment terminal_style::reset); util::println("{}", pch_location()); util::println("{}", check_cpp_jit()); - util::println("{}", check_ir_jit()); + //util::println("{}", check_ir_jit()); util::println("{}", check_aot()); util::println(""); diff --git a/compiler+runtime/test/bash/clojure-test-suite/clojure-test-suite b/compiler+runtime/test/bash/clojure-test-suite/clojure-test-suite index b7882f5eb..5bd9fd054 160000 --- a/compiler+runtime/test/bash/clojure-test-suite/clojure-test-suite +++ b/compiler+runtime/test/bash/clojure-test-suite/clojure-test-suite @@ -1 +1 @@ -Subproject commit b7882f5eb12818ebdf608b9d379839f7a174c811 +Subproject commit 5bd9fd05419aee86d4831cdcf16a762850383517 From 5ac392e37df0762b52613f248a104c26d8e27af7 Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 19 Dec 2025 10:17:35 -0800 Subject: [PATCH 078/122] Address some clang-tidy issues --- .../include/cpp/clojure/core_native.hpp | 88 +-- .../include/cpp/clojure/string_native.hpp | 33 +- .../include/cpp/jank/analyze/expr/call.hpp | 2 +- .../cpp/jank/analyze/expr/cpp_type.hpp | 2 +- .../cpp/jank/analyze/expr/cpp_value.hpp | 2 +- .../include/cpp/jank/analyze/expr/def.hpp | 2 +- .../cpp/jank/analyze/expr/function.hpp | 2 +- .../cpp/jank/analyze/expr/local_reference.hpp | 2 +- .../cpp/jank/analyze/expr/named_recursion.hpp | 2 +- .../jank/analyze/expr/primitive_literal.hpp | 2 +- .../include/cpp/jank/analyze/expr/recur.hpp | 2 +- .../cpp/jank/analyze/expr/var_deref.hpp | 4 +- .../include/cpp/jank/analyze/expr/var_ref.hpp | 4 +- .../include/cpp/jank/analyze/local_frame.hpp | 7 +- .../include/cpp/jank/analyze/processor.hpp | 74 +- compiler+runtime/include/cpp/jank/error.hpp | 12 +- .../include/cpp/jank/error/analyze.hpp | 98 +-- compiler+runtime/include/cpp/jank/hash.hpp | 2 +- .../include/cpp/jank/read/parse.hpp | 12 +- .../include/cpp/jank/read/reparse.hpp | 6 +- .../include/cpp/jank/read/source.hpp | 2 +- .../cpp/jank/runtime/behavior/callable.hpp | 227 +++--- .../cpp/jank/runtime/behavior/metadatable.hpp | 2 +- .../include/cpp/jank/runtime/context.hpp | 12 +- .../cpp/jank/runtime/convert/builtin.hpp | 50 +- .../cpp/jank/runtime/convert/function.hpp | 9 +- .../include/cpp/jank/runtime/core.hpp | 172 ++--- .../include/cpp/jank/runtime/core/equal.hpp | 8 +- .../include/cpp/jank/runtime/core/math.hpp | 376 +++++----- .../include/cpp/jank/runtime/core/meta.hpp | 12 +- .../include/cpp/jank/runtime/core/munge.hpp | 2 +- .../include/cpp/jank/runtime/core/seq.hpp | 180 ++--- .../include/cpp/jank/runtime/core/seq_ext.hpp | 8 +- .../cpp/jank/runtime/core/to_string.hpp | 22 +- .../include/cpp/jank/runtime/core/truthy.hpp | 6 +- .../jank/runtime/detail/native_array_map.hpp | 8 +- .../include/cpp/jank/runtime/detail/type.hpp | 2 +- .../include/cpp/jank/runtime/ns.hpp | 19 +- .../cpp/jank/runtime/obj/array_chunk.hpp | 4 +- .../include/cpp/jank/runtime/obj/atom.hpp | 33 +- .../cpp/jank/runtime/obj/chunk_buffer.hpp | 4 +- .../cpp/jank/runtime/obj/chunked_cons.hpp | 8 +- .../include/cpp/jank/runtime/obj/cons.hpp | 6 +- .../include/cpp/jank/runtime/obj/delay.hpp | 2 +- .../obj/detail/base_persistent_map.hpp | 14 +- .../detail/base_persistent_map_sequence.hpp | 8 +- .../runtime/obj/detail/iterator_sequence.hpp | 2 +- .../cpp/jank/runtime/obj/integer_range.hpp | 27 +- .../include/cpp/jank/runtime/obj/iterator.hpp | 4 +- .../cpp/jank/runtime/obj/jit_closure.hpp | 88 ++- .../cpp/jank/runtime/obj/jit_function.hpp | 89 ++- .../include/cpp/jank/runtime/obj/keyword.hpp | 6 +- .../cpp/jank/runtime/obj/lazy_sequence.hpp | 8 +- .../cpp/jank/runtime/obj/multi_function.hpp | 108 +-- .../runtime/obj/native_array_sequence.hpp | 4 +- .../runtime/obj/native_function_wrapper.hpp | 116 ++-- .../runtime/obj/native_vector_sequence.hpp | 4 +- .../include/cpp/jank/runtime/obj/nil.hpp | 12 +- .../cpp/jank/runtime/obj/opaque_box.hpp | 2 +- .../jank/runtime/obj/persistent_array_map.hpp | 20 +- .../jank/runtime/obj/persistent_hash_map.hpp | 26 +- .../jank/runtime/obj/persistent_hash_set.hpp | 14 +- .../cpp/jank/runtime/obj/persistent_list.hpp | 14 +- .../runtime/obj/persistent_sorted_map.hpp | 25 +- .../runtime/obj/persistent_sorted_set.hpp | 16 +- .../jank/runtime/obj/persistent_string.hpp | 16 +- .../obj/persistent_string_sequence.hpp | 6 +- .../jank/runtime/obj/persistent_vector.hpp | 26 +- .../obj/persistent_vector_sequence.hpp | 6 +- .../include/cpp/jank/runtime/obj/range.hpp | 50 +- .../include/cpp/jank/runtime/obj/ratio.hpp | 74 +- .../cpp/jank/runtime/obj/re_matcher.hpp | 2 +- .../include/cpp/jank/runtime/obj/reduced.hpp | 2 +- .../include/cpp/jank/runtime/obj/repeat.hpp | 12 +- .../include/cpp/jank/runtime/obj/symbol.hpp | 6 +- .../cpp/jank/runtime/obj/tagged_literal.hpp | 10 +- .../jank/runtime/obj/transient_array_map.hpp | 18 +- .../jank/runtime/obj/transient_hash_map.hpp | 18 +- .../jank/runtime/obj/transient_hash_set.hpp | 16 +- .../jank/runtime/obj/transient_sorted_map.hpp | 18 +- .../jank/runtime/obj/transient_sorted_set.hpp | 16 +- .../cpp/jank/runtime/obj/transient_vector.hpp | 12 +- .../include/cpp/jank/runtime/obj/volatile.hpp | 4 +- .../include/cpp/jank/runtime/object.hpp | 12 +- .../include/cpp/jank/runtime/oref.hpp | 25 +- .../include/cpp/jank/runtime/perf.hpp | 2 +- .../include/cpp/jank/runtime/rtti.hpp | 2 +- .../cpp/jank/runtime/sequence_range.hpp | 6 +- .../include/cpp/jank/runtime/var.hpp | 34 +- .../include/cpp/jank/runtime/visit.hpp | 35 +- .../include/cpp/jank/runtime/weak_oref.hpp | 4 +- .../include/cpp/jank/util/try.hpp | 2 +- .../include/cpp/jtl/immutable_string.hpp | 5 + compiler+runtime/include/cpp/jtl/panic.hpp | 1 + .../src/cpp/clojure/core_native.cpp | 174 ++--- .../src/cpp/clojure/string_native.cpp | 38 +- .../src/cpp/jank/analyze/expr/call.cpp | 2 +- .../src/cpp/jank/analyze/expr/cpp_type.cpp | 2 +- .../src/cpp/jank/analyze/expr/cpp_value.cpp | 2 +- .../src/cpp/jank/analyze/expr/def.cpp | 2 +- .../src/cpp/jank/analyze/expr/function.cpp | 2 +- .../cpp/jank/analyze/expr/local_reference.cpp | 2 +- .../cpp/jank/analyze/expr/named_recursion.cpp | 2 +- .../jank/analyze/expr/primitive_literal.cpp | 2 +- .../src/cpp/jank/analyze/expr/recur.cpp | 2 +- .../src/cpp/jank/analyze/expr/var_deref.cpp | 4 +- .../src/cpp/jank/analyze/expr/var_ref.cpp | 4 +- .../src/cpp/jank/analyze/local_frame.cpp | 11 +- .../src/cpp/jank/analyze/processor.cpp | 93 ++- .../src/cpp/jank/codegen/llvm_processor.cpp | 68 +- .../src/cpp/jank/codegen/processor.cpp | 16 +- .../src/cpp/jank/compiler_native.cpp | 2 +- compiler+runtime/src/cpp/jank/error.cpp | 14 +- .../src/cpp/jank/error/analyze.cpp | 96 +-- compiler+runtime/src/cpp/jank/hash.cpp | 4 +- compiler+runtime/src/cpp/jank/read/parse.cpp | 38 +- .../src/cpp/jank/read/reparse.cpp | 12 +- compiler+runtime/src/cpp/jank/read/source.cpp | 2 +- .../cpp/jank/runtime/behavior/callable.cpp | 293 ++++---- .../cpp/jank/runtime/behavior/metadatable.cpp | 4 +- .../src/cpp/jank/runtime/context.cpp | 32 +- .../src/cpp/jank/runtime/core.cpp | 221 +++--- .../src/cpp/jank/runtime/core/equal.cpp | 16 +- .../src/cpp/jank/runtime/core/math.cpp | 650 +++++++++--------- .../src/cpp/jank/runtime/core/meta.cpp | 30 +- .../src/cpp/jank/runtime/core/munge.cpp | 2 +- .../src/cpp/jank/runtime/core/seq.cpp | 362 +++++----- .../src/cpp/jank/runtime/core/to_string.cpp | 12 +- .../src/cpp/jank/runtime/core/truthy.cpp | 6 +- .../jank/runtime/detail/native_array_map.cpp | 14 +- .../src/cpp/jank/runtime/detail/type.cpp | 2 +- .../src/cpp/jank/runtime/module/loader.cpp | 4 +- compiler+runtime/src/cpp/jank/runtime/ns.cpp | 18 +- .../src/cpp/jank/runtime/obj/array_chunk.cpp | 4 +- .../src/cpp/jank/runtime/obj/atom.cpp | 36 +- .../src/cpp/jank/runtime/obj/big_decimal.cpp | 7 +- .../src/cpp/jank/runtime/obj/big_integer.cpp | 5 +- .../src/cpp/jank/runtime/obj/chunk_buffer.cpp | 4 +- .../src/cpp/jank/runtime/obj/chunked_cons.cpp | 14 +- .../src/cpp/jank/runtime/obj/cons.cpp | 6 +- .../src/cpp/jank/runtime/obj/delay.cpp | 2 +- .../obj/detail/base_persistent_map.cpp | 8 +- .../detail/base_persistent_map_sequence.cpp | 4 +- .../runtime/obj/detail/iterator_sequence.cpp | 4 +- .../cpp/jank/runtime/obj/integer_range.cpp | 30 +- .../src/cpp/jank/runtime/obj/iterator.cpp | 4 +- .../src/cpp/jank/runtime/obj/jit_closure.cpp | 110 +-- .../src/cpp/jank/runtime/obj/jit_function.cpp | 110 +-- .../src/cpp/jank/runtime/obj/keyword.cpp | 4 +- .../cpp/jank/runtime/obj/lazy_sequence.cpp | 8 +- .../cpp/jank/runtime/obj/multi_function.cpp | 140 ++-- .../runtime/obj/native_array_sequence.cpp | 2 +- .../runtime/obj/native_function_wrapper.cpp | 117 ++-- .../runtime/obj/native_vector_sequence.cpp | 4 +- .../src/cpp/jank/runtime/obj/nil.cpp | 12 +- .../src/cpp/jank/runtime/obj/number.cpp | 12 +- .../src/cpp/jank/runtime/obj/opaque_box.cpp | 2 +- .../jank/runtime/obj/persistent_array_map.cpp | 16 +- .../jank/runtime/obj/persistent_hash_map.cpp | 24 +- .../jank/runtime/obj/persistent_hash_set.cpp | 14 +- .../cpp/jank/runtime/obj/persistent_list.cpp | 12 +- .../runtime/obj/persistent_sorted_map.cpp | 24 +- .../runtime/obj/persistent_sorted_set.cpp | 16 +- .../jank/runtime/obj/persistent_string.cpp | 16 +- .../obj/persistent_string_sequence.cpp | 6 +- .../jank/runtime/obj/persistent_vector.cpp | 26 +- .../obj/persistent_vector_sequence.cpp | 6 +- .../src/cpp/jank/runtime/obj/range.cpp | 46 +- .../src/cpp/jank/runtime/obj/ratio.cpp | 78 +-- .../src/cpp/jank/runtime/obj/re_matcher.cpp | 2 +- .../src/cpp/jank/runtime/obj/reduced.cpp | 2 +- .../src/cpp/jank/runtime/obj/repeat.cpp | 12 +- .../src/cpp/jank/runtime/obj/symbol.cpp | 8 +- .../cpp/jank/runtime/obj/tagged_literal.cpp | 10 +- .../jank/runtime/obj/transient_array_map.cpp | 18 +- .../jank/runtime/obj/transient_hash_map.cpp | 18 +- .../jank/runtime/obj/transient_hash_set.cpp | 16 +- .../jank/runtime/obj/transient_sorted_map.cpp | 18 +- .../jank/runtime/obj/transient_sorted_set.cpp | 18 +- .../cpp/jank/runtime/obj/transient_vector.cpp | 12 +- .../src/cpp/jank/runtime/obj/volatile.cpp | 4 +- .../src/cpp/jank/runtime/object.cpp | 10 +- .../src/cpp/jank/runtime/perf.cpp | 6 +- compiler+runtime/src/cpp/jank/runtime/var.cpp | 38 +- compiler+runtime/src/cpp/jank/util/try.cpp | 2 +- compiler+runtime/src/cpp/jtl/panic.cpp | 1 + .../src/cpp/jtl/string_builder.cpp | 3 + 187 files changed, 3057 insertions(+), 2913 deletions(-) diff --git a/compiler+runtime/include/cpp/clojure/core_native.hpp b/compiler+runtime/include/cpp/clojure/core_native.hpp index d284b3a27..af7948cf2 100644 --- a/compiler+runtime/include/cpp/clojure/core_native.hpp +++ b/compiler+runtime/include/cpp/clojure/core_native.hpp @@ -9,56 +9,62 @@ namespace clojure::core_native { using namespace jank::runtime; - object_ref is_var(object_ref o); - object_ref var_get(object_ref o); - object_ref alter_var_root(object_ref o, object_ref fn, object_ref args); - object_ref is_var_bound(object_ref o); - object_ref is_var_thread_bound(object_ref o); - object_ref var_bind_root(object_ref v, object_ref o); - object_ref var_get_root(object_ref o); - object_ref intern_var(object_ref sym); + object_ref is_var(object_ref const &o); + object_ref var_get(object_ref const &o); + object_ref alter_var_root(object_ref const &o, object_ref const &fn, object_ref const &args); + object_ref is_var_bound(object_ref const &o); + object_ref is_var_thread_bound(object_ref const &o); + object_ref var_bind_root(object_ref const &v, object_ref const &o); + object_ref var_get_root(object_ref const &o); + object_ref intern_var(object_ref const &sym); - object_ref ns_unalias(object_ref current_ns, object_ref alias); - object_ref ns_unmap(object_ref current_ns, object_ref sym); - object_ref in_ns(object_ref sym); - object_ref intern_ns(object_ref sym); - object_ref find_ns(object_ref sym); - object_ref find_var(object_ref sym); - object_ref remove_ns(object_ref sym); - object_ref is_ns(object_ref ns_or_sym); - object_ref ns_name(object_ref ns); - object_ref ns_map(object_ref ns); - object_ref var_ns(object_ref v); - object_ref ns_resolve(object_ref ns, object_ref sym); - object_ref alias(object_ref current_ns, object_ref remote_ns, object_ref alias); - object_ref refer(object_ref current_ns, object_ref sym, object_ref var); - object_ref load_module(object_ref path); - object_ref compile(object_ref path); + object_ref ns_unalias(object_ref const ¤t_ns, object_ref const &alias); + object_ref ns_unmap(object_ref const ¤t_ns, object_ref const &sym); + object_ref in_ns(object_ref const &sym); + object_ref intern_ns(object_ref const &sym); + object_ref find_ns(object_ref const &sym); + object_ref find_var(object_ref const &sym); + object_ref remove_ns(object_ref const &sym); + object_ref is_ns(object_ref const &ns_or_sym); + object_ref ns_name(object_ref const &ns); + object_ref ns_map(object_ref const &ns); + object_ref var_ns(object_ref const &v); + object_ref ns_resolve(object_ref const &ns, object_ref const &sym); + object_ref + alias(object_ref const ¤t_ns, object_ref const &remote_ns, object_ref const &alias); + object_ref refer(object_ref const ¤t_ns, object_ref const &sym, object_ref const &var); + object_ref load_module(object_ref const &path); + object_ref compile(object_ref const &path); - object_ref not_(object_ref o); + object_ref not_(object_ref const &o); - object_ref is_fn(object_ref o); - object_ref is_multi_fn(object_ref o); + object_ref is_fn(object_ref const &o); + object_ref is_multi_fn(object_ref const &o); + object_ref multi_fn(object_ref const &name, + object_ref const &dispatch_fn, + object_ref const &default_, + object_ref const &hierarchy); object_ref - multi_fn(object_ref name, object_ref dispatch_fn, object_ref default_, object_ref hierarchy); - object_ref defmethod(object_ref multifn, object_ref dispatch_val, object_ref fn); - object_ref remove_all_methods(object_ref multifn); - object_ref remove_method(object_ref multifn, object_ref dispatch_val); - object_ref prefer_method(object_ref multifn, object_ref dispatch_val_x, object_ref ispatch_val_y); - object_ref methods(object_ref multifn); - object_ref get_method(object_ref multifn, object_ref dispatch_val); - object_ref prefers(object_ref multifn); + defmethod(object_ref const &multifn, object_ref const &dispatch_val, object_ref const &fn); + object_ref remove_all_methods(object_ref const &multifn); + object_ref remove_method(object_ref const &multifn, object_ref const &dispatch_val); + object_ref prefer_method(object_ref const &multifn, + object_ref const &dispatch_val_x, + object_ref const &ispatch_val_y); + object_ref methods(object_ref const &multifn); + object_ref get_method(object_ref const &multifn, object_ref const &dispatch_val); + object_ref prefers(object_ref const &multifn); - object_ref sleep(object_ref ms); + object_ref sleep(object_ref const &ms); object_ref current_time(); - object_ref eval(object_ref expr); - object_ref read_string(object_ref /* opts */, object_ref str); + object_ref eval(object_ref const &expr); + object_ref read_string(object_ref const & /* opts */, object_ref const &str); - object_ref lazy_seq(object_ref o); + object_ref lazy_seq(object_ref const &o); - object_ref hash_unordered(object_ref coll); + object_ref hash_unordered(object_ref const &coll); object_ref jank_version(); - object_ref delay(object_ref fn); + object_ref delay(object_ref const &fn); } diff --git a/compiler+runtime/include/cpp/clojure/string_native.hpp b/compiler+runtime/include/cpp/clojure/string_native.hpp index 3554516ab..44b475b0d 100644 --- a/compiler+runtime/include/cpp/clojure/string_native.hpp +++ b/compiler+runtime/include/cpp/clojure/string_native.hpp @@ -7,23 +7,24 @@ namespace clojure::string_native using namespace jank; using namespace jank::runtime; - object_ref blank(object_ref s); - object_ref reverse(object_ref s); - object_ref lower_case(object_ref s); - object_ref starts_with(object_ref s, object_ref substr); - object_ref ends_with(object_ref s, object_ref substr); - object_ref includes(object_ref s, object_ref substr); - object_ref upper_case(object_ref s); - object_ref replace_first(object_ref s, object_ref match, object_ref replacement); + object_ref blank(object_ref const &s); + object_ref reverse(object_ref const &s); + object_ref lower_case(object_ref const &s); + object_ref starts_with(object_ref const &s, object_ref const &substr); + object_ref ends_with(object_ref const &s, object_ref const &substr); + object_ref includes(object_ref const &s, object_ref const &substr); + object_ref upper_case(object_ref const &s); + object_ref + replace_first(object_ref const &s, object_ref const &match, object_ref const &replacement); - i64 index_of(object_ref s, object_ref value, object_ref from_index); - i64 last_index_of(object_ref s, object_ref value, object_ref from_index); + i64 index_of(object_ref const &s, object_ref const &value, object_ref const &from_index); + i64 last_index_of(object_ref const &s, object_ref const &value, object_ref const &from_index); - object_ref triml(object_ref s); - object_ref trimr(object_ref s); - object_ref trim(object_ref s); - object_ref trim_newline(object_ref s); + object_ref triml(object_ref const &s); + object_ref trimr(object_ref const &s); + object_ref trim(object_ref const &s); + object_ref trim_newline(object_ref const &s); - object_ref split(object_ref s, object_ref re); - object_ref split(object_ref s, object_ref re, object_ref limit); + object_ref split(object_ref const &s, object_ref const &re); + object_ref split(object_ref const &s, object_ref const &re, object_ref const &limit); } diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/call.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/call.hpp index cea812555..dcc9074e9 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/call.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/call.hpp @@ -20,7 +20,7 @@ namespace jank::analyze::expr bool needs_box, expression_ref source, native_vector &&arg_exprs, - runtime::obj::persistent_list_ref form); + runtime::obj::persistent_list_ref const &form); runtime::object_ref to_runtime_data() const override; void walk(std::function)> const &f) override; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/cpp_type.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/cpp_type.hpp index 1f6ab7d5b..15f154845 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/cpp_type.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/cpp_type.hpp @@ -18,7 +18,7 @@ namespace jank::analyze::expr cpp_type(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::obj::symbol_ref sym, + runtime::obj::symbol_ref const &sym, jtl::ptr type); void propagate_position(expression_position const pos) override; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/cpp_value.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/cpp_value.hpp index 176394709..af7b23826 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/cpp_value.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/cpp_value.hpp @@ -32,7 +32,7 @@ namespace jank::analyze::expr cpp_value(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::obj::symbol_ref sym, + runtime::obj::symbol_ref const &sym, jtl::ptr type, jtl::ptr scope, value_kind val_kind); diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/def.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/def.hpp index c82b0ab6d..19ef19252 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/def.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/def.hpp @@ -20,7 +20,7 @@ namespace jank::analyze::expr def(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::obj::symbol_ref name, + runtime::obj::symbol_ref const &name, jtl::option const &value); runtime::object_ref to_runtime_data() const override; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp index 8a0cdbd80..a4bc74e17 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp @@ -61,7 +61,7 @@ namespace jank::analyze::expr jtl::immutable_string const &name, jtl::immutable_string const &unique_name, native_vector &&arities, - runtime::obj::persistent_hash_map_ref meta); + runtime::obj::persistent_hash_map_ref const &meta); /* Aggregates all `frame->captures` from each arity so that we can know the overall * captures for all arities of this fn. This is necessary for codegen to IR, since we diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/local_reference.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/local_reference.hpp index 492c2b80d..fc566fa24 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/local_reference.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/local_reference.hpp @@ -19,7 +19,7 @@ namespace jank::analyze::expr local_reference(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::obj::symbol_ref name, + runtime::obj::symbol_ref const &name, local_binding_ptr binding); runtime::object_ref to_runtime_data() const override; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/named_recursion.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/named_recursion.hpp index 744f6118e..7d4726e41 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/named_recursion.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/named_recursion.hpp @@ -19,7 +19,7 @@ namespace jank::analyze::expr local_frame_ptr frame, bool needs_box, recursion_reference &&recursion_ref, - runtime::obj::persistent_list_ref args, + runtime::obj::persistent_list_ref const &args, native_vector &&arg_exprs); runtime::object_ref to_runtime_data() const override; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/primitive_literal.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/primitive_literal.hpp index 0814976e4..33278f538 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/primitive_literal.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/primitive_literal.hpp @@ -13,7 +13,7 @@ namespace jank::analyze::expr primitive_literal(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::object_ref data); + runtime::object_ref const &data); runtime::object_ref to_runtime_data() const override; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/recur.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/recur.hpp index af3d1e195..7fb33f729 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/recur.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/recur.hpp @@ -24,7 +24,7 @@ namespace jank::analyze::expr recur(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::obj::persistent_list_ref args, + runtime::obj::persistent_list_ref const &args, native_vector &&arg_exprs, jtl::option const &loop_target); diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/var_deref.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/var_deref.hpp index 739d2b05e..9f5b160fa 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/var_deref.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/var_deref.hpp @@ -23,8 +23,8 @@ namespace jank::analyze::expr var_deref(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::obj::symbol_ref qualified_name, - runtime::var_ref var); + runtime::obj::symbol_ref const &qualified_name, + runtime::var_ref const &var); runtime::object_ref to_runtime_data() const override; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/var_ref.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/var_ref.hpp index 6ddae3921..c75577aa5 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/var_ref.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/var_ref.hpp @@ -21,8 +21,8 @@ namespace jank::analyze::expr var_ref(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::obj::symbol_ref qualified_name, - runtime::var_ref var); + runtime::obj::symbol_ref const &qualified_name, + runtime::var_ref const &var); runtime::object_ref to_runtime_data() const override; diff --git a/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp b/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp index 0540017b9..0390478b7 100644 --- a/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp @@ -104,16 +104,17 @@ namespace jank::analyze /* This is used to find both captures and regular locals, since it's * impossible to know which one a sym is without finding it. */ - jtl::option find_local_or_capture(runtime::obj::symbol_ref sym); + jtl::option find_local_or_capture(runtime::obj::symbol_ref const &sym); static void register_captures(binding_find_result const &result); static void register_captures(jtl::ptr frame, named_recursion_find_result const &result); /* This can be used when you have a capture, but you want to trace it back to the * originating local. */ - jtl::option find_originating_local(runtime::obj::symbol_ref sym); + jtl::option find_originating_local(runtime::obj::symbol_ref const &sym); - jtl::option find_named_recursion(runtime::obj::symbol_ref sym); + jtl::option + find_named_recursion(runtime::obj::symbol_ref const &sym); static bool within_same_fn(jtl::ptr, jtl::ptr); diff --git a/compiler+runtime/include/cpp/jank/analyze/processor.hpp b/compiler+runtime/include/cpp/jank/analyze/processor.hpp index eb8916de2..da3c2480a 100644 --- a/compiler+runtime/include/cpp/jank/analyze/processor.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/processor.hpp @@ -49,175 +49,175 @@ namespace jank::analyze expression_result analyze(read::parse::processor::iterator, read::parse::processor::iterator const &); - expression_result analyze(runtime::object_ref, expression_position); - expression_result analyze(runtime::object_ref, + expression_result analyze(runtime::object_ref const &, expression_position); + expression_result analyze(runtime::object_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_call(runtime::obj::persistent_list_ref const, + expression_result analyze_call(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_def(runtime::obj::persistent_list_ref const, + expression_result analyze_def(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_symbol(runtime::obj::symbol_ref const, + expression_result analyze_symbol(runtime::obj::symbol_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_fn(runtime::obj::persistent_list_ref const, + expression_result analyze_fn(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_recur(runtime::obj::persistent_list_ref const, + expression_result analyze_recur(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_do(runtime::obj::persistent_list_ref const, + expression_result analyze_do(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); jtl::result - analyze_fn_arity(runtime::obj::persistent_list_ref const, + analyze_fn_arity(runtime::obj::persistent_list_ref const &, jtl::immutable_string const &name, local_frame_ptr); - expression_result analyze_let(runtime::obj::persistent_list_ref const, + expression_result analyze_let(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_letfn(runtime::obj::persistent_list_ref const, + expression_result analyze_letfn(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_loop(runtime::obj::persistent_list_ref const, + expression_result analyze_loop(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_if(runtime::obj::persistent_list_ref const, + expression_result analyze_if(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_quote(runtime::obj::persistent_list_ref const, + expression_result analyze_quote(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_var_call(runtime::obj::persistent_list_ref const, + expression_result analyze_var_call(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_var_val(runtime::var_ref const, + expression_result analyze_var_val(runtime::var_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_throw(runtime::obj::persistent_list_ref const, + expression_result analyze_throw(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_try(runtime::obj::persistent_list_ref const, + expression_result analyze_try(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_primitive_literal(runtime::object_ref, + expression_result analyze_primitive_literal(runtime::object_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_vector(runtime::obj::persistent_vector_ref const, + expression_result analyze_vector(runtime::obj::persistent_vector_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_map(runtime::object_ref const, + expression_result analyze_map(runtime::object_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_set(runtime::object_ref const, + expression_result analyze_set(runtime::object_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_case(runtime::obj::persistent_list_ref const, + expression_result analyze_case(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_symbol(runtime::obj::symbol_ref const, + expression_result analyze_cpp_symbol(runtime::obj::symbol_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_call(runtime::obj::persistent_list_ref const, + expression_result analyze_cpp_call(runtime::obj::persistent_list_ref const &, expression_ref, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_raw(runtime::obj::persistent_list_ref const, + expression_result analyze_cpp_raw(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_literal(runtime::obj::persistent_list_ref const, + expression_result analyze_cpp_literal(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box, literal_kind kind); - expression_result analyze_cpp_type(runtime::obj::persistent_list_ref const, + expression_result analyze_cpp_type(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_value(runtime::obj::persistent_list_ref const, + expression_result analyze_cpp_value(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_cast(runtime::obj::persistent_list_ref const, + expression_result analyze_cpp_cast(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_box(runtime::obj::persistent_list_ref const, + expression_result analyze_cpp_box(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_unbox(runtime::obj::persistent_list_ref const, + expression_result analyze_cpp_unbox(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_new(runtime::obj::persistent_list_ref const, + expression_result analyze_cpp_new(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_delete(runtime::obj::persistent_list_ref const, + expression_result analyze_cpp_delete(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_member_access(runtime::obj::persistent_list_ref const, + expression_result analyze_cpp_member_access(runtime::obj::persistent_list_ref const &, expr::cpp_value_ref, local_frame_ptr, expression_position, @@ -225,10 +225,10 @@ namespace jank::analyze bool needs_box); /* Returns whether the form is a special symbol. */ - bool is_special(runtime::object_ref form); + bool is_special(runtime::object_ref const &form); using special_function_type - = expression_result (processor::*)(runtime::obj::persistent_list_ref const, + = expression_result (processor::*)(runtime::obj::persistent_list_ref const &, local_frame_ptr, expression_position, jtl::option const &, diff --git a/compiler+runtime/include/cpp/jank/error.hpp b/compiler+runtime/include/cpp/jank/error.hpp index aad6be87d..c7fd37d44 100644 --- a/compiler+runtime/include/cpp/jank/error.hpp +++ b/compiler+runtime/include/cpp/jank/error.hpp @@ -392,17 +392,17 @@ namespace jank::error base(kind k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); base(kind k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion, + runtime::object_ref const &expansion, std::unique_ptr trace); base(kind k, jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const ¬e_message, - runtime::object_ref expansion); + runtime::object_ref const &expansion); base(kind k, read::source const &source, jtl::immutable_string const ¬e_message); base(kind k, jtl::immutable_string const &message, @@ -417,7 +417,7 @@ namespace jank::error jtl::immutable_string const &message, read::source const &source, note const ¬e, - runtime::object_ref expansion); + runtime::object_ref const &expansion); base(kind k, jtl::immutable_string const &message, read::source const &source, @@ -425,12 +425,12 @@ namespace jank::error base(kind k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion, + runtime::object_ref const &expansion, jtl::ref cause); base(kind k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion, + runtime::object_ref const &expansion, jtl::ref cause, std::unique_ptr trace); diff --git a/compiler+runtime/include/cpp/jank/error/analyze.hpp b/compiler+runtime/include/cpp/jank/error/analyze.hpp index 0c5dfda7f..33708e3fc 100644 --- a/compiler+runtime/include/cpp/jank/error/analyze.hpp +++ b/compiler+runtime/include/cpp/jank/error/analyze.hpp @@ -11,151 +11,151 @@ namespace jank::error { error_ref analyze_invalid_case(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_def(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_def(jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const ¬e, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_fn(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_fn_parameters(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_fn_parameters(jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const &error_note_message, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_recur_position(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_recur_from_try(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_recur_args(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_let(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_letfn(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_loop(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_if(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_if(jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const &error_note_message, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_quote(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_var_reference(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_throw(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_try(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_try(jtl::immutable_string const &message, read::source const &source, note &&extra, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_unresolved_var(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_unresolved_symbol(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_macro_expansion_exception(std::exception const &e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref expansion); - error_ref analyze_macro_expansion_exception(runtime::object_ref const e, + runtime::object_ref const &expansion); + error_ref analyze_macro_expansion_exception(runtime::object_ref const &e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_macro_expansion_exception(jtl::immutable_string const &e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_macro_expansion_exception(error_ref e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_conversion(jtl::immutable_string const &message); error_ref analyze_invalid_cpp_operator_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_constructor_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_member_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_capture(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_mismatched_if_types(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_function_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_conversion(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_symbol(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_unresolved_cpp_symbol(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_raw(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_type(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_value(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_cast(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_box(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_unbox(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_new(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_delete(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_invalid_cpp_member_access(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); error_ref analyze_known_issue(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); - error_ref - internal_analyze_failure(jtl::immutable_string const &message, runtime::object_ref expansion); + runtime::object_ref const &expansion); + error_ref internal_analyze_failure(jtl::immutable_string const &message, + runtime::object_ref const &expansion); error_ref internal_analyze_failure(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref expansion); + runtime::object_ref const &expansion); } diff --git a/compiler+runtime/include/cpp/jank/hash.hpp b/compiler+runtime/include/cpp/jank/hash.hpp index 452224760..46133f98c 100644 --- a/compiler+runtime/include/cpp/jank/hash.hpp +++ b/compiler+runtime/include/cpp/jank/hash.hpp @@ -38,7 +38,7 @@ namespace jank::hash u32 string(jtl::immutable_string_view const &input); - u32 visit(runtime::oref const o); + u32 visit(runtime::oref const &o); u32 visit(char const ch); u32 ordered(runtime::object const * const sequence); diff --git a/compiler+runtime/include/cpp/jank/read/parse.hpp b/compiler+runtime/include/cpp/jank/read/parse.hpp index e42d364d4..3408623e6 100644 --- a/compiler+runtime/include/cpp/jank/read/parse.hpp +++ b/compiler+runtime/include/cpp/jank/read/parse.hpp @@ -100,12 +100,14 @@ namespace jank::read::parse iterator end(); private: - jtl::result syntax_quote(runtime::object_ref form); - jtl::result syntax_quote_expand_seq(runtime::object_ref seq); - jtl::result syntax_quote_expand_set(runtime::object_ref seq); + jtl::result syntax_quote(runtime::object_ref const &form); + jtl::result + syntax_quote_expand_seq(runtime::object_ref const &seq); + jtl::result + syntax_quote_expand_set(runtime::object_ref const &seq); static jtl::result - syntax_quote_flatten_map(runtime::object_ref seq); - static bool syntax_quote_is_unquote(runtime::object_ref form, bool splice); + syntax_quote_flatten_map(runtime::object_ref const &seq); + static bool syntax_quote_is_unquote(runtime::object_ref const &form, bool splice); public: lex::processor::iterator token_current, token_end; diff --git a/compiler+runtime/include/cpp/jank/read/reparse.hpp b/compiler+runtime/include/cpp/jank/read/reparse.hpp index 0b6e988cf..ddc49526d 100644 --- a/compiler+runtime/include/cpp/jank/read/reparse.hpp +++ b/compiler+runtime/include/cpp/jank/read/reparse.hpp @@ -20,7 +20,7 @@ namespace jank::runtime::obj * to parse the nth form inside that list. That gives us the source for `:foo`. */ namespace jank::read::parse { - source reparse_nth(runtime::obj::persistent_list_ref o, usize n); - source reparse_nth(runtime::obj::persistent_vector_ref o, usize n); - source reparse_nth(runtime::object_ref o, usize n); + source reparse_nth(runtime::obj::persistent_list_ref const &o, usize n); + source reparse_nth(runtime::obj::persistent_vector_ref const &o, usize n); + source reparse_nth(runtime::object_ref const &o, usize n); } diff --git a/compiler+runtime/include/cpp/jank/read/source.hpp b/compiler+runtime/include/cpp/jank/read/source.hpp index a0f7337a0..f4435d7d6 100644 --- a/compiler+runtime/include/cpp/jank/read/source.hpp +++ b/compiler+runtime/include/cpp/jank/read/source.hpp @@ -38,7 +38,7 @@ namespace jank::read jtl::immutable_string const &module, source_position const &start, source_position const &end, - runtime::object_ref macro_expansion); + runtime::object_ref const ¯o_expansion); source &operator=(source const &rhs) = default; source &operator=(source &&rhs) = default; diff --git a/compiler+runtime/include/cpp/jank/runtime/behavior/callable.hpp b/compiler+runtime/include/cpp/jank/runtime/behavior/callable.hpp index 832d753ff..b7784c187 100644 --- a/compiler+runtime/include/cpp/jank/runtime/behavior/callable.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/behavior/callable.hpp @@ -21,72 +21,83 @@ namespace jank::runtime * supported arities at compile-time, but that's not always the case in * dynamic code. We may not every know if the source is callable at all, so * codegen will use this suite of fns instead. */ - object_ref dynamic_call(object_ref const source); - object_ref dynamic_call(object_ref const source, object_ref); - object_ref dynamic_call(object_ref const source, object_ref, object_ref); - object_ref dynamic_call(object_ref const source, object_ref, object_ref, object_ref); - object_ref dynamic_call(object_ref const source, object_ref, object_ref, object_ref, object_ref); - object_ref - dynamic_call(object_ref const source, object_ref, object_ref, object_ref, object_ref, object_ref); - object_ref dynamic_call(object_ref const source, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref); - object_ref dynamic_call(object_ref const source, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref); - object_ref dynamic_call(object_ref const source, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref); - object_ref dynamic_call(object_ref const source, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref); - object_ref dynamic_call(object_ref const source, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref); - object_ref dynamic_call(object_ref const source, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - obj::persistent_list_ref); - - object_ref apply_to(object_ref source, object_ref args); + object_ref dynamic_call(object_ref const &source); + object_ref dynamic_call(object_ref const &source, object_ref const &); + object_ref dynamic_call(object_ref const &source, object_ref const &, object_ref const &); + object_ref dynamic_call(object_ref const &source, + object_ref const &, + object_ref const &, + object_ref const &); + object_ref dynamic_call(object_ref const &source, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &); + object_ref dynamic_call(object_ref const &source, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &); + object_ref dynamic_call(object_ref const &source, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &); + object_ref dynamic_call(object_ref const &source, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &); + object_ref dynamic_call(object_ref const &source, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &); + object_ref dynamic_call(object_ref const &source, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &); + object_ref dynamic_call(object_ref const &source, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &); + object_ref dynamic_call(object_ref const &source, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + obj::persistent_list_ref const &); + + object_ref apply_to(object_ref const &source, object_ref const &args); namespace behavior { @@ -98,42 +109,56 @@ namespace jank::runtime virtual ~callable() = default; virtual object_ref call(); - virtual object_ref call(object_ref); - virtual object_ref call(object_ref, object_ref); - virtual object_ref call(object_ref, object_ref, object_ref); - virtual object_ref call(object_ref, object_ref, object_ref, object_ref); - virtual object_ref call(object_ref, object_ref, object_ref, object_ref, object_ref); - virtual object_ref - call(object_ref, object_ref, object_ref, object_ref, object_ref, object_ref); + virtual object_ref call(object_ref const &); + virtual object_ref call(object_ref const &, object_ref const &); + virtual object_ref call(object_ref const &, object_ref const &, object_ref const &); virtual object_ref - call(object_ref, object_ref, object_ref, object_ref, object_ref, object_ref, object_ref); - virtual object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref); - virtual object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref); - virtual object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref); + call(object_ref const &, object_ref const &, object_ref const &, object_ref const &); + virtual object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &); + virtual object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &); + virtual object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &); + virtual object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &); + virtual object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &); + virtual object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &); /* Callables need a way to get back to the root object so we can do helpful * error reporting on failed calls. */ diff --git a/compiler+runtime/include/cpp/jank/runtime/behavior/metadatable.hpp b/compiler+runtime/include/cpp/jank/runtime/behavior/metadatable.hpp index 3233abe38..633da4eae 100644 --- a/compiler+runtime/include/cpp/jank/runtime/behavior/metadatable.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/behavior/metadatable.hpp @@ -14,6 +14,6 @@ namespace jank::runtime::behavior namespace detail { - object_ref validate_meta(object_ref const m); + object_ref validate_meta(object_ref const &m); } } diff --git a/compiler+runtime/include/cpp/jank/runtime/context.hpp b/compiler+runtime/include/cpp/jank/runtime/context.hpp index ad084965d..b1253aeb3 100644 --- a/compiler+runtime/include/cpp/jank/runtime/context.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/context.hpp @@ -77,8 +77,8 @@ namespace jank::runtime jtl::result intern_keyword(jtl::immutable_string const &s); - object_ref macroexpand1(object_ref o); - object_ref macroexpand(object_ref o); + object_ref macroexpand1(object_ref const &o); + object_ref macroexpand(object_ref const &o); object_ref eval_file(jtl::immutable_string const &path); object_ref eval_string(jtl::immutable_string const &code); @@ -104,7 +104,7 @@ namespace jank::runtime /* Does all the same work as load_module, but also writes compiled files to the file system. */ jtl::result compile_module(jtl::immutable_string const &module); - object_ref eval(object_ref const o); + object_ref eval(object_ref const &o); jtl::string_result write_module(jtl::immutable_string const &module_name, jtl::ref const &module) const; @@ -124,13 +124,13 @@ namespace jank::runtime struct binding_scope { binding_scope(); - binding_scope(obj::persistent_hash_map_ref const bindings); + binding_scope(obj::persistent_hash_map_ref const &bindings); ~binding_scope(); }; jtl::string_result push_thread_bindings(); - jtl::string_result push_thread_bindings(object_ref const bindings); - jtl::string_result push_thread_bindings(obj::persistent_hash_map_ref const bindings); + jtl::string_result push_thread_bindings(object_ref const &bindings); + jtl::string_result push_thread_bindings(obj::persistent_hash_map_ref const &bindings); jtl::string_result pop_thread_bindings(); obj::persistent_hash_map_ref get_thread_bindings() const; jtl::option current_thread_binding_frame(); diff --git a/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp b/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp index 21e20bb64..1b8366217 100644 --- a/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp @@ -15,12 +15,12 @@ namespace jank::runtime template <> struct convert { - static object_ref into_object(object_ref const t) + static object_ref into_object(object_ref const &t) { return t; } - static object_ref from_object(object_ref const t) + static object_ref from_object(object_ref const &t) { return t; } @@ -49,7 +49,7 @@ namespace jank::runtime return const_cast(t); } - static object_ref into_object(object_ref const t) + static object_ref into_object(object_ref const &t) { return t.erase(); } @@ -59,7 +59,7 @@ namespace jank::runtime return const_cast(t); } - static object_ref from_object(object_ref const t) + static object_ref from_object(object_ref const &t) { return t.erase(); } @@ -70,7 +70,7 @@ namespace jank::runtime requires typed_object_ref struct convert { - static T into_object(T const t) + static T into_object(T const &t) { return t; } @@ -110,7 +110,7 @@ namespace jank::runtime return jank_nil(); } - static void from_object(object_ref) + static void from_object(object_ref const &) { } }; @@ -123,7 +123,7 @@ namespace jank::runtime return jank_nil(); } - static jtl::nullptr_t from_object(object_ref) + static jtl::nullptr_t from_object(object_ref const &) { return nullptr; } @@ -137,12 +137,12 @@ namespace jank::runtime return make_box(o); } - static bool from_object(object_ref const o) + static bool from_object(object_ref const &o) { return try_object(o)->data; } - static bool from_object(obj::boolean_ref const o) + static bool from_object(obj::boolean_ref const &o) { return o->data; } @@ -156,12 +156,12 @@ namespace jank::runtime return make_box(o); } - static char from_object(object_ref const o) + static char from_object(object_ref const &o) { return try_object(o)->data[0]; } - static char from_object(obj::character_ref const o) + static char from_object(obj::character_ref const &o) { return o->data[0]; } @@ -176,12 +176,12 @@ namespace jank::runtime return make_box(static_cast(o)); } - static T from_object(object_ref const o) + static T from_object(object_ref const &o) { return try_object(o); } - static T from_object(obj::integer_ref const o) + static T from_object(obj::integer_ref const &o) { return o->data; } @@ -198,12 +198,12 @@ namespace jank::runtime return make_box(static_cast(o)); } - static T from_object(object_ref const o) + static T from_object(object_ref const &o) { return static_cast(try_object(o)->data); } - static T from_object(obj::integer_ref const o) + static T from_object(obj::integer_ref const &o) { return static_cast(o->data); } @@ -218,12 +218,12 @@ namespace jank::runtime return make_box(o); } - static native_big_integer from_object(object_ref const o) + static native_big_integer from_object(object_ref const &o) { return try_object(o)->data; } - static native_big_integer from_object(obj::big_integer_ref const o) + static native_big_integer from_object(obj::big_integer_ref const &o) { return o->data; } @@ -239,12 +239,12 @@ namespace jank::runtime return make_box(static_cast(o)); } - static T from_object(object_ref const o) + static T from_object(object_ref const &o) { return static_cast(try_object(o)->data); } - static T from_object(obj::real_ref const o) + static T from_object(obj::real_ref const &o) { return static_cast(o->data); } @@ -264,12 +264,12 @@ namespace jank::runtime return make_box(o); } - static char const *from_object(object_ref const o) + static char const *from_object(object_ref const &o) { return try_object(o)->data.c_str(); } - static char const *from_object(obj::persistent_string_ref const o) + static char const *from_object(obj::persistent_string_ref const &o) { return o->data.c_str(); } @@ -285,12 +285,12 @@ namespace jank::runtime return make_box(o); } - static T from_object(object_ref const o) + static T from_object(object_ref const &o) { return try_object(o)->data; } - static T from_object(obj::persistent_string_ref const o) + static T from_object(obj::persistent_string_ref const &o) { return o->data; } @@ -312,12 +312,12 @@ namespace jank::runtime return make_box(trans); } - static V from_object(object_ref const o) + static V from_object(object_ref const &o) { return from_object(try_object(o)); } - static V from_object(obj::persistent_vector_ref const o) + static V from_object(obj::persistent_vector_ref const &o) { V ret; for(auto const &e : o->data) diff --git a/compiler+runtime/include/cpp/jank/runtime/convert/function.hpp b/compiler+runtime/include/cpp/jank/runtime/convert/function.hpp index d7500e4dc..4c630bf90 100644 --- a/compiler+runtime/include/cpp/jank/runtime/convert/function.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/convert/function.hpp @@ -7,13 +7,14 @@ namespace jank::runtime template struct always_object_ref { - using type = object_ref; + using type = object_ref const &; }; template auto convert_function(R (* const fn)(Args...)) { - if constexpr(std::conjunction_v, std::is_same...>) + if constexpr(std::conjunction_v, + std::is_same...>) { return fn; } @@ -23,13 +24,13 @@ namespace jank::runtime [fn](Args &&...args) -> object_ref { if constexpr(jtl::is_void) { - fn(convert::into_object(jtl::forward(args))...); + fn(convert>::into_object(jtl::forward(args))...); return convert::into_object(); } else { return convert::into_object( - fn(convert::into_object(jtl::forward(args))...)); + fn(convert>::into_object(jtl::forward(args))...)); } } }; diff --git a/compiler+runtime/include/cpp/jank/runtime/core.hpp b/compiler+runtime/include/cpp/jank/runtime/core.hpp index e760e2b30..295b348ab 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core.hpp @@ -12,94 +12,108 @@ namespace jank::runtime { - jtl::immutable_string type(object_ref o); - bool is_nil(object_ref o); - bool is_true(object_ref o); - bool is_false(object_ref o); - bool is_some(object_ref o); - bool is_string(object_ref o); - bool is_char(object_ref o); - - bool is_symbol(object_ref o); - bool is_simple_symbol(object_ref o); - bool is_qualified_symbol(object_ref o); - - object_ref to_unqualified_symbol(object_ref o); - object_ref to_qualified_symbol(object_ref ns, object_ref name); - - object_ref print(object_ref args); - object_ref println(object_ref args); - object_ref pr(object_ref args); - object_ref prn(object_ref args); - - obj::persistent_string_ref subs(object_ref s, object_ref start); - obj::persistent_string_ref subs(object_ref s, object_ref start, object_ref end); - i64 first_index_of(object_ref s, object_ref m); - i64 last_index_of(object_ref s, object_ref m); - - bool is_named(object_ref o); - jtl::immutable_string name(object_ref o); - object_ref namespace_(object_ref o); - - object_ref keyword(object_ref ns, object_ref name); - bool is_keyword(object_ref o); - bool is_simple_keyword(object_ref o); - bool is_qualified_keyword(object_ref o); - - bool is_callable(object_ref o); - - uhash to_hash(object_ref o); - - object_ref macroexpand1(object_ref o); - object_ref macroexpand(object_ref o); - - object_ref gensym(object_ref o); - - object_ref atom(object_ref o); - object_ref deref(object_ref o); - object_ref swap_atom(object_ref atom, object_ref fn); - object_ref swap_atom(object_ref atom, object_ref fn, object_ref a1); - object_ref swap_atom(object_ref atom, object_ref fn, object_ref a1, object_ref a2); + jtl::immutable_string type(object_ref const &o); + bool is_nil(object_ref const &o); + bool is_true(object_ref const &o); + bool is_false(object_ref const &o); + bool is_some(object_ref const &o); + bool is_string(object_ref const &o); + bool is_char(object_ref const &o); + + bool is_symbol(object_ref const &o); + bool is_simple_symbol(object_ref const &o); + bool is_qualified_symbol(object_ref const &o); + + object_ref to_unqualified_symbol(object_ref const &o); + object_ref to_qualified_symbol(object_ref const &ns, object_ref const &name); + + object_ref print(object_ref const &args); + object_ref println(object_ref const &args); + object_ref pr(object_ref const &args); + object_ref prn(object_ref const &args); + + obj::persistent_string_ref subs(object_ref const &s, object_ref const &start); + obj::persistent_string_ref + subs(object_ref const &s, object_ref const &start, object_ref const &end); + i64 first_index_of(object_ref const &s, object_ref const &m); + i64 last_index_of(object_ref const &s, object_ref const &m); + + bool is_named(object_ref const &o); + jtl::immutable_string name(object_ref const &o); + object_ref namespace_(object_ref const &o); + + object_ref keyword(object_ref const &ns, object_ref const &name); + bool is_keyword(object_ref const &o); + bool is_simple_keyword(object_ref const &o); + bool is_qualified_keyword(object_ref const &o); + + bool is_callable(object_ref const &o); + + uhash to_hash(object_ref const &o); + + object_ref macroexpand1(object_ref const &o); + object_ref macroexpand(object_ref const &o); + + object_ref gensym(object_ref const &o); + + object_ref atom(object_ref const &o); + object_ref deref(object_ref const &o); + object_ref swap_atom(object_ref const &atom, object_ref const &fn); + object_ref swap_atom(object_ref const &atom, object_ref const &fn, object_ref const &a1); + object_ref swap_atom(object_ref const &atom, + object_ref const &fn, + object_ref const &a1, + object_ref const &a2); + object_ref swap_atom(object_ref const &atom, + object_ref const &fn, + object_ref const &a1, + object_ref const &a2, + object_ref const &rest); + object_ref swap_vals(object_ref const &atom, object_ref const &fn); + object_ref swap_vals(object_ref const &atom, object_ref const &fn, object_ref const &a1); + object_ref swap_vals(object_ref const &atom, + object_ref const &fn, + object_ref const &a1, + object_ref const &a2); + object_ref swap_vals(object_ref const &atom, + object_ref const &fn, + object_ref const &a1, + object_ref const &a2, + object_ref const &rest); object_ref - swap_atom(object_ref atom, object_ref fn, object_ref a1, object_ref a2, object_ref rest); - object_ref swap_vals(object_ref atom, object_ref fn); - object_ref swap_vals(object_ref atom, object_ref fn, object_ref a1); - object_ref swap_vals(object_ref atom, object_ref fn, object_ref a1, object_ref a2); - object_ref - swap_vals(object_ref atom, object_ref fn, object_ref a1, object_ref a2, object_ref rest); - object_ref compare_and_set(object_ref atom, object_ref old_val, object_ref new_val); - object_ref reset(object_ref atom, object_ref new_val); - object_ref reset_vals(object_ref atom, object_ref new_val); - - object_ref volatile_(object_ref o); - bool is_volatile(object_ref o); - object_ref vswap(object_ref v, object_ref fn); - object_ref vswap(object_ref v, object_ref fn, object_ref args); - object_ref vreset(object_ref v, object_ref new_val); - - void push_thread_bindings(object_ref o); + compare_and_set(object_ref const &atom, object_ref const &old_val, object_ref const &new_val); + object_ref reset(object_ref const &atom, object_ref const &new_val); + object_ref reset_vals(object_ref const &atom, object_ref const &new_val); + + object_ref volatile_(object_ref const &o); + bool is_volatile(object_ref const &o); + object_ref vswap(object_ref const &v, object_ref const &fn); + object_ref vswap(object_ref const &v, object_ref const &fn, object_ref const &args); + object_ref vreset(object_ref const &v, object_ref const &new_val); + + void push_thread_bindings(object_ref const &o); void pop_thread_bindings(); object_ref get_thread_bindings(); - object_ref force(object_ref o); + object_ref force(object_ref const &o); - object_ref tagged_literal(object_ref tag, object_ref form); - bool is_tagged_literal(object_ref o); + object_ref tagged_literal(object_ref const &tag, object_ref const &form); + bool is_tagged_literal(object_ref const &o); - object_ref parse_uuid(object_ref o); - bool is_uuid(object_ref o); + object_ref parse_uuid(object_ref const &o); + bool is_uuid(object_ref const &o); object_ref random_uuid(); - bool is_inst(object_ref o); - i64 inst_ms(object_ref o); + bool is_inst(object_ref const &o); + i64 inst_ms(object_ref const &o); - object_ref re_pattern(object_ref o); - object_ref re_matcher(object_ref re, object_ref s); - object_ref re_find(object_ref m); - object_ref re_groups(object_ref m); - object_ref re_matches(object_ref re, object_ref s); + object_ref re_pattern(object_ref const &o); + object_ref re_matcher(object_ref const &re, object_ref const &s); + object_ref re_find(object_ref const &m); + object_ref re_groups(object_ref const &m); + object_ref re_matches(object_ref const &re, object_ref const &s); object_ref smatch_to_vector(std::smatch const &match_results); - object_ref add_watch(object_ref reference, object_ref key, object_ref fn); - object_ref remove_watch(object_ref reference, object_ref key); + object_ref add_watch(object_ref const &reference, object_ref const &key, object_ref const &fn); + object_ref remove_watch(object_ref const &reference, object_ref const &key); } diff --git a/compiler+runtime/include/cpp/jank/runtime/core/equal.hpp b/compiler+runtime/include/cpp/jank/runtime/core/equal.hpp index 35a429ccd..34bfb71c1 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/equal.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/equal.hpp @@ -4,8 +4,8 @@ namespace jank::runtime { - bool equal(char lhs, object_ref rhs); - bool equal(object_ref lhs, object_ref rhs); - i64 compare(object_ref, object_ref); - bool is_identical(object_ref lhs, object_ref rhs); + bool equal(char lhs, object_ref const &rhs); + bool equal(object_ref const &lhs, object_ref const &rhs); + i64 compare(object_ref const &, object_ref const &); + bool is_identical(object_ref const &lhs, object_ref const &rhs); } diff --git a/compiler+runtime/include/cpp/jank/runtime/core/math.hpp b/compiler+runtime/include/cpp/jank/runtime/core/math.hpp index 57ced0510..ff4bad927 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/math.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/math.hpp @@ -12,272 +12,272 @@ namespace jank::runtime using big_decimal_ref = oref; } - object_ref add(object_ref l, object_ref r); - object_ref add(obj::integer_ref l, object_ref r); - object_ref add(object_ref l, obj::integer_ref r); - object_ref add(object_ref l, obj::ratio_ref r); - object_ref add(obj::big_decimal_ref l, object_ref r); - object_ref add(object_ref l, obj::big_decimal_ref r); - i64 add(obj::integer_ref l, obj::integer_ref r); - f64 add(obj::real_ref l, obj::real_ref r); - object_ref add(obj::real_ref l, object_ref r); - object_ref add(object_ref l, obj::real_ref r); - f64 add(obj::real_ref l, obj::integer_ref r); - f64 add(obj::integer_ref l, obj::real_ref r); - - object_ref add(object_ref l, f64 r); - object_ref add(f64 l, object_ref r); + object_ref add(object_ref const &l, object_ref const &r); + object_ref add(obj::integer_ref const &l, object_ref const &r); + object_ref add(object_ref const &l, obj::integer_ref const &r); + object_ref add(object_ref const &l, obj::ratio_ref const &r); + object_ref add(obj::big_decimal_ref const &l, object_ref const &r); + object_ref add(object_ref const &l, obj::big_decimal_ref const &r); + i64 add(obj::integer_ref const &l, obj::integer_ref const &r); + f64 add(obj::real_ref const &l, obj::real_ref const &r); + object_ref add(obj::real_ref const &l, object_ref const &r); + object_ref add(object_ref const &l, obj::real_ref const &r); + f64 add(obj::real_ref const &l, obj::integer_ref const &r); + f64 add(obj::integer_ref const &l, obj::real_ref const &r); + + object_ref add(object_ref const &l, f64 r); + object_ref add(f64 l, object_ref const &r); f64 add(f64 l, f64 r); f64 add(i64 l, f64 r); f64 add(f64 l, i64 r); - object_ref add(object_ref l, i64 r); - object_ref add(i64 l, object_ref r); + object_ref add(object_ref const &l, i64 r); + object_ref add(i64 l, object_ref const &r); i64 add(i64 l, i64 r); - obj::ratio_ref add(obj::ratio_ref l, obj::ratio_ref r); - object_ref add(obj::ratio_ref l, obj::integer_ref r); - obj::ratio_ref add(obj::integer_ref l, obj::ratio_ref r); - - object_ref sub(object_ref l, object_ref r); - object_ref sub(obj::integer_ref l, object_ref r); - object_ref sub(object_ref l, obj::integer_ref r); - object_ref sub(obj::big_decimal_ref l, object_ref r); - object_ref sub(object_ref l, obj::big_decimal_ref r); - i64 sub(obj::integer_ref l, obj::integer_ref r); - f64 sub(obj::real_ref l, obj::real_ref r); - object_ref sub(obj::real_ref l, object_ref r); - object_ref sub(object_ref l, obj::real_ref r); - f64 sub(obj::real_ref l, obj::integer_ref r); - f64 sub(obj::integer_ref l, obj::real_ref r); - - object_ref sub(object_ref l, f64 r); - object_ref sub(f64 l, object_ref r); + obj::ratio_ref add(obj::ratio_ref const &l, obj::ratio_ref const &r); + object_ref add(obj::ratio_ref const &l, obj::integer_ref const &r); + obj::ratio_ref add(obj::integer_ref const &l, obj::ratio_ref const &r); + + object_ref sub(object_ref const &l, object_ref const &r); + object_ref sub(obj::integer_ref const &l, object_ref const &r); + object_ref sub(object_ref const &l, obj::integer_ref const &r); + object_ref sub(obj::big_decimal_ref const &l, object_ref const &r); + object_ref sub(object_ref const &l, obj::big_decimal_ref const &r); + i64 sub(obj::integer_ref const &l, obj::integer_ref const &r); + f64 sub(obj::real_ref const &l, obj::real_ref const &r); + object_ref sub(obj::real_ref const &l, object_ref const &r); + object_ref sub(object_ref const &l, obj::real_ref const &r); + f64 sub(obj::real_ref const &l, obj::integer_ref const &r); + f64 sub(obj::integer_ref const &l, obj::real_ref const &r); + + object_ref sub(object_ref const &l, f64 r); + object_ref sub(f64 l, object_ref const &r); f64 sub(f64 l, f64 r); f64 sub(i64 l, f64 r); f64 sub(f64 l, i64 r); - object_ref sub(object_ref l, i64 r); - object_ref sub(i64 l, object_ref r); + object_ref sub(object_ref const &l, i64 r); + object_ref sub(i64 l, object_ref const &r); i64 sub(i64 l, i64 r); - object_ref div(object_ref l, object_ref r); - object_ref div(obj::integer_ref l, object_ref r); - object_ref div(object_ref l, obj::integer_ref r); - object_ref div(obj::big_decimal_ref l, object_ref r); - object_ref div(object_ref l, obj::big_decimal_ref r); - i64 div(obj::integer_ref l, obj::integer_ref r); - f64 div(obj::real_ref l, obj::real_ref r); - object_ref div(obj::real_ref l, object_ref r); - object_ref div(object_ref l, obj::real_ref r); - f64 div(obj::real_ref l, obj::integer_ref r); - f64 div(obj::integer_ref l, obj::real_ref r); - - object_ref div(object_ref l, f64 r); - object_ref div(f64 l, object_ref r); + object_ref div(object_ref const &l, object_ref const &r); + object_ref div(obj::integer_ref const &l, object_ref const &r); + object_ref div(object_ref const &l, obj::integer_ref const &r); + object_ref div(obj::big_decimal_ref const &l, object_ref const &r); + object_ref div(object_ref const &l, obj::big_decimal_ref const &r); + i64 div(obj::integer_ref const &l, obj::integer_ref const &r); + f64 div(obj::real_ref const &l, obj::real_ref const &r); + object_ref div(obj::real_ref const &l, object_ref const &r); + object_ref div(object_ref const &l, obj::real_ref const &r); + f64 div(obj::real_ref const &l, obj::integer_ref const &r); + f64 div(obj::integer_ref const &l, obj::real_ref const &r); + + object_ref div(object_ref const &l, f64 r); + object_ref div(f64 l, object_ref const &r); f64 div(f64 l, f64 r); f64 div(i64 l, f64 r); f64 div(f64 l, i64 r); - object_ref div(object_ref l, i64 r); - object_ref div(i64 l, object_ref r); + object_ref div(object_ref const &l, i64 r); + object_ref div(i64 l, object_ref const &r); i64 div(i64 l, i64 r); - object_ref mul(object_ref l, object_ref r); - object_ref mul(obj::integer_ref l, object_ref r); - object_ref mul(object_ref l, obj::integer_ref r); - object_ref mul(obj::big_decimal_ref l, object_ref r); - object_ref mul(object_ref l, obj::big_decimal_ref r); - i64 mul(obj::integer_ref l, obj::integer_ref r); - f64 mul(obj::real_ref l, obj::real_ref r); - object_ref mul(obj::real_ref l, object_ref r); - object_ref mul(object_ref l, obj::real_ref r); - f64 mul(obj::real_ref l, obj::integer_ref r); - f64 mul(obj::integer_ref l, obj::real_ref r); - - object_ref mul(object_ref l, f64 r); - object_ref mul(f64 l, object_ref r); + object_ref mul(object_ref const &l, object_ref const &r); + object_ref mul(obj::integer_ref const &l, object_ref const &r); + object_ref mul(object_ref const &l, obj::integer_ref const &r); + object_ref mul(obj::big_decimal_ref const &l, object_ref const &r); + object_ref mul(object_ref const &l, obj::big_decimal_ref const &r); + i64 mul(obj::integer_ref const &l, obj::integer_ref const &r); + f64 mul(obj::real_ref const &l, obj::real_ref const &r); + object_ref mul(obj::real_ref const &l, object_ref const &r); + object_ref mul(object_ref const &l, obj::real_ref const &r); + f64 mul(obj::real_ref const &l, obj::integer_ref const &r); + f64 mul(obj::integer_ref const &l, obj::real_ref const &r); + + object_ref mul(object_ref const &l, f64 r); + object_ref mul(f64 l, object_ref const &r); f64 mul(f64 l, f64 r); f64 mul(i64 l, f64 r); f64 mul(f64 l, i64 r); - object_ref mul(object_ref l, i64 r); - object_ref mul(i64 l, object_ref r); + object_ref mul(object_ref const &l, i64 r); + object_ref mul(i64 l, object_ref const &r); i64 mul(i64 l, i64 r); - bool lt(object_ref l, object_ref r); - bool lt(obj::integer_ref l, object_ref r); - bool lt(object_ref l, obj::integer_ref r); - bool lt(obj::integer_ref const l, obj::integer_ref const r); - bool lt(obj::real_ref const l, obj::real_ref const r); - bool lt(obj::real_ref l, object_ref r); - bool lt(object_ref l, obj::real_ref r); - bool lt(obj::real_ref l, obj::integer_ref r); - bool lt(obj::integer_ref l, obj::real_ref r); - - bool lt(object_ref l, f64 r); - bool lt(f64 l, object_ref r); + bool lt(object_ref const &l, object_ref const &r); + bool lt(obj::integer_ref const &l, object_ref const &r); + bool lt(object_ref const &l, obj::integer_ref const &r); + bool lt(obj::integer_ref const &l, obj::integer_ref const &r); + bool lt(obj::real_ref const &l, obj::real_ref const &r); + bool lt(obj::real_ref const &l, object_ref const &r); + bool lt(object_ref const &l, obj::real_ref const &r); + bool lt(obj::real_ref const &l, obj::integer_ref const &r); + bool lt(obj::integer_ref const &l, obj::real_ref const &r); + + bool lt(object_ref const &l, f64 r); + bool lt(f64 l, object_ref const &r); bool lt(f64 l, f64 r); bool lt(i64 l, f64 r); bool lt(f64 l, i64 r); - bool lt(object_ref l, i64 r); - bool lt(i64 l, object_ref r); + bool lt(object_ref const &l, i64 r); + bool lt(i64 l, object_ref const &r); bool lt(i64 l, i64 r); - bool lte(object_ref l, object_ref r); - bool lte(obj::integer_ref l, object_ref r); - bool lte(object_ref l, obj::integer_ref r); - bool lte(obj::integer_ref const l, obj::integer_ref const r); - bool lte(obj::real_ref const l, obj::real_ref const r); - bool lte(obj::real_ref l, object_ref r); - bool lte(object_ref l, obj::real_ref r); - bool lte(obj::real_ref l, obj::integer_ref r); - bool lte(obj::integer_ref l, obj::real_ref r); - - bool lte(object_ref l, f64 r); - bool lte(f64 l, object_ref r); + bool lte(object_ref const &l, object_ref const &r); + bool lte(obj::integer_ref const &l, object_ref const &r); + bool lte(object_ref const &l, obj::integer_ref const &r); + bool lte(obj::integer_ref const &l, obj::integer_ref const &r); + bool lte(obj::real_ref const &l, obj::real_ref const &r); + bool lte(obj::real_ref const &l, object_ref const &r); + bool lte(object_ref const &l, obj::real_ref const &r); + bool lte(obj::real_ref const &l, obj::integer_ref const &r); + bool lte(obj::integer_ref const &l, obj::real_ref const &r); + + bool lte(object_ref const &l, f64 r); + bool lte(f64 l, object_ref const &r); bool lte(f64 l, f64 r); bool lte(i64 l, f64 r); bool lte(f64 l, i64 r); - bool lte(object_ref l, i64 r); - bool lte(i64 l, object_ref r); + bool lte(object_ref const &l, i64 r); + bool lte(i64 l, object_ref const &r); bool lte(i64 l, i64 r); - object_ref min(object_ref l, object_ref r); - object_ref min(obj::integer_ref l, object_ref r); - object_ref min(object_ref l, obj::integer_ref r); - i64 min(obj::integer_ref l, obj::integer_ref r); - f64 min(obj::real_ref l, obj::real_ref r); - f64 min(obj::real_ref l, object_ref r); - f64 min(object_ref l, obj::real_ref r); - f64 min(obj::real_ref l, obj::integer_ref r); - f64 min(obj::integer_ref l, obj::real_ref r); - - f64 min(object_ref l, f64 r); - f64 min(f64 l, object_ref r); + object_ref min(object_ref const &l, object_ref const &r); + object_ref min(obj::integer_ref const &l, object_ref const &r); + object_ref min(object_ref const &l, obj::integer_ref const &r); + i64 min(obj::integer_ref const &l, obj::integer_ref const &r); + f64 min(obj::real_ref const &l, obj::real_ref const &r); + f64 min(obj::real_ref const &l, object_ref const &r); + f64 min(object_ref const &l, obj::real_ref const &r); + f64 min(obj::real_ref const &l, obj::integer_ref const &r); + f64 min(obj::integer_ref const &l, obj::real_ref const &r); + + f64 min(object_ref const &l, f64 r); + f64 min(f64 l, object_ref const &r); f64 min(f64 l, f64 r); f64 min(i64 l, f64 r); f64 min(f64 l, i64 r); - object_ref min(object_ref l, i64 r); - object_ref min(i64 l, object_ref r); + object_ref min(object_ref const &l, i64 r); + object_ref min(i64 l, object_ref const &r); i64 min(i64 l, i64 r); - object_ref max(object_ref l, object_ref r); - object_ref max(obj::integer_ref l, object_ref r); - object_ref max(object_ref l, obj::integer_ref r); - i64 max(obj::integer_ref l, obj::integer_ref r); - f64 max(obj::real_ref l, obj::real_ref r); - f64 max(obj::real_ref l, object_ref r); - f64 max(object_ref l, obj::real_ref r); - f64 max(obj::real_ref l, obj::integer_ref r); - f64 max(obj::integer_ref l, obj::real_ref r); - - object_ref max(object_ref l, f64 r); - object_ref max(f64 l, object_ref r); + object_ref max(object_ref const &l, object_ref const &r); + object_ref max(obj::integer_ref const &l, object_ref const &r); + object_ref max(object_ref const &l, obj::integer_ref const &r); + i64 max(obj::integer_ref const &l, obj::integer_ref const &r); + f64 max(obj::real_ref const &l, obj::real_ref const &r); + f64 max(obj::real_ref const &l, object_ref const &r); + f64 max(object_ref const &l, obj::real_ref const &r); + f64 max(obj::real_ref const &l, obj::integer_ref const &r); + f64 max(obj::integer_ref const &l, obj::real_ref const &r); + + object_ref max(object_ref const &l, f64 r); + object_ref max(f64 l, object_ref const &r); f64 max(f64 l, f64 r); f64 max(i64 l, f64 r); f64 max(f64 l, i64 r); - object_ref max(object_ref l, i64 r); - object_ref max(i64 l, object_ref r); + object_ref max(object_ref const &l, i64 r); + object_ref max(i64 l, object_ref const &r); i64 max(i64 l, i64 r); - object_ref abs(object_ref l); - i64 abs(obj::integer_ref l); - f64 abs(obj::real_ref l); + object_ref abs(object_ref const &l); + i64 abs(obj::integer_ref const &l); + f64 abs(obj::real_ref const &l); i64 abs(i64 l); f64 abs(f64 l); - f64 tan(object_ref l); + f64 tan(object_ref const &l); - f64 sqrt(object_ref l); - f64 sqrt(obj::integer_ref l); - f64 sqrt(obj::real_ref l); + f64 sqrt(object_ref const &l); + f64 sqrt(obj::integer_ref const &l); + f64 sqrt(obj::real_ref const &l); f64 sqrt(i64 l); f64 sqrt(f64 l); - f64 pow(object_ref l, object_ref r); - f64 pow(obj::integer_ref l, object_ref r); - f64 pow(object_ref l, obj::integer_ref r); - f64 pow(obj::integer_ref l, obj::integer_ref r); - f64 pow(obj::real_ref l, obj::real_ref r); - f64 pow(obj::real_ref l, object_ref r); - f64 pow(object_ref l, obj::real_ref r); - f64 pow(obj::real_ref l, obj::integer_ref r); - f64 pow(obj::integer_ref l, obj::real_ref r); - - object_ref pow(object_ref l, f64 r); - object_ref pow(f64 l, object_ref r); + f64 pow(object_ref const &l, object_ref const &r); + f64 pow(obj::integer_ref const &l, object_ref const &r); + f64 pow(object_ref const &l, obj::integer_ref const &r); + f64 pow(obj::integer_ref const &l, obj::integer_ref const &r); + f64 pow(obj::real_ref const &l, obj::real_ref const &r); + f64 pow(obj::real_ref const &l, object_ref const &r); + f64 pow(object_ref const &l, obj::real_ref const &r); + f64 pow(obj::real_ref const &l, obj::integer_ref const &r); + f64 pow(obj::integer_ref const &l, obj::real_ref const &r); + + object_ref pow(object_ref const &l, f64 r); + object_ref pow(f64 l, object_ref const &r); f64 pow(f64 l, f64 r); f64 pow(i64 l, f64 r); f64 pow(f64 l, i64 r); - f64 pow(object_ref l, i64 r); - f64 pow(i64 l, object_ref r); + f64 pow(object_ref const &l, i64 r); + f64 pow(i64 l, object_ref const &r); f64 pow(i64 l, i64 r); - object_ref rem(object_ref l, object_ref r); - object_ref quot(object_ref l, object_ref r); - object_ref inc(object_ref l); - object_ref dec(object_ref l); - - bool is_zero(object_ref l); - bool is_pos(object_ref l); - bool is_neg(object_ref l); - bool is_even(object_ref l); - bool is_odd(object_ref l); - - bool is_equiv(object_ref l, object_ref r); - - i64 bit_not(object_ref l); - i64 bit_and(object_ref l, object_ref r); - i64 bit_or(object_ref l, object_ref r); - i64 bit_xor(object_ref l, object_ref r); - i64 bit_and_not(object_ref l, object_ref r); - i64 bit_clear(object_ref l, object_ref r); - i64 bit_set(object_ref l, object_ref r); - i64 bit_flip(object_ref l, object_ref r); - bool bit_test(object_ref l, object_ref r); - i64 bit_shift_left(object_ref l, object_ref r); - i64 bit_shift_right(object_ref l, object_ref r); - i64 bit_unsigned_shift_right(object_ref l, object_ref r); + object_ref rem(object_ref const &l, object_ref const &r); + object_ref quot(object_ref const &l, object_ref const &r); + object_ref inc(object_ref const &l); + object_ref dec(object_ref const &l); + + bool is_zero(object_ref const &l); + bool is_pos(object_ref const &l); + bool is_neg(object_ref const &l); + bool is_even(object_ref const &l); + bool is_odd(object_ref const &l); + + bool is_equiv(object_ref const &l, object_ref const &r); + + i64 bit_not(object_ref const &l); + i64 bit_and(object_ref const &l, object_ref const &r); + i64 bit_or(object_ref const &l, object_ref const &r); + i64 bit_xor(object_ref const &l, object_ref const &r); + i64 bit_and_not(object_ref const &l, object_ref const &r); + i64 bit_clear(object_ref const &l, object_ref const &r); + i64 bit_set(object_ref const &l, object_ref const &r); + i64 bit_flip(object_ref const &l, object_ref const &r); + bool bit_test(object_ref const &l, object_ref const &r); + i64 bit_shift_left(object_ref const &l, object_ref const &r); + i64 bit_shift_right(object_ref const &l, object_ref const &r); + i64 bit_unsigned_shift_right(object_ref const &l, object_ref const &r); f64 rand(); - native_big_integer numerator(object_ref o); - native_big_integer denominator(object_ref o); + native_big_integer numerator(object_ref const &o); + native_big_integer denominator(object_ref const &o); - i64 to_int(object_ref l); - i64 to_int(obj::integer_ref l); - i64 to_int(obj::real_ref l); + i64 to_int(object_ref const &l); + i64 to_int(obj::integer_ref const &l); + i64 to_int(obj::real_ref const &l); i64 to_int(i64 l); i64 to_int(f64 l); - f64 to_real(object_ref o); + f64 to_real(object_ref const &o); - bool is_number(object_ref o); - bool is_integer(object_ref o); - bool is_real(object_ref o); - bool is_ratio(object_ref o); - bool is_boolean(object_ref o); - bool is_nan(object_ref o); - bool is_infinite(object_ref o); + bool is_number(object_ref const &o); + bool is_integer(object_ref const &o); + bool is_real(object_ref const &o); + bool is_ratio(object_ref const &o); + bool is_boolean(object_ref const &o); + bool is_nan(object_ref const &o); + bool is_infinite(object_ref const &o); - i64 parse_long(object_ref o); - f64 parse_double(object_ref o); + i64 parse_long(object_ref const &o); + f64 parse_double(object_ref const &o); - bool is_big_decimal(object_ref const o); - obj::big_decimal_ref to_big_decimal(object_ref const o); + bool is_big_decimal(object_ref const &o); + obj::big_decimal_ref to_big_decimal(object_ref const &o); } diff --git a/compiler+runtime/include/cpp/jank/runtime/core/meta.hpp b/compiler+runtime/include/cpp/jank/runtime/core/meta.hpp index 971ab226d..abc403ba9 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/meta.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/meta.hpp @@ -12,16 +12,16 @@ namespace jank::runtime using persistent_hash_map_ref = oref; } - object_ref meta(object_ref m); - object_ref with_meta(object_ref o, object_ref m); - object_ref with_meta_graceful(object_ref o, object_ref m); - object_ref reset_meta(object_ref o, object_ref m); + object_ref meta(object_ref const &m); + object_ref with_meta(object_ref const &o, object_ref const &m); + object_ref with_meta_graceful(object_ref const &o, object_ref const &m); + object_ref reset_meta(object_ref const &o, object_ref const &m); read::source meta_source(jtl::option const &o); - read::source object_source(object_ref const o); + read::source object_source(object_ref const &o); obj::persistent_hash_map_ref source_to_meta(read::source const &source); obj::persistent_hash_map_ref source_to_meta(read::source_position const &start, read::source_position const &end); - object_ref strip_source_from_meta(object_ref meta); + object_ref strip_source_from_meta(object_ref const &meta); jtl::option strip_source_from_meta_opt(jtl::option const &meta); } diff --git a/compiler+runtime/include/cpp/jank/runtime/core/munge.hpp b/compiler+runtime/include/cpp/jank/runtime/core/munge.hpp index 38e04cbd9..d20123ed9 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/munge.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/munge.hpp @@ -8,6 +8,6 @@ namespace jank::runtime jtl::immutable_string munge_and_replace(jtl::immutable_string const &o, jtl::immutable_string const &search, char const * const replace); - object_ref munge(object_ref o); + object_ref munge(object_ref const &o); jtl::immutable_string demunge(jtl::immutable_string const &o); } diff --git a/compiler+runtime/include/cpp/jank/runtime/core/seq.hpp b/compiler+runtime/include/cpp/jank/runtime/core/seq.hpp index 4622c1945..0e8ec1b66 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/seq.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/seq.hpp @@ -14,157 +14,157 @@ namespace jank::runtime template requires behavior::seqable - auto seq(jtl::ref const s) + auto seq(oref const &s) { return s->seq(); } - object_ref seq(object_ref s); + object_ref seq(object_ref const &s); template requires behavior::seqable - auto fresh_seq(jtl::ref const s) + auto fresh_seq(oref const &s) { return s->fresh_seq(); } - object_ref fresh_seq(object_ref s); + object_ref fresh_seq(object_ref const &s); template requires behavior::sequenceable - auto next(jtl::ref const s) + auto next(oref const &s) { return s->next(); } - object_ref next(object_ref s); + object_ref next(object_ref const &s); template requires behavior::sequenceable_in_place - auto next_in_place(jtl::ref const s) + auto next_in_place(oref const &s) { return s->next_in_place(); } template requires(behavior::sequenceable && !behavior::sequenceable_in_place) - auto next_in_place(jtl::ref const s) + auto next_in_place(oref const &s) { /* Not all sequences can be updated in place. For those, just gracefully * do a normal next. */ return s->next(); } - object_ref next_in_place(object_ref s); + object_ref next_in_place(object_ref const &s); - object_ref rest(object_ref s); + object_ref rest(object_ref const &s); template requires behavior::sequenceable - auto first(jtl::ref const s) + auto first(oref const &s) { return s->first(); } - object_ref first(object_ref s); + object_ref first(object_ref const &s); template requires behavior::sequenceable - auto second(jtl::ref const s) + auto second(oref const &s) { return next(s)->first(); } - object_ref second(object_ref s); - - bool is_empty(object_ref o); - bool is_seq(object_ref o); - bool is_sequential(object_ref o); - bool is_seqable(object_ref o); - bool is_collection(object_ref o); - bool is_list(object_ref o); - bool is_vector(object_ref o); - bool is_map(object_ref o); - bool is_associative(object_ref o); - bool is_set(object_ref o); - bool is_counted(object_ref o); - bool is_transientable(object_ref o); - bool is_sorted(object_ref o); - - object_ref transient(object_ref o); - object_ref persistent(object_ref o); - object_ref conj_in_place(object_ref coll, object_ref o); - object_ref disj_in_place(object_ref coll, object_ref o); + object_ref second(object_ref const &s); + + bool is_empty(object_ref const &o); + bool is_seq(object_ref const &o); + bool is_sequential(object_ref const &o); + bool is_seqable(object_ref const &o); + bool is_collection(object_ref const &o); + bool is_list(object_ref const &o); + bool is_vector(object_ref const &o); + bool is_map(object_ref const &o); + bool is_associative(object_ref const &o); + bool is_set(object_ref const &o); + bool is_counted(object_ref const &o); + bool is_transientable(object_ref const &o); + bool is_sorted(object_ref const &o); + + object_ref transient(object_ref const &o); + object_ref persistent(object_ref const &o); + object_ref conj_in_place(object_ref const &coll, object_ref const &o); + object_ref disj_in_place(object_ref const &coll, object_ref const &o); template requires behavior::associatively_writable_in_place - auto assoc_in_place(oref const m, object_ref const k, object_ref const v) + auto assoc_in_place(oref const &m, object_ref const &k, object_ref const &v) { return m->assoc_in_place(k, v); } - object_ref assoc_in_place(object_ref coll, object_ref k, object_ref v); - object_ref dissoc_in_place(object_ref coll, object_ref k); - object_ref pop_in_place(object_ref coll); + object_ref assoc_in_place(object_ref const &coll, object_ref const &k, object_ref const &v); + object_ref dissoc_in_place(object_ref const &coll, object_ref const &k); + object_ref pop_in_place(object_ref const &coll); - object_ref cons(object_ref head, object_ref tail); - object_ref conj(object_ref s, object_ref o); - object_ref disj(object_ref s, object_ref o); + object_ref cons(object_ref const &head, object_ref const &tail); + object_ref conj(object_ref const &s, object_ref const &o); + object_ref disj(object_ref const &s, object_ref const &o); template requires behavior::associatively_writable - auto assoc(oref const m, object_ref const k, object_ref const v) + auto assoc(oref const &m, object_ref const &k, object_ref const &v) { return m->assoc(k, v); } - object_ref assoc(object_ref m, object_ref k, object_ref v); - object_ref dissoc(object_ref m, object_ref k); - object_ref get(object_ref m, object_ref key); - object_ref get(object_ref m, object_ref key, object_ref fallback); - object_ref get_in(object_ref m, object_ref keys); - object_ref get_in(object_ref m, object_ref keys, object_ref fallback); - object_ref find(object_ref s, object_ref key); - bool contains(object_ref s, object_ref key); - object_ref merge(object_ref m, object_ref other); - object_ref merge_in_place(object_ref m, object_ref other); - object_ref subvec(object_ref o, i64 start, i64 end); - object_ref nth(object_ref o, object_ref idx); - object_ref nth(object_ref o, object_ref idx, object_ref fallback); - object_ref peek(object_ref o); - object_ref pop(object_ref o); - object_ref empty(object_ref o); - - jtl::immutable_string str(object_ref o); - jtl::immutable_string str(object_ref o, object_ref args); - - obj::persistent_list_ref list(object_ref s); - obj::persistent_vector_ref vec(object_ref s); - - bool sequence_equal(object_ref l, object_ref r); - - usize sequence_length(object_ref const s); - usize sequence_length(object_ref const s, usize const max); - - object_ref reduce(object_ref f, object_ref init, object_ref s); - object_ref reduced(object_ref o); - bool is_reduced(object_ref o); - - object_ref chunk_buffer(object_ref capacity); - object_ref chunk_append(object_ref buff, object_ref val); - object_ref chunk(object_ref buff); - object_ref chunk_first(object_ref o); - object_ref chunk_next(object_ref o); - object_ref chunk_rest(object_ref o); - object_ref chunk_cons(object_ref chunk, object_ref rest); - bool is_chunked_seq(object_ref o); - - object_ref iterate(object_ref fn, object_ref o); - - object_ref repeat(object_ref val); - object_ref repeat(object_ref n, object_ref val); - - object_ref sort(object_ref coll); - - object_ref shuffle(object_ref coll); + object_ref assoc(object_ref const &m, object_ref const &k, object_ref const &v); + object_ref dissoc(object_ref const &m, object_ref const &k); + object_ref get(object_ref const &m, object_ref const &key); + object_ref get(object_ref const &m, object_ref const &key, object_ref const &fallback); + object_ref get_in(object_ref const &m, object_ref const &keys); + object_ref get_in(object_ref const &m, object_ref const &keys, object_ref const &fallback); + object_ref find(object_ref const &s, object_ref const &key); + bool contains(object_ref const &s, object_ref const &key); + object_ref merge(object_ref const &m, object_ref const &other); + object_ref merge_in_place(object_ref const &m, object_ref const &other); + object_ref subvec(object_ref const &o, i64 start, i64 end); + object_ref nth(object_ref const &o, object_ref const &idx); + object_ref nth(object_ref const &o, object_ref const &idx, object_ref const &fallback); + object_ref peek(object_ref const &o); + object_ref pop(object_ref const &o); + object_ref empty(object_ref const &o); + + jtl::immutable_string str(object_ref const &o); + jtl::immutable_string str(object_ref const &o, object_ref const &args); + + obj::persistent_list_ref list(object_ref const &s); + obj::persistent_vector_ref vec(object_ref const &s); + + bool sequence_equal(object_ref const &l, object_ref const &r); + + usize sequence_length(object_ref const &s); + usize sequence_length(object_ref const &s, usize const max); + + object_ref reduce(object_ref const &f, object_ref const &init, object_ref const &s); + object_ref reduced(object_ref const &o); + bool is_reduced(object_ref const &o); + + object_ref chunk_buffer(object_ref const &capacity); + object_ref chunk_append(object_ref const &buff, object_ref const &val); + object_ref chunk(object_ref const &buff); + object_ref chunk_first(object_ref const &o); + object_ref chunk_next(object_ref const &o); + object_ref chunk_rest(object_ref const &o); + object_ref chunk_cons(object_ref const &chunk, object_ref const &rest); + bool is_chunked_seq(object_ref const &o); + + object_ref iterate(object_ref const &fn, object_ref const &o); + + object_ref repeat(object_ref const &val); + object_ref repeat(object_ref const &n, object_ref const &val); + + object_ref sort(object_ref const &coll); + + object_ref shuffle(object_ref const &coll); } diff --git a/compiler+runtime/include/cpp/jank/runtime/core/seq_ext.hpp b/compiler+runtime/include/cpp/jank/runtime/core/seq_ext.hpp index 4ec98e53e..89bf6fa78 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/seq_ext.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/seq_ext.hpp @@ -10,11 +10,11 @@ namespace jank::runtime { template - bool equal(object const &o, It const begin, It const end) + bool equal(object const &o, It const &begin, It const &end) { return visit_seqable( - [](auto const typed_o, auto const begin, auto const end) -> bool { - using T = typename decltype(typed_o)::value_type; + [](auto const &typed_o, auto const &begin, auto const &end) -> bool { + using T = typename jtl::decay_t::value_type; /* nil is seqable, but we don't want it to be equal to an empty collection. An empty seq itself is nil, but that's different. */ @@ -45,7 +45,7 @@ namespace jank::runtime template requires behavior::sequenceable - auto rest(oref const seq) + auto rest(oref const &seq) { if(seq.is_nil()) { diff --git a/compiler+runtime/include/cpp/jank/runtime/core/to_string.hpp b/compiler+runtime/include/cpp/jank/runtime/core/to_string.hpp index 1e1860d0e..4b8ddba51 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/to_string.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/to_string.hpp @@ -5,20 +5,20 @@ namespace jank::runtime { - object_ref first(object_ref s); - object_ref next(object_ref s); + object_ref first(object_ref const &s); + object_ref next(object_ref const &s); jtl::immutable_string to_string(weak_object_ref const o); void to_string(char ch, jtl::string_builder &buff); - void to_string(object_ref o, jtl::string_builder &buff); + void to_string(object_ref const &o, jtl::string_builder &buff); - jtl::immutable_string to_code_string(object_ref const o); + jtl::immutable_string to_code_string(object_ref const &o); void to_code_string(char ch, jtl::string_builder &buff); - void to_code_string(object_ref o, jtl::string_builder &buff); + void to_code_string(object_ref const &o, jtl::string_builder &buff); template requires(behavior::object_like && !behavior::sequenceable) - void to_string(oref const s, jtl::string_builder &buff) + void to_string(oref const &s, jtl::string_builder &buff) { s->to_string(buff); } @@ -48,7 +48,7 @@ namespace jank::runtime template requires behavior::sequenceable - void to_string(oref const s, jtl::string_builder &buff) + void to_string(oref const &s, jtl::string_builder &buff) { if(s.is_nil()) { @@ -87,7 +87,7 @@ namespace jank::runtime template requires behavior::sequenceable - jtl::immutable_string to_string(oref const s) + jtl::immutable_string to_string(oref const &s) { jtl::string_builder buff; runtime::to_string(s, buff); @@ -96,7 +96,7 @@ namespace jank::runtime template requires(behavior::object_like && !behavior::sequenceable) - void to_code_string(oref const s, jtl::string_builder &buff) + void to_code_string(oref const &s, jtl::string_builder &buff) { buff(s->to_code_string()); } @@ -126,7 +126,7 @@ namespace jank::runtime template requires behavior::sequenceable - void to_code_string(oref const s, jtl::string_builder &buff) + void to_code_string(oref const &s, jtl::string_builder &buff) { if(s.is_nil()) { @@ -165,7 +165,7 @@ namespace jank::runtime template requires behavior::sequenceable - jtl::immutable_string to_code_string(oref const s) + jtl::immutable_string to_code_string(oref const &s) { jtl::string_builder buff; runtime::to_code_string(s, buff); diff --git a/compiler+runtime/include/cpp/jank/runtime/core/truthy.hpp b/compiler+runtime/include/cpp/jank/runtime/core/truthy.hpp index 4eccaa19a..0ee4d0e41 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/truthy.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/truthy.hpp @@ -6,9 +6,9 @@ namespace jank::runtime { bool truthy(object const *o); - bool truthy(object_ref o); - bool truthy(obj::nil_ref); - bool truthy(obj::boolean_ref const o); + bool truthy(object_ref const &o); + bool truthy(obj::nil_ref const &); + bool truthy(obj::boolean_ref const &o); bool truthy(bool const o); template diff --git a/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp b/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp index f9aaaaea6..d08e06f09 100644 --- a/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp @@ -37,13 +37,13 @@ namespace jank::runtime::detail ~native_array_map(); - void insert_unique(object_ref const key, object_ref const val); + void insert_unique(object_ref const &key, object_ref const &val); - void insert_or_assign(object_ref const key, object_ref const val); + void insert_or_assign(object_ref const &key, object_ref const &val); - void erase(object_ref const key); + void erase(object_ref const &key); - jtl::option find(object_ref const key) const; + jtl::option find(object_ref const &key) const; uhash to_hash() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/detail/type.hpp b/compiler+runtime/include/cpp/jank/runtime/detail/type.hpp index a115e6602..b22808aa4 100644 --- a/compiler+runtime/include/cpp/jank/runtime/detail/type.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/detail/type.hpp @@ -15,7 +15,7 @@ namespace jank::runtime::detail { struct object_ref_compare { - bool operator()(object_ref const l, object_ref const r) const; + bool operator()(object_ref const &l, object_ref const &r) const; }; } diff --git a/compiler+runtime/include/cpp/jank/runtime/ns.hpp b/compiler+runtime/include/cpp/jank/runtime/ns.hpp index a3fce0e48..f985f5ce3 100644 --- a/compiler+runtime/include/cpp/jank/runtime/ns.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/ns.hpp @@ -21,20 +21,21 @@ namespace jank::runtime static constexpr bool pointer_free{ false }; ns() = delete; - ns(obj::symbol_ref const name); + ns(obj::symbol_ref const &name); var_ref intern_var(jtl::immutable_string_view const &); - var_ref intern_var(obj::symbol_ref); + var_ref intern_var(obj::symbol_ref const &); var_ref intern_owned_var(jtl::immutable_string_view const &); - var_ref intern_owned_var(obj::symbol_ref); - var_ref find_var(obj::symbol_ref); - jtl::result unmap(obj::symbol_ref sym); + var_ref intern_owned_var(obj::symbol_ref const &); + var_ref find_var(obj::symbol_ref const &); + jtl::result unmap(obj::symbol_ref const &sym); - jtl::result add_alias(obj::symbol_ref sym, ns_ref ns); - void remove_alias(obj::symbol_ref sym); - ns_ref find_alias(obj::symbol_ref sym) const; + jtl::result + add_alias(obj::symbol_ref const &sym, ns_ref const &ns); + void remove_alias(obj::symbol_ref const &sym); + ns_ref find_alias(obj::symbol_ref const &sym) const; - jtl::result refer(obj::symbol_ref sym, var_ref var); + jtl::result refer(obj::symbol_ref const &sym, var_ref const &var); obj::persistent_hash_map_ref get_mappings() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/array_chunk.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/array_chunk.hpp index 7e32d9d1d..4af7cfd89 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/array_chunk.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/array_chunk.hpp @@ -27,8 +27,8 @@ namespace jank::runtime::obj array_chunk_ref chunk_next() const; array_chunk_ref chunk_next_in_place(); usize count() const; - object_ref nth(object_ref index) const; - object_ref nth(object_ref index, object_ref fallback) const; + object_ref nth(object_ref const &index) const; + object_ref nth(object_ref const &index, object_ref const &fallback) const; object base{ obj_type }; native_vector buffer; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp index 8048dc0fa..7969fd0f1 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp @@ -16,7 +16,7 @@ namespace jank::runtime::obj static constexpr bool pointer_free{ false }; atom() = default; - atom(object_ref o); + atom(object_ref const &o); ~atom(); /* behavior::object_like */ @@ -30,27 +30,32 @@ namespace jank::runtime::obj object_ref deref() const; /* Replaces the old value with the specified value. Returns the new value. */ - object_ref reset(object_ref o); + object_ref reset(object_ref const &o); /* Same as reset, but returns a vector of the old value and the new value. */ - persistent_vector_ref reset_vals(object_ref o); + persistent_vector_ref reset_vals(object_ref const &o); /* Atomically updates the value of the atom with the specified fn. Returns the new value. */ - object_ref swap(object_ref fn); - object_ref swap(object_ref fn, object_ref a1); - object_ref swap(object_ref fn, object_ref a1, object_ref a2); - object_ref swap(object_ref fn, object_ref a1, object_ref a2, object_ref rest); + object_ref swap(object_ref const &fn); + object_ref swap(object_ref const &fn, object_ref const &a1); + object_ref swap(object_ref const &fn, object_ref const &a1, object_ref const &a2); + object_ref + swap(object_ref const &fn, object_ref const &a1, object_ref const &a2, object_ref const &rest); /* Same as swap, but returns a vector of the old value and the new value. */ - persistent_vector_ref swap_vals(object_ref fn); - persistent_vector_ref swap_vals(object_ref fn, object_ref a1); - persistent_vector_ref swap_vals(object_ref fn, object_ref a1, object_ref a2); - persistent_vector_ref swap_vals(object_ref fn, object_ref a1, object_ref a2, object_ref rest); + persistent_vector_ref swap_vals(object_ref const &fn); + persistent_vector_ref swap_vals(object_ref const &fn, object_ref const &a1); + persistent_vector_ref + swap_vals(object_ref const &fn, object_ref const &a1, object_ref const &a2); + persistent_vector_ref swap_vals(object_ref const &fn, + object_ref const &a1, + object_ref const &a2, + object_ref const &rest); - object_ref compare_and_set(object_ref old_val, object_ref new_val); + object_ref compare_and_set(object_ref const &old_val, object_ref const &new_val); /* behavior::ref_like */ - void add_watch(object_ref key, object_ref fn); - void remove_watch(object_ref key); + void add_watch(object_ref const &key, object_ref const &fn); + void remove_watch(object_ref const &key); object base{ obj_type }; /* We have to hold only a raw pointer here, since std::atomic doesn't diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/chunk_buffer.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/chunk_buffer.hpp index f75a23213..106496bae 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/chunk_buffer.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/chunk_buffer.hpp @@ -14,7 +14,7 @@ namespace jank::runtime::obj chunk_buffer() = default; chunk_buffer(usize capacity); - chunk_buffer(object_ref capacity); + chunk_buffer(object_ref const &capacity); /* behavior::object_like */ bool equal(object const &) const; @@ -26,7 +26,7 @@ namespace jank::runtime::obj /* behavior::countable */ usize count() const; - void append(object_ref o); + void append(object_ref const &o); obj::array_chunk_ref chunk(); object base{ obj_type }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/chunked_cons.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/chunked_cons.hpp index 18c715ff7..d033ada83 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/chunked_cons.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/chunked_cons.hpp @@ -18,8 +18,8 @@ namespace jank::runtime::obj chunked_cons() = default; chunked_cons(chunked_cons &&) noexcept = default; chunked_cons(chunked_cons const &) = default; - chunked_cons(object_ref head, object_ref tail); - chunked_cons(object_ref meta, object_ref head, object_ref tail); + chunked_cons(object_ref const &head, object_ref const &tail); + chunked_cons(object_ref const &meta, object_ref const &head, object_ref const &tail); /* behavior::object_like */ bool equal(object const &) const; @@ -29,7 +29,7 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - chunked_cons_ref with_meta(object_ref m) const; + chunked_cons_ref with_meta(object_ref const &m) const; /* behavior::seqable */ chunked_cons_ref seq() const; @@ -38,7 +38,7 @@ namespace jank::runtime::obj /* behavior::sequenceable */ object_ref first() const; object_ref next() const; - obj::cons_ref conj(object_ref head) const; + obj::cons_ref conj(object_ref const &head) const; /* behavior::sequenceable_in_place */ chunked_cons_ref next_in_place(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/cons.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/cons.hpp index cc71746f2..2fb461bb1 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/cons.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/cons.hpp @@ -17,7 +17,7 @@ namespace jank::runtime::obj cons() = default; cons(cons &&) noexcept = default; cons(cons const &) = default; - cons(object_ref const head, object_ref const tail); + cons(object_ref const &head, object_ref const &tail); /* behavior::object_like */ bool equal(object const &) const; @@ -27,7 +27,7 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - cons_ref with_meta(object_ref m) const; + cons_ref with_meta(object_ref const &m) const; /* behavior::seqable */ cons_ref seq() const; @@ -38,7 +38,7 @@ namespace jank::runtime::obj object_ref next() const; /* behavior::conjable */ - cons_ref conj(object_ref head) const; + cons_ref conj(object_ref const &head) const; object base{ obj_type }; object_ref head{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/delay.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/delay.hpp index 5895a636e..2415504b9 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/delay.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/delay.hpp @@ -12,7 +12,7 @@ namespace jank::runtime::obj static constexpr bool pointer_free{ false }; delay() = default; - delay(object_ref fn); + delay(object_ref const &fn); /* behavior::object_like */ bool equal(object const &) const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map.hpp index 5b34aef6c..85f55f6c5 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map.hpp @@ -6,14 +6,14 @@ namespace jank::runtime { - bool is_map(object_ref o); - bool equal(object_ref l, object_ref r); - void to_string(object_ref o, jtl::string_builder &buff); - void to_code_string(object_ref o, jtl::string_builder &buff); + bool is_map(object_ref const &o); + bool equal(object_ref const &l, object_ref const &r); + void to_string(object_ref const &o, jtl::string_builder &buff); + void to_code_string(object_ref const &o, jtl::string_builder &buff); namespace behavior::detail { - object_ref validate_meta(object_ref const m); + object_ref validate_meta(object_ref const &m); } } @@ -52,10 +52,10 @@ namespace jank::runtime::obj::detail usize count() const; /* behavior::metadatable */ - oref with_meta(object_ref const m) const; + oref with_meta(object_ref const &m) const; /* behavior::conjable */ - object_ref conj(object_ref const head) const; + object_ref conj(object_ref const &head) const; object base{ PT::obj_type }; jtl::option meta; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.hpp index 477110412..8f7536efe 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.hpp @@ -5,8 +5,8 @@ namespace jank::runtime { - void to_string(object_ref o, jtl::string_builder &buff); - void to_code_string(object_ref o, jtl::string_builder &buff); + void to_string(object_ref const &o, jtl::string_builder &buff); + void to_code_string(object_ref const &o, jtl::string_builder &buff); namespace obj { @@ -25,7 +25,7 @@ namespace jank::runtime::obj::detail base_persistent_map_sequence() = default; base_persistent_map_sequence(base_persistent_map_sequence &&) = default; base_persistent_map_sequence(base_persistent_map_sequence const &) = default; - base_persistent_map_sequence(object_ref const c, IT const &b, IT const &e); + base_persistent_map_sequence(object_ref const &c, IT const &b, IT const &e); /* behavior::object_like */ bool equal(object const &o) const; @@ -50,7 +50,7 @@ namespace jank::runtime::obj::detail oref next_in_place(); /* behavior::conjable */ - obj::cons_ref conj(object_ref const head); + obj::cons_ref conj(object_ref const &head); object base{ PT::obj_type }; object_ref coll{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/detail/iterator_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/detail/iterator_sequence.hpp index 6dc8f22f4..63bf373e3 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/detail/iterator_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/detail/iterator_sequence.hpp @@ -41,7 +41,7 @@ namespace jank::runtime::obj::detail oref next_in_place(); /* behavior::conjable */ - obj::cons_ref conj(object_ref const head); + obj::cons_ref conj(object_ref const &head); object_ref coll{}; /* Not default constructible. */ diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/integer_range.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/integer_range.hpp index 45b99a23a..0128138c6 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/integer_range.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/integer_range.hpp @@ -18,18 +18,20 @@ namespace jank::runtime::obj static constexpr bool pointer_free{ false }; static constexpr bool is_sequential{ true }; - using bounds_check_t = bool (*)(integer_ref, integer_ref); + using bounds_check_t = bool (*)(integer_ref const &, integer_ref const &); /* Constructors are only to be used within integer_range.cpp. Prefer integer_range::create. */ integer_range() = default; integer_range(integer_range &&) noexcept = default; integer_range(integer_range const &) = default; - integer_range(integer_ref end); - integer_range(integer_ref start, obj::integer_ref end); - integer_range(integer_ref start, obj::integer_ref end, obj::integer_ref step); - integer_range(integer_ref start, - integer_ref end, - integer_ref step, + integer_range(integer_ref const &end); + integer_range(integer_ref const &start, obj::integer_ref const &end); + integer_range(integer_ref const &start, + obj::integer_ref const &end, + obj::integer_ref const &step); + integer_range(integer_ref const &start, + integer_ref const &end, + integer_ref const &step, bounds_check_t bounds_check); //integer_range(integer_ptr start, // integer_ptr end, @@ -38,9 +40,10 @@ namespace jank::runtime::obj // array_chunk_ptr chunk, // integer_range_ptr chunk_next); - static object_ref create(integer_ref end); - static object_ref create(integer_ref start, obj::integer_ref end); - static object_ref create(integer_ref start, obj::integer_ref end, obj::integer_ref step); + static object_ref create(integer_ref const &end); + static object_ref create(integer_ref const &start, obj::integer_ref const &end); + static object_ref + create(integer_ref const &start, obj::integer_ref const &end, obj::integer_ref const &step); /* behavior::object_like */ bool equal(object const &) const; @@ -66,10 +69,10 @@ namespace jank::runtime::obj /* void force_chunk() const; */ /* behavior::conjable */ - cons_ref conj(object_ref head) const; + cons_ref conj(object_ref const &head) const; /* behavior::metadatable */ - integer_range_ref with_meta(object_ref m) const; + integer_range_ref with_meta(object_ref const &m) const; /* behavior::countable */ usize count() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/iterator.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/iterator.hpp index 7f6aff14e..048d25256 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/iterator.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/iterator.hpp @@ -18,7 +18,7 @@ namespace jank::runtime::obj iterator() = default; iterator(iterator &&) noexcept = default; iterator(iterator const &) = default; - iterator(object_ref const fn, object_ref const start); + iterator(object_ref const &fn, object_ref const &start); /* behavior::object_like */ bool equal(object const &) const; @@ -34,7 +34,7 @@ namespace jank::runtime::obj /* behavior::sequenceable */ object_ref first() const; iterator_ref next() const; - obj::cons_ref conj(object_ref head) const; + obj::cons_ref conj(object_ref const &head) const; /* behavior::sequenceable_in_place */ iterator_ref next_in_place(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp index 4305b027e..52818d2e8 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp @@ -16,7 +16,7 @@ namespace jank::runtime::obj jit_closure(jit_closure &&) noexcept = default; jit_closure(jit_closure const &) = default; jit_closure(arity_flag_t arity_flags, void *context); - jit_closure(object_ref meta); + jit_closure(object_ref const &meta); /* behavior::object_like */ bool equal(object const &) const; @@ -26,46 +26,60 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - jit_closure_ref with_meta(object_ref m); + jit_closure_ref with_meta(object_ref const &m); /* behavior::callable */ object_ref call() final; - object_ref call(object_ref) final; - object_ref call(object_ref, object_ref) final; - object_ref call(object_ref, object_ref, object_ref) final; - object_ref call(object_ref, object_ref, object_ref, object_ref) final; - object_ref call(object_ref, object_ref, object_ref, object_ref, object_ref) final; - object_ref call(object_ref, object_ref, object_ref, object_ref, object_ref, object_ref) final; + object_ref call(object_ref const &) final; + object_ref call(object_ref const &, object_ref const &) final; + object_ref call(object_ref const &, object_ref const &, object_ref const &) final; object_ref - call(object_ref, object_ref, object_ref, object_ref, object_ref, object_ref, object_ref) - final; - object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) final; - object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) final; - object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) final; + call(object_ref const &, object_ref const &, object_ref const &, object_ref const &) final; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) final; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) final; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) final; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) final; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) final; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) final; arity_flag_t get_arity_flags() const final; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp index 312f031e6..9773e80c2 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp @@ -16,7 +16,7 @@ namespace jank::runtime::obj jit_function(jit_function &&) noexcept = default; jit_function(jit_function const &) = default; jit_function(arity_flag_t arity_flags); - jit_function(object_ref meta); + jit_function(object_ref const &meta); /* behavior::object_like */ bool equal(object const &) const; @@ -26,47 +26,60 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - jit_function_ref with_meta(object_ref m); + jit_function_ref with_meta(object_ref const &m); /* behavior::callable */ object_ref call() override; - object_ref call(object_ref) override; - object_ref call(object_ref, object_ref) override; - object_ref call(object_ref, object_ref, object_ref) override; - object_ref call(object_ref, object_ref, object_ref, object_ref) override; - object_ref call(object_ref, object_ref, object_ref, object_ref, object_ref) override; + object_ref call(object_ref const &) override; + object_ref call(object_ref const &, object_ref const &) override; + object_ref call(object_ref const &, object_ref const &, object_ref const &) override; object_ref - call(object_ref, object_ref, object_ref, object_ref, object_ref, object_ref) override; - object_ref - call(object_ref, object_ref, object_ref, object_ref, object_ref, object_ref, object_ref) - override; - object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) override; - object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) override; - object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) override; + call(object_ref const &, object_ref const &, object_ref const &, object_ref const &) override; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) override; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) override; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) override; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) override; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) override; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) override; arity_flag_t get_arity_flags() const override; object_ref this_object_ref() override; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp index 06c62feb4..ebfc65eef 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp @@ -40,8 +40,8 @@ namespace jank::runtime::obj jtl::immutable_string const &get_namespace() const; /* behavior::callable */ - object_ref call(object_ref); - object_ref call(object_ref, object_ref); + object_ref call(object_ref const &); + object_ref call(object_ref const &, object_ref const &); bool operator==(keyword const &rhs) const; @@ -58,7 +58,7 @@ namespace std template <> struct hash { - size_t operator()(jank::runtime::obj::keyword_ref const o) const noexcept + size_t operator()(jank::runtime::obj::keyword_ref const &o) const noexcept { return o->to_hash(); } diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/lazy_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/lazy_sequence.hpp index 779ae78df..4172b6da1 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/lazy_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/lazy_sequence.hpp @@ -20,8 +20,8 @@ namespace jank::runtime::obj lazy_sequence() = default; lazy_sequence(lazy_sequence &&) noexcept = default; lazy_sequence(lazy_sequence const &) = default; - lazy_sequence(object_ref fn); - lazy_sequence(object_ref fn, object_ref sequence); + lazy_sequence(object_ref const &fn); + lazy_sequence(object_ref const &fn, object_ref const &sequence); /* behavior::object_like */ bool equal(object const &) const; @@ -37,13 +37,13 @@ namespace jank::runtime::obj /* behavior::sequenceable */ object_ref first() const; object_ref next() const; - obj::cons_ref conj(object_ref head) const; + obj::cons_ref conj(object_ref const &head) const; /* behavior::sequenceable_in_place */ //lazy_sequence_ref next_in_place(); /* behavior::metadatable */ - lazy_sequence_ref with_meta(object_ref m) const; + lazy_sequence_ref with_meta(object_ref const &m) const; private: object_ref resolve_fn() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp index a3424a0f2..3f4de87c2 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp @@ -17,7 +17,10 @@ namespace jank::runtime::obj static constexpr bool pointer_free{ false }; multi_function() = delete; - multi_function(object_ref name, object_ref dispatch, object_ref default_, object_ref hierarchy); + multi_function(object_ref const &name, + object_ref const &dispatch, + object_ref const &default_, + object_ref const &hierarchy); /* behavior::object_like */ bool equal(object const &) const; @@ -28,58 +31,71 @@ namespace jank::runtime::obj /* behavior::callable */ object_ref call() override; - object_ref call(object_ref) override; - object_ref call(object_ref, object_ref) override; - object_ref call(object_ref, object_ref, object_ref) override; - object_ref call(object_ref, object_ref, object_ref, object_ref) override; - object_ref call(object_ref, object_ref, object_ref, object_ref, object_ref) override; + object_ref call(object_ref const &) override; + object_ref call(object_ref const &, object_ref const &) override; + object_ref call(object_ref const &, object_ref const &, object_ref const &) override; object_ref - call(object_ref, object_ref, object_ref, object_ref, object_ref, object_ref) override; - object_ref - call(object_ref, object_ref, object_ref, object_ref, object_ref, object_ref, object_ref) - override; - object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) override; - object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) override; - object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) override; + call(object_ref const &, object_ref const &, object_ref const &, object_ref const &) override; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) override; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) override; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) override; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) override; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) override; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) override; object_ref this_object_ref() final; multi_function_ref reset(); persistent_hash_map_ref reset_cache(); - multi_function_ref add_method(object_ref dispatch_val, object_ref method); - multi_function_ref remove_method(object_ref dispatch_val); - multi_function_ref prefer_method(object_ref x, object_ref y); - bool is_preferred(object_ref hierarchy, object_ref x, object_ref y) const; + multi_function_ref add_method(object_ref const &dispatch_val, object_ref const &method); + multi_function_ref remove_method(object_ref const &dispatch_val); + multi_function_ref prefer_method(object_ref const &x, object_ref const &y); + bool is_preferred(object_ref const &hierarchy, object_ref const &x, object_ref const &y) const; - static bool is_a(object_ref hierarchy, object_ref x, object_ref y); - bool is_dominant(object_ref hierarchy, object_ref x, object_ref y) const; + static bool is_a(object_ref const &hierarchy, object_ref const &x, object_ref const &y); + bool is_dominant(object_ref const &hierarchy, object_ref const &x, object_ref const &y) const; - object_ref get_fn(object_ref dispatch_val); - object_ref get_method(object_ref dispatch_val); - object_ref find_and_cache_best_method(object_ref dispatch_val); + object_ref get_fn(object_ref const &dispatch_val); + object_ref get_method(object_ref const &dispatch_val); + object_ref find_and_cache_best_method(object_ref const &dispatch_val); object base{ obj_type }; object_ref dispatch{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/native_array_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/native_array_sequence.hpp index bb623391d..f361fdd82 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/native_array_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/native_array_sequence.hpp @@ -20,7 +20,7 @@ namespace jank::runtime::obj native_array_sequence(object_ref * const arr, usize const index, usize const size); template - native_array_sequence(object_ref const first, Args const... rest) + native_array_sequence(object_ref const &first, Args const &...rest) : arr{ make_array_box(first, rest...) } , size{ sizeof...(Args) + 1 } { @@ -43,7 +43,7 @@ namespace jank::runtime::obj /* behavior::sequence */ object_ref first() const; native_array_sequence_ref next() const; - obj::cons_ref conj(object_ref head); + obj::cons_ref conj(object_ref const &head); /* behavior::sequenceable_in_place */ native_array_sequence_ref next_in_place(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp index 691729484..0396ee185 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp @@ -12,7 +12,7 @@ namespace jank::runtime { /* This must be constructed with a std::function object, since we need put it into a * std::any and pull it out based on how we call it. i.e. if we try to call it with - * one param, we try to grab it from the std::any as a std::function. + * one param, we try to grab it from the std::any as a std::function. * * This means you can't just dump a lambda into this. Build a std::function from it first. */ struct function_type @@ -84,79 +84,65 @@ namespace jank::runtime /* behavior::callable */ object_ref call() final; - object_ref call(object_ref) final; - object_ref call(object_ref, object_ref) final; - object_ref call(object_ref, object_ref, object_ref) final; - object_ref call(object_ref, object_ref, object_ref, object_ref) final; - object_ref call(object_ref, object_ref, object_ref, object_ref, object_ref) final; - object_ref call(object_ref, object_ref, object_ref, object_ref, object_ref, object_ref) final; + object_ref call(object_ref const &) final; + object_ref call(object_ref const &, object_ref const &) final; + object_ref call(object_ref const &, object_ref const &, object_ref const &) final; object_ref - call(object_ref, object_ref, object_ref, object_ref, object_ref, object_ref, object_ref) - final; - object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) final; - object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) final; - object_ref call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) final; + call(object_ref const &, object_ref const &, object_ref const &, object_ref const &) final; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) final; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) final; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) final; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) final; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) final; + object_ref call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) final; object_ref this_object_ref() final; /* behavior::metadatable */ - native_function_wrapper_ref with_meta(object_ref m) const; + native_function_wrapper_ref with_meta(object_ref const &m) const; object base{ obj_type }; obj::detail::function_type data{}; jtl::option meta; }; } - - namespace detail - { - /* TODO: Is this needed, given dynamic_call? */ - template - object_ref invoke(F const &f, Args &&...args) - { - if constexpr(std::is_function_v>>) - { - return f(std::forward(args)...); - } - else - { - auto const * const c((*f)->as_callable()); - - if(c) - { - return c->call(std::forward(args)...); - } - else - { - /* TODO: Better error. */ - std::cout << "(invoke) object is not callable: " << **f << std::endl; - throw std::runtime_error{ "object is not callable" }; - } - } - } - } } diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/native_vector_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/native_vector_sequence.hpp index 5455463e3..75c6e55d3 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/native_vector_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/native_vector_sequence.hpp @@ -40,13 +40,13 @@ namespace jank::runtime::obj /* behavior::sequence */ object_ref first() const; native_vector_sequence_ref next() const; - obj::cons_ref conj(object_ref head); + obj::cons_ref conj(object_ref const &head); /* behavior::sequenceable_in_place */ native_vector_sequence_ref next_in_place(); /* behavior::metadatable */ - native_vector_sequence_ref with_meta(object_ref const m) const; + native_vector_sequence_ref with_meta(object_ref const &m) const; object base{ obj_type }; native_vector data{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp index 486fbbf4c..f74e23e1e 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp @@ -30,14 +30,14 @@ namespace jank::runtime::obj i64 compare(nil const &) const; /* behavior::associatively_readable */ - object_ref get(object_ref const key); - object_ref get(object_ref const key, object_ref const fallback); - object_ref get_entry(object_ref key); - bool contains(object_ref key) const; + object_ref get(object_ref const &key); + object_ref get(object_ref const &key, object_ref const &fallback); + object_ref get_entry(object_ref const &key); + bool contains(object_ref const &key) const; /* behavior::associatively_writable */ - obj::persistent_array_map_ref assoc(object_ref key, object_ref val) const; - nil_ref dissoc(object_ref key) const; + obj::persistent_array_map_ref assoc(object_ref const &key, object_ref const &val) const; + nil_ref dissoc(object_ref const &key) const; /* behavior::seqable */ nil_ref seq(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/opaque_box.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/opaque_box.hpp index 9b846a2a3..2a324bfc1 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/opaque_box.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/opaque_box.hpp @@ -23,7 +23,7 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - opaque_box_ref with_meta(object_ref m); + opaque_box_ref with_meta(object_ref const &m); object base{ obj_type }; jtl::ptr data{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_array_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_array_map.hpp index fb698099e..12117b247 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_array_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_array_map.hpp @@ -36,7 +36,7 @@ namespace jank::runtime::obj } template - persistent_array_map(object_ref const meta, runtime::detail::in_place_unique, Args &&...args) + persistent_array_map(object_ref const &meta, runtime::detail::in_place_unique, Args &&...args) : data{ runtime::detail::in_place_unique{}, std::forward(args)... } { this->meta = meta; @@ -59,7 +59,7 @@ namespace jank::runtime::obj } template - static persistent_array_map_ref create_unique_with_meta(object_ref const meta, Args &&...args) + static persistent_array_map_ref create_unique_with_meta(object_ref const &meta, Args &&...args) { return make_box(meta, runtime::detail::in_place_unique{}, @@ -68,18 +68,18 @@ namespace jank::runtime::obj } /* behavior::associatively_readable */ - object_ref get(object_ref const key) const; - object_ref get(object_ref const key, object_ref const fallback) const; - object_ref get_entry(object_ref key) const; - bool contains(object_ref key) const; + object_ref get(object_ref const &key) const; + object_ref get(object_ref const &key, object_ref const &fallback) const; + object_ref get_entry(object_ref const &key) const; + bool contains(object_ref const &key) const; /* behavior::associatively_writable */ - object_ref assoc(object_ref key, object_ref val) const; - persistent_array_map_ref dissoc(object_ref key) const; + object_ref assoc(object_ref const &key, object_ref const &val) const; + persistent_array_map_ref dissoc(object_ref const &key) const; /* behavior::callable */ - object_ref call(object_ref) const; - object_ref call(object_ref, object_ref) const; + object_ref call(object_ref const &) const; + object_ref call(object_ref const &, object_ref const &) const; /* behavior::transientable */ transient_array_map_ref to_transient() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp index 53678455a..e1e8ba2fd 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp @@ -30,8 +30,8 @@ namespace jank::runtime::obj persistent_hash_map(persistent_hash_map const &) = default; persistent_hash_map(jtl::option const &meta, runtime::detail::native_array_map const &m, - object_ref key, - object_ref val); + object_ref const &key, + object_ref const &val); persistent_hash_map(value_type &&d); persistent_hash_map(value_type const &d); persistent_hash_map(jtl::option const &meta, value_type &&d); @@ -43,7 +43,7 @@ namespace jank::runtime::obj } template - persistent_hash_map(object_ref const meta, runtime::detail::in_place_unique, Args &&...args) + persistent_hash_map(object_ref const &meta, runtime::detail::in_place_unique, Args &&...args) : data{ std::forward(args)... } { this->meta = meta; @@ -61,28 +61,28 @@ namespace jank::runtime::obj } template - static persistent_hash_map_ref create_unique_with_meta(object_ref const meta, Args &&...pairs) + static persistent_hash_map_ref create_unique_with_meta(object_ref const &meta, Args &&...pairs) { return make_box(meta, runtime::detail::in_place_unique{}, std::forward(pairs)...); } - static persistent_hash_map_ref create_from_seq(object_ref const seq); + static persistent_hash_map_ref create_from_seq(object_ref const &seq); /* behavior::associatively_readable */ - object_ref get(object_ref const key) const; - object_ref get(object_ref const key, object_ref const fallback) const; - object_ref get_entry(object_ref key) const; - bool contains(object_ref key) const; + object_ref get(object_ref const &key) const; + object_ref get(object_ref const &key, object_ref const &fallback) const; + object_ref get_entry(object_ref const &key) const; + bool contains(object_ref const &key) const; /* behavior::associatively_writable */ - persistent_hash_map_ref assoc(object_ref key, object_ref val) const; - persistent_hash_map_ref dissoc(object_ref key) const; + persistent_hash_map_ref assoc(object_ref const &key, object_ref const &val) const; + persistent_hash_map_ref dissoc(object_ref const &key) const; /* behavior::callable */ - object_ref call(object_ref) const; - object_ref call(object_ref, object_ref) const; + object_ref call(object_ref const &) const; + object_ref call(object_ref const &, object_ref const &) const; /* behavior::transientable */ obj::transient_hash_map_ref to_transient() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp index 327e1c66a..b5c3c82f1 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp @@ -31,7 +31,7 @@ namespace jank::runtime::obj } template - persistent_hash_set(object_ref const meta, std::in_place_t, Args &&...args) + persistent_hash_set(object_ref const &meta, std::in_place_t, Args &&...args) : data{ std::forward(args)... } , meta{ meta } { @@ -39,7 +39,7 @@ namespace jank::runtime::obj static persistent_hash_set_ref empty(); - static persistent_hash_set_ref create_from_seq(object_ref const seq); + static persistent_hash_set_ref create_from_seq(object_ref const &seq); /* behavior::object_like */ bool equal(object const &) const; @@ -49,7 +49,7 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - persistent_hash_set_ref with_meta(object_ref m) const; + persistent_hash_set_ref with_meta(object_ref const &m) const; /* behavior::seqable */ obj::persistent_hash_set_sequence_ref seq() const; @@ -59,16 +59,16 @@ namespace jank::runtime::obj usize count() const; /* behavior::conjable */ - persistent_hash_set_ref conj(object_ref head) const; + persistent_hash_set_ref conj(object_ref const &head) const; /* behavior::callable */ - object_ref call(object_ref) const; + object_ref call(object_ref const &) const; /* behavior::transientable */ obj::transient_hash_set_ref to_transient() const; - bool contains(object_ref o) const; - persistent_hash_set_ref disj(object_ref o) const; + bool contains(object_ref const &o) const; + persistent_hash_set_ref disj(object_ref const &o) const; object base{ obj_type }; value_type data; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_list.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_list.hpp index 854314fbb..96bb4d599 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_list.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_list.hpp @@ -17,10 +17,10 @@ namespace jank::runtime::obj static constexpr bool is_sequential{ true }; /* Create from a sequence. */ - static persistent_list_ref create(object_ref meta, object_ref s); - static persistent_list_ref create(object_ref s); - static persistent_list_ref create(persistent_list_ref s); - static persistent_list_ref create(nil_ref s); + static persistent_list_ref create(object_ref const &meta, object_ref const &s); + static persistent_list_ref create(object_ref const &s); + static persistent_list_ref create(persistent_list_ref const &s); + static persistent_list_ref create(nil_ref const &s); persistent_list() = default; persistent_list(persistent_list &&) noexcept = default; @@ -37,7 +37,7 @@ namespace jank::runtime::obj } template - persistent_list(object_ref const meta, std::in_place_t, Args &&...args) + persistent_list(object_ref const &meta, std::in_place_t, Args &&...args) : data{ std::forward(args)... } , meta{ meta } { @@ -57,7 +57,7 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - persistent_list_ref with_meta(object_ref m) const; + persistent_list_ref with_meta(object_ref const &m) const; /* behavior::seqable */ obj::persistent_list_ref seq() const; @@ -67,7 +67,7 @@ namespace jank::runtime::obj usize count() const; /* behavior::conjable */ - persistent_list_ref conj(object_ref head) const; + persistent_list_ref conj(object_ref const &head) const; /* behavior::sequenceable */ object_ref first() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_map.hpp index d23242dfd..5df60095e 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_map.hpp @@ -28,7 +28,7 @@ namespace jank::runtime::obj persistent_sorted_map(persistent_sorted_map const &) = default; persistent_sorted_map(value_type &&d); persistent_sorted_map(value_type const &d); - persistent_sorted_map(object_ref meta, value_type &&d); + persistent_sorted_map(object_ref const &meta, value_type &&d); persistent_sorted_map(jtl::option const &meta, value_type &&d); template @@ -38,7 +38,7 @@ namespace jank::runtime::obj } template - persistent_sorted_map(object_ref const meta, runtime::detail::in_place_unique, Args &&...args) + persistent_sorted_map(object_ref const &meta, runtime::detail::in_place_unique, Args &&...args) : data{ std::forward(args)... } { this->meta = meta; @@ -56,28 +56,29 @@ namespace jank::runtime::obj } template - static persistent_sorted_map_ref create_unique_with_meta(object_ref const meta, Args &&...pairs) + static persistent_sorted_map_ref + create_unique_with_meta(object_ref const &meta, Args &&...pairs) { return make_box(meta, runtime::detail::in_place_unique{}, std::forward(pairs)...); } - static persistent_sorted_map_ref create_from_seq(object_ref const seq); + static persistent_sorted_map_ref create_from_seq(object_ref const &seq); /* behavior::associatively_readable */ - object_ref get(object_ref const key) const; - object_ref get(object_ref const key, object_ref const fallback) const; - object_ref get_entry(object_ref key) const; - bool contains(object_ref key) const; + object_ref get(object_ref const &key) const; + object_ref get(object_ref const &key, object_ref const &fallback) const; + object_ref get_entry(object_ref const &key) const; + bool contains(object_ref const &key) const; /* behavior::associatively_writable */ - persistent_sorted_map_ref assoc(object_ref key, object_ref val) const; - persistent_sorted_map_ref dissoc(object_ref key) const; + persistent_sorted_map_ref assoc(object_ref const &key, object_ref const &val) const; + persistent_sorted_map_ref dissoc(object_ref const &key) const; /* behavior::callable */ - object_ref call(object_ref) const; - object_ref call(object_ref, object_ref) const; + object_ref call(object_ref const &) const; + object_ref call(object_ref const &, object_ref const &) const; /* behavior::transientable */ obj::transient_sorted_map_ref to_transient() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp index ae3e2d7e9..2992e1ca8 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp @@ -22,7 +22,7 @@ namespace jank::runtime::obj persistent_sorted_set(persistent_sorted_set const &) = default; persistent_sorted_set(value_type &&d); persistent_sorted_set(value_type const &d); - persistent_sorted_set(object_ref meta, value_type &&d); + persistent_sorted_set(object_ref const &meta, value_type &&d); persistent_sorted_set(jtl::option const &meta, value_type &&d); template @@ -32,14 +32,14 @@ namespace jank::runtime::obj } template - persistent_sorted_set(object_ref const meta, std::in_place_t, Args &&...args) + persistent_sorted_set(object_ref const &meta, std::in_place_t, Args &&...args) : data{ std::forward(args)... } , meta{ meta } { } static persistent_sorted_set_ref empty(); - static persistent_sorted_set_ref create_from_seq(object_ref const seq); + static persistent_sorted_set_ref create_from_seq(object_ref const &seq); /* behavior::object_like */ bool equal(object const &) const; @@ -49,7 +49,7 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - persistent_sorted_set_ref with_meta(object_ref m) const; + persistent_sorted_set_ref with_meta(object_ref const &m) const; /* behavior::seqable */ persistent_sorted_set_sequence_ref seq() const; @@ -59,16 +59,16 @@ namespace jank::runtime::obj usize count() const; /* behavior::conjable */ - persistent_sorted_set_ref conj(object_ref head) const; + persistent_sorted_set_ref conj(object_ref const &head) const; /* behavior::callable */ - object_ref call(object_ref); + object_ref call(object_ref const &); /* behavior::transientable */ obj::transient_sorted_set_ref to_transient() const; - bool contains(object_ref o) const; - persistent_sorted_set_ref disj(object_ref o) const; + bool contains(object_ref const &o) const; + persistent_sorted_set_ref disj(object_ref const &o) const; object base{ obj_type }; value_type data; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string.hpp index 86533ccc9..003ee7ad1 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string.hpp @@ -40,22 +40,22 @@ namespace jank::runtime::obj i64 compare(persistent_string const &) const; /* behavior::associatively_readable */ - object_ref get(object_ref const key) const; - object_ref get(object_ref const key, object_ref const fallback) const; - object_ref get_entry(object_ref key) const; - bool contains(object_ref key) const; + object_ref get(object_ref const &key) const; + object_ref get(object_ref const &key, object_ref const &fallback) const; + object_ref get_entry(object_ref const &key) const; + bool contains(object_ref const &key) const; /* behavior::indexable */ - object_ref nth(object_ref const index) const; - object_ref nth(object_ref const index, object_ref const fallback) const; + object_ref nth(object_ref const &index) const; + object_ref nth(object_ref const &index, object_ref const &fallback) const; jtl::string_result substring(i64 start) const; jtl::string_result substring(i64 start, i64 end) const; /* Returns -1 when not found. Turns the arg into a string, so it accepts anything. * Searches for the whole string, not just a char. */ - i64 first_index_of(object_ref const m) const; - i64 last_index_of(object_ref const m) const; + i64 first_index_of(object_ref const &m) const; + i64 last_index_of(object_ref const &m) const; /* behavior::countable */ usize count() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string_sequence.hpp index d96219307..9ae98c584 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string_sequence.hpp @@ -17,8 +17,8 @@ namespace jank::runtime::obj persistent_string_sequence() = default; persistent_string_sequence(persistent_string_sequence &&) noexcept = default; persistent_string_sequence(persistent_string_sequence const &) = default; - persistent_string_sequence(obj::persistent_string_ref const s); - persistent_string_sequence(obj::persistent_string_ref const s, usize const i); + persistent_string_sequence(obj::persistent_string_ref const &s); + persistent_string_sequence(obj::persistent_string_ref const &s, usize const i); /* behavior::object_like */ bool equal(object const &) const; @@ -37,7 +37,7 @@ namespace jank::runtime::obj /* behavior::sequenceable */ object_ref first() const; persistent_string_sequence_ref next() const; - obj::cons_ref conj(object_ref head); + obj::cons_ref conj(object_ref const &head); /* behavior::sequenceable_in_place */ persistent_string_sequence_ref next_in_place(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp index 1b8d65f67..049eb089d 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp @@ -32,13 +32,13 @@ namespace jank::runtime::obj } template - persistent_vector(object_ref const meta, std::in_place_t, Args &&...args) + persistent_vector(object_ref const &meta, std::in_place_t, Args &&...args) : data{ std::forward(args)... } , meta{ meta } { } - static persistent_vector_ref create(object_ref s); + static persistent_vector_ref create(object_ref const &s); static persistent_vector_ref empty(); @@ -56,7 +56,7 @@ namespace jank::runtime::obj i64 compare(persistent_vector const &) const; /* behavior::metadatable */ - persistent_vector_ref with_meta(object_ref m) const; + persistent_vector_ref with_meta(object_ref const &m) const; /* behavior::seqable */ persistent_vector_sequence_ref seq() const; @@ -66,28 +66,28 @@ namespace jank::runtime::obj usize count() const; /* behavior::associatively_readable */ - object_ref get(object_ref key) const; - object_ref get(object_ref key, object_ref fallback) const; - object_ref get_entry(object_ref key) const; - bool contains(object_ref key) const; + object_ref get(object_ref const &key) const; + object_ref get(object_ref const &key, object_ref const &fallback) const; + object_ref get_entry(object_ref const &key) const; + bool contains(object_ref const &key) const; /* behavior::associatively_writable */ - persistent_vector_ref assoc(object_ref key, object_ref val) const; - persistent_vector_ref dissoc(object_ref key) const; + persistent_vector_ref assoc(object_ref const &key, object_ref const &val) const; + persistent_vector_ref dissoc(object_ref const &key) const; /* behavior::conjable */ - persistent_vector_ref conj(object_ref head) const; + persistent_vector_ref conj(object_ref const &head) const; /* behavior::stackable */ object_ref peek() const; persistent_vector_ref pop() const; /* behavior::indexable */ - object_ref nth(object_ref index) const; - object_ref nth(object_ref index, object_ref fallback) const; + object_ref nth(object_ref const &index) const; + object_ref nth(object_ref const &index, object_ref const &fallback) const; /* behavior::callable */ - object_ref call(object_ref) const; + object_ref call(object_ref const &) const; /* behavior::transientable */ obj::transient_vector_ref to_transient() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector_sequence.hpp index 6e529e8d5..300076146 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector_sequence.hpp @@ -17,8 +17,8 @@ namespace jank::runtime::obj persistent_vector_sequence() = default; persistent_vector_sequence(persistent_vector_sequence &&) noexcept = default; persistent_vector_sequence(persistent_vector_sequence const &) = default; - persistent_vector_sequence(obj::persistent_vector_ref v); - persistent_vector_sequence(obj::persistent_vector_ref v, usize i); + persistent_vector_sequence(obj::persistent_vector_ref const &v); + persistent_vector_sequence(obj::persistent_vector_ref const &v, usize i); /* behavior::object_like */ bool equal(object const &) const; @@ -37,7 +37,7 @@ namespace jank::runtime::obj /* behavior::sequenceable */ object_ref first() const; persistent_vector_sequence_ref next() const; - obj::cons_ref conj(object_ref head); + obj::cons_ref conj(object_ref const &head); /* behavior::sequenceable_in_place */ persistent_vector_sequence_ref next_in_place(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp index 245ffe046..5cf73e0c6 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp @@ -8,7 +8,7 @@ namespace jank::runtime::obj { using array_chunk_ref = oref; using cons_ref = oref; - using range_ptr = oref; + using range_ref = oref; /* A range from X to Y, exclusive, incrementing by S. This is for non-integer values. * For integer values, use integer_range. This is not countable in constant time, due @@ -20,26 +20,30 @@ namespace jank::runtime::obj static constexpr bool is_sequential{ true }; static constexpr i64 chunk_size{ 32 }; - using bounds_check_t = bool (*)(object_ref, object_ref); + using bounds_check_t = bool (*)(object_ref const &, object_ref const &); /* Constructors are only to be used within range.cpp. Prefer range::create. */ range() = default; range(range &&) noexcept = default; range(range const &) = default; - range(object_ref end); - range(object_ref start, object_ref end); - range(object_ref start, object_ref end, object_ref step); - range(object_ref start, object_ref end, object_ref step, bounds_check_t bounds_check); - range(object_ref start, - object_ref end, - object_ref step, + range(object_ref const &end); + range(object_ref const &start, object_ref const &end); + range(object_ref const &start, object_ref const &end, object_ref const &step); + range(object_ref const &start, + object_ref const &end, + object_ref const &step, + bounds_check_t bounds_check); + range(object_ref const &start, + object_ref const &end, + object_ref const &step, bounds_check_t bounds_check, - obj::array_chunk_ref chunk, - range_ptr chunk_next); + obj::array_chunk_ref const &chunk, + range_ref const &chunk_next); - static object_ref create(object_ref end); - static object_ref create(object_ref start, object_ref end); - static object_ref create(object_ref start, object_ref end, object_ref step); + static object_ref create(object_ref const &end); + static object_ref create(object_ref const &start, object_ref const &end); + static object_ref + create(object_ref const &start, object_ref const &end, object_ref const &step); /* behavior::object_like */ bool equal(object const &) const; @@ -49,26 +53,26 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::seqable */ - range_ptr seq(); - range_ptr fresh_seq() const; + range_ref seq(); + range_ref fresh_seq() const; /* behavior::sequenceable */ object_ref first() const; - range_ptr next() const; + range_ref next() const; /* behavior::sequenceable_in_place */ - range_ptr next_in_place(); + range_ref next_in_place(); /* behavior::chunkable */ obj::array_chunk_ref chunked_first() const; - range_ptr chunked_next() const; + range_ref chunked_next() const; void force_chunk() const; /* behavior::conjable */ - obj::cons_ref conj(object_ref head) const; + obj::cons_ref conj(object_ref const &head) const; /* behavior::metadatable */ - range_ptr with_meta(object_ref m) const; + range_ref with_meta(object_ref const &m) const; object base{ obj_type }; object_ref start{}; @@ -76,8 +80,8 @@ namespace jank::runtime::obj object_ref step{}; bounds_check_t bounds_check{}; mutable obj::array_chunk_ref chunk{}; - mutable range_ptr chunk_next{}; - mutable range_ptr cached_next{}; + mutable range_ref chunk_next{}; + mutable range_ref cached_next{}; jtl::option meta{}; }; } diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp index efe9d3214..66cacce3d 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp @@ -10,7 +10,7 @@ namespace jank::runtime::obj ratio_data(i64 const, i64 const); ratio_data(native_big_integer const &, native_big_integer const &); ratio_data(big_integer const &, big_integer const &); - ratio_data(object_ref, object_ref); + ratio_data(object_ref const &, object_ref const &); ratio_data(ratio_data const &) = default; f64 to_real() const; @@ -58,55 +58,55 @@ namespace jank::runtime::obj }; object_ref operator+(ratio_data const &l, ratio_data const &r); - ratio_ref operator+(integer_ref l, ratio_data const &r); - ratio_ref operator+(ratio_data const &l, integer_ref r); - f64 operator+(real_ref l, ratio_data const &r); - f64 operator+(ratio_data const &l, real_ref r); + ratio_ref operator+(integer_ref const &l, ratio_data const &r); + ratio_ref operator+(ratio_data const &l, integer_ref const &r); + f64 operator+(real_ref const &l, ratio_data const &r); + f64 operator+(ratio_data const &l, real_ref const &r); f64 operator+(ratio_data const &l, f64 r); f64 operator+(f64 l, ratio_data const &r); ratio_ref operator+(ratio_data const &l, i64 r); ratio_ref operator+(i64 l, ratio_data const &r); object_ref operator-(ratio_data const &l, ratio_data const &r); - ratio_ref operator-(integer_ref l, ratio_data const &r); - ratio_ref operator-(ratio_data const &l, integer_ref r); - f64 operator-(real_ref l, ratio_data const &r); - f64 operator-(ratio_data const &l, real_ref r); + ratio_ref operator-(integer_ref const &l, ratio_data const &r); + ratio_ref operator-(ratio_data const &l, integer_ref const &r); + f64 operator-(real_ref const &l, ratio_data const &r); + f64 operator-(ratio_data const &l, real_ref const &r); f64 operator-(ratio_data const &l, f64 r); f64 operator-(f64 l, ratio_data const &r); ratio_ref operator-(ratio_data const &l, i64 r); ratio_ref operator-(i64 l, ratio_data const &r); object_ref operator*(ratio_data const &l, ratio_data const &r); - object_ref operator*(integer_ref l, ratio_data const &r); - object_ref operator*(ratio_data const &l, integer_ref r); - f64 operator*(real_ref l, ratio_data const &r); - f64 operator*(ratio_data const &l, real_ref r); + object_ref operator*(integer_ref const &l, ratio_data const &r); + object_ref operator*(ratio_data const &l, integer_ref const &r); + f64 operator*(real_ref const &l, ratio_data const &r); + f64 operator*(ratio_data const &l, real_ref const &r); f64 operator*(ratio_data const &l, f64 r); f64 operator*(f64 l, ratio_data const &r); object_ref operator*(ratio_data const &l, i64 r); object_ref operator*(i64 l, ratio_data const &r); object_ref operator/(ratio_data const &l, ratio_data const &r); - object_ref operator/(integer_ref l, ratio_data const &r); - ratio_ref operator/(ratio_data const &l, integer_ref r); - f64 operator/(real_ref l, ratio_data const &r); - f64 operator/(ratio_data const &l, real_ref r); + object_ref operator/(integer_ref const &l, ratio_data const &r); + ratio_ref operator/(ratio_data const &l, integer_ref const &r); + f64 operator/(real_ref const &l, ratio_data const &r); + f64 operator/(ratio_data const &l, real_ref const &r); f64 operator/(ratio_data const &l, f64 r); f64 operator/(f64 l, ratio_data const &r); ratio_ref operator/(ratio_data const &l, i64 r); object_ref operator/(i64 l, ratio_data const &r); bool operator==(ratio_data const &l, ratio_data const &r); - bool operator==(integer_ref l, ratio_data const &r); - bool operator==(ratio_data const &l, integer_ref r); - bool operator==(real_ref l, ratio_data const &r); - bool operator==(ratio_data const &l, real_ref r); + bool operator==(integer_ref const &l, ratio_data const &r); + bool operator==(ratio_data const &l, integer_ref const &r); + bool operator==(real_ref const &l, ratio_data const &r); + bool operator==(ratio_data const &l, real_ref const &r); bool operator==(ratio_data const &l, f64 r); bool operator==(f64 l, ratio_data const &r); bool operator==(ratio_data const &l, i64 r); bool operator==(i64 l, ratio_data const &r); bool operator<(ratio_data const &l, ratio_data const &r); - bool operator<(integer_ref l, ratio_data const &r); - bool operator<(ratio_data const &l, integer_ref r); - bool operator<(real_ref l, ratio_data const &r); - bool operator<(ratio_data const &l, real_ref r); + bool operator<(integer_ref const &l, ratio_data const &r); + bool operator<(ratio_data const &l, integer_ref const &r); + bool operator<(real_ref const &l, ratio_data const &r); + bool operator<(ratio_data const &l, real_ref const &r); bool operator<(ratio_data const &l, f64 r); bool operator<(f64 l, ratio_data const &r); bool operator<(ratio_data const &l, i64 r); @@ -114,19 +114,19 @@ namespace jank::runtime::obj bool operator<(bool l, ratio_data const &r); bool operator<(ratio_data const &l, bool r); bool operator<=(ratio_data const &l, ratio_data const &r); - bool operator<=(integer_ref l, ratio_data const &r); - bool operator<=(ratio_data const &l, integer_ref r); - bool operator<=(real_ref l, ratio_data const &r); - bool operator<=(ratio_data const &l, real_ref r); + bool operator<=(integer_ref const &l, ratio_data const &r); + bool operator<=(ratio_data const &l, integer_ref const &r); + bool operator<=(real_ref const &l, ratio_data const &r); + bool operator<=(ratio_data const &l, real_ref const &r); bool operator<=(ratio_data const &l, f64 r); bool operator<=(f64 l, ratio_data const &r); bool operator<=(ratio_data const &l, i64 r); bool operator<=(i64 l, ratio_data const &r); bool operator>(ratio_data const &l, ratio_data const &r); - bool operator>(integer_ref l, ratio_data const &r); - bool operator>(ratio_data const &l, integer_ref r); - bool operator>(real_ref l, ratio_data const &r); - bool operator>(ratio_data const &l, real_ref r); + bool operator>(integer_ref const &l, ratio_data const &r); + bool operator>(ratio_data const &l, integer_ref const &r); + bool operator>(real_ref const &l, ratio_data const &r); + bool operator>(ratio_data const &l, real_ref const &r); bool operator>(ratio_data const &l, f64 r); bool operator>(f64 l, ratio_data const &r); bool operator>(ratio_data const &l, i64 r); @@ -134,10 +134,10 @@ namespace jank::runtime::obj bool operator>(bool l, ratio_data const &r); bool operator>(ratio_data const &l, bool r); bool operator>=(ratio_data const &l, ratio_data const &r); - bool operator>=(integer_ref l, ratio_data const &r); - bool operator>=(ratio_data const &l, integer_ref r); - bool operator>=(real_ref l, ratio_data const &r); - bool operator>=(ratio_data const &l, real_ref r); + bool operator>=(integer_ref const &l, ratio_data const &r); + bool operator>=(ratio_data const &l, integer_ref const &r); + bool operator>=(real_ref const &l, ratio_data const &r); + bool operator>=(ratio_data const &l, real_ref const &r); bool operator>=(ratio_data const &l, f64 r); bool operator>=(f64 l, ratio_data const &r); bool operator>=(ratio_data const &l, i64 r); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/re_matcher.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/re_matcher.hpp index 65860f48c..5808831dd 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/re_matcher.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/re_matcher.hpp @@ -15,7 +15,7 @@ namespace jank::runtime::obj static constexpr object_type obj_type{ object_type::re_matcher }; static constexpr bool pointer_free{ false }; - re_matcher(re_pattern_ref re, jtl::immutable_string const &s); + re_matcher(re_pattern_ref const &re, jtl::immutable_string const &s); /* behavior::object_like */ bool equal(object const &) const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/reduced.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/reduced.hpp index e134b8eb9..a6e46babb 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/reduced.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/reduced.hpp @@ -12,7 +12,7 @@ namespace jank::runtime::obj static constexpr bool pointer_free{ false }; reduced() = default; - reduced(object_ref o); + reduced(object_ref const &o); /* behavior::object_like */ bool equal(object const &) const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/repeat.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/repeat.hpp index b9cd17153..03793fb3c 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/repeat.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/repeat.hpp @@ -17,11 +17,11 @@ namespace jank::runtime::obj static constexpr i64 infinite{ -1 }; repeat() = default; - repeat(object_ref value); - repeat(object_ref count, object_ref value); + repeat(object_ref const &value); + repeat(object_ref const &count, object_ref const &value); - static object_ref create(object_ref value); - static object_ref create(object_ref count, object_ref value); + static object_ref create(object_ref const &value); + static object_ref create(object_ref const &count, object_ref const &value); /* behavior::object_like */ bool equal(object const &) const; @@ -42,10 +42,10 @@ namespace jank::runtime::obj repeat_ref next_in_place(); /* behavior::conjable */ - obj::cons_ref conj(object_ref head) const; + obj::cons_ref conj(object_ref const &head) const; /* behavior::metadatable */ - repeat_ref with_meta(object_ref m) const; + repeat_ref with_meta(object_ref const &m) const; object base{ obj_type }; object_ref value{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/symbol.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/symbol.hpp index e1d70698e..d1659572a 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/symbol.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/symbol.hpp @@ -21,8 +21,8 @@ namespace jank::runtime::obj symbol(jtl::immutable_string &&d); symbol(jtl::immutable_string const &ns, jtl::immutable_string const &n); symbol(jtl::immutable_string &&ns, jtl::immutable_string &&n); - symbol(object_ref meta, jtl::immutable_string const &ns, jtl::immutable_string const &n); - symbol(object_ref ns, object_ref n); + symbol(object_ref const &meta, jtl::immutable_string const &ns, jtl::immutable_string const &n); + symbol(object_ref const &ns, object_ref const &n); symbol &operator=(symbol const &) = default; symbol &operator=(symbol &&) = default; @@ -44,7 +44,7 @@ namespace jank::runtime::obj i64 compare(symbol const &) const; /* behavior::metadatable */ - symbol_ref with_meta(object_ref m) const; + symbol_ref with_meta(object_ref const &m) const; /* behavior::nameable */ jtl::immutable_string const &get_name() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/tagged_literal.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/tagged_literal.hpp index 0ebdbacd2..f42bf8303 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/tagged_literal.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/tagged_literal.hpp @@ -11,7 +11,7 @@ namespace jank::runtime::obj static constexpr object_type obj_type{ object_type::tagged_literal }; static constexpr bool pointer_free{ false }; - tagged_literal(object_ref tag, object_ref form); + tagged_literal(object_ref const &tag, object_ref const &form); /* behavior::object_like */ bool equal(object const &) const; @@ -21,10 +21,10 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::associatively_readable */ - object_ref get(object_ref const key) const; - object_ref get(object_ref const key, object_ref const fallback) const; - object_ref get_entry(object_ref key) const; - bool contains(object_ref key) const; + object_ref get(object_ref const &key) const; + object_ref get(object_ref const &key, object_ref const &fallback) const; + object_ref get_entry(object_ref const &key) const; + bool contains(object_ref const &key) const; object base{ obj_type }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp index f69f05373..fb2a07649 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp @@ -35,24 +35,24 @@ namespace jank::runtime::obj u8 count() const; /* behavior::associatively_readable */ - object_ref get(object_ref const key) const; - object_ref get(object_ref const key, object_ref const fallback) const; - object_ref get_entry(object_ref const key) const; - bool contains(object_ref const key) const; + object_ref get(object_ref const &key) const; + object_ref get(object_ref const &key, object_ref const &fallback) const; + object_ref get_entry(object_ref const &key) const; + bool contains(object_ref const &key) const; /* behavior::associatively_writable_in_place */ - object_ref assoc_in_place(object_ref const key, object_ref const val); - transient_array_map_ref dissoc_in_place(object_ref const key); + object_ref assoc_in_place(object_ref const &key, object_ref const &val); + transient_array_map_ref dissoc_in_place(object_ref const &key); /* behavior::conjable_in_place */ - object_ref conj_in_place(object_ref const head); + object_ref conj_in_place(object_ref const &head); /* behavior::persistentable */ persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const) const; - object_ref call(object_ref const, object_ref const) const; + object_ref call(object_ref const &) const; + object_ref call(object_ref const &, object_ref const &) const; void assert_active() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp index a67b9ce48..06b66ed50 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp @@ -41,24 +41,24 @@ namespace jank::runtime::obj usize count() const; /* behavior::associatively_readable */ - object_ref get(object_ref const key) const; - object_ref get(object_ref const key, object_ref const fallback) const; - object_ref get_entry(object_ref key) const; - bool contains(object_ref key) const; + object_ref get(object_ref const &key) const; + object_ref get(object_ref const &key, object_ref const &fallback) const; + object_ref get_entry(object_ref const &key) const; + bool contains(object_ref const &key) const; /* behavior::associatively_writable_in_place */ - transient_hash_map_ref assoc_in_place(object_ref const key, object_ref const val); - transient_hash_map_ref dissoc_in_place(object_ref const key); + transient_hash_map_ref assoc_in_place(object_ref const &key, object_ref const &val); + transient_hash_map_ref dissoc_in_place(object_ref const &key); /* behavior::conjable_in_place */ - transient_hash_map_ref conj_in_place(object_ref head); + transient_hash_map_ref conj_in_place(object_ref const &head); /* behavior::persistentable */ persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref) const; - object_ref call(object_ref, object_ref) const; + object_ref call(object_ref const &) const; + object_ref call(object_ref const &, object_ref const &) const; void assert_active() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp index 20ee8fe8d..6993c2224 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp @@ -35,22 +35,22 @@ namespace jank::runtime::obj usize count() const; /* behavior::conjable_in_place */ - transient_hash_set_ref conj_in_place(object_ref elem); + transient_hash_set_ref conj_in_place(object_ref const &elem); /* behavior::persistentable */ persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const) const; - object_ref call(object_ref const, object_ref const fallback) const; + object_ref call(object_ref const &) const; + object_ref call(object_ref const &, object_ref const &fallback) const; /* behavior::associatively_readable */ - object_ref get(object_ref const elem) const; - object_ref get(object_ref const elem, object_ref const fallback) const; - object_ref get_entry(object_ref const elem) const; - bool contains(object_ref const elem) const; + object_ref get(object_ref const &elem) const; + object_ref get(object_ref const &elem, object_ref const &fallback) const; + object_ref get_entry(object_ref const &elem) const; + bool contains(object_ref const &elem) const; - transient_hash_set_ref disjoin_in_place(object_ref const elem); + transient_hash_set_ref disjoin_in_place(object_ref const &elem); void assert_active() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp index 546eb4c8d..6d0542b97 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp @@ -34,24 +34,24 @@ namespace jank::runtime::obj usize count() const; /* behavior::associatively_readable */ - object_ref get(object_ref const key) const; - object_ref get(object_ref const key, object_ref const fallback) const; - object_ref get_entry(object_ref key) const; - bool contains(object_ref key) const; + object_ref get(object_ref const &key) const; + object_ref get(object_ref const &key, object_ref const &fallback) const; + object_ref get_entry(object_ref const &key) const; + bool contains(object_ref const &key) const; /* behavior::associatively_writable_in_place */ - transient_sorted_map_ref assoc_in_place(object_ref const key, object_ref const val); - transient_sorted_map_ref dissoc_in_place(object_ref const key); + transient_sorted_map_ref assoc_in_place(object_ref const &key, object_ref const &val); + transient_sorted_map_ref dissoc_in_place(object_ref const &key); /* behavior::conjable_in_place */ - transient_sorted_map_ref conj_in_place(object_ref head); + transient_sorted_map_ref conj_in_place(object_ref const &head); /* behavior::persistentable */ persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref) const; - object_ref call(object_ref, object_ref) const; + object_ref call(object_ref const &) const; + object_ref call(object_ref const &, object_ref const &) const; void assert_active() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp index 80723695e..cc229d397 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp @@ -34,22 +34,22 @@ namespace jank::runtime::obj usize count() const; /* behavior::conjable_in_place */ - transient_sorted_set_ref conj_in_place(object_ref elem); + transient_sorted_set_ref conj_in_place(object_ref const &elem); /* behavior::persistentable */ persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const); - object_ref call(object_ref const, object_ref const fallback); + object_ref call(object_ref const &); + object_ref call(object_ref const &, object_ref const &fallback); /* behavior::associatively_readable */ - object_ref get(object_ref const elem); - object_ref get(object_ref const elem, object_ref const fallback); - object_ref get_entry(object_ref const elem); - bool contains(object_ref const elem) const; + object_ref get(object_ref const &elem); + object_ref get(object_ref const &elem, object_ref const &fallback); + object_ref get_entry(object_ref const &elem); + bool contains(object_ref const &elem) const; - transient_sorted_set_ref disjoin_in_place(object_ref const elem); + transient_sorted_set_ref disjoin_in_place(object_ref const &elem); void assert_active() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp index a6663e9a3..b5c0135d6 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp @@ -35,19 +35,19 @@ namespace jank::runtime::obj usize count() const; /* behavior::conjable_in_place */ - transient_vector_ref conj_in_place(object_ref head); + transient_vector_ref conj_in_place(object_ref const &head); /* behavior::persistentable */ persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const) const; + object_ref call(object_ref const &) const; /* behavior::associatively_readable */ - object_ref get(object_ref const idx) const; - object_ref get(object_ref const idx, object_ref const fallback) const; - object_ref get_entry(object_ref const idx) const; - bool contains(object_ref const elem) const; + object_ref get(object_ref const &idx) const; + object_ref get(object_ref const &idx, object_ref const &fallback) const; + object_ref get_entry(object_ref const &idx) const; + bool contains(object_ref const &elem) const; transient_vector_ref pop_in_place(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/volatile.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/volatile.hpp index f181cbb9a..b3f0daa6a 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/volatile.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/volatile.hpp @@ -12,7 +12,7 @@ namespace jank::runtime::obj static constexpr bool pointer_free{ false }; volatile_() = default; - volatile_(object_ref o); + volatile_(object_ref const &o); /* behavior::object_like */ bool equal(object const &) const; @@ -24,7 +24,7 @@ namespace jank::runtime::obj /* behavior::derefable */ object_ref deref() const; - object_ref reset(object_ref o); + object_ref reset(object_ref const &o); object base{ obj_type }; object_ref val{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/object.hpp b/compiler+runtime/include/cpp/jank/runtime/object.hpp index ab2e64d8b..6427c2e35 100644 --- a/compiler+runtime/include/cpp/jank/runtime/object.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/object.hpp @@ -315,11 +315,11 @@ namespace jank::runtime * constants during codegen, since we don't want to be lossy in how we generate values. */ struct very_equal_to { - bool operator()(object_ref const lhs, object_ref const rhs) const noexcept; + bool operator()(object_ref const &lhs, object_ref const &rhs) const noexcept; }; - bool operator==(object const *, object_ref); - bool operator!=(object const *, object_ref); + bool operator==(object const *, object_ref const &); + bool operator!=(object const *, object_ref const &); } namespace std @@ -327,7 +327,7 @@ namespace std template <> struct hash { - size_t operator()(jank::runtime::object_ref const o) const noexcept; + size_t operator()(jank::runtime::object_ref const &o) const noexcept; }; template <> @@ -339,7 +339,7 @@ namespace std template <> struct equal_to { - bool operator()(jank::runtime::object_ref const lhs, - jank::runtime::object_ref const rhs) const noexcept; + bool operator()(jank::runtime::object_ref const &lhs, + jank::runtime::object_ref const &rhs) const noexcept; }; } diff --git a/compiler+runtime/include/cpp/jank/runtime/oref.hpp b/compiler+runtime/include/cpp/jank/runtime/oref.hpp index 69210d50d..09d9eddaa 100644 --- a/compiler+runtime/include/cpp/jank/runtime/oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/oref.hpp @@ -36,11 +36,7 @@ namespace jank::runtime { using value_type = object; - oref() - : data{ std::bit_cast(jank_const_nil()) } - { - jank_debug_assert(data); - } + oref() = default; oref(oref const &rhs) : data{ rhs.data } @@ -228,6 +224,7 @@ namespace jank::runtime bool is_some() const noexcept { + /* NOLINTNEXTLINE(clang-analyzer-core.NullDereference): I cannot see how this can happen. We initialize to non-null and always ensure non-null on mutation. That's the whole point of this type. */ return data->type != object_type::nil; } @@ -236,7 +233,7 @@ namespace jank::runtime return data->type == object_type::nil; } - value_type *data{}; + value_type *data{ std::bit_cast(jank_const_nil()) }; }; /* This specialization of oref is for fully-typed objects like nil, @@ -248,11 +245,7 @@ namespace jank::runtime { using value_type = T; - oref() - : data{ std::bit_cast(jank_const_nil()) } - { - jank_debug_assert(data); - } + oref() = default; oref(oref const &rhs) noexcept : data{ rhs.data } @@ -480,7 +473,7 @@ namespace jank::runtime return data == std::bit_cast(jank_const_nil()); } - void *data{}; + void *data{ std::bit_cast(jank_const_nil()) }; }; template <> @@ -488,11 +481,7 @@ namespace jank::runtime { using value_type = obj::nil; - oref() - : data{ std::bit_cast(jank_const_nil()) } - { - jank_debug_assert(data); - } + oref() = default; oref(nullptr_t) = delete; @@ -584,7 +573,7 @@ namespace jank::runtime return true; } - value_type *data{}; + value_type *data{ std::bit_cast(jank_const_nil()) }; }; template diff --git a/compiler+runtime/include/cpp/jank/runtime/perf.hpp b/compiler+runtime/include/cpp/jank/runtime/perf.hpp index 7de330e1e..c7c412e0e 100644 --- a/compiler+runtime/include/cpp/jank/runtime/perf.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/perf.hpp @@ -4,5 +4,5 @@ namespace jank::runtime::perf { - object_ref benchmark(object_ref opts, object_ref f); + object_ref benchmark(object_ref const &opts, object_ref const &f); } diff --git a/compiler+runtime/include/cpp/jank/runtime/rtti.hpp b/compiler+runtime/include/cpp/jank/runtime/rtti.hpp index 207422e82..7582c3371 100644 --- a/compiler+runtime/include/cpp/jank/runtime/rtti.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/rtti.hpp @@ -28,7 +28,7 @@ namespace jank::runtime template requires behavior::object_like [[gnu::always_inline, gnu::flatten, gnu::hot]] - oref try_object(object_ref const o) + oref try_object(object_ref const &o) { if(o->type != T::obj_type) { diff --git a/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp b/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp index 38ab3607f..252e38bf7 100644 --- a/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp @@ -21,7 +21,7 @@ namespace jank::runtime iterator(iterator const &) noexcept = default; iterator(iterator &&) noexcept = default; - iterator(object_ref const data) + iterator(object_ref const &data) : data{ data } { } @@ -99,7 +99,7 @@ namespace jank::runtime iterator(iterator const &) noexcept = default; iterator(iterator &&) noexcept = default; - iterator(oref const data) + iterator(oref const &data) : data{ data } { } @@ -163,7 +163,7 @@ namespace jank::runtime template requires behavior::seqable - auto make_sequence_range(oref const s) + auto make_sequence_range(oref const &s) { using S = typename decltype(s->seq())::value_type; diff --git a/compiler+runtime/include/cpp/jank/runtime/var.hpp b/compiler+runtime/include/cpp/jank/runtime/var.hpp index c3669c756..2176f0052 100644 --- a/compiler+runtime/include/cpp/jank/runtime/var.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/var.hpp @@ -24,10 +24,10 @@ namespace jank::runtime var() = delete; var(weak_ns_ref const &n, obj::symbol_ref const &name); - var(weak_ns_ref const &n, obj::symbol_ref const &name, object_ref root); + var(weak_ns_ref const &n, obj::symbol_ref const &name, object_ref const &root); var(weak_ns_ref const &n, obj::symbol_ref const &name, - object_ref const root, + object_ref const &root, bool dynamic, bool thread_bound); @@ -42,16 +42,16 @@ namespace jank::runtime bool equal(var const &) const; /* behavior::metadatable */ - var_ref with_meta(object_ref m); + var_ref with_meta(object_ref const &m); bool is_bound() const; object_ref get_root() const; /* Binding a root changes it for all threads. */ - var_ref bind_root(object_ref r); - object_ref alter_root(object_ref f, object_ref args); + var_ref bind_root(object_ref const &r); + object_ref alter_root(object_ref const &f, object_ref const &args); /* Setting a var does not change its root, it only affects the current thread * binding. If there is no thread binding, a var cannot be set. */ - jtl::string_result set(object_ref r) const; + jtl::string_result set(object_ref const &r) const; var_ref set_dynamic(bool dyn); @@ -85,7 +85,7 @@ namespace jank::runtime static constexpr object_type obj_type{ object_type::var_thread_binding }; static constexpr bool pointer_free{ false }; - var_thread_binding(object_ref value, std::thread::id id); + var_thread_binding(object_ref const &value, std::thread::id id); /* behavior::object_like */ bool equal(object const &) const; @@ -109,7 +109,7 @@ namespace jank::runtime static constexpr object_type obj_type{ object_type::var_unbound_root }; static constexpr bool pointer_free{ true }; - var_unbound_root(var_ref var); + var_unbound_root(var_ref const &var); /* behavior::object_like */ bool equal(object const &) const; @@ -123,36 +123,24 @@ namespace jank::runtime }; } -/* TODO: Move these to the .cpp */ namespace std { template <> struct hash { - size_t operator()(jank::runtime::var const &o) const noexcept - { - static auto hasher(std::hash{}); - return hasher(*o.name); - } + size_t operator()(jank::runtime::var const &o) const noexcept; }; template <> struct hash { - size_t operator()(jank::runtime::var_ref const &o) const noexcept - { - static auto hasher(std::hash{}); - return hasher(*o->name); - } + size_t operator()(jank::runtime::var_ref const &o) const noexcept; }; template <> struct equal_to { bool - operator()(jank::runtime::var_ref const &lhs, jank::runtime::var_ref const &rhs) const noexcept - { - return lhs->equal(*rhs); - } + operator()(jank::runtime::var_ref const &lhs, jank::runtime::var_ref const &rhs) const noexcept; }; } diff --git a/compiler+runtime/include/cpp/jank/runtime/visit.hpp b/compiler+runtime/include/cpp/jank/runtime/visit.hpp index 1210ccba2..3fe2fa95b 100644 --- a/compiler+runtime/include/cpp/jank/runtime/visit.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/visit.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -213,21 +214,16 @@ namespace jank::runtime case object_type::opaque_box: return fn(expect_object(erased), std::forward(args)...); default: - { - jtl::string_builder sb; - sb("invalid object type: "); - sb(object_type_str(erased->type)); - sb(" raw value "); - sb(static_cast(erased->type)); - throw std::runtime_error{ sb.str() }; - } + jtl::panic("invalid object type: {}, raw value {}", + object_type_str(erased->type), + static_cast(erased->type)); } } /* Allows the visiting of a single type. */ template [[gnu::hot]] - auto visit_type(F const &fn, object_ref const erased, Args &&...args) + auto visit_type(F const &fn, object_ref const &erased, Args &&...args) { if(erased->type == T::obj_type) { @@ -235,15 +231,16 @@ namespace jank::runtime } else { - throw std::runtime_error{ "invalid object type: " - + std::to_string(static_cast(erased->type)) }; + jtl::panic("invalid object type: {}, raw value {}", + object_type_str(erased->type), + static_cast(erased->type)); } } template requires(visitable && !std::convertible_to) [[gnu::hot]] - auto visit_seqable(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) + auto visit_seqable(F1 const &fn, F2 const &else_fn, object_ref const &erased, Args &&...args) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -317,7 +314,7 @@ namespace jank::runtime /* Throws if the object isn't seqable. */ template [[gnu::hot]] - auto visit_seqable(F1 const &fn, object_ref const erased, Args &&...args) + auto visit_seqable(F1 const &fn, object_ref const &erased, Args &&...args) { return visit_seqable( fn, @@ -335,7 +332,7 @@ namespace jank::runtime template requires(map_visitable && !std::convertible_to) [[gnu::hot]] - auto visit_map_like(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) + auto visit_map_like(F1 const &fn, F2 const &else_fn, object_ref const &erased, Args &&...args) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -357,7 +354,7 @@ namespace jank::runtime /* Throws if the object isn't map-like. */ template [[gnu::hot]] - auto visit_map_like(F1 const &fn, object_ref const erased, Args &&...args) + auto visit_map_like(F1 const &fn, object_ref const &erased, Args &&...args) { return visit_map_like( fn, @@ -371,7 +368,7 @@ namespace jank::runtime template requires(visitable && !std::convertible_to) [[gnu::hot]] - auto visit_set_like(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) + auto visit_set_like(F1 const &fn, F2 const &else_fn, object_ref const &erased, Args &&...args) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -391,7 +388,7 @@ namespace jank::runtime /* Throws if the object isn't set-like. */ template [[gnu::hot]] - auto visit_set_like(F1 const &fn, object_ref const erased, Args &&...args) + auto visit_set_like(F1 const &fn, object_ref const &erased, Args &&...args) { return visit_set_like( fn, @@ -405,7 +402,7 @@ namespace jank::runtime template requires(!std::convertible_to) [[gnu::hot]] - auto visit_number_like(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) + auto visit_number_like(F1 const &fn, F2 const &else_fn, object_ref const &erased, Args &&...args) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -430,7 +427,7 @@ namespace jank::runtime /* Throws if the object isn't number-like. */ template [[gnu::hot]] - auto visit_number_like(F1 const &fn, object_ref const erased, Args &&...args) + auto visit_number_like(F1 const &fn, object_ref const &erased, Args &&...args) { return visit_number_like( fn, diff --git a/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp b/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp index 2484a112d..b37eb5336 100644 --- a/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp @@ -68,7 +68,7 @@ namespace jank::runtime template requires behavior::object_like - weak_oref(oref const typed_data) noexcept + weak_oref(oref const &typed_data) noexcept : data{ typed_data.erase() } { } @@ -194,7 +194,7 @@ namespace jank::runtime template requires jtl::is_convertible - weak_oref(oref const data) noexcept + weak_oref(oref const &data) noexcept : data{ data.data } { } diff --git a/compiler+runtime/include/cpp/jank/util/try.hpp b/compiler+runtime/include/cpp/jank/util/try.hpp index 17ed277fe..1e34bb330 100644 --- a/compiler+runtime/include/cpp/jank/util/try.hpp +++ b/compiler+runtime/include/cpp/jank/util/try.hpp @@ -17,7 +17,7 @@ namespace jank namespace jank::util { void print_exception(std::exception const &e); - void print_exception(runtime::object_ref const e); + void print_exception(runtime::object_ref const &e); void print_exception(jtl::immutable_string const &e); void print_exception(error_ref e); } diff --git a/compiler+runtime/include/cpp/jtl/immutable_string.hpp b/compiler+runtime/include/cpp/jtl/immutable_string.hpp index 15bc247b9..c23d420a0 100644 --- a/compiler+runtime/include/cpp/jtl/immutable_string.hpp +++ b/compiler+runtime/include/cpp/jtl/immutable_string.hpp @@ -722,6 +722,7 @@ namespace jtl /* NOTE: No performance difference between if/switch here. */ if(get_category() == category::large_owned) { + /* NOLINTNEXTLINE(cppcoreguidelines-no-malloc) */ free(store.large.data); } } @@ -837,6 +838,7 @@ namespace jtl jank_debug_assert(max_small_size < size); /* TODO: Apply gnu::malloc to this fn. */ store.large.data + /* NOLINTNEXTLINE(cppcoreguidelines-no-malloc) */ = std::assume_aligned(static_cast(malloc(size + 1))); traits_type::copy(store.large.data, data, size); store.large.data[size] = 0; @@ -849,6 +851,7 @@ namespace jtl { jank_debug_assert(max_small_size < size); store.large.data + /* NOLINTNEXTLINE(cppcoreguidelines-no-malloc) */ = std::assume_aligned(static_cast(malloc(size + 1))); traits_type::assign(store.large.data, size, fill); store.large.data[size] = 0; @@ -865,6 +868,7 @@ namespace jtl auto const size(lhs_size + rhs_size); jank_debug_assert(max_small_size < size); store.large.data + /* NOLINTNEXTLINE(cppcoreguidelines-no-malloc) */ = std::assume_aligned(static_cast(malloc(size + 1))); traits_type::copy(store.large.data, lhs, lhs_size); traits_type::copy(store.large.data + lhs_size, rhs, rhs_size); @@ -880,6 +884,7 @@ namespace jtl auto const size(std::distance(begin, end)); jank_debug_assert(max_small_size < size); store.large.data + /* NOLINTNEXTLINE(cppcoreguidelines-no-malloc) */ = std::assume_aligned(static_cast(malloc(size + 1))); std::copy(begin, end, store.large.data); store.large.data[size] = 0; diff --git a/compiler+runtime/include/cpp/jtl/panic.hpp b/compiler+runtime/include/cpp/jtl/panic.hpp index 19d39a02e..4a42ddf70 100644 --- a/compiler+runtime/include/cpp/jtl/panic.hpp +++ b/compiler+runtime/include/cpp/jtl/panic.hpp @@ -8,6 +8,7 @@ namespace jtl { namespace detail { + [[noreturn]] void panic(char const *msg); } diff --git a/compiler+runtime/src/cpp/clojure/core_native.cpp b/compiler+runtime/src/cpp/clojure/core_native.cpp index d237fc487..f71374251 100644 --- a/compiler+runtime/src/cpp/clojure/core_native.cpp +++ b/compiler+runtime/src/cpp/clojure/core_native.cpp @@ -14,12 +14,12 @@ namespace clojure::core_native using namespace jank; using namespace jank::runtime; - static object_ref subvec(object_ref const o, object_ref const start, object_ref const end) + static object_ref subvec(object_ref const &o, object_ref const &start, object_ref const &end) { return runtime::subvec(o, runtime::to_int(start), runtime::to_int(end)); } - object_ref not_(object_ref const o) + object_ref not_(object_ref const &o) { if(runtime::is_nil(o)) { @@ -28,11 +28,11 @@ namespace clojure::core_native return make_box(runtime::is_false(o)); } - static object_ref to_unqualified_symbol(object_ref const o) + static object_ref to_unqualified_symbol(object_ref const &o) { return runtime::visit_object( - [&](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [&](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -59,118 +59,119 @@ namespace clojure::core_native o); } - static object_ref to_qualified_symbol(object_ref const ns, object_ref const name) + static object_ref to_qualified_symbol(object_ref const &ns, object_ref const &name) { return make_box(ns, name); } - object_ref lazy_seq(object_ref const o) + object_ref lazy_seq(object_ref const &o) { return make_box(o); } - object_ref is_var(object_ref const o) + object_ref is_var(object_ref const &o) { return make_box(o->type == object_type::var); } - object_ref var_get(object_ref const o) + object_ref var_get(object_ref const &o) { return try_object(o)->deref(); } - object_ref intern_var(object_ref const sym) + object_ref intern_var(object_ref const &sym) { return __rt_ctx->intern_var(try_object(sym)).expect_ok(); } - object_ref var_get_root(object_ref const o) + object_ref var_get_root(object_ref const &o) { return try_object(o)->get_root(); } - object_ref var_bind_root(object_ref const v, object_ref const o) + object_ref var_bind_root(object_ref const &v, object_ref const &o) { return try_object(v)->bind_root(o); } - object_ref alter_var_root(object_ref const o, object_ref const fn, object_ref const args) + object_ref alter_var_root(object_ref const &o, object_ref const &fn, object_ref const &args) { return try_object(o)->alter_root(fn, args); } - object_ref is_var_bound(object_ref const o) + object_ref is_var_bound(object_ref const &o) { return make_box(try_object(o)->is_bound()); } - object_ref is_var_thread_bound(object_ref const o) + object_ref is_var_thread_bound(object_ref const &o) { return make_box(try_object(o)->get_thread_binding().is_some()); } - object_ref delay(object_ref const fn) + object_ref delay(object_ref const &fn) { return make_box(fn); } - object_ref is_fn(object_ref const o) + object_ref is_fn(object_ref const &o) { return make_box(o->type == object_type::native_function_wrapper || o->type == object_type::jit_function); } - object_ref is_multi_fn(object_ref const o) + object_ref is_multi_fn(object_ref const &o) { return make_box(o->type == object_type::multi_function); } - object_ref multi_fn(object_ref const name, - object_ref const dispatch_fn, - object_ref const default_, - object_ref const hierarchy) + object_ref multi_fn(object_ref const &name, + object_ref const &dispatch_fn, + object_ref const &default_, + object_ref const &hierarchy) { return make_box(name, dispatch_fn, default_, hierarchy); } - object_ref defmethod(object_ref const multifn, object_ref const dispatch_val, object_ref const fn) + object_ref + defmethod(object_ref const &multifn, object_ref const &dispatch_val, object_ref const &fn) { return try_object(multifn)->add_method(dispatch_val, fn); } - object_ref remove_all_methods(object_ref const multifn) + object_ref remove_all_methods(object_ref const &multifn) { return try_object(multifn)->reset(); } - object_ref remove_method(object_ref const multifn, object_ref const dispatch_val) + object_ref remove_method(object_ref const &multifn, object_ref const &dispatch_val) { return try_object(multifn)->remove_method(dispatch_val); } - object_ref prefer_method(object_ref const multifn, - object_ref const dispatch_val_x, - object_ref const dispatch_val_y) + object_ref prefer_method(object_ref const &multifn, + object_ref const &dispatch_val_x, + object_ref const &dispatch_val_y) { return try_object(multifn)->prefer_method(dispatch_val_x, dispatch_val_y); } - object_ref methods(object_ref const multifn) + object_ref methods(object_ref const &multifn) { return try_object(multifn)->method_table; } - object_ref get_method(object_ref const multifn, object_ref const dispatch_val) + object_ref get_method(object_ref const &multifn, object_ref const &dispatch_val) { return try_object(multifn)->get_fn(dispatch_val); } - object_ref prefers(object_ref const multifn) + object_ref prefers(object_ref const &multifn) { return try_object(multifn)->prefer_table; } - object_ref sleep(object_ref const ms) + object_ref sleep(object_ref const &ms) { std::this_thread::sleep_for(std::chrono::milliseconds(to_int(ms))); return jank_nil(); @@ -183,60 +184,61 @@ namespace clojure::core_native return make_box(duration_cast(t.time_since_epoch()).count()); } - object_ref in_ns(object_ref const sym) + object_ref in_ns(object_ref const &sym) { __rt_ctx->current_ns_var->set(__rt_ctx->intern_ns(try_object(sym))).expect_ok(); return jank_nil(); } - object_ref intern_ns(object_ref const sym) + object_ref intern_ns(object_ref const &sym) { return __rt_ctx->intern_ns(try_object(sym)); } - object_ref find_ns(object_ref const sym) + object_ref find_ns(object_ref const &sym) { return __rt_ctx->find_ns(try_object(sym)); } - object_ref find_var(object_ref const sym) + object_ref find_var(object_ref const &sym) { return __rt_ctx->find_var(try_object(sym)); } - object_ref remove_ns(object_ref const sym) + object_ref remove_ns(object_ref const &sym) { return __rt_ctx->remove_ns(try_object(sym)); } - object_ref is_ns(object_ref const ns_or_sym) + object_ref is_ns(object_ref const &ns_or_sym) { return make_box(ns_or_sym->type == object_type::ns); } - object_ref ns_name(object_ref const ns) + object_ref ns_name(object_ref const &ns) { return try_object(ns)->name; } - object_ref ns_map(object_ref const ns) + object_ref ns_map(object_ref const &ns) { return try_object(ns)->get_mappings(); } - object_ref var_ns(object_ref const v) + object_ref var_ns(object_ref const &v) { return try_object(v)->n; } - object_ref ns_resolve(object_ref const ns, object_ref const sym) + object_ref ns_resolve(object_ref const &ns, object_ref const &sym) { auto const n(try_object(ns)); auto const found(n->find_var(try_object(sym))); return found; } - object_ref alias(object_ref const current_ns, object_ref const remote_ns, object_ref const alias) + object_ref + alias(object_ref const ¤t_ns, object_ref const &remote_ns, object_ref const &alias) { try_object(current_ns) ->add_alias(try_object(alias), try_object(remote_ns)) @@ -244,19 +246,19 @@ namespace clojure::core_native return jank_nil(); } - object_ref ns_unalias(object_ref const current_ns, object_ref const alias) + object_ref ns_unalias(object_ref const ¤t_ns, object_ref const &alias) { try_object(current_ns)->remove_alias(try_object(alias)); return jank_nil(); } - object_ref ns_unmap(object_ref const current_ns, object_ref const sym) + object_ref ns_unmap(object_ref const ¤t_ns, object_ref const &sym) { try_object(current_ns)->unmap(try_object(sym)).expect_ok(); return jank_nil(); } - object_ref refer(object_ref const current_ns, object_ref const sym, object_ref const var) + object_ref refer(object_ref const ¤t_ns, object_ref const &sym, object_ref const &var) { expect_object(current_ns) ->refer(try_object(sym), expect_object(var)) @@ -264,30 +266,30 @@ namespace clojure::core_native return jank_nil(); } - object_ref load_module(object_ref const path) + object_ref load_module(object_ref const &path) { __rt_ctx->load_module(runtime::to_string(path), module::origin::latest).expect_ok(); return jank_nil(); } - object_ref compile(object_ref const path) + object_ref compile(object_ref const &path) { __rt_ctx->compile_module(runtime::to_string(path)).expect_ok(); return jank_nil(); } - object_ref eval(object_ref const expr) + object_ref eval(object_ref const &expr) { return __rt_ctx->eval(expr); } - object_ref hash_unordered(object_ref const coll) + object_ref hash_unordered(object_ref const &coll) { return make_box(hash::unordered(coll.data)).erase(); } /* TODO: implement opts for `read-string` */ - object_ref read_string(object_ref const /* opts */, object_ref const str) + object_ref read_string(object_ref const & /* opts */, object_ref const &str) { return __rt_ctx->read_string(runtime::to_string(str)); } @@ -316,7 +318,7 @@ void jank_load_clojure_core_native() __rt_ctx->intern_keyword("name").expect_ok(), make_box(obj::symbol{ __rt_ctx->current_ns()->to_string(), name }.to_string()))))); }); - auto const intern_fn_obj([=](jtl::immutable_string const &name, object_ref const fn) { + auto const intern_fn_obj([=](jtl::immutable_string const &name, object_ref const &fn) { ns->intern_var(name)->bind_root(with_meta( fn, obj::persistent_hash_map::create_unique(std::make_pair( @@ -329,17 +331,17 @@ void jank_load_clojure_core_native() intern_fn("identical?", &is_identical); intern_fn("empty?", &is_empty); intern_fn("empty", &empty); - intern_fn("count", static_cast(&sequence_length)); - intern_fn("boolean", static_cast(&truthy)); - intern_fn("integer", static_cast(&to_int)); - intern_fn("real", static_cast(&to_real)); - intern_fn("seq", static_cast(&seq)); - intern_fn("fresh-seq", static_cast(&fresh_seq)); - intern_fn("first", static_cast(&first)); - intern_fn("second", static_cast(&second)); - intern_fn("next", static_cast(&next)); - intern_fn("next-in-place", static_cast(&next_in_place)); - intern_fn("rest", static_cast(&rest)); + intern_fn("count", static_cast(&sequence_length)); + intern_fn("boolean", static_cast(&truthy)); + intern_fn("integer", static_cast(&to_int)); + intern_fn("real", static_cast(&to_real)); + intern_fn("seq", static_cast(&seq)); + intern_fn("fresh-seq", static_cast(&fresh_seq)); + intern_fn("first", static_cast(&first)); + intern_fn("second", static_cast(&second)); + intern_fn("next", static_cast(&next)); + intern_fn("next-in-place", static_cast(&next_in_place)); + intern_fn("rest", static_cast(&rest)); intern_fn("cons", &cons); intern_fn("coll?", &is_collection); intern_fn("seq?", &is_seq); @@ -351,11 +353,14 @@ void jank_load_clojure_core_native() intern_fn("conj", &conj); intern_fn("map?", &is_map); intern_fn("associative?", &is_associative); - intern_fn("assoc", static_cast(&assoc)); - intern_fn("pr-str", static_cast(&to_code_string)); + intern_fn("assoc", + static_cast( + &assoc)); + intern_fn("pr-str", static_cast(&to_code_string)); intern_fn("string?", &is_string); intern_fn("char?", &is_char); - intern_fn("str", static_cast(&str)); + intern_fn("str", + static_cast(&str)); intern_fn("symbol?", &is_symbol); intern_fn("true?", &is_true); intern_fn("false?", &is_false); @@ -375,7 +380,8 @@ void jank_load_clojure_core_native() intern_fn("persistent!", &persistent); intern_fn("conj-in-place!", &conj_in_place); intern_fn("assoc-in-place!", - static_cast(&assoc_in_place)); + static_cast( + &assoc_in_place)); intern_fn("dissoc-in-place!", &dissoc_in_place); intern_fn("pop-in-place!", &pop_in_place); intern_fn("disj-in-place!", &disj_in_place); @@ -392,10 +398,10 @@ void jank_load_clojure_core_native() intern_fn("volatile!", &volatile_); intern_fn("volatile?", &is_volatile); intern_fn("vreset!", &vreset); - intern_fn("+", static_cast(&add)); - intern_fn("-", static_cast(&sub)); - intern_fn("/", static_cast(&div)); - intern_fn("*", static_cast(&mul)); + intern_fn("+", static_cast(&add)); + intern_fn("-", static_cast(&sub)); + intern_fn("/", static_cast(&div)); + intern_fn("*", static_cast(&mul)); intern_fn("bit-not", &bit_not); intern_fn("bit-and", &bit_and); intern_fn("bit-or", &bit_or); @@ -408,20 +414,20 @@ void jank_load_clojure_core_native() intern_fn("bit-shift-left", &bit_shift_left); intern_fn("bit-shift-right", &bit_shift_right); intern_fn("unsigned-bit-shift-right", &bit_unsigned_shift_right); - intern_fn("<", static_cast(<)); - intern_fn("<=", static_cast(<e)); + intern_fn("<", static_cast(<)); + intern_fn("<=", static_cast(<e)); intern_fn("compare", &runtime::compare); - intern_fn("min", static_cast(&min)); - intern_fn("max", static_cast(&max)); - intern_fn("inc", static_cast(&inc)); - intern_fn("dec", static_cast(&dec)); + intern_fn("min", static_cast(&min)); + intern_fn("max", static_cast(&max)); + intern_fn("inc", static_cast(&inc)); + intern_fn("dec", static_cast(&dec)); intern_fn("numerator", &numerator); intern_fn("denominator", &denominator); intern_fn("pos?", &is_pos); intern_fn("neg?", &is_neg); intern_fn("zero?", &is_zero); - intern_fn("rem", static_cast(&rem)); - intern_fn("quot", static_cast(")); + intern_fn("rem", static_cast(&rem)); + intern_fn("quot", static_cast(")); intern_fn("integer?", &is_integer); intern_fn("real?", &is_real); intern_fn("ratio?", &is_ratio); @@ -530,10 +536,10 @@ void jank_load_clojure_core_native() intern_fn("re-matches", &re_matches); /* TODO: jank.math? */ - intern_fn("sqrt", static_cast(&runtime::sqrt)); - intern_fn("tan", static_cast(&runtime::tan)); - intern_fn("abs", static_cast(&runtime::abs)); - intern_fn("pow", static_cast(&runtime::pow)); + intern_fn("sqrt", static_cast(&runtime::sqrt)); + intern_fn("tan", static_cast(&runtime::tan)); + intern_fn("abs", static_cast(&runtime::abs)); + intern_fn("pow", static_cast(&runtime::pow)); { auto const fn( @@ -557,7 +563,7 @@ void jank_load_clojure_core_native() } return visit_seqable( - [](auto const typed_rest, object_ref const l) { + [](auto const &typed_rest, object_ref const &l) { for(auto const e : make_sequence_range(typed_rest)) { if(!equal(l, e)) diff --git a/compiler+runtime/src/cpp/clojure/string_native.cpp b/compiler+runtime/src/cpp/clojure/string_native.cpp index 8a18fde4c..eeedace97 100644 --- a/compiler+runtime/src/cpp/clojure/string_native.cpp +++ b/compiler+runtime/src/cpp/clojure/string_native.cpp @@ -13,7 +13,7 @@ namespace clojure::string_native using namespace jank; using namespace jank::runtime; - object_ref blank(object_ref const s) + object_ref blank(object_ref const &s) { if(runtime::is_nil(s)) { @@ -23,40 +23,40 @@ namespace clojure::string_native return make_box(s_str.is_blank()); } - object_ref reverse(object_ref const s) + object_ref reverse(object_ref const &s) { auto const s_str(runtime::to_string(s)); return make_box(jtl::immutable_string{ s_str.rbegin(), s_str.rend() }); } - object_ref lower_case(object_ref const s) + object_ref lower_case(object_ref const &s) { auto const s_str(runtime::to_string(s)); return make_box(util::to_lowercase(s_str)); } - object_ref starts_with(object_ref const s, object_ref const substr) + object_ref starts_with(object_ref const &s, object_ref const &substr) { auto const s_str(runtime::to_string(s)); auto const substr_str(runtime::to_string(substr)); return make_box(s_str.starts_with(substr_str)); } - object_ref ends_with(object_ref const s, object_ref const substr) + object_ref ends_with(object_ref const &s, object_ref const &substr) { auto const s_str(runtime::to_string(s)); auto const substr_str(runtime::to_string(substr)); return make_box(s_str.ends_with(substr_str)); } - object_ref includes(object_ref const s, object_ref const substr) + object_ref includes(object_ref const &s, object_ref const &substr) { auto const s_str(runtime::to_string(s)); auto const substr_str(runtime::to_string(substr)); return make_box(s_str.contains(substr_str)); } - object_ref upper_case(object_ref const s) + object_ref upper_case(object_ref const &s) { auto const s_str(runtime::to_string(s)); return make_box(util::to_uppercase(s_str)); @@ -105,7 +105,7 @@ namespace clojure::string_native static jtl::immutable_string replace_first(jtl::immutable_string const &s, std::regex const &match, - object_ref const replacement) + object_ref const &replacement) { std::smatch match_results{}; std::string const search_str{ s.c_str() }; @@ -136,8 +136,8 @@ namespace clojure::string_native } static jtl::immutable_string replace_first(jtl::immutable_string const &s, - object_ref const match, - object_ref const replacement) + object_ref const &match, + object_ref const &replacement) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -167,7 +167,7 @@ namespace clojure::string_native #pragma clang diagnostic pop } - object_ref replace_first(object_ref const s, object_ref const match, object_ref const replacement) + object_ref replace_first(object_ref const &s, object_ref const &match, object_ref const &replacement) { auto const is_string(s->type == object_type::persistent_string); auto const &s_str(is_string ? try_object(s)->data @@ -178,7 +178,7 @@ namespace clojure::string_native return is_string && output_str == s_str ? s : make_box(output_str); } - i64 index_of(object_ref const s, object_ref const value, object_ref const from_index) + i64 index_of(object_ref const &s, object_ref const &value, object_ref const &from_index) { auto const s_str(runtime::to_string(s)); auto const value_str(runtime::to_string(value)); @@ -186,7 +186,7 @@ namespace clojure::string_native return static_cast(s_str.find(value_str, pos)); } - i64 last_index_of(object_ref const s, object_ref const value, object_ref const from_index) + i64 last_index_of(object_ref const &s, object_ref const &value, object_ref const &from_index) { auto const s_str(runtime::to_string(s)); auto const value_str(runtime::to_string(value)); @@ -216,7 +216,7 @@ namespace clojure::string_native return i; } - object_ref triml(object_ref const s) + object_ref triml(object_ref const &s) { auto const s_str(runtime::to_string(s)); auto const l(triml_index(s_str)); @@ -250,7 +250,7 @@ namespace clojure::string_native return i; } - object_ref trimr(object_ref const s) + object_ref trimr(object_ref const &s) { auto const s_str(try_object(s)->data); auto const r(trimr_index(s_str)); @@ -268,7 +268,7 @@ namespace clojure::string_native return make_box(s_str.substr(0, r)); } - object_ref trim(object_ref const s) + object_ref trim(object_ref const &s) { auto const s_str(try_object(s)->data); auto const r(trimr_index(s_str)); @@ -305,7 +305,7 @@ namespace clojure::string_native return i; } - object_ref trim_newline(object_ref const s) + object_ref trim_newline(object_ref const &s) { auto const s_str(try_object(s)->data); auto const r(trim_newline_index(s_str)); @@ -318,7 +318,7 @@ namespace clojure::string_native return make_box(s_str.substr(0, r)); } - object_ref split(object_ref const s, object_ref const re) + object_ref split(object_ref const &s, object_ref const &re) { auto const s_str(try_object(s)->data); auto const regex(try_object(re)->regex); @@ -343,7 +343,7 @@ namespace clojure::string_native runtime::detail::native_persistent_vector{ vec.begin(), vec.end() }); } - object_ref split(object_ref const s, object_ref const re, object_ref const limit) + object_ref split(object_ref const &s, object_ref const &re, object_ref const &limit) { auto const limit_int(try_object(limit)->data); diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/call.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/call.cpp index cd1789bc7..8da1f4108 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/call.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/call.cpp @@ -10,7 +10,7 @@ namespace jank::analyze::expr bool const needs_box, expression_ref const source, native_vector &&arg_exprs, - runtime::obj::persistent_list_ref const form) + runtime::obj::persistent_list_ref const &form) : expression{ expr_kind, position, frame, needs_box } , source_expr{ source } , arg_exprs{ std::move(arg_exprs) } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/cpp_type.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/cpp_type.cpp index 5cc5fb46b..85ae57214 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/cpp_type.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/cpp_type.cpp @@ -8,7 +8,7 @@ namespace jank::analyze::expr cpp_type::cpp_type(expression_position const position, local_frame_ptr const frame, bool const needs_box, - runtime::obj::symbol_ref sym, + runtime::obj::symbol_ref const &sym, jtl::ptr const type) : expression{ expr_kind, position, frame, needs_box } , sym{ sym } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/cpp_value.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/cpp_value.cpp index db71d1787..92cb9a780 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/cpp_value.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/cpp_value.cpp @@ -8,7 +8,7 @@ namespace jank::analyze::expr cpp_value::cpp_value(expression_position const position, local_frame_ptr const frame, bool const needs_box, - obj::symbol_ref const sym, + obj::symbol_ref const &sym, jtl::ptr const type, jtl::ptr const scope, value_kind const val_kind) diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/def.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/def.cpp index ab2f14154..177064f53 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/def.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/def.cpp @@ -8,7 +8,7 @@ namespace jank::analyze::expr def::def(expression_position const position, local_frame_ptr const frame, bool const needs_box, - runtime::obj::symbol_ref const name, + runtime::obj::symbol_ref const &name, jtl::option const &value) : expression{ expr_kind, position, frame, needs_box } , name{ name } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/function.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/function.cpp index 388adbc89..caec2e4b4 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/function.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/function.cpp @@ -17,7 +17,7 @@ namespace jank::analyze::expr jtl::immutable_string const &name, jtl::immutable_string const &unique_name, native_vector &&arities, - runtime::obj::persistent_hash_map_ref const meta) + runtime::obj::persistent_hash_map_ref const &meta) : expression{ expr_kind, position, frame, needs_box } , name{ name } , unique_name{ unique_name } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/local_reference.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/local_reference.cpp index ee78a12f5..6ff8ad1bf 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/local_reference.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/local_reference.cpp @@ -9,7 +9,7 @@ namespace jank::analyze::expr local_reference::local_reference(expression_position const position, local_frame_ptr const frame, bool const needs_box, - runtime::obj::symbol_ref const name, + runtime::obj::symbol_ref const &name, local_binding_ptr const binding) : expression{ expr_kind, position, frame, needs_box } , name{ name } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/named_recursion.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/named_recursion.cpp index 1729b9c0d..9890b5fa3 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/named_recursion.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/named_recursion.cpp @@ -9,7 +9,7 @@ namespace jank::analyze::expr local_frame_ptr const frame, bool const needs_box, recursion_reference &&recursion_ref, - runtime::obj::persistent_list_ref const args, + runtime::obj::persistent_list_ref const &args, native_vector &&arg_exprs) : expression{ expr_kind, position, frame, needs_box } , recursion_ref{ std::move(recursion_ref) } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/primitive_literal.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/primitive_literal.cpp index 6c2fae1c0..2bdc4b5df 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/primitive_literal.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/primitive_literal.cpp @@ -8,7 +8,7 @@ namespace jank::analyze::expr primitive_literal::primitive_literal(expression_position const position, local_frame_ptr const frame, bool const needs_box, - runtime::object_ref const data) + runtime::object_ref const &data) : expression{ expr_kind, position, frame, needs_box } , data{ data } { diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/recur.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/recur.cpp index 83a8ce0ed..9a495054c 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/recur.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/recur.cpp @@ -8,7 +8,7 @@ namespace jank::analyze::expr recur::recur(expression_position const position, local_frame_ptr const frame, bool const needs_box, - runtime::obj::persistent_list_ref const args, + runtime::obj::persistent_list_ref const &args, native_vector &&arg_exprs, jtl::option const &loop_target) : expression{ expr_kind, position, frame, needs_box } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/var_deref.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/var_deref.cpp index 0942dbb3b..75fe2a321 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/var_deref.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/var_deref.cpp @@ -9,8 +9,8 @@ namespace jank::analyze::expr var_deref::var_deref(expression_position const position, local_frame_ptr const frame, bool const needs_box, - runtime::obj::symbol_ref const qualified_name, - runtime::var_ref const var) + runtime::obj::symbol_ref const &qualified_name, + runtime::var_ref const &var) : expression{ expr_kind, position, frame, needs_box } , qualified_name{ qualified_name } , var{ var } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/var_ref.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/var_ref.cpp index aed26e4a5..079f3ef88 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/var_ref.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/var_ref.cpp @@ -9,8 +9,8 @@ namespace jank::analyze::expr var_ref::var_ref(expression_position const position, local_frame_ptr const frame, bool const needs_box, - runtime::obj::symbol_ref const qualified_name, - runtime::var_ref const var) + runtime::obj::symbol_ref const &qualified_name, + runtime::var_ref const &var) : expression{ expr_kind, position, frame, needs_box } , qualified_name{ qualified_name } , var{ var } diff --git a/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp b/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp index 523014dbf..be0e8d31b 100644 --- a/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp @@ -37,8 +37,9 @@ namespace jank::analyze { } - static jtl::option - find_local_impl(local_frame_ptr const start, obj::symbol_ref sym, bool const allow_captures) + static jtl::option find_local_impl(local_frame_ptr const start, + obj::symbol_ref const &sym, + bool const allow_captures) { decltype(local_frame::binding_find_result::crossed_fns) crossed_fns; @@ -78,7 +79,7 @@ namespace jank::analyze } jtl::option - local_frame::find_local_or_capture(obj::symbol_ref const sym) + local_frame::find_local_or_capture(obj::symbol_ref const &sym) { return find_local_impl(this, sym, true); } @@ -119,13 +120,13 @@ namespace jank::analyze } jtl::option - local_frame::find_originating_local(obj::symbol_ref const sym) + local_frame::find_originating_local(obj::symbol_ref const &sym) { return find_local_impl(this, sym, false); } jtl::option - local_frame::find_named_recursion(obj::symbol_ref const sym) + local_frame::find_named_recursion(obj::symbol_ref const &sym) { decltype(local_frame::named_recursion_find_result::crossed_fns) crossed_fns; diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index f9bb4856a..7fd44ebfb 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -1,5 +1,4 @@ #include -#include #include @@ -73,7 +72,7 @@ namespace jank::analyze * a scope_exit which will do so. Since we don't always push something, we lift this * up into a nullable pointer. */ static std::unique_ptr - push_macro_expansions(processor &proc, object_ref const o) + push_macro_expansions(processor &proc, object_ref const &o) { auto const meta(runtime::meta(o)); auto const expansion( @@ -981,7 +980,7 @@ namespace jank::analyze * function pointers and custom functor objects. Function pointers have no * overloads and no Clang decl/scope. Custom functors use the call operator. */ static processor::expression_result - build_indirect_cpp_call(obj::persistent_list_ref const o, + build_indirect_cpp_call(obj::persistent_list_ref const &o, expression_ref const source, native_vector arg_exprs, std::vector arg_types, @@ -1244,7 +1243,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_def(runtime::obj::persistent_list_ref const l, + processor::analyze_def(runtime::obj::persistent_list_ref const &l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -1342,7 +1341,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_case(obj::persistent_list_ref const o, + processor::analyze_case(obj::persistent_list_ref const &o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -1442,7 +1441,7 @@ namespace jank::analyze }; auto keys_exprs{ visit_map_like( - [&](auto const typed_imap_obj) -> jtl::string_result { + [&](auto const &typed_imap_obj) -> jtl::string_result { keys_and_exprs ret{}; for(auto seq{ typed_imap_obj->fresh_seq() }; seq.is_some(); seq = seq->next_in_place()) { @@ -1490,7 +1489,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_symbol(runtime::obj::symbol_ref const sym, + processor::analyze_symbol(runtime::obj::symbol_ref const &sym, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fc, @@ -1597,7 +1596,7 @@ namespace jank::analyze } jtl::result - processor::analyze_fn_arity(runtime::obj::persistent_list_ref const list, + processor::analyze_fn_arity(runtime::obj::persistent_list_ref const &list, jtl::immutable_string const &name, local_frame_ptr const current_frame) { @@ -1609,7 +1608,7 @@ namespace jank::analyze "The missing [] was expected here.", latest_expansion(macro_expansions)); } - auto const params_obj(first_form.unwrap()); + auto const ¶ms_obj(first_form.unwrap()); if(params_obj->type != runtime::object_type::persistent_vector) { return error::analyze_invalid_fn_parameters("A function parameter vector must be a vector.", @@ -1629,7 +1628,7 @@ namespace jank::analyze bool is_variadic{}; for(auto it(params->data.begin()); it != params->data.end(); ++it) { - auto const p(*it); + auto const &p(*it); if(p->type != runtime::object_type::symbol) { auto const param_idx{ std::distance(params->data.begin(), it) }; @@ -1767,7 +1766,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_fn(runtime::obj::persistent_list_ref const full_list, + processor::analyze_fn(runtime::obj::persistent_list_ref const &full_list, local_frame_ptr const current_frame, expression_position const position, jtl::option const &, @@ -1940,7 +1939,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_recur(runtime::obj::persistent_list_ref const list, + processor::analyze_recur(runtime::obj::persistent_list_ref const &list, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2040,7 +2039,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_do(runtime::obj::persistent_list_ref const list, + processor::analyze_do(runtime::obj::persistent_list_ref const &list, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2089,7 +2088,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_let(runtime::obj::persistent_list_ref const o, + processor::analyze_let(runtime::obj::persistent_list_ref const &o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2211,7 +2210,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_letfn(runtime::obj::persistent_list_ref const o, + processor::analyze_letfn(runtime::obj::persistent_list_ref const &o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2344,7 +2343,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_loop(runtime::obj::persistent_list_ref const list, + processor::analyze_loop(runtime::obj::persistent_list_ref const &list, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2372,7 +2371,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_if(runtime::obj::persistent_list_ref const o, + processor::analyze_if(runtime::obj::persistent_list_ref const &o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2487,7 +2486,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_quote(runtime::obj::persistent_list_ref const o, + processor::analyze_quote(runtime::obj::persistent_list_ref const &o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2510,7 +2509,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_var_call(runtime::obj::persistent_list_ref const o, + processor::analyze_var_call(runtime::obj::persistent_list_ref const &o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &, @@ -2554,7 +2553,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_var_val(runtime::var_ref const o, + processor::analyze_var_val(runtime::var_ref const &o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &, @@ -2567,7 +2566,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_throw(runtime::obj::persistent_list_ref const o, + processor::analyze_throw(runtime::obj::persistent_list_ref const &o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2600,7 +2599,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_try(runtime::obj::persistent_list_ref const list, + processor::analyze_try(runtime::obj::persistent_list_ref const &list, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2637,8 +2636,8 @@ namespace jank::analyze { auto const item(it->first()); auto const type(runtime::visit_seqable( - [](auto const typed_item) { - using T = typename decltype(typed_item)::value_type; + [](auto const &typed_item) { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -2806,7 +2805,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_primitive_literal(runtime::object_ref const o, + processor::analyze_primitive_literal(runtime::object_ref const &o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &, @@ -2818,7 +2817,7 @@ namespace jank::analyze /* TODO: Test for this. */ processor::expression_result - processor::analyze_vector(runtime::obj::persistent_vector_ref const o, + processor::analyze_vector(runtime::obj::persistent_vector_ref const &o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2864,7 +2863,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_map(object_ref const o, + processor::analyze_map(object_ref const &o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2874,7 +2873,7 @@ namespace jank::analyze /* TODO: Detect literal and act accordingly. */ return visit_map_like( - [&](auto const typed_o) -> processor::expression_result { + [&](auto const &typed_o) -> processor::expression_result { native_vector> exprs; exprs.reserve(typed_o->data.size()); @@ -2921,7 +2920,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_set(object_ref const o, + processor::analyze_set(object_ref const &o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2930,7 +2929,7 @@ namespace jank::analyze auto const pop_macro_expansions{ push_macro_expansions(*this, o) }; return visit_set_like( - [&](auto const typed_o) -> processor::expression_result { + [&](auto const &typed_o) -> processor::expression_result { native_vector exprs; exprs.reserve(typed_o->count()); bool literal{ true }; @@ -2978,7 +2977,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_call(runtime::obj::persistent_list_ref const o, + processor::analyze_call(runtime::obj::persistent_list_ref const &o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -3216,7 +3215,7 @@ namespace jank::analyze } static processor::expression_result - build_cpp_value(runtime::obj::symbol_ref const sym, + build_cpp_value(runtime::obj::symbol_ref const &sym, jtl::ptr const scope, bool const is_ctor, u8 const ptr_count, @@ -3373,7 +3372,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_symbol(obj::symbol_ref const sym, + processor::analyze_cpp_symbol(obj::symbol_ref const &sym, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -3538,7 +3537,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_call(obj::persistent_list_ref const o, + processor::analyze_cpp_call(obj::persistent_list_ref const &o, expression_ref const source, local_frame_ptr const current_frame, expression_position const position, @@ -3602,7 +3601,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_raw(obj::persistent_list_ref const l, + processor::analyze_cpp_raw(obj::persistent_list_ref const &l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -3666,7 +3665,7 @@ namespace jank::analyze }; processor::expression_result - processor::analyze_cpp_literal(obj::persistent_list_ref const l, + processor::analyze_cpp_literal(obj::persistent_list_ref const &l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -3835,7 +3834,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_type(obj::persistent_list_ref const l, + processor::analyze_cpp_type(obj::persistent_list_ref const &l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -3845,7 +3844,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_value(obj::persistent_list_ref const l, + processor::analyze_cpp_value(obj::persistent_list_ref const &l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -3855,7 +3854,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_cast(obj::persistent_list_ref const l, + processor::analyze_cpp_cast(obj::persistent_list_ref const &l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -3968,7 +3967,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_box(obj::persistent_list_ref const l, + processor::analyze_cpp_box(obj::persistent_list_ref const &l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -4035,7 +4034,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_unbox(obj::persistent_list_ref const l, + processor::analyze_cpp_unbox(obj::persistent_list_ref const &l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -4130,7 +4129,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_new(obj::persistent_list_ref const l, + processor::analyze_cpp_new(obj::persistent_list_ref const &l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -4194,7 +4193,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_delete(obj::persistent_list_ref const l, + processor::analyze_cpp_delete(obj::persistent_list_ref const &l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -4242,7 +4241,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_member_access(obj::persistent_list_ref const l, + processor::analyze_cpp_member_access(obj::persistent_list_ref const &l, expr::cpp_value_ref const val, local_frame_ptr const current_frame, expression_position const position, @@ -4356,13 +4355,13 @@ namespace jank::analyze } processor::expression_result - processor::analyze(object_ref const o, expression_position const position) + processor::analyze(object_ref const &o, expression_position const position) { return analyze(o, root_frame, position, none, true); } processor::expression_result - processor::analyze(object_ref const o, + processor::analyze(object_ref const &o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -4430,7 +4429,7 @@ namespace jank::analyze o); } - bool processor::is_special(runtime::object_ref const form) + bool processor::is_special(runtime::object_ref const &form) { if(form->type != runtime::object_type::symbol) { diff --git a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp index f1a6bd7ee..0d317a373 100644 --- a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp @@ -126,8 +126,8 @@ namespace jank::codegen llvm::Value *gen(analyze::expr::cpp_new_ref, analyze::expr::function_arity const &); llvm::Value *gen(analyze::expr::cpp_delete_ref, analyze::expr::function_arity const &); - llvm::Value *gen_var(obj::symbol_ref qualified_name) const; - llvm::Value *gen_var_root(obj::symbol_ref qualified_name, var_root_kind kind) const; + llvm::Value *gen_var(obj::symbol_ref const &qualified_name) const; + llvm::Value *gen_var_root(obj::symbol_ref const &qualified_name, var_root_kind kind) const; llvm::Value *gen_c_string(jtl::immutable_string const &s) const; void create_function(); @@ -136,21 +136,21 @@ namespace jank::codegen llvm::GlobalVariable *create_global_var(jtl::immutable_string const &name) const; llvm::Value *gen_global(runtime::obj::weak_nil_ref) const; - llvm::Value *gen_global(runtime::obj::nil_ref) const; - llvm::Value *gen_global(runtime::obj::boolean_ref b) const; - llvm::Value *gen_global(runtime::obj::integer_ref i) const; - llvm::Value *gen_global(runtime::obj::big_integer_ref i) const; - llvm::Value *gen_global(runtime::obj::big_decimal_ref i) const; - llvm::Value *gen_global(runtime::obj::real_ref r) const; - llvm::Value *gen_global(runtime::obj::ratio_ref r) const; - llvm::Value *gen_global(runtime::obj::persistent_string_ref s) const; - llvm::Value *gen_global(runtime::obj::symbol_ref s) const; - llvm::Value *gen_global(runtime::obj::keyword_ref k) const; - llvm::Value *gen_global(runtime::obj::character_ref c) const; - llvm::Value *gen_global(runtime::obj::re_pattern_ref re) const; - llvm::Value *gen_global(runtime::obj::uuid_ref u) const; - llvm::Value *gen_global(runtime::obj::inst_ref i) const; - llvm::Value *gen_global_from_read_string(runtime::object_ref o) const; + llvm::Value *gen_global(runtime::obj::nil_ref const &) const; + llvm::Value *gen_global(runtime::obj::boolean_ref const &b) const; + llvm::Value *gen_global(runtime::obj::integer_ref const &i) const; + llvm::Value *gen_global(runtime::obj::big_integer_ref const &i) const; + llvm::Value *gen_global(runtime::obj::big_decimal_ref const &i) const; + llvm::Value *gen_global(runtime::obj::real_ref const &r) const; + llvm::Value *gen_global(runtime::obj::ratio_ref const &r) const; + llvm::Value *gen_global(runtime::obj::persistent_string_ref const &s) const; + llvm::Value *gen_global(runtime::obj::symbol_ref const &s) const; + llvm::Value *gen_global(runtime::obj::keyword_ref const &k) const; + llvm::Value *gen_global(runtime::obj::character_ref const &c) const; + llvm::Value *gen_global(runtime::obj::re_pattern_ref const &re) const; + llvm::Value *gen_global(runtime::obj::uuid_ref const &u) const; + llvm::Value *gen_global(runtime::obj::inst_ref const &i) const; + llvm::Value *gen_global_from_read_string(runtime::object_ref const &o) const; llvm::Value *gen_function_instance(analyze::expr::function_ref expr, analyze::expr::function_arity const &fn_arity); llvm::Value *gen_aot_call(Cpp::AotCall const &call, @@ -2840,7 +2840,7 @@ namespace jank::codegen return ret; } - llvm::Value *llvm_processor::impl::gen_var(obj::symbol_ref const qualified_name) const + llvm::Value *llvm_processor::impl::gen_var(obj::symbol_ref const &qualified_name) const { auto const found(ctx->var_globals.find(qualified_name)); if(found != ctx->var_globals.end()) @@ -2878,7 +2878,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_var_root(obj::symbol_ref const qualified_name, + llvm::Value *llvm_processor::impl::gen_var_root(obj::symbol_ref const &qualified_name, var_root_kind const kind) const { auto it(ctx->var_root_globals.find(qualified_name)); @@ -2959,7 +2959,7 @@ namespace jank::codegen return gen_global(obj::nil_ref{ nil }); } - llvm::Value *llvm_processor::impl::gen_global(obj::nil_ref const nil) const + llvm::Value *llvm_processor::impl::gen_global(obj::nil_ref const &nil) const { auto const found(ctx->literal_globals.find(nil)); if(found != ctx->literal_globals.end()) @@ -2992,7 +2992,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::boolean_ref const b) const + llvm::Value *llvm_processor::impl::gen_global(obj::boolean_ref const &b) const { auto const found(ctx->literal_globals.find(b)); if(found != ctx->literal_globals.end()) @@ -3027,7 +3027,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::integer_ref const i) const + llvm::Value *llvm_processor::impl::gen_global(obj::integer_ref const &i) const { auto const found(ctx->literal_globals.find(i)); if(found != ctx->literal_globals.end()) @@ -3062,7 +3062,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::big_integer_ref const i) const + llvm::Value *llvm_processor::impl::gen_global(obj::big_integer_ref const &i) const { auto const found(ctx->literal_globals.find(i)); if(found != ctx->literal_globals.end()) @@ -3102,7 +3102,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::big_decimal_ref const i) const + llvm::Value *llvm_processor::impl::gen_global(obj::big_decimal_ref const &i) const { auto const found(ctx->literal_globals.find(i)); if(found != ctx->literal_globals.end()) @@ -3139,7 +3139,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::real_ref const r) const + llvm::Value *llvm_processor::impl::gen_global(obj::real_ref const &r) const { auto const found(ctx->literal_globals.find(r)); if(found != ctx->literal_globals.end()) @@ -3174,7 +3174,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::ratio_ref const r) const + llvm::Value *llvm_processor::impl::gen_global(obj::ratio_ref const &r) const { if(auto const found(ctx->literal_globals.find(r)); found != ctx->literal_globals.end()) { @@ -3211,7 +3211,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::persistent_string_ref const s) const + llvm::Value *llvm_processor::impl::gen_global(obj::persistent_string_ref const &s) const { auto const found(ctx->literal_globals.find(s)); if(found != ctx->literal_globals.end()) @@ -3247,7 +3247,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::re_pattern_ref const re) const + llvm::Value *llvm_processor::impl::gen_global(obj::re_pattern_ref const &re) const { auto const found(ctx->literal_globals.find(re)); if(found != ctx->literal_globals.end()) @@ -3283,7 +3283,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::uuid_ref const u) const + llvm::Value *llvm_processor::impl::gen_global(obj::uuid_ref const &u) const { auto const found(ctx->literal_globals.find(u)); if(found != ctx->literal_globals.end()) @@ -3319,7 +3319,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::inst_ref const i) const + llvm::Value *llvm_processor::impl::gen_global(obj::inst_ref const &i) const { auto const found(ctx->literal_globals.find(i)); if(found != ctx->literal_globals.end()) @@ -3355,7 +3355,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::symbol_ref const s) const + llvm::Value *llvm_processor::impl::gen_global(obj::symbol_ref const &s) const { auto const found(ctx->literal_globals.find(s)); if(found != ctx->literal_globals.end()) @@ -3408,7 +3408,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::keyword_ref const k) const + llvm::Value *llvm_processor::impl::gen_global(obj::keyword_ref const &k) const { auto const found(ctx->literal_globals.find(k)); if(found != ctx->literal_globals.end()) @@ -3447,7 +3447,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::character_ref const c) const + llvm::Value *llvm_processor::impl::gen_global(obj::character_ref const &c) const { auto const found(ctx->literal_globals.find(c)); if(found != ctx->literal_globals.end()) @@ -3484,7 +3484,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global_from_read_string(object_ref const o) const + llvm::Value *llvm_processor::impl::gen_global_from_read_string(object_ref const &o) const { auto const found(ctx->literal_globals.find(o)); if(found != ctx->literal_globals.end()) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index c391c287d..30d97c1cf 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -90,7 +90,7 @@ namespace jank::codegen return native_name; } - static jtl::immutable_string gen_constant_type(runtime::object_ref const o, bool const boxed) + static jtl::immutable_string gen_constant_type(runtime::object_ref const &o, bool const boxed) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -146,7 +146,7 @@ namespace jank::codegen } static void - gen_constant(runtime::object_ref const o, jtl::string_builder &buffer, bool const boxed) + gen_constant(runtime::object_ref const &o, jtl::string_builder &buffer, bool const boxed) { if(!boxed) { @@ -461,9 +461,9 @@ namespace jank::codegen } handle::handle(jtl::immutable_string const &name, bool const) + : boxed_name{ name } + , unboxed_name{ boxed_name } { - boxed_name = name; - unboxed_name = boxed_name; } handle::handle(jtl::immutable_string const &boxed_name) @@ -483,9 +483,9 @@ namespace jank::codegen } handle::handle(analyze::local_binding_ptr const binding) + : boxed_name{ runtime::munge(binding->native_name) } + , unboxed_name{ boxed_name } { - boxed_name = runtime::munge(binding->native_name); - unboxed_name = boxed_name; } jtl::immutable_string handle::str(bool const) const @@ -1282,7 +1282,7 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::local_reference_ref const expr, analyze::expr::function_arity const &) { - auto const ret(runtime::munge(expr->binding->native_name)); + auto ret(runtime::munge(expr->binding->native_name)); switch(expr->position) { @@ -2624,7 +2624,7 @@ namespace jank::codegen for(auto const ¶m : arity.params) { util::format_to(body_buffer, - "{} jank::runtime::object_ref const {}{}", + "{} jank::runtime::object_ref const &{}{}", (param_comma ? ", " : ""), runtime::munge(param->name), recur_suffix); diff --git a/compiler+runtime/src/cpp/jank/compiler_native.cpp b/compiler+runtime/src/cpp/jank/compiler_native.cpp index a18aad6e1..30a87a547 100644 --- a/compiler+runtime/src/cpp/jank/compiler_native.cpp +++ b/compiler+runtime/src/cpp/jank/compiler_native.cpp @@ -19,7 +19,7 @@ namespace jank::compiler_native using namespace jank; using namespace jank::runtime; - static object_ref native_source(object_ref const form) + static object_ref native_source(object_ref const &form) { /* We use a clean analyze::processor so we don't share lifted items from other REPL * evaluations. */ diff --git a/compiler+runtime/src/cpp/jank/error.cpp b/compiler+runtime/src/cpp/jank/error.cpp index ab54ddba8..087a7d37c 100644 --- a/compiler+runtime/src/cpp/jank/error.cpp +++ b/compiler+runtime/src/cpp/jank/error.cpp @@ -234,7 +234,7 @@ namespace jank::error .release(); } - static void add_expansion_note(base &e, runtime::object_ref const expansion) + static void add_expansion_note(base &e, runtime::object_ref const &expansion) { auto source{ runtime::object_source(expansion) }; /* We just want to point at the start of the expansion, not underline the @@ -274,7 +274,7 @@ namespace jank::error base::base(enum kind const k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) : kind{ k } @@ -288,7 +288,7 @@ namespace jank::error base::base(enum kind const k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion, + runtime::object_ref const &expansion, std::unique_ptr trace) : kind{ k @@ -330,7 +330,7 @@ namespace jank::error jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const ¬e_message, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) : kind{ k } @@ -364,7 +364,7 @@ namespace jank::error jtl::immutable_string const &message, read::source const &source, note const ¬e, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) : kind{ k } , message{ message } , source{ source } @@ -387,7 +387,7 @@ namespace jank::error base::base(enum kind const k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion, + runtime::object_ref const &expansion, jtl::ref const cause) : kind{ k @@ -403,7 +403,7 @@ namespace jank::error base::base(enum kind const k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion, + runtime::object_ref const &expansion, jtl::ref const cause, std::unique_ptr trace) : kind{ diff --git a/compiler+runtime/src/cpp/jank/error/analyze.cpp b/compiler+runtime/src/cpp/jank/error/analyze.cpp index 2d04d1d02..48fe128aa 100644 --- a/compiler+runtime/src/cpp/jank/error/analyze.cpp +++ b/compiler+runtime/src/cpp/jank/error/analyze.cpp @@ -12,7 +12,7 @@ namespace jank::error { error_ref analyze_invalid_case(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error( kind::analyze_invalid_case, @@ -24,7 +24,7 @@ namespace jank::error error_ref analyze_invalid_def(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_def, message, source, expansion); } @@ -32,21 +32,21 @@ namespace jank::error error_ref analyze_invalid_def(jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const ¬e, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_def, message, source, note, expansion); } error_ref analyze_invalid_fn(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_fn, message, source, expansion); } error_ref analyze_invalid_fn_parameters(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_fn_parameters, message, source, expansion); } @@ -54,7 +54,7 @@ namespace jank::error error_ref analyze_invalid_fn_parameters(jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const &error_note_message, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_fn_parameters, message, @@ -65,49 +65,49 @@ namespace jank::error error_ref analyze_invalid_recur_position(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_recur_position, message, source, expansion); } error_ref analyze_invalid_recur_from_try(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_recur_from_try, message, source, expansion); } error_ref analyze_invalid_recur_args(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_recur_args, message, source, expansion); } error_ref analyze_invalid_let(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_let, message, source, expansion); } error_ref analyze_invalid_letfn(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_letfn, message, source, expansion); } error_ref analyze_invalid_loop(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_loop, message, source, expansion); } error_ref analyze_invalid_if(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_if, message, source, expansion); } @@ -115,35 +115,35 @@ namespace jank::error error_ref analyze_invalid_if(jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const &error_note_message, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_if, message, source, error_note_message, expansion); } error_ref analyze_invalid_quote(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_quote, message, source, expansion); } error_ref analyze_invalid_var_reference(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_var_reference, message, source, expansion); } error_ref analyze_invalid_throw(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_throw, message, source, expansion); } error_ref analyze_invalid_try(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_try, message, source, expansion); } @@ -151,21 +151,21 @@ namespace jank::error error_ref analyze_invalid_try(jtl::immutable_string const &message, read::source const &source, note &&extra, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_try, message, source, jtl::move(extra), expansion); } error_ref analyze_unresolved_var(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_unresolved_var, message, source, expansion); } error_ref analyze_unresolved_symbol(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_unresolved_symbol, message, source, expansion); } @@ -173,7 +173,7 @@ namespace jank::error error_ref analyze_macro_expansion_exception(std::exception const &e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_macro_expansion_exception, e.what(), @@ -182,10 +182,10 @@ namespace jank::error std::make_unique(trace)); } - error_ref analyze_macro_expansion_exception(runtime::object_ref const e, + error_ref analyze_macro_expansion_exception(runtime::object_ref const &e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_macro_expansion_exception, e->type == runtime::object_type::persistent_string @@ -199,7 +199,7 @@ namespace jank::error error_ref analyze_macro_expansion_exception(jtl::immutable_string const &e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_macro_expansion_exception, e, @@ -211,7 +211,7 @@ namespace jank::error error_ref analyze_macro_expansion_exception(error_ref const e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_macro_expansion_exception, /* TODO: Macro name. */ @@ -229,28 +229,28 @@ namespace jank::error error_ref analyze_invalid_cpp_operator_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_operator_call, message, source, expansion); } error_ref analyze_invalid_cpp_constructor_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_constructor_call, message, source, expansion); } error_ref analyze_invalid_cpp_member_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_member_call, message, source, expansion); } error_ref analyze_invalid_cpp_capture(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_capture, message, @@ -261,125 +261,125 @@ namespace jank::error error_ref analyze_mismatched_if_types(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_mismatched_if_types, message, source, expansion); } error_ref analyze_invalid_cpp_function_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_function_call, message, source, expansion); } error_ref analyze_invalid_cpp_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_call, message, source, expansion); } error_ref analyze_invalid_cpp_conversion(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_conversion, message, source, expansion); } error_ref analyze_invalid_cpp_symbol(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_symbol, message, source, expansion); } error_ref analyze_unresolved_cpp_symbol(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_unresolved_cpp_symbol, message, source, expansion); } error_ref analyze_invalid_cpp_raw(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_raw, message, source, expansion); } error_ref analyze_invalid_cpp_type(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_type, message, source, expansion); } error_ref analyze_invalid_cpp_value(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_value, message, source, expansion); } error_ref analyze_invalid_cpp_cast(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_cast, message, source, expansion); } error_ref analyze_invalid_cpp_box(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_box, message, source, expansion); } error_ref analyze_invalid_cpp_unbox(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_unbox, message, source, expansion); } error_ref analyze_invalid_cpp_new(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_new, message, source, expansion); } error_ref analyze_invalid_cpp_delete(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_delete, message, source, expansion); } error_ref analyze_invalid_cpp_member_access(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_invalid_cpp_member_access, message, source, expansion); } error_ref analyze_known_issue(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::analyze_known_issue, message, source, expansion); } error_ref internal_analyze_failure(jtl::immutable_string const &message, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::internal_analyze_failure, message, read::source::unknown(), expansion); } error_ref internal_analyze_failure(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const expansion) + runtime::object_ref const &expansion) { return make_error(kind::internal_analyze_failure, message, source, expansion); } diff --git a/compiler+runtime/src/cpp/jank/hash.cpp b/compiler+runtime/src/cpp/jank/hash.cpp index c222e8f01..965e311db 100644 --- a/compiler+runtime/src/cpp/jank/hash.cpp +++ b/compiler+runtime/src/cpp/jank/hash.cpp @@ -153,14 +153,14 @@ namespace jank::hash return static_cast(ch); } - u32 visit(runtime::object_ref const o) + u32 visit(runtime::object_ref const &o) { return runtime::visit_object([](auto const typed_o) -> u32 { return typed_o->to_hash(); }, o); } template requires runtime::behavior::object_like - static u32 visit(runtime::oref const o) + static u32 visit(runtime::oref const &o) { return o->to_hash(); } diff --git a/compiler+runtime/src/cpp/jank/read/parse.cpp b/compiler+runtime/src/cpp/jank/read/parse.cpp index 21e1c6dfe..f3121cba0 100644 --- a/compiler+runtime/src/cpp/jank/read/parse.cpp +++ b/compiler+runtime/src/cpp/jank/read/parse.cpp @@ -536,8 +536,8 @@ namespace jank::read::parse } auto meta_result(visit_object( - [&](auto const typed_val) -> processor::object_result { - using T = typename decltype(typed_val)::value_type; + [&](auto const &typed_val) -> processor::object_result { + using T = typename jtl::decay_t::value_type; if constexpr(jtl::is_same) { return object_source_info{ obj::persistent_array_map::create_unique(typed_val, jank_true), @@ -571,8 +571,8 @@ namespace jank::read::parse } return visit_object( - [&](auto const typed_val) -> processor::object_result { - using T = typename decltype(typed_val)::value_type; + [&](auto const &typed_val) -> processor::object_result { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::metadatable) { if(typed_val->meta.is_none()) @@ -1082,7 +1082,7 @@ namespace jank::read::parse auto const s(*(++it)); return visit_seqable( - [&](auto const typed_s) -> processor::object_result { + [&](auto const &typed_s) -> processor::object_result { auto const r{ make_sequence_range(typed_s) }; if(r.begin() == r.end()) { @@ -1115,7 +1115,7 @@ namespace jank::read::parse return ok(none); } - jtl::result processor::syntax_quote_expand_seq(object_ref const seq) + jtl::result processor::syntax_quote_expand_seq(object_ref const &seq) { if(seq.is_nil()) { @@ -1123,7 +1123,7 @@ namespace jank::read::parse } return visit_seqable( - [this](auto const typed_seq) -> jtl::result { + [this](auto const &typed_seq) -> jtl::result { runtime::detail::native_transient_vector ret; for(auto const item : make_sequence_range(typed_seq)) { @@ -1151,7 +1151,7 @@ namespace jank::read::parse quoted_item.expect_ok())); } } - auto const vec(make_box(ret.persistent())->seq()); + auto vec(make_box(ret.persistent())->seq()); return vec; }, []() -> jtl::result { @@ -1160,7 +1160,7 @@ namespace jank::read::parse seq); } - jtl::result processor::syntax_quote_flatten_map(object_ref const seq) + jtl::result processor::syntax_quote_flatten_map(object_ref const &seq) { if(seq.is_nil()) { @@ -1168,14 +1168,14 @@ namespace jank::read::parse } return visit_seqable( - [](auto const typed_seq) -> jtl::result { + [](auto const &typed_seq) -> jtl::result { runtime::detail::native_transient_vector ret; for(auto const item : make_sequence_range(typed_seq)) { ret.push_back(first(item)); ret.push_back(second(item)); } - auto const vec(make_box(ret.persistent())->seq()); + auto vec(make_box(ret.persistent())->seq()); return vec; }, []() -> jtl::result { @@ -1184,7 +1184,7 @@ namespace jank::read::parse seq); } - jtl::result processor::syntax_quote_expand_set(object_ref const seq) + jtl::result processor::syntax_quote_expand_set(object_ref const &seq) { if(seq.is_nil()) { @@ -1192,7 +1192,7 @@ namespace jank::read::parse } return visit_seqable( - [this](auto const typed_seq) -> jtl::result { + [this](auto const &typed_seq) -> jtl::result { runtime::detail::native_transient_vector ret; for(auto const item : make_sequence_range(typed_seq)) { @@ -1220,7 +1220,7 @@ namespace jank::read::parse quoted_item.expect_ok())); } } - auto const vec(make_box(ret.persistent())->seq()); + auto vec(make_box(ret.persistent())->seq()); return vec; }, []() -> jtl::result { @@ -1229,10 +1229,10 @@ namespace jank::read::parse seq); } - bool processor::syntax_quote_is_unquote(object_ref const form, bool const splice) + bool processor::syntax_quote_is_unquote(object_ref const &form, bool const splice) { return visit_seqable( - [splice](auto const typed_form) { + [splice](auto const &typed_form) { auto const s(typed_form->seq()); object_ref const item{ s.is_some() ? first(s).erase() : s.erase() }; @@ -1243,7 +1243,7 @@ namespace jank::read::parse form); } - jtl::result processor::syntax_quote(object_ref const form) + jtl::result processor::syntax_quote(object_ref const &form) { object_ref ret{}; @@ -1311,8 +1311,8 @@ namespace jank::read::parse * flattening them, qualifying the symbols, and then building up code which will * reassemble them. */ auto const res{ visit_seqable( - [&](auto const typed_form) -> jtl::result { - using T = typename decltype(typed_form)::value_type; + [&](auto const &typed_form) -> jtl::result { + using T = typename jtl::decay_t::value_type; if constexpr(jtl::is_same) { diff --git a/compiler+runtime/src/cpp/jank/read/reparse.cpp b/compiler+runtime/src/cpp/jank/read/reparse.cpp index 2aef559e8..67d02523f 100644 --- a/compiler+runtime/src/cpp/jank/read/reparse.cpp +++ b/compiler+runtime/src/cpp/jank/read/reparse.cpp @@ -16,7 +16,7 @@ namespace jank::read::parse jtl::immutable_string const &module, usize const offset, usize const n, - object_ref const macro_expansion) + object_ref const ¯o_expansion) { if(module == no_source_path) { @@ -62,7 +62,7 @@ namespace jank::read::parse return source{ file, module, res.start.start, res.end.end, macro_expansion }; } - source reparse_nth(obj::persistent_list_ref const o, usize const n) + source reparse_nth(obj::persistent_list_ref const &o, usize const n) { auto source(object_source(o)); if(source == source::unknown()) @@ -81,7 +81,7 @@ namespace jank::read::parse return res.expect_ok(); } - source reparse_nth(runtime::obj::persistent_vector_ref const o, usize const n) + source reparse_nth(runtime::obj::persistent_vector_ref const &o, usize const n) { auto source(object_source(o)); if(source == source::unknown()) @@ -100,15 +100,15 @@ namespace jank::read::parse return res.expect_ok(); } - source reparse_nth(runtime::object_ref const o, usize const n) + source reparse_nth(runtime::object_ref const &o, usize const n) { /* When we have an object, but we're not sure of the type, let's just * see if it's one of the types we support. If not, we'll error out. * We can do more here, going forward, by supporting various sequences and such, * but this will be fine for now. */ return visit_seqable( - [](auto const typed_o, usize const n) -> source { - using T = typename decltype(typed_o)::value_type; + [](auto const &typed_o, usize const n) -> source { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as || std::same_as) diff --git a/compiler+runtime/src/cpp/jank/read/source.cpp b/compiler+runtime/src/cpp/jank/read/source.cpp index b4457208a..fc666cb40 100644 --- a/compiler+runtime/src/cpp/jank/read/source.cpp +++ b/compiler+runtime/src/cpp/jank/read/source.cpp @@ -45,7 +45,7 @@ namespace jank::read jtl::immutable_string const &module, source_position const &start, source_position const &end, - runtime::object_ref const macro_expansion) + runtime::object_ref const ¯o_expansion) : file{ file } , module{ module } , start{ start } diff --git a/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp b/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp index 18cf846ae..7607775c8 100644 --- a/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp @@ -19,12 +19,12 @@ namespace jank::runtime return source; } - object_ref dynamic_call(object_ref const source) + object_ref dynamic_call(object_ref const &source) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const typed_source) -> object_ref { - using T = typename decltype(typed_source)::value_type; + [=](auto const &typed_source) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) { @@ -47,12 +47,12 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const source, object_ref const a1) + object_ref dynamic_call(object_ref const &source, object_ref const &a1) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const typed_source) -> object_ref { - using T = typename decltype(typed_source)::value_type; + [=](auto const &typed_source) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) { @@ -91,12 +91,12 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const source, object_ref const a1, object_ref const a2) + object_ref dynamic_call(object_ref const &source, object_ref const &a1, object_ref const &a2) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const typed_source) -> object_ref { - using T = typename decltype(typed_source)::value_type; + [=](auto const &typed_source) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) { @@ -134,15 +134,15 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const source, - object_ref const a1, - object_ref const a2, - object_ref const a3) + object_ref dynamic_call(object_ref const &source, + object_ref const &a1, + object_ref const &a2, + object_ref const &a3) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const typed_source) -> object_ref { - using T = typename decltype(typed_source)::value_type; + [=](auto const &typed_source) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) { @@ -175,16 +175,16 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const source, - object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4) + object_ref dynamic_call(object_ref const &source, + object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const typed_source) -> object_ref { - using T = typename decltype(typed_source)::value_type; + [=](auto const &typed_source) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) { @@ -219,17 +219,17 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const source, - object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5) + object_ref dynamic_call(object_ref const &source, + object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const typed_source) -> object_ref { - using T = typename decltype(typed_source)::value_type; + [=](auto const &typed_source) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) { @@ -266,18 +266,18 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const source, - object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6) + object_ref dynamic_call(object_ref const &source, + object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const typed_source) -> object_ref { - using T = typename decltype(typed_source)::value_type; + [=](auto const &typed_source) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) { @@ -328,19 +328,19 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const source, - object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7) + object_ref dynamic_call(object_ref const &source, + object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const typed_source) -> object_ref { - using T = typename decltype(typed_source)::value_type; + [=](auto const &typed_source) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) { @@ -395,20 +395,20 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const source, - object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7, - object_ref const a8) + object_ref dynamic_call(object_ref const &source, + object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7, + object_ref const &a8) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const typed_source) -> object_ref { - using T = typename decltype(typed_source)::value_type; + [=](auto const &typed_source) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) { @@ -467,21 +467,21 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const source, - object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7, - object_ref const a8, - object_ref const a9) + object_ref dynamic_call(object_ref const &source, + object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7, + object_ref const &a8, + object_ref const &a9) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const typed_source) -> object_ref { - using T = typename decltype(typed_source)::value_type; + [=](auto const &typed_source) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) { @@ -541,22 +541,22 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const source, - object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7, - object_ref const a8, - object_ref const a9, - object_ref const a10) + object_ref dynamic_call(object_ref const &source, + object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7, + object_ref const &a8, + object_ref const &a9, + object_ref const &a10) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const typed_source) -> object_ref { - using T = typename decltype(typed_source)::value_type; + [=](auto const &typed_source) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) { @@ -662,24 +662,24 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const source, - object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7, - object_ref const a8, - object_ref const a9, - object_ref const a10, - obj::persistent_list_ref const rest) + object_ref dynamic_call(object_ref const &source, + object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7, + object_ref const &a8, + object_ref const &a9, + object_ref const &a10, + obj::persistent_list_ref const &rest) { /* TODO: Move call fns into var so we can remove these checks. */ auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const typed_source) -> object_ref { - using T = typename decltype(typed_source)::value_type; + [=](auto const &typed_source) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) { @@ -827,10 +827,10 @@ namespace jank::runtime processed_source); } - object_ref apply_to(object_ref const source, object_ref const args) + object_ref apply_to(object_ref const &source, object_ref const &args) { return visit_seqable( - [=](auto const typed_args) -> object_ref { + [=](auto const &typed_args) -> object_ref { auto const s(typed_args->fresh_seq()); auto const length(sequence_length(s, max_params + 1)); auto const r{ make_sequence_range(s) }; @@ -975,83 +975,92 @@ namespace jank::runtime throw invalid_arity<0>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref) + object_ref callable::call(object_ref const &) { throw invalid_arity<1>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref, object_ref) + object_ref callable::call(object_ref const &, object_ref const &) { throw invalid_arity<2>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref, object_ref, object_ref) + object_ref callable::call(object_ref const &, object_ref const &, object_ref const &) { throw invalid_arity<3>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref, object_ref, object_ref, object_ref) + object_ref + callable::call(object_ref const &, object_ref const &, object_ref const &, object_ref const &) { throw invalid_arity<4>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref, object_ref, object_ref, object_ref, object_ref) + object_ref callable::call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) { throw invalid_arity<5>{ runtime::to_code_string(this_object_ref()) }; } - object_ref - callable::call(object_ref, object_ref, object_ref, object_ref, object_ref, object_ref) + object_ref callable::call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) { throw invalid_arity<6>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) + object_ref callable::call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) { throw invalid_arity<7>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) + object_ref callable::call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) { throw invalid_arity<8>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) + object_ref callable::call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) { throw invalid_arity<9>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref, - object_ref) + object_ref callable::call(object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &, + object_ref const &) { throw invalid_arity<10>{ runtime::to_code_string(this_object_ref()) }; } diff --git a/compiler+runtime/src/cpp/jank/runtime/behavior/metadatable.cpp b/compiler+runtime/src/cpp/jank/runtime/behavior/metadatable.cpp index 03ef403eb..c37aef25b 100644 --- a/compiler+runtime/src/cpp/jank/runtime/behavior/metadatable.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/behavior/metadatable.cpp @@ -6,9 +6,9 @@ namespace jank::runtime::behavior::detail { - object_ref validate_meta(object_ref const m) + object_ref validate_meta(object_ref const &m) { - if(!is_map(m) && m != jank_nil()) + if(!is_map(m) && m.is_some()) { throw std::runtime_error{ util::format("invalid meta: {}", runtime::to_string(m)) }; } diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index dd59d14c1..9fc7f9b43 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -1,5 +1,3 @@ -#include - #include #include #include @@ -363,7 +361,7 @@ namespace jank::runtime return load_module(util::format("/{}", module), module::origin::latest); } - object_ref context::eval(object_ref const o) + object_ref context::eval(object_ref const &o) { auto const expr( analyze::pass::optimize(an_prc.analyze(o, analyze::expression_position::value).expect_ok())); @@ -507,7 +505,7 @@ namespace jank::runtime ns_ref context::resolve_ns(obj::symbol_ref const &target) { auto const ns(current_ns()); - auto const alias(ns->find_alias(target)); + auto alias(ns->find_alias(target)); if(alias.is_some()) { return alias; @@ -534,24 +532,24 @@ namespace jank::runtime } jtl::result - context::intern_var(obj::symbol_ref const &qualified_sym) + context::intern_var(obj::symbol_ref const &qualified_name) { profile::timer const timer{ "intern_var" }; - if(qualified_sym->ns.empty()) + if(qualified_name->ns.empty()) { return err( - util::format("Can't intern var. Sym isn't qualified: {}", qualified_sym->to_string())); + util::format("Can't intern var. Sym isn't qualified: {}", qualified_name->to_string())); } auto locked_namespaces(namespaces.wlock()); - obj::symbol_ref ns_sym{ make_box(qualified_sym->ns) }; + obj::symbol_ref const ns_sym{ make_box(qualified_name->ns) }; auto const found_ns(locked_namespaces->find(ns_sym)); if(found_ns == locked_namespaces->end()) { - return err(util::format("Can't intern var. Namespace doesn't exist: {}", qualified_sym->ns)); + return err(util::format("Can't intern var. Namespace doesn't exist: {}", qualified_name->ns)); } - return ok(found_ns->second->intern_var(qualified_sym)); + return ok(found_ns->second->intern_var(qualified_name)); } jtl::result @@ -632,12 +630,12 @@ namespace jank::runtime return res.first->second; } - object_ref context::macroexpand1(object_ref const o) + object_ref context::macroexpand1(object_ref const &o) { profile::timer const timer{ "rt macroexpand1" }; return visit_seqable( - [this](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [this](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(!behavior::sequenceable) { @@ -674,7 +672,7 @@ namespace jank::runtime o); } - object_ref context::macroexpand(object_ref const o) + object_ref context::macroexpand(object_ref const &o) { auto expanded(macroexpand1(o)); if(expanded != o) @@ -701,7 +699,7 @@ namespace jank::runtime __rt_ctx->push_thread_bindings().expect_ok(); } - context::binding_scope::binding_scope(obj::persistent_hash_map_ref const bindings) + context::binding_scope::binding_scope(obj::persistent_hash_map_ref const &bindings) { __rt_ctx->push_thread_bindings(bindings).expect_ok(); } @@ -735,7 +733,7 @@ namespace jank::runtime return push_thread_bindings(bindings); } - jtl::string_result context::push_thread_bindings(object_ref const bindings) + jtl::string_result context::push_thread_bindings(object_ref const &bindings) { if(bindings->type != object_type::persistent_hash_map) { @@ -747,7 +745,7 @@ namespace jank::runtime } jtl::string_result - context::push_thread_bindings(obj::persistent_hash_map_ref const bindings) + context::push_thread_bindings(obj::persistent_hash_map_ref const &bindings) { thread_binding_frame frame{ obj::persistent_hash_map::empty() }; auto &tbfs(thread_binding_frames); diff --git a/compiler+runtime/src/cpp/jank/runtime/core.cpp b/compiler+runtime/src/cpp/jank/runtime/core.cpp index e5a13393c..e6c0b1d46 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core.cpp @@ -9,61 +9,61 @@ namespace jank::runtime { - jtl::immutable_string type(object_ref const o) + jtl::immutable_string type(object_ref const &o) { return object_type_str(o->type); } - bool is_nil(object_ref const o) + bool is_nil(object_ref const &o) { return o == jank_nil(); } - bool is_true(object_ref const o) + bool is_true(object_ref const &o) { return o == jank_true; } - bool is_false(object_ref const o) + bool is_false(object_ref const &o) { return o == jank_false; } - bool is_some(object_ref const o) + bool is_some(object_ref const &o) { return o != jank_nil(); } - bool is_string(object_ref const o) + bool is_string(object_ref const &o) { return o->type == object_type::persistent_string; } - bool is_char(object_ref const o) + bool is_char(object_ref const &o) { return o->type == object_type::character; } - bool is_symbol(object_ref const o) + bool is_symbol(object_ref const &o) { return o->type == object_type::symbol; } - bool is_simple_symbol(object_ref const o) + bool is_simple_symbol(object_ref const &o) { return o->type == object_type::symbol && expect_object(o)->ns.empty(); } - bool is_qualified_symbol(object_ref const o) + bool is_qualified_symbol(object_ref const &o) { return o->type == object_type::symbol && !expect_object(o)->ns.empty(); } - object_ref to_unqualified_symbol(object_ref const o) + object_ref to_unqualified_symbol(object_ref const &o) { return runtime::visit_object( - [&](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [&](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -90,16 +90,16 @@ namespace jank::runtime o); } - object_ref to_qualified_symbol(object_ref const ns, object_ref const name) + object_ref to_qualified_symbol(object_ref const &ns, object_ref const &name) { return make_box(ns, name); } - object_ref print(object_ref const args) + object_ref print(object_ref const &args) { visit_object( - [](auto const typed_args) { - using T = typename decltype(typed_args)::value_type; + [](auto const &typed_args) { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::sequenceable) { @@ -122,11 +122,11 @@ namespace jank::runtime return jank_nil(); } - object_ref println(object_ref const args) + object_ref println(object_ref const &args) { visit_object( - [](auto const typed_more) { - using T = typename decltype(typed_more)::value_type; + [](auto const &typed_more) { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -154,11 +154,11 @@ namespace jank::runtime return jank_nil(); } - object_ref pr(object_ref const args) + object_ref pr(object_ref const &args) { visit_object( - [](auto const typed_args) { - using T = typename decltype(typed_args)::value_type; + [](auto const &typed_args) { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::sequenceable) { @@ -181,11 +181,11 @@ namespace jank::runtime return jank_nil(); } - object_ref prn(object_ref const args) + object_ref prn(object_ref const &args) { visit_object( - [](auto const typed_args) { - using T = typename decltype(typed_args)::value_type; + [](auto const &typed_args) { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -213,28 +213,21 @@ namespace jank::runtime return jank_nil(); } - f64 to_real(object_ref const o) - { - return visit_number_like( - [](auto const typed_o) -> f64 { return typed_o->to_real(); }, - [=]() -> f64 { throw std::runtime_error{ util::format("not a number: {}", to_string(o)) }; }, - o); - } - - obj::persistent_string_ref subs(object_ref const s, object_ref const start) + obj::persistent_string_ref subs(object_ref const &s, object_ref const &start) { return visit_type( - [](auto const typed_s, i64 const start) -> obj::persistent_string_ref { + [](auto const &typed_s, i64 const start) -> obj::persistent_string_ref { return typed_s->substring(start).expect_ok(); }, s, to_int(start)); } - obj::persistent_string_ref subs(object_ref const s, object_ref const start, object_ref const end) + obj::persistent_string_ref + subs(object_ref const &s, object_ref const &start, object_ref const &end) { return visit_type( - [](auto const typed_s, i64 const start, i64 const end) -> obj::persistent_string_ref { + [](auto const &typed_s, i64 const start, i64 const end) -> obj::persistent_string_ref { return typed_s->substring(start, end).expect_ok(); }, s, @@ -242,38 +235,38 @@ namespace jank::runtime to_int(end)); } - i64 first_index_of(object_ref const s, object_ref const m) + i64 first_index_of(object_ref const &s, object_ref const &m) { return visit_type( - [](auto const typed_s, object_ref const m) -> i64 { return typed_s->first_index_of(m); }, + [](auto const &typed_s, object_ref const &m) -> i64 { return typed_s->first_index_of(m); }, s, m); } - i64 last_index_of(object_ref const s, object_ref const m) + i64 last_index_of(object_ref const &s, object_ref const &m) { return visit_type( - [](auto const typed_s, object_ref const m) -> i64 { return typed_s->last_index_of(m); }, + [](auto const &typed_s, object_ref const &m) -> i64 { return typed_s->last_index_of(m); }, s, m); } - bool is_named(object_ref const o) + bool is_named(object_ref const &o) { return visit_object( - [](auto const typed_o) { - using T = typename decltype(typed_o)::value_type; + [](auto const &typed_o) { + using T = typename jtl::decay_t::value_type; return behavior::nameable; }, o); } - jtl::immutable_string name(object_ref const o) + jtl::immutable_string name(object_ref const &o) { return visit_object( - [](auto const typed_o) -> jtl::immutable_string { - using T = typename decltype(typed_o)::value_type; + [](auto const &typed_o) -> jtl::immutable_string { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -291,11 +284,11 @@ namespace jank::runtime o); } - object_ref namespace_(object_ref const o) + object_ref namespace_(object_ref const &o) { return visit_object( - [](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::nameable) { @@ -314,7 +307,7 @@ namespace jank::runtime o); } - object_ref keyword(object_ref const ns, object_ref const name) + object_ref keyword(object_ref const &ns, object_ref const &name) { if(!ns.is_nil() && ns->type != object_type::persistent_string) { @@ -337,128 +330,132 @@ namespace jank::runtime return __rt_ctx->intern_keyword(runtime::to_string(ns), runtime::to_string(name)).expect_ok(); } - bool is_keyword(object_ref const o) + bool is_keyword(object_ref const &o) { return o->type == object_type::keyword; } - bool is_simple_keyword(object_ref const o) + bool is_simple_keyword(object_ref const &o) { return o->type == object_type::keyword && expect_object(o)->sym->ns.empty(); } - bool is_qualified_keyword(object_ref const o) + bool is_qualified_keyword(object_ref const &o) { return o->type == object_type::keyword && !expect_object(o)->sym->ns.empty(); } - bool is_callable(object_ref const o) + bool is_callable(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> bool { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> bool { + using T = typename jtl::decay_t::value_type; return std::is_base_of_v; }, o); } - uhash to_hash(object_ref const o) + uhash to_hash(object_ref const &o) { - return visit_object([=](auto const typed_o) -> uhash { return typed_o->to_hash(); }, o); + return visit_object([=](auto const &typed_o) -> uhash { return typed_o->to_hash(); }, o); } - object_ref macroexpand1(object_ref const o) + object_ref macroexpand1(object_ref const &o) { return __rt_ctx->macroexpand1(o); } - object_ref macroexpand(object_ref const o) + object_ref macroexpand(object_ref const &o) { return __rt_ctx->macroexpand(o); } - object_ref gensym(object_ref const o) + object_ref gensym(object_ref const &o) { return __rt_ctx->unique_symbol(to_string(o)); } - object_ref atom(object_ref const o) + object_ref atom(object_ref const &o) { return make_box(o); } - object_ref swap_atom(object_ref const atom, object_ref const fn) + object_ref swap_atom(object_ref const &atom, object_ref const &fn) { return try_object(atom)->swap(fn); } - object_ref swap_atom(object_ref const atom, object_ref const fn, object_ref const a1) + object_ref swap_atom(object_ref const &atom, object_ref const &fn, object_ref const &a1) { return try_object(atom)->swap(fn, a1); } - object_ref - swap_atom(object_ref const atom, object_ref const fn, object_ref const a1, object_ref const a2) + object_ref swap_atom(object_ref const &atom, + object_ref const &fn, + object_ref const &a1, + object_ref const &a2) { return try_object(atom)->swap(fn, a1, a2); } - object_ref swap_atom(object_ref const atom, - object_ref const fn, - object_ref const a1, - object_ref const a2, - object_ref const rest) + object_ref swap_atom(object_ref const &atom, + object_ref const &fn, + object_ref const &a1, + object_ref const &a2, + object_ref const &rest) { return try_object(atom)->swap(fn, a1, a2, rest); } - object_ref swap_vals(object_ref const atom, object_ref const fn) + object_ref swap_vals(object_ref const &atom, object_ref const &fn) { return try_object(atom)->swap_vals(fn); } - object_ref swap_vals(object_ref const atom, object_ref const fn, object_ref const a1) + object_ref swap_vals(object_ref const &atom, object_ref const &fn, object_ref const &a1) { return try_object(atom)->swap_vals(fn, a1); } - object_ref - swap_vals(object_ref const atom, object_ref const fn, object_ref const a1, object_ref const a2) + object_ref swap_vals(object_ref const &atom, + object_ref const &fn, + object_ref const &a1, + object_ref const &a2) { return try_object(atom)->swap_vals(fn, a1, a2); } - object_ref swap_vals(object_ref const atom, - object_ref const fn, - object_ref const a1, - object_ref const a2, - object_ref const rest) + object_ref swap_vals(object_ref const &atom, + object_ref const &fn, + object_ref const &a1, + object_ref const &a2, + object_ref const &rest) { return try_object(atom)->swap_vals(fn, a1, a2, rest); } object_ref - compare_and_set(object_ref const atom, object_ref const old_val, object_ref const new_val) + compare_and_set(object_ref const &atom, object_ref const &old_val, object_ref const &new_val) { return try_object(atom)->compare_and_set(old_val, new_val); } - object_ref reset(object_ref const atom, object_ref const new_val) + object_ref reset(object_ref const &atom, object_ref const &new_val) { return try_object(atom)->reset(new_val); } - object_ref reset_vals(object_ref const atom, object_ref const new_val) + object_ref reset_vals(object_ref const &atom, object_ref const &new_val) { return try_object(atom)->reset_vals(new_val); } - object_ref deref(object_ref const o) + object_ref deref(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::derefable) { @@ -472,34 +469,34 @@ namespace jank::runtime o); } - object_ref volatile_(object_ref const o) + object_ref volatile_(object_ref const &o) { return make_box(o); } - bool is_volatile(object_ref const o) + bool is_volatile(object_ref const &o) { return o->type == object_type::volatile_; } - object_ref vswap(object_ref const v, object_ref const fn) + object_ref vswap(object_ref const &v, object_ref const &fn) { auto const v_obj(try_object(v)); return v_obj->reset(dynamic_call(fn, v_obj->deref())); } - object_ref vswap(object_ref const v, object_ref const fn, object_ref const args) + object_ref vswap(object_ref const &v, object_ref const &fn, object_ref const &args) { auto const v_obj(try_object(v)); return v_obj->reset(apply_to(fn, make_box(v_obj->deref(), args))); } - object_ref vreset(object_ref const v, object_ref const new_val) + object_ref vreset(object_ref const &v, object_ref const &new_val) { return try_object(v)->reset(new_val); } - void push_thread_bindings(object_ref const o) + void push_thread_bindings(object_ref const &o) { __rt_ctx->push_thread_bindings(o).expect_ok(); } @@ -514,7 +511,7 @@ namespace jank::runtime return __rt_ctx->get_thread_bindings(); } - object_ref force(object_ref const o) + object_ref force(object_ref const &o) { if(o->type == object_type::delay) { @@ -523,22 +520,22 @@ namespace jank::runtime return o; } - object_ref tagged_literal(object_ref const tag, object_ref const form) + object_ref tagged_literal(object_ref const &tag, object_ref const &form) { return make_box(tag, form); } - bool is_tagged_literal(object_ref const o) + bool is_tagged_literal(object_ref const &o) { return o->type == object_type::tagged_literal; } - object_ref re_pattern(object_ref const o) + object_ref re_pattern(object_ref const &o) { return make_box(try_object(o)->data); } - object_ref re_matcher(object_ref const re, object_ref const s) + object_ref re_matcher(object_ref const &re, object_ref const &s) { return make_box(try_object(re), try_object(s)->data); @@ -571,7 +568,7 @@ namespace jank::runtime } } - object_ref re_find(object_ref const m) + object_ref re_find(object_ref const &m) { std::smatch match_results{}; auto const matcher(try_object(m)); @@ -589,7 +586,7 @@ namespace jank::runtime return matcher->groups; } - object_ref re_groups(object_ref const m) + object_ref re_groups(object_ref const &m) { auto const matcher(try_object(m)); @@ -601,7 +598,7 @@ namespace jank::runtime return matcher->groups; } - object_ref re_matches(object_ref const re, object_ref const s) + object_ref re_matches(object_ref const &re, object_ref const &s) { std::smatch match_results{}; std::string const search_str{ try_object(s)->data.c_str() }; @@ -619,7 +616,7 @@ namespace jank::runtime return smatch_to_vector(match_results); } - object_ref parse_uuid(object_ref const o) + object_ref parse_uuid(object_ref const &o) { if(o->type == object_type::persistent_string) { @@ -638,7 +635,7 @@ namespace jank::runtime } } - bool is_uuid(object_ref const o) + bool is_uuid(object_ref const &o) { return o->type == object_type::uuid; } @@ -648,12 +645,12 @@ namespace jank::runtime return make_box(); } - bool is_inst(object_ref const o) + bool is_inst(object_ref const &o) { return o->type == object_type::inst; } - i64 inst_ms(object_ref const o) + i64 inst_ms(object_ref const &o) { if(o->type != object_type::inst) { @@ -666,11 +663,11 @@ namespace jank::runtime .count(); } - object_ref add_watch(object_ref const reference, object_ref const key, object_ref const fn) + object_ref add_watch(object_ref const &reference, object_ref const &key, object_ref const &fn) { visit_object( - [=](auto const typed_reference) -> void { - using T = typename decltype(typed_reference)::value_type; + [=](auto const &typed_reference) -> void { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::ref_like) { @@ -688,11 +685,11 @@ namespace jank::runtime return reference; } - object_ref remove_watch(object_ref const reference, object_ref const key) + object_ref remove_watch(object_ref const &reference, object_ref const &key) { visit_object( - [=](auto const typed_reference) -> void { - using T = typename decltype(typed_reference)::value_type; + [=](auto const &typed_reference) -> void { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::ref_like) { diff --git a/compiler+runtime/src/cpp/jank/runtime/core/equal.cpp b/compiler+runtime/src/cpp/jank/runtime/core/equal.cpp index f234d01c3..a493bf44d 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/equal.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/equal.cpp @@ -5,18 +5,18 @@ namespace jank::runtime { - bool equal(char const lhs, object_ref const rhs) + bool equal(char const lhs, object_ref const &rhs) { if(rhs.is_nil() || rhs->type != object_type::character) { return false; } - auto const typed_rhs = expect_object(rhs); + auto const typed_rhs{ expect_object(rhs) }; return typed_rhs->to_hash() == static_cast(lhs); } - bool equal(object_ref const lhs, object_ref const rhs) + bool equal(object_ref const &lhs, object_ref const &rhs) { if(lhs.is_nil()) { @@ -27,10 +27,10 @@ namespace jank::runtime return false; } - return visit_object([&](auto const typed_lhs) { return typed_lhs->equal(*rhs); }, lhs); + return visit_object([&](auto const &typed_lhs) { return typed_lhs->equal(*rhs); }, lhs); } - i64 compare(object_ref const l, object_ref const r) + i64 compare(object_ref const &l, object_ref const &r) { if(l == r) { @@ -45,8 +45,8 @@ namespace jank::runtime } return visit_object( - [](auto const typed_l, auto const r) -> i64 { - using L = typename decltype(typed_l)::value_type; + [](auto const &typed_l, auto const &r) -> i64 { + using L = typename jtl::decay_t::value_type; if constexpr(behavior::comparable) { return typed_l->compare(*r); @@ -63,7 +63,7 @@ namespace jank::runtime return -1; } - bool is_identical(object_ref const lhs, object_ref const rhs) + bool is_identical(object_ref const &lhs, object_ref const &rhs) { return lhs == rhs; } diff --git a/compiler+runtime/src/cpp/jank/runtime/core/math.cpp b/compiler+runtime/src/cpp/jank/runtime/core/math.cpp index d70a90362..76d842d97 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/math.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/math.cpp @@ -36,12 +36,12 @@ namespace jank::runtime } /* TODO: visit_number_like */ - object_ref add(object_ref const l, object_ref const r) + object_ref add(object_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const r) -> object_ref { + [](auto const &typed_l, auto const &r) -> object_ref { return visit_number_like( - [](auto const typed_r, auto const &typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l + typed_r->data).erase(); }, r, @@ -51,80 +51,80 @@ namespace jank::runtime r); } - object_ref add(obj::integer_ref const l, object_ref const r) + object_ref add(obj::integer_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l + typed_r->data); }, r, l->data); } - object_ref add(object_ref const l, obj::integer_ref const r) + object_ref add(object_ref const &l, obj::integer_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const &typed_r) -> object_ref { return make_box(typed_l->data + typed_r); }, l, r->data); } - i64 add(obj::integer_ref const l, obj::integer_ref const r) + i64 add(obj::integer_ref const &l, obj::integer_ref const &r) { return l->data + r->data; } - f64 add(obj::real_ref const l, obj::real_ref const r) + f64 add(obj::real_ref const &l, obj::real_ref const &r) { return l->data + r->data; } - object_ref add(obj::real_ref const l, object_ref const r) + object_ref add(obj::real_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l + typed_r->data); }, r, l->data); } - object_ref add(object_ref const l, obj::real_ref const r) + object_ref add(object_ref const &l, obj::real_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data + typed_r); }, l, r->data); } - f64 add(obj::real_ref const l, obj::integer_ref const r) + f64 add(obj::real_ref const &l, obj::integer_ref const &r) { return l->data + static_cast(r->data); } - f64 add(obj::integer_ref const l, obj::real_ref const r) + f64 add(obj::integer_ref const &l, obj::real_ref const &r) { return static_cast(l->data) + r->data; } - object_ref add(object_ref const l, f64 const r) + object_ref add(object_ref const &l, f64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data + typed_r); }, l, r); } - object_ref add(f64 const l, object_ref const r) + object_ref add(f64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const typed_l) -> object_ref { return make_box(typed_l + typed_r->data); }, r, @@ -146,20 +146,20 @@ namespace jank::runtime return l + static_cast(r); } - object_ref add(object_ref const l, i64 const r) + object_ref add(object_ref const &l, i64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const &typed_r) -> object_ref { return make_box(typed_l->data + typed_r); }, l, r); } - object_ref add(i64 const l, object_ref const r) + object_ref add(i64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l + typed_r->data); }, r, @@ -171,12 +171,12 @@ namespace jank::runtime return l + r; } - object_ref sub(object_ref const l, object_ref const r) + object_ref sub(object_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const r) -> object_ref { + [](auto const &typed_l, auto const &r) -> object_ref { return visit_number_like( - [](auto const typed_r, auto const &typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l - typed_r->data).erase(); }, r, @@ -186,80 +186,80 @@ namespace jank::runtime r); } - object_ref sub(obj::integer_ref const l, object_ref const r) + object_ref sub(obj::integer_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l - typed_r->data); }, r, l->data); } - object_ref sub(object_ref const l, obj::integer_ref const r) + object_ref sub(object_ref const &l, obj::integer_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const &typed_r) -> object_ref { return make_box(typed_l->data - typed_r); }, l, r->data); } - i64 sub(obj::integer_ref const l, obj::integer_ref const r) + i64 sub(obj::integer_ref const &l, obj::integer_ref const &r) { return l->data - r->data; } - f64 sub(obj::real_ref const l, obj::real_ref const r) + f64 sub(obj::real_ref const &l, obj::real_ref const &r) { return l->data - r->data; } - object_ref sub(obj::real_ref const l, object_ref const r) + object_ref sub(obj::real_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l - typed_r->data); }, r, l->data); } - object_ref sub(object_ref const l, obj::real_ref const r) + object_ref sub(object_ref const &l, obj::real_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const &typed_r) -> object_ref { return make_box(typed_l->data - typed_r); }, l, r->data); } - f64 sub(obj::real_ref const l, obj::integer_ref const r) + f64 sub(obj::real_ref const &l, obj::integer_ref const &r) { return l->data - static_cast(r->data); } - f64 sub(obj::integer_ref const l, obj::real_ref const r) + f64 sub(obj::integer_ref const &l, obj::real_ref const &r) { return static_cast(l->data) - r->data; } - object_ref sub(object_ref const l, f64 const r) + object_ref sub(object_ref const &l, f64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data - typed_r); }, l, r); } - object_ref sub(f64 const l, object_ref const r) + object_ref sub(f64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const typed_l) -> object_ref { return make_box(typed_l - typed_r->data); }, r, @@ -281,20 +281,20 @@ namespace jank::runtime return l - static_cast(r); } - object_ref sub(object_ref const l, i64 const r) + object_ref sub(object_ref const &l, i64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data - typed_r); }, l, r); } - object_ref sub(i64 const l, object_ref const r) + object_ref sub(i64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const typed_l) -> object_ref { return make_box(typed_l - typed_r->data); }, r, @@ -306,12 +306,12 @@ namespace jank::runtime return l - r; } - object_ref div(object_ref const l, object_ref const r) + object_ref div(object_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const r) -> object_ref { + [](auto const &typed_l, auto const &r) -> object_ref { return visit_number_like( - [](auto const typed_r, auto const &typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l / typed_r->data).erase(); }, r, @@ -321,80 +321,80 @@ namespace jank::runtime r); } - object_ref div(obj::integer_ref const l, object_ref const r) + object_ref div(obj::integer_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l / typed_r->data); }, r, l->data); } - object_ref div(object_ref const l, obj::integer_ref const r) + object_ref div(object_ref const &l, obj::integer_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const &typed_r) -> object_ref { return make_box(typed_l->data / typed_r); }, l, r->data); } - i64 div(obj::integer_ref const l, obj::integer_ref const r) + i64 div(obj::integer_ref const &l, obj::integer_ref const &r) { return l->data / r->data; } - f64 div(obj::real_ref const l, obj::real_ref const r) + f64 div(obj::real_ref const &l, obj::real_ref const &r) { return l->data / r->data; } - object_ref div(obj::real_ref const l, object_ref const r) + object_ref div(obj::real_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l / typed_r->data); }, r, l->data); } - object_ref div(object_ref const l, obj::real_ref const r) + object_ref div(object_ref const &l, obj::real_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const &typed_r) -> object_ref { return make_box(typed_l->data / typed_r); }, l, r->data); } - f64 div(obj::real_ref const l, obj::integer_ref const r) + f64 div(obj::real_ref const &l, obj::integer_ref const &r) { return l->data / static_cast(r->data); } - f64 div(obj::integer_ref const l, obj::real_ref const r) + f64 div(obj::integer_ref const &l, obj::real_ref const &r) { return static_cast(l->data) / r->data; } - object_ref div(object_ref const l, f64 const r) + object_ref div(object_ref const &l, f64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data / typed_r); }, l, r); } - object_ref div(f64 const l, object_ref const r) + object_ref div(f64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const typed_l) -> object_ref { return make_box(typed_l / typed_r->data); }, r, @@ -416,20 +416,20 @@ namespace jank::runtime return l / static_cast(r); } - object_ref div(object_ref const l, i64 const r) + object_ref div(object_ref const &l, i64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data / typed_r); }, l, r); } - object_ref div(i64 const l, object_ref const r) + object_ref div(i64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const typed_l) -> object_ref { return make_box(typed_l / typed_r->data); }, r, @@ -441,12 +441,12 @@ namespace jank::runtime return l / r; } - object_ref mul(object_ref const l, object_ref const r) + object_ref mul(object_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const r) -> object_ref { + [](auto const &typed_l, auto const &r) -> object_ref { return visit_number_like( - [](auto const typed_r, auto const &typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l * typed_r->data).erase(); }, r, @@ -456,80 +456,80 @@ namespace jank::runtime r); } - object_ref mul(obj::integer_ref const l, object_ref const r) + object_ref mul(obj::integer_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l * typed_r->data); }, r, l->data); } - object_ref mul(object_ref const l, obj::integer_ref const r) + object_ref mul(object_ref const &l, obj::integer_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const &typed_r) -> object_ref { return make_box(typed_l->data * typed_r); }, l, r->data); } - i64 mul(obj::integer_ref const l, obj::integer_ref const r) + i64 mul(obj::integer_ref const &l, obj::integer_ref const &r) { return l->data * r->data; } - f64 mul(obj::real_ref const l, obj::real_ref const r) + f64 mul(obj::real_ref const &l, obj::real_ref const &r) { return l->data * r->data; } - object_ref mul(obj::real_ref const l, object_ref const r) + object_ref mul(obj::real_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l * typed_r->data); }, r, l->data); } - object_ref mul(object_ref const l, obj::real_ref const r) + object_ref mul(object_ref const &l, obj::real_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const &typed_r) -> object_ref { return make_box(typed_l->data * typed_r); }, l, r->data); } - f64 mul(obj::real_ref const l, obj::integer_ref const r) + f64 mul(obj::real_ref const &l, obj::integer_ref const &r) { return l->data * static_cast(r->data); } - f64 mul(obj::integer_ref const l, obj::real_ref const r) + f64 mul(obj::integer_ref const &l, obj::real_ref const &r) { return static_cast(l->data) * r->data; } - object_ref mul(object_ref const l, f64 const r) + object_ref mul(object_ref const &l, f64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data * typed_r); }, l, r); } - object_ref mul(f64 const l, object_ref const r) + object_ref mul(f64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const typed_l) -> object_ref { return make_box(typed_l * typed_r->data); }, r, @@ -551,20 +551,20 @@ namespace jank::runtime return l * static_cast(r); } - object_ref mul(object_ref const l, i64 const r) + object_ref mul(object_ref const &l, i64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data * typed_r); }, l, r); } - object_ref mul(i64 const l, object_ref const r) + object_ref mul(i64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const typed_l) -> object_ref { return make_box(typed_l * typed_r->data); }, r, @@ -576,12 +576,12 @@ namespace jank::runtime return l * r; } - object_ref rem(object_ref const l, object_ref const r) + object_ref rem(object_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const r_obj) -> object_ref { + [](auto const &typed_l, auto const &r_obj) -> object_ref { return visit_number_like( - [](auto const typed_r, T const &typed_l_data) -> object_ref { + [](auto const &typed_r, T const &typed_l_data) -> object_ref { using LeftType = std::decay_t; using RightType = std::decay_tdata)>; @@ -621,13 +621,13 @@ namespace jank::runtime r); } - object_ref quot(object_ref const l, object_ref const r) + object_ref quot(object_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const r) -> object_ref { + [](auto const &typed_l, auto const &r) -> object_ref { return visit_number_like( - [](auto const typed_r, auto const &typed_l) -> object_ref { - auto const typed_l_data{ to_real(typed_l) }; + [](auto const &typed_r, auto const &typed_l) -> object_ref { + auto const &typed_l_data{ to_real(typed_l) }; auto const typed_r_data{ to_real(typed_r->data) }; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" @@ -648,10 +648,10 @@ namespace jank::runtime r); } - object_ref inc(object_ref const l) + object_ref inc(object_ref const &l) { return visit_number_like( - [](auto const typed_l) -> object_ref { + [](auto const &typed_l) -> object_ref { auto const ret{ make_box(typed_l->data + 1ll) }; object_ref r{ ret }; return r; @@ -659,17 +659,17 @@ namespace jank::runtime l); } - object_ref dec(object_ref const l) + object_ref dec(object_ref const &l) { return visit_number_like( - [](auto const typed_l) -> object_ref { return make_box(typed_l->data - 1ll).erase(); }, + [](auto const &typed_l) -> object_ref { return make_box(typed_l->data - 1ll).erase(); }, l); } - bool is_zero(object_ref const l) + bool is_zero(object_ref const &l) { return visit_number_like( - [](auto const typed_l) -> bool { + [](auto const &typed_l) -> bool { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" { @@ -680,10 +680,10 @@ namespace jank::runtime l); } - bool is_pos(object_ref const l) + bool is_pos(object_ref const &l) { return visit_number_like( - [](auto const typed_l) -> bool { + [](auto const &typed_l) -> bool { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" { @@ -694,10 +694,10 @@ namespace jank::runtime l); } - bool is_neg(object_ref const l) + bool is_neg(object_ref const &l) { return visit_number_like( - [](auto const typed_l) -> bool { + [](auto const &typed_l) -> bool { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" { @@ -708,30 +708,31 @@ namespace jank::runtime l); } - bool is_even(object_ref const l) + bool is_even(object_ref const &l) { return visit_type( - [=](auto const typed_l) -> bool { return typed_l->data % 2 == 0; }, + [=](auto const &typed_l) -> bool { return typed_l->data % 2 == 0; }, l); } - bool is_odd(object_ref const l) + bool is_odd(object_ref const &l) { return visit_type( - [=](auto const typed_l) -> bool { return typed_l->data % 2 == 1; }, + [=](auto const &typed_l) -> bool { return typed_l->data % 2 == 1; }, l); } - bool is_equiv(object_ref const l, object_ref const r) + bool is_equiv(object_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_l, object_ref const r) -> bool { + [](auto const &typed_l, object_ref const &r) -> bool { return visit_number_like( - [](auto const typed_r, auto const &typed_l) -> bool { + [](auto const &typed_r, auto const &typed_l) -> bool { auto const data_l{ to_real(typed_l) }; auto const data_r{ to_real(typed_r->data) }; - using C = std::common_type_t; + using C + = std::common_type_t, jtl::decay_t>; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" return static_cast(data_l) == static_cast(data_r); @@ -744,17 +745,17 @@ namespace jank::runtime r); } - i64 bit_not(object_ref const l) + i64 bit_not(object_ref const &l) { - return visit_type([](auto const typed_l) -> i64 { return ~typed_l->data; }, l); + return visit_type([](auto const &typed_l) -> i64 { return ~typed_l->data; }, l); } - i64 bit_and(object_ref const l, object_ref const r) + i64 bit_and(object_ref const &l, object_ref const &r) { return visit_type( - [](auto const typed_l, auto const r) -> i64 { + [](auto const &typed_l, auto const &r) -> i64 { return visit_type( - [](auto const typed_r, auto const typed_l) -> i64 { return typed_l & typed_r->data; }, + [](auto const &typed_r, auto const &typed_l) -> i64 { return typed_l & typed_r->data; }, r, typed_l->data); }, @@ -762,12 +763,12 @@ namespace jank::runtime r); } - i64 bit_or(object_ref const l, object_ref const r) + i64 bit_or(object_ref const &l, object_ref const &r) { return visit_type( - [](auto const typed_l, auto const r) -> i64 { + [](auto const &typed_l, auto const &r) -> i64 { return visit_type( - [](auto const typed_r, auto const typed_l) -> i64 { return typed_l | typed_r->data; }, + [](auto const &typed_r, auto const &typed_l) -> i64 { return typed_l | typed_r->data; }, r, typed_l->data); }, @@ -775,12 +776,12 @@ namespace jank::runtime r); } - i64 bit_xor(object_ref const l, object_ref const r) + i64 bit_xor(object_ref const &l, object_ref const &r) { return visit_type( - [](auto const typed_l, auto const r) -> i64 { + [](auto const &typed_l, auto const &r) -> i64 { return visit_type( - [](auto const typed_r, auto const typed_l) -> i64 { return typed_l ^ typed_r->data; }, + [](auto const &typed_r, auto const &typed_l) -> i64 { return typed_l ^ typed_r->data; }, r, typed_l->data); }, @@ -788,12 +789,14 @@ namespace jank::runtime r); } - i64 bit_and_not(object_ref const l, object_ref const r) + i64 bit_and_not(object_ref const &l, object_ref const &r) { return visit_type( - [](auto const typed_l, auto const r) -> i64 { + [](auto const &typed_l, auto const &r) -> i64 { return visit_type( - [](auto const typed_r, auto const typed_l) -> i64 { return typed_l & (~typed_r->data); }, + [](auto const &typed_r, auto const &typed_l) -> i64 { + return typed_l & (~typed_r->data); + }, r, typed_l->data); }, @@ -801,12 +804,12 @@ namespace jank::runtime r); } - i64 bit_clear(object_ref const l, object_ref const r) + i64 bit_clear(object_ref const &l, object_ref const &r) { return visit_type( - [](auto const typed_l, auto const r) -> i64 { + [](auto const &typed_l, auto const &r) -> i64 { return visit_type( - [](auto const typed_r, auto const typed_l) -> i64 { + [](auto const &typed_r, auto const &typed_l) -> i64 { return typed_l & ~(static_cast(1) << typed_r->data); }, r, @@ -816,12 +819,12 @@ namespace jank::runtime r); } - i64 bit_set(object_ref const l, object_ref const r) + i64 bit_set(object_ref const &l, object_ref const &r) { return visit_type( - [](auto const typed_l, auto const r) -> i64 { + [](auto const &typed_l, auto const &r) -> i64 { return visit_type( - [](auto const typed_r, auto const typed_l) -> i64 { + [](auto const &typed_r, auto const &typed_l) -> i64 { return typed_l | (static_cast(1) << typed_r->data); }, r, @@ -831,12 +834,12 @@ namespace jank::runtime r); } - i64 bit_flip(object_ref const l, object_ref const r) + i64 bit_flip(object_ref const &l, object_ref const &r) { return visit_type( - [](auto const typed_l, auto const r) -> i64 { + [](auto const &typed_l, auto const &r) -> i64 { return visit_type( - [](auto const typed_r, auto const typed_l) -> i64 { + [](auto const &typed_r, auto const &typed_l) -> i64 { return typed_l ^ (static_cast(1) << typed_r->data); }, r, @@ -846,12 +849,12 @@ namespace jank::runtime r); } - bool bit_test(object_ref const l, object_ref const r) + bool bit_test(object_ref const &l, object_ref const &r) { return visit_type( - [](auto const typed_l, auto const r) -> bool { + [](auto const &typed_l, auto const &r) -> bool { return visit_type( - [](auto const typed_r, auto const typed_l) -> bool { + [](auto const &typed_r, auto const &typed_l) -> bool { return (typed_l >> typed_r->data) & static_cast(1); }, r, @@ -861,12 +864,12 @@ namespace jank::runtime r); } - i64 bit_shift_left(object_ref const l, object_ref const r) + i64 bit_shift_left(object_ref const &l, object_ref const &r) { return visit_type( - [](auto const typed_l, auto const r) -> i64 { + [](auto const &typed_l, auto const &r) -> i64 { return visit_type( - [](auto const typed_r, auto const typed_l) -> i64 { return typed_l << typed_r->data; }, + [](auto const &typed_r, auto const &typed_l) -> i64 { return typed_l << typed_r->data; }, r, typed_l->data); }, @@ -874,12 +877,12 @@ namespace jank::runtime r); } - i64 bit_shift_right(object_ref const l, object_ref const r) + i64 bit_shift_right(object_ref const &l, object_ref const &r) { return visit_type( - [](auto const typed_l, auto const r) -> i64 { + [](auto const &typed_l, auto const &r) -> i64 { return visit_type( - [](auto const typed_r, auto const typed_l) -> i64 { return typed_l >> typed_r->data; }, + [](auto const &typed_r, auto const &typed_l) -> i64 { return typed_l >> typed_r->data; }, r, typed_l->data); }, @@ -887,12 +890,12 @@ namespace jank::runtime r); } - i64 bit_unsigned_shift_right(object_ref const l, object_ref const r) + i64 bit_unsigned_shift_right(object_ref const &l, object_ref const &r) { return visit_type( - [](auto const typed_l, auto const r) -> i64 { + [](auto const &typed_l, auto const &r) -> i64 { return visit_type( - [](auto const typed_r, auto const typed_l) -> i64 { + [](auto const &typed_r, auto const &typed_l) -> i64 { using uni = std::make_unsigned_t; return static_cast(typed_l) >> static_cast(typed_r->data); }, @@ -910,12 +913,12 @@ namespace jank::runtime return dis(gen); } - bool lt(object_ref const l, object_ref const r) + bool lt(object_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const r) -> bool { + [](auto const &typed_l, auto const &r) -> bool { return visit_number_like( - [](auto const typed_r, auto const &typed_l) -> bool { return typed_l < typed_r->data; }, + [](auto const &typed_r, auto const &typed_l) -> bool { return typed_l < typed_r->data; }, r, typed_l->data); }, @@ -923,70 +926,70 @@ namespace jank::runtime r); } - bool lt(obj::integer_ref const l, object_ref const r) + bool lt(obj::integer_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> bool { return typed_l < typed_r->data; }, + [](auto const &typed_r, auto const &typed_l) -> bool { return typed_l < typed_r->data; }, r, l->data); } - bool lt(object_ref const l, obj::integer_ref const r) + bool lt(object_ref const &l, obj::integer_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data < typed_r; }, + [](auto const &typed_l, auto const &typed_r) -> bool { return typed_l->data < typed_r; }, l, r->data); } - bool lt(obj::integer_ref const l, obj::integer_ref const r) + bool lt(obj::integer_ref const &l, obj::integer_ref const &r) { return l->data < r->data; } - bool lt(obj::real_ref const l, obj::real_ref const r) + bool lt(obj::real_ref const &l, obj::real_ref const &r) { return l->data < r->data; } - bool lt(obj::real_ref const l, object_ref const r) + bool lt(obj::real_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> bool { return typed_l < typed_r->data; }, + [](auto const &typed_r, auto const &typed_l) -> bool { return typed_l < typed_r->data; }, r, l->data); } - bool lt(object_ref const l, obj::real_ref const r) + bool lt(object_ref const &l, obj::real_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data < typed_r; }, + [](auto const &typed_l, auto const &typed_r) -> bool { return typed_l->data < typed_r; }, l, r->data); } - bool lt(obj::real_ref const l, obj::integer_ref const r) + bool lt(obj::real_ref const &l, obj::integer_ref const &r) { return l->data < static_cast(r->data); } - bool lt(obj::integer_ref const l, obj::real_ref const r) + bool lt(obj::integer_ref const &l, obj::real_ref const &r) { return static_cast(l->data) < r->data; } - bool lt(object_ref const l, f64 const r) + bool lt(object_ref const &l, f64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data < typed_r; }, + [](auto const &typed_l, auto const typed_r) -> bool { return typed_l->data < typed_r; }, l, r); } - bool lt(f64 const l, object_ref const r) + bool lt(f64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> bool { return typed_l < typed_r->data; }, + [](auto const &typed_r, auto const typed_l) -> bool { return typed_l < typed_r->data; }, r, l); } @@ -1006,18 +1009,18 @@ namespace jank::runtime return l < static_cast(r); } - bool lt(object_ref const l, i64 const r) + bool lt(object_ref const &l, i64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data < typed_r; }, + [](auto const &typed_l, auto const typed_r) -> bool { return typed_l->data < typed_r; }, l, r); } - bool lt(i64 const l, object_ref const r) + bool lt(i64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> bool { return typed_l < typed_r->data; }, + [](auto const &typed_r, auto const typed_l) -> bool { return typed_l < typed_r->data; }, r, l); } @@ -1027,12 +1030,12 @@ namespace jank::runtime return l < r; } - bool lte(object_ref const l, object_ref const r) + bool lte(object_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const r) -> bool { + [](auto const &typed_l, auto const &r) -> bool { return visit_number_like( - [](auto const typed_r, auto const &typed_l) -> bool { return typed_l <= typed_r->data; }, + [](auto const &typed_r, auto const &typed_l) -> bool { return typed_l <= typed_r->data; }, r, typed_l->data); }, @@ -1040,70 +1043,70 @@ namespace jank::runtime r); } - bool lte(obj::integer_ref const l, object_ref const r) + bool lte(obj::integer_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> bool { return typed_l <= typed_r->data; }, + [](auto const &typed_r, auto const &typed_l) -> bool { return typed_l <= typed_r->data; }, r, l->data); } - bool lte(object_ref const l, obj::integer_ref const r) + bool lte(object_ref const &l, obj::integer_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data <= typed_r; }, + [](auto const &typed_l, auto const &typed_r) -> bool { return typed_l->data <= typed_r; }, l, r->data); } - bool lte(obj::integer_ref const l, obj::integer_ref const r) + bool lte(obj::integer_ref const &l, obj::integer_ref const &r) { return l->data <= r->data; } - bool lte(obj::real_ref const l, obj::real_ref const r) + bool lte(obj::real_ref const &l, obj::real_ref const &r) { return l->data <= r->data; } - bool lte(obj::real_ref const l, object_ref const r) + bool lte(obj::real_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> bool { return typed_l <= typed_r->data; }, + [](auto const &typed_r, auto const &typed_l) -> bool { return typed_l <= typed_r->data; }, r, l->data); } - bool lte(object_ref const l, obj::real_ref const r) + bool lte(object_ref const &l, obj::real_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data <= typed_r; }, + [](auto const &typed_l, auto const &typed_r) -> bool { return typed_l->data <= typed_r; }, l, r->data); } - bool lte(obj::real_ref const l, obj::integer_ref const r) + bool lte(obj::real_ref const &l, obj::integer_ref const &r) { return l->data <= static_cast(r->data); } - bool lte(obj::integer_ref const l, obj::real_ref const r) + bool lte(obj::integer_ref const &l, obj::real_ref const &r) { return static_cast(l->data) <= r->data; } - bool lte(object_ref const l, f64 const r) + bool lte(object_ref const &l, f64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data <= typed_r; }, + [](auto const &typed_l, auto const typed_r) -> bool { return typed_l->data <= typed_r; }, l, r); } - bool lte(f64 const l, object_ref const r) + bool lte(f64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> bool { return typed_l <= typed_r->data; }, + [](auto const &typed_r, auto const typed_l) -> bool { return typed_l <= typed_r->data; }, r, l); } @@ -1123,18 +1126,18 @@ namespace jank::runtime return l <= static_cast(r); } - bool lte(object_ref const l, i64 const r) + bool lte(object_ref const &l, i64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data <= typed_r; }, + [](auto const &typed_l, auto const typed_r) -> bool { return typed_l->data <= typed_r; }, l, r); } - bool lte(i64 const l, object_ref const r) + bool lte(i64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> bool { return typed_l <= typed_r->data; }, + [](auto const &typed_r, auto const typed_l) -> bool { return typed_l <= typed_r->data; }, r, l); } @@ -1144,12 +1147,12 @@ namespace jank::runtime return l <= r; } - object_ref min(object_ref const l, object_ref const r) + object_ref min(object_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const r) -> object_ref { + [](auto const &typed_l, auto const &r) -> object_ref { return visit_number_like( - [](auto const typed_r, auto const &typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return typed_l < typed_r->data ? make_box(typed_l).erase() : make_box(typed_r->data).erase(); }, @@ -1160,10 +1163,10 @@ namespace jank::runtime r); } - object_ref min(obj::integer_ref const l, object_ref const r) + object_ref min(obj::integer_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return typed_l < typed_r->data ? make_box(typed_l).erase() : make_box(typed_r->data).erase(); }, @@ -1171,10 +1174,10 @@ namespace jank::runtime l->data); } - object_ref min(object_ref const l, obj::integer_ref const r) + object_ref min(object_ref const &l, obj::integer_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const &typed_r) -> object_ref { return typed_l->data < typed_r ? make_box(typed_l->data).erase() : make_box(typed_r).erase(); }, @@ -1182,68 +1185,70 @@ namespace jank::runtime r->data); } - i64 min(obj::integer_ref const l, obj::integer_ref const r) + i64 min(obj::integer_ref const &l, obj::integer_ref const &r) { return std::min(l->data, r->data); } - f64 min(obj::real_ref const l, obj::real_ref const r) + f64 min(obj::real_ref const &l, obj::real_ref const &r) { return std::min(l->data, r->data); } - f64 min(obj::real_ref const l, object_ref const r) + f64 min(obj::real_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> f64 { + [](auto const &typed_r, auto const &typed_l) -> f64 { auto const typed_r_data{ to_real(typed_r->data) }; - using C = std::common_type_t; + using C = std::common_type_t, + jtl::decay_t>; return std::min(static_cast(typed_l), static_cast(typed_r_data)); }, r, l->data); } - f64 min(object_ref const l, obj::real_ref const r) + f64 min(object_ref const &l, obj::real_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> f64 { + [](auto const &typed_l, auto const &typed_r) -> f64 { auto const typed_l_data{ to_real(typed_l->data) }; - using C = std::common_type_t; + using C = std::common_type_t, + jtl::decay_t>; return std::min(static_cast(typed_l_data), static_cast(typed_r)); }, l, r->data); } - f64 min(obj::real_ref const l, obj::integer_ref const r) + f64 min(obj::real_ref const &l, obj::integer_ref const &r) { return std::min(l->data, static_cast(r->data)); } - f64 min(obj::integer_ref const l, obj::real_ref const r) + f64 min(obj::integer_ref const &l, obj::real_ref const &r) { return std::min(static_cast(l->data), r->data); } - f64 min(object_ref const l, f64 const r) + f64 min(object_ref const &l, f64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> f64 { + [](auto const &typed_l, auto const typed_r) -> f64 { auto const typed_l_data{ to_real(typed_l->data) }; - using C = std::common_type_t; + using C = std::common_type_t>; return std::min(static_cast(typed_l_data), static_cast(typed_r)); }, l, r); } - f64 min(f64 const l, object_ref const r) + f64 min(f64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> f64 { - auto const typed_r_data{ to_real(typed_r->data) }; - using C = std::common_type_t; + [](auto const &typed_r, auto const typed_l) -> f64 { + auto const &typed_r_data{ to_real(typed_r->data) }; + using C = std::common_type_t>; return std::min(static_cast(typed_r_data), static_cast(typed_l)); }, r, @@ -1265,20 +1270,20 @@ namespace jank::runtime return std::min(l, static_cast(r)); } - object_ref min(object_ref const l, i64 const r) + object_ref min(object_ref const &l, i64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const typed_r) -> object_ref { return typed_l->data < typed_r ? make_box(typed_l).erase() : make_box(typed_r).erase(); }, l, r); } - object_ref min(i64 const l, object_ref const r) + object_ref min(i64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const typed_l) -> object_ref { return typed_l < typed_r->data ? make_box(typed_l).erase() : make_box(typed_r).erase(); }, r, @@ -1290,12 +1295,12 @@ namespace jank::runtime return std::min(l, r); } - object_ref max(object_ref const l, object_ref const r) + object_ref max(object_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const r) -> object_ref { + [](auto const &typed_l, auto const &r) -> object_ref { return visit_number_like( - [](auto const typed_r, auto const &typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return typed_r->data > typed_l ? make_box(typed_r).erase() : make_box(typed_l).erase(); }, r, @@ -1305,88 +1310,88 @@ namespace jank::runtime r); } - object_ref max(obj::integer_ref const l, object_ref const r) + object_ref max(obj::integer_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const &typed_l) -> object_ref { return typed_l > typed_r->data ? make_box(typed_l).erase() : make_box(typed_r).erase(); }, r, l->data); } - object_ref max(object_ref const l, obj::integer_ref const r) + object_ref max(object_ref const &l, obj::integer_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const &typed_r) -> object_ref { return typed_l->data > typed_r ? make_box(typed_l).erase() : make_box(typed_r).erase(); }, l, r->data); } - i64 max(obj::integer_ref const l, obj::integer_ref const r) + i64 max(obj::integer_ref const &l, obj::integer_ref const &r) { return std::max(l->data, r->data); } - f64 max(obj::real_ref const l, obj::real_ref const r) + f64 max(obj::real_ref const &l, obj::real_ref const &r) { return std::max(l->data, r->data); } - f64 max(obj::real_ref const l, object_ref const r) + f64 max(obj::real_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> f64 { + [](auto const &typed_r, auto const &typed_l) -> f64 { auto const typed_r_data{ to_real(typed_r->data) }; - using C = std::common_type_t; + using C = std::common_type_t, decltype(typed_r_data)>; return std::max(static_cast(typed_l), static_cast(typed_r_data)); }, r, l->data); } - f64 max(object_ref const l, obj::real_ref const r) + f64 max(object_ref const &l, obj::real_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> f64 { + [](auto const &typed_l, auto const &typed_r) -> f64 { auto const typed_l_data{ to_real(typed_l->data) }; - using C = std::common_type_t; + using C = std::common_type_t>; return std::max(static_cast(typed_r), static_cast(typed_l_data)); }, l, r->data); } - f64 max(obj::real_ref const l, obj::integer_ref const r) + f64 max(obj::real_ref const &l, obj::integer_ref const &r) { return std::max(l->data, static_cast(r->data)); } - f64 max(obj::integer_ref const l, obj::real_ref const r) + f64 max(obj::integer_ref const &l, obj::real_ref const &r) { return std::max(static_cast(l->data), r->data); } - object_ref max(object_ref const l, f64 const r) + object_ref max(object_ref const &l, f64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const &typed_r) -> object_ref { auto const typed_l_data{ to_real(typed_l->data) }; - using C = std::common_type_t; + using C = std::common_type_t>; return make_box(std::max(static_cast(typed_r), static_cast(typed_l_data))); }, l, r); } - object_ref max(f64 const l, object_ref const r) + object_ref max(f64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const typed_l) -> object_ref { auto const typed_r_data{ to_real(typed_r->data) }; - using C = std::common_type_t; + using C = std::common_type_t, decltype(typed_r_data)>; return make_box(std::max(static_cast(typed_l), static_cast(typed_r_data))); }, r, @@ -1408,20 +1413,20 @@ namespace jank::runtime return std::max(l, static_cast(r)); } - object_ref max(object_ref const l, i64 const r) + object_ref max(object_ref const &l, i64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const typed_r) -> object_ref { return typed_l->data > typed_r ? make_box(typed_l).erase() : make_box(typed_r).erase(); }, l, r); } - object_ref max(i64 const l, object_ref const r) + object_ref max(i64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const typed_l) -> object_ref { return typed_l > typed_r->data ? make_box(typed_l).erase() : make_box(typed_r).erase(); }, r, @@ -1433,22 +1438,22 @@ namespace jank::runtime return std::max(l, r); } - object_ref abs(object_ref const l) + object_ref abs(object_ref const &l) { return visit_number_like( - [](auto const typed_l) -> object_ref { + [](auto const &typed_l) -> object_ref { return typed_l->data < 0ll ? make_box(-1ll * typed_l->data).erase() : make_box(typed_l->data).erase(); }, l); } - i64 abs(obj::integer_ref const l) + i64 abs(obj::integer_ref const &l) { return std::abs(l->data); } - f64 abs(obj::real_ref const l) + f64 abs(obj::real_ref const &l) { return std::fabs(l->data); } @@ -1463,24 +1468,25 @@ namespace jank::runtime return std::fabs(l); } - f64 tan(object_ref const l) + f64 tan(object_ref const &l) { - return visit_number_like([](auto const typed_l) -> f64 { return tanf(typed_l->to_real()); }, l); + return visit_number_like([](auto const &typed_l) -> f64 { return tanf(typed_l->to_real()); }, + l); } - f64 sqrt(object_ref const l) + f64 sqrt(object_ref const &l) { return visit_number_like( - [](auto const typed_l) -> f64 { return std::sqrt(typed_l->to_real()); }, + [](auto const &typed_l) -> f64 { return std::sqrt(typed_l->to_real()); }, l); } - f64 sqrt(obj::integer_ref const l) + f64 sqrt(obj::integer_ref const &l) { return std::sqrt(l->data); } - f64 sqrt(obj::real_ref const l) + f64 sqrt(obj::real_ref const &l) { return std::sqrt(l->data); } @@ -1495,12 +1501,12 @@ namespace jank::runtime return std::sqrt(l); } - f64 pow(object_ref const l, object_ref const r) + f64 pow(object_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const r) -> f64 { + [](auto const &typed_l, auto const &r) -> f64 { return visit_number_like( - [](auto const typed_r, auto const &typed_l) -> f64 { + [](auto const &typed_r, auto const &typed_l) -> f64 { auto const typed_r_data{ to_real(typed_r->data) }; auto const typed_l_data{ to_real(typed_l) }; using C = std::common_type_t; @@ -1513,10 +1519,10 @@ namespace jank::runtime r); } - f64 pow(obj::integer_ref const l, object_ref const r) + f64 pow(obj::integer_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> f64 { + [](auto const &typed_r, auto const &typed_l) -> f64 { auto const typed_r_data{ to_real(typed_r->data) }; auto const typed_l_data{ to_real(typed_l) }; using C = std::common_type_t; @@ -1526,80 +1532,80 @@ namespace jank::runtime l->data); } - f64 pow(object_ref const l, obj::integer_ref const r) + f64 pow(object_ref const &l, obj::integer_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> f64 { + [](auto const &typed_l, auto const &typed_r) -> f64 { auto const typed_l_data{ to_real(typed_l->data) }; - using C = std::common_type_t; + using C = std::common_type_t>; return std::pow(static_cast(typed_l_data), static_cast(typed_r)); }, l, r->data); } - f64 pow(obj::integer_ref const l, obj::integer_ref const r) + f64 pow(obj::integer_ref const &l, obj::integer_ref const &r) { return std::pow(l->data, r->data); } - f64 pow(obj::real_ref const l, obj::real_ref const r) + f64 pow(obj::real_ref const &l, obj::real_ref const &r) { return std::pow(l->data, r->data); } - f64 pow(obj::real_ref const l, object_ref const r) + f64 pow(obj::real_ref const &l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> f64 { + [](auto const &typed_r, auto const &typed_l) -> f64 { auto const typed_r_data{ to_real(typed_r->data) }; - using C = std::common_type_t; + using C = std::common_type_t, decltype(typed_r_data)>; return std::pow(static_cast(typed_l), static_cast(typed_r_data)); }, r, l->data); } - f64 pow(object_ref const l, obj::real_ref const r) + f64 pow(object_ref const &l, obj::real_ref const &r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> f64 { + [](auto const &typed_l, auto const &typed_r) -> f64 { auto const typed_l_data{ to_real(typed_l->data) }; - using C = std::common_type_t; + using C = std::common_type_t>; return std::pow(static_cast(typed_l_data), static_cast(typed_r)); }, l, r->data); } - f64 pow(obj::real_ref const l, obj::integer_ref const r) + f64 pow(obj::real_ref const &l, obj::integer_ref const &r) { return std::pow(l->data, static_cast(r->data)); } - f64 pow(obj::integer_ref const l, obj::real_ref const r) + f64 pow(obj::integer_ref const &l, obj::real_ref const &r) { return std::pow(static_cast(l->data), r->data); } - object_ref pow(object_ref const l, f64 const r) + object_ref pow(object_ref const &l, f64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> object_ref { + [](auto const &typed_l, auto const typed_r) -> object_ref { auto const typed_l_data{ to_real(typed_l->data) }; - using C = std::common_type_t; + using C = std::common_type_t>; return make_box(std::pow(static_cast(typed_l_data), static_cast(typed_r))); }, l, r); } - object_ref pow(f64 const l, object_ref const r) + object_ref pow(f64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const &typed_r, auto const typed_l) -> object_ref { auto const typed_r_data{ to_real(typed_r->data) }; - using C = std::common_type_t; + using C = std::common_type_t, decltype(typed_r_data)>; return make_box(std::pow(static_cast(typed_l), static_cast(typed_r_data))); }, r, @@ -1621,24 +1627,24 @@ namespace jank::runtime return std::pow(l, static_cast(r)); } - f64 pow(object_ref const l, i64 const r) + f64 pow(object_ref const &l, i64 const r) { return visit_number_like( - [](auto const typed_l, auto const typed_r) -> f64 { + [](auto const &typed_l, auto const typed_r) -> f64 { auto const typed_l_data{ to_real(typed_l->data) }; - using C = std::common_type_t; + using C = std::common_type_t>; return std::pow(static_cast(typed_l_data), static_cast(typed_r)); }, l, r); } - f64 pow(i64 const l, object_ref const r) + f64 pow(i64 const l, object_ref const &r) { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> f64 { - auto const typed_r_data{ to_real(typed_r->data) }; - using C = std::common_type_t; + [](auto const &typed_r, auto const typed_l) -> f64 { + auto const &typed_r_data{ to_real(typed_r->data) }; + using C = std::common_type_t, decltype(typed_r_data)>; return std::pow(static_cast(typed_l), static_cast(typed_r_data)); }, r, @@ -1650,27 +1656,27 @@ namespace jank::runtime return std::pow(l, r); } - native_big_integer numerator(object_ref const o) + native_big_integer numerator(object_ref const &o) { return try_object(o)->data.numerator; } - native_big_integer denominator(object_ref const o) + native_big_integer denominator(object_ref const &o) { return try_object(o)->data.denominator; } - i64 to_int(object_ref const l) + i64 to_int(object_ref const &l) { - return visit_number_like([](auto const typed_l) -> i64 { return typed_l->to_integer(); }, l); + return visit_number_like([](auto const &typed_l) -> i64 { return typed_l->to_integer(); }, l); } - i64 to_int(obj::integer_ref const l) + i64 to_int(obj::integer_ref const &l) { return l->data; } - i64 to_int(obj::real_ref const l) + i64 to_int(obj::real_ref const &l) { return static_cast(l->data); } @@ -1685,38 +1691,46 @@ namespace jank::runtime return static_cast(l); } - bool is_number(object_ref const o) + f64 to_real(object_ref const &o) + { + return visit_number_like( + [](auto const &typed_o) -> f64 { return typed_o->to_real(); }, + [=]() -> f64 { throw std::runtime_error{ util::format("not a number: {}", to_string(o)) }; }, + o); + } + + bool is_number(object_ref const &o) { - return visit_number_like([=](auto const) -> bool { return true; }, + return visit_number_like([=](auto const &) -> bool { return true; }, [=]() -> bool { return false; }, o); } - bool is_integer(object_ref const o) + bool is_integer(object_ref const &o) { return o->type == object_type::integer; } - bool is_real(object_ref const o) + bool is_real(object_ref const &o) { return o->type == object_type::real; } - bool is_ratio(object_ref const o) + bool is_ratio(object_ref const &o) { return o->type == object_type::ratio; } - bool is_boolean(object_ref const o) + bool is_boolean(object_ref const &o) { return o->type == object_type::boolean; } - bool is_nan(object_ref const o) + bool is_nan(object_ref const &o) { return visit_number_like( - [=](auto const typed_o) -> bool { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> bool { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -1730,11 +1744,11 @@ namespace jank::runtime o); } - bool is_infinite(object_ref const o) + bool is_infinite(object_ref const &o) { return visit_number_like( - [=](auto const typed_o) -> bool { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> bool { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -1749,7 +1763,7 @@ namespace jank::runtime } /* TODO: Rename these to match the type name. */ - i64 parse_long(object_ref const o) + i64 parse_long(object_ref const &o) { auto const typed_o{ dyn_cast(o) }; if(typed_o.is_some()) @@ -1762,7 +1776,7 @@ namespace jank::runtime } } - f64 parse_double(object_ref const o) + f64 parse_double(object_ref const &o) { auto const typed_o{ dyn_cast(o) }; if(typed_o.is_some()) @@ -1775,16 +1789,16 @@ namespace jank::runtime } } - bool is_big_decimal(object_ref const o) + bool is_big_decimal(object_ref const &o) { return o->type == object_type::big_decimal; } - obj::big_decimal_ref to_big_decimal(object_ref const o) + obj::big_decimal_ref to_big_decimal(object_ref const &o) { return visit_number_like( - [&](auto const typed_o) -> obj::big_decimal_ref { - using T = typename decltype(typed_o)::value_type; + [&](auto const &typed_o) -> obj::big_decimal_ref { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { diff --git a/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp b/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp index 903c9eb53..dff17c2f5 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp @@ -10,7 +10,7 @@ namespace jank::runtime { - object_ref meta(object_ref const m) + object_ref meta(object_ref const &m) { if(m.is_nil()) { @@ -18,8 +18,8 @@ namespace jank::runtime } return visit_object( - [](auto const typed_m) -> object_ref { - using T = typename decltype(typed_m)::value_type; + [](auto const &typed_m) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::metadatable) { @@ -33,11 +33,11 @@ namespace jank::runtime m); } - object_ref with_meta(object_ref const o, object_ref const m) + object_ref with_meta(object_ref const &o, object_ref const &m) { return visit_object( - [&o](auto const typed_o, object_ref const m) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [&o](auto const &typed_o, object_ref const &m) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::metadatable) { @@ -59,11 +59,11 @@ namespace jank::runtime /* This is the same as with_meta, but it gracefully handles the target * not supporting metadata. In that case, the target is returned and nothing * is done with the meta. */ - object_ref with_meta_graceful(object_ref const o, object_ref const m) + object_ref with_meta_graceful(object_ref const &o, object_ref const &m) { return visit_object( - [](auto const typed_o, object_ref const m) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [](auto const &typed_o, object_ref const &m) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::metadatable) { @@ -78,11 +78,11 @@ namespace jank::runtime m); } - object_ref reset_meta(object_ref const o, object_ref const m) + object_ref reset_meta(object_ref const &o, object_ref const &m) { return visit_object( - [](auto const typed_o, object_ref const m) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [](auto const &typed_o, object_ref const &m) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::metadatable) { @@ -147,7 +147,7 @@ namespace jank::runtime }; } - read::source object_source(object_ref const o) + read::source object_source(object_ref const &o) { auto const meta(runtime::meta(o)); if(meta == jank_nil()) @@ -212,7 +212,7 @@ namespace jank::runtime return source_to_meta(source); } - object_ref strip_source_from_meta(object_ref const meta) + object_ref strip_source_from_meta(object_ref const &meta) { auto const kw{ __rt_ctx->intern_keyword("jank/source").expect_ok() }; return dissoc(meta, kw); @@ -225,7 +225,7 @@ namespace jank::runtime return meta; } - auto const stripped{ strip_source_from_meta(meta.unwrap()) }; + auto stripped{ strip_source_from_meta(meta.unwrap()) }; if(is_empty(stripped)) { return none; diff --git a/compiler+runtime/src/cpp/jank/runtime/core/munge.cpp b/compiler+runtime/src/cpp/jank/runtime/core/munge.cpp index 449eaffa4..c2b27d3cb 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/munge.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/munge.cpp @@ -299,7 +299,7 @@ namespace jank::runtime } /* TODO: Support symbols and other data; Clojure takes in anything and passes it through str. */ - object_ref munge(object_ref const o) + object_ref munge(object_ref const &o) { auto const s{ dyn_cast(o) }; if(s.is_some()) diff --git a/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp b/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp index 3ea0e78eb..ae78b19ec 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp @@ -24,11 +24,11 @@ namespace jank::runtime { - bool is_empty(object_ref const o) + bool is_empty(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> bool { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> bool { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -51,115 +51,115 @@ namespace jank::runtime o); } - bool is_seq(object_ref const o) + bool is_seq(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> bool { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> bool { + using T = typename jtl::decay_t::value_type; return behavior::sequenceable; }, o); } - bool is_seqable(object_ref const o) + bool is_seqable(object_ref const &o) { - return visit_seqable([=](auto const) -> bool { return true; }, + return visit_seqable([=](auto const &) -> bool { return true; }, [=]() -> bool { return false; }, o); } - bool is_sequential(object_ref const o) + bool is_sequential(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> bool { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> bool { + using T = typename jtl::decay_t::value_type; return behavior::sequential; }, o); } - bool is_collection(object_ref const o) + bool is_collection(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> bool { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> bool { + using T = typename jtl::decay_t::value_type; return behavior::collection_like; }, o); } - bool is_list(object_ref const o) + bool is_list(object_ref const &o) { /* TODO: Visit and use a behavior for this check instead. * It should apply to conses and others. */ return o->type == object_type::persistent_list; } - bool is_vector(object_ref const o) + bool is_vector(object_ref const &o) { return o->type == object_type::persistent_vector; } - bool is_map(object_ref const o) + bool is_map(object_ref const &o) { return (o->type == object_type::persistent_hash_map || o->type == object_type::persistent_array_map || o->type == object_type::persistent_sorted_map); } - bool is_associative(object_ref const o) + bool is_associative(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> bool { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> bool { + using T = typename jtl::decay_t::value_type; return (behavior::associatively_readable && behavior::associatively_writable); }, o); } - bool is_set(object_ref const o) + bool is_set(object_ref const &o) { return (o->type == object_type::persistent_hash_set || o->type == object_type::persistent_sorted_set); } - bool is_counted(object_ref const o) + bool is_counted(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> bool { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> bool { + using T = typename jtl::decay_t::value_type; return behavior::countable; }, o); } - bool is_transientable(object_ref const o) + bool is_transientable(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> bool { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> bool { + using T = typename jtl::decay_t::value_type; return behavior::transientable; }, o); } - bool is_sorted(object_ref const o) + bool is_sorted(object_ref const &o) { return o->type == object_type::persistent_sorted_map || o->type == object_type::persistent_sorted_set; } - object_ref transient(object_ref const o) + object_ref transient(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::transientable) { @@ -174,11 +174,11 @@ namespace jank::runtime o); } - object_ref persistent(object_ref const o) + object_ref persistent(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::persistentable) { @@ -193,11 +193,11 @@ namespace jank::runtime o); } - object_ref conj_in_place(object_ref const coll, object_ref const o) + object_ref conj_in_place(object_ref const &coll, object_ref const &o) { return visit_object( - [](auto const typed_coll, auto const o) -> object_ref { - using T = typename decltype(typed_coll)::value_type; + [](auto const &typed_coll, auto const &o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::conjable_in_place) { @@ -213,7 +213,7 @@ namespace jank::runtime o); } - object_ref disj_in_place(object_ref const coll, object_ref const o) + object_ref disj_in_place(object_ref const &coll, object_ref const &o) { /* TODO: disjoinable_in_place */ if(coll->type == object_type::transient_hash_set) @@ -233,11 +233,11 @@ namespace jank::runtime runtime::to_code_string(coll)) }; } - object_ref assoc_in_place(object_ref const coll, object_ref const k, object_ref const v) + object_ref assoc_in_place(object_ref const &coll, object_ref const &k, object_ref const &v) { return visit_object( - [](auto const typed_coll, auto const k, auto const v) -> object_ref { - using T = typename decltype(typed_coll)::value_type; + [](auto const &typed_coll, auto const &k, auto const &v) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_writable_in_place) { @@ -254,11 +254,11 @@ namespace jank::runtime v); } - object_ref dissoc_in_place(object_ref const coll, object_ref const k) + object_ref dissoc_in_place(object_ref const &coll, object_ref const &k) { return visit_object( - [](auto const typed_coll, auto const k) -> object_ref { - using T = typename decltype(typed_coll)::value_type; + [](auto const &typed_coll, auto const &k) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_writable_in_place) { @@ -274,17 +274,17 @@ namespace jank::runtime k); } - object_ref pop_in_place(object_ref const coll) + object_ref pop_in_place(object_ref const &coll) { auto const trans(try_object(coll)); return trans->pop_in_place(); } - object_ref seq(object_ref const s) + object_ref seq(object_ref const &s) { return visit_object( - [](auto const typed_s) -> object_ref { - using T = typename decltype(typed_s)::value_type; + [](auto const &typed_s) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -308,11 +308,11 @@ namespace jank::runtime s); } - object_ref fresh_seq(object_ref const s) + object_ref fresh_seq(object_ref const &s) { return visit_object( - [](auto const typed_s) -> object_ref { - using T = typename decltype(typed_s)::value_type; + [](auto const &typed_s) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -336,11 +336,11 @@ namespace jank::runtime s); } - object_ref first(object_ref const s) + object_ref first(object_ref const &s) { return visit_object( - [](auto const typed_s) -> object_ref { - using T = typename decltype(typed_s)::value_type; + [](auto const &typed_s) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -368,16 +368,16 @@ namespace jank::runtime s); } - object_ref second(object_ref const s) + object_ref second(object_ref const &s) { return first(next(s)); } - object_ref next(object_ref const s) + object_ref next(object_ref const &s) { return visit_object( - [](auto const typed_s) -> object_ref { - using T = typename decltype(typed_s)::value_type; + [](auto const &typed_s) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -405,11 +405,11 @@ namespace jank::runtime s); } - object_ref next_in_place(object_ref const s) + object_ref next_in_place(object_ref const &s) { return visit_object( - [](auto const typed_s) -> object_ref { - using T = typename decltype(typed_s)::value_type; + [](auto const &typed_s) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -441,20 +441,20 @@ namespace jank::runtime s); } - object_ref rest(object_ref const s) + object_ref rest(object_ref const &s) { if(s.is_nil()) { return obj::persistent_list::empty(); } return visit_seqable( - [=](auto const typed_s) -> object_ref { + [=](auto const &typed_s) -> object_ref { auto const seq(typed_s->seq()); if(seq.is_nil()) { return obj::persistent_list::empty(); } - auto const ret(next(seq)); + auto ret(next(seq)); if(ret.is_nil()) { return obj::persistent_list::empty(); @@ -464,11 +464,11 @@ namespace jank::runtime s); } - object_ref cons(object_ref const head, object_ref const tail) + object_ref cons(object_ref const &head, object_ref const &tail) { return visit_seqable( - [=](auto const typed_tail) -> object_ref { - using T = typename decltype(typed_tail)::value_type; + [=](auto const &typed_tail) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(jtl::is_same) { @@ -489,11 +489,11 @@ namespace jank::runtime tail); } - object_ref conj(object_ref const s, object_ref const o) + object_ref conj(object_ref const &s, object_ref const &o) { return visit_object( - [&](auto const typed_s) -> object_ref { - using T = typename decltype(typed_s)::value_type; + [&](auto const &typed_s) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -511,7 +511,7 @@ namespace jank::runtime s); } - object_ref disj(object_ref const s, object_ref const o) + object_ref disj(object_ref const &s, object_ref const &o) { if(s->type == object_type::nil) { @@ -528,11 +528,11 @@ namespace jank::runtime } } - object_ref assoc(object_ref const m, object_ref const k, object_ref const v) + object_ref assoc(object_ref const &m, object_ref const &k, object_ref const &v) { return visit_object( - [&](auto const typed_m) -> object_ref { - using T = typename decltype(typed_m)::value_type; + [&](auto const &typed_m) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_writable) { @@ -547,11 +547,11 @@ namespace jank::runtime m); } - object_ref dissoc(object_ref const m, object_ref const k) + object_ref dissoc(object_ref const &m, object_ref const &k) { return visit_object( - [&](auto const typed_m) -> object_ref { - using T = typename decltype(typed_m)::value_type; + [&](auto const &typed_m) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_writable) { @@ -566,11 +566,11 @@ namespace jank::runtime m); } - object_ref get(object_ref const m, object_ref const key) + object_ref get(object_ref const &m, object_ref const &key) { return visit_object( - [&](auto const typed_m) -> object_ref { - using T = typename decltype(typed_m)::value_type; + [&](auto const &typed_m) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_readable) { @@ -584,11 +584,11 @@ namespace jank::runtime m); } - object_ref get(object_ref const m, object_ref const key, object_ref const fallback) + object_ref get(object_ref const &m, object_ref const &key, object_ref const &fallback) { return visit_object( - [&](auto const typed_m) -> object_ref { - using T = typename decltype(typed_m)::value_type; + [&](auto const &typed_m) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_readable) { @@ -602,18 +602,18 @@ namespace jank::runtime m); } - object_ref get_in(object_ref const m, object_ref const keys) + object_ref get_in(object_ref const &m, object_ref const &keys) { return visit_object( - [&](auto const typed_m) -> object_ref { - using T = typename decltype(typed_m)::value_type; + [&](auto const &typed_m) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_readable) { return visit_seqable( - [&](auto const typed_keys) -> object_ref { + [&](auto const &typed_keys) -> object_ref { object_ref ret{ typed_m }; - for(auto const e : make_sequence_range(typed_keys)) + for(auto const &e : make_sequence_range(typed_keys)) { ret = get(ret, e); } @@ -629,18 +629,18 @@ namespace jank::runtime m); } - object_ref get_in(object_ref const m, object_ref const keys, object_ref const fallback) + object_ref get_in(object_ref const &m, object_ref const &keys, object_ref const &fallback) { return visit_object( - [&](auto const typed_m) -> object_ref { - using T = typename decltype(typed_m)::value_type; + [&](auto const &typed_m) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_readable) { return visit_seqable( - [&](auto const typed_keys) -> object_ref { + [&](auto const &typed_keys) -> object_ref { object_ref ret{ typed_m }; - for(auto const e : make_sequence_range(typed_keys)) + for(auto const &e : make_sequence_range(typed_keys)) { ret = get(ret, e); } @@ -661,7 +661,7 @@ namespace jank::runtime m); } - object_ref find(object_ref const s, object_ref const key) + object_ref find(object_ref const &s, object_ref const &key) { if(s.is_nil()) { @@ -669,8 +669,8 @@ namespace jank::runtime } return visit_object( - [](auto const typed_s, object_ref const key) -> object_ref { - using S = typename decltype(typed_s)::value_type; + [](auto const &typed_s, object_ref const &key) -> object_ref { + using S = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_readable) { @@ -685,7 +685,7 @@ namespace jank::runtime key); } - bool contains(object_ref const s, object_ref const key) + bool contains(object_ref const &s, object_ref const &key) { if(s.is_nil()) { @@ -693,8 +693,8 @@ namespace jank::runtime } return visit_object( - [&](auto const typed_s) -> bool { - using S = typename decltype(typed_s)::value_type; + [&](auto const &typed_s) -> bool { + using S = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_readable || behavior::set_like) { @@ -708,11 +708,11 @@ namespace jank::runtime s); } - object_ref merge(object_ref const m, object_ref const other) + object_ref merge(object_ref const &m, object_ref const &other) { return visit_object( - [](auto const typed_m, object_ref const other) -> object_ref { - using T = typename decltype(typed_m)::value_type; + [](auto const &typed_m, object_ref const &other) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(jtl::is_same) { @@ -723,11 +723,11 @@ namespace jank::runtime using R = decltype(assoc(typed_m, jank_nil(), jank_nil())); return visit_map_like( - [](auto const typed_other, auto const typed_m) -> object_ref { + [](auto const &typed_other, auto const &typed_m) -> object_ref { R ret{ typed_m }; for(auto seq{ typed_other->fresh_seq() }; seq.is_some(); seq = seq->next_in_place()) { - auto const e(seq->first()); + auto const &e(seq->first()); ret = assoc(ret, e->data[0], e->data[1]); } return ret; @@ -745,25 +745,25 @@ namespace jank::runtime other); } - object_ref merge_in_place(object_ref const m, object_ref const other) + object_ref merge_in_place(object_ref const &m, object_ref const &other) { if(other.is_nil()) { return m; } return visit_object( - [](auto const typed_m, auto const other) -> object_ref { - using T = typename decltype(typed_m)::value_type; + [](auto const &typed_m, auto const &other) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_writable_in_place) { using R = decltype(assoc_in_place(typed_m, jank_nil(), jank_nil())); return visit_map_like( - [](auto const typed_other, auto const typed_m) -> object_ref { + [](auto const &typed_other, auto const &typed_m) -> object_ref { R ret{ typed_m }; for(auto seq{ typed_other->fresh_seq() }; seq.is_some(); seq = seq->next_in_place()) { - auto const e(seq->first()); + auto const &e(seq->first()); ret = assoc_in_place(ret, e->data[0], e->data[1]); } return ret; @@ -781,14 +781,14 @@ namespace jank::runtime other); } - object_ref subvec(object_ref const o, i64 const start, i64 const end) + object_ref subvec(object_ref const &o, i64 const start, i64 const end) { if(o->type != object_type::persistent_vector) { throw std::runtime_error{ "not a vector" }; } - auto const v(expect_object(o)); + auto const &v(expect_object(o)); if(end < start || start < 0 || static_cast(end) > v->count()) { @@ -802,7 +802,7 @@ namespace jank::runtime detail::native_persistent_vector{ v->data.begin() + start, v->data.begin() + end }); } - object_ref nth(object_ref const o, object_ref const idx) + object_ref nth(object_ref const &o, object_ref const &idx) { auto const index(to_int(idx)); if(index < 0) @@ -815,8 +815,8 @@ namespace jank::runtime } return visit_object( - [&](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [&](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::indexable) { @@ -825,7 +825,7 @@ namespace jank::runtime else if constexpr(behavior::seqable && behavior::sequential) { i64 i{}; - for(auto const e : make_sequence_range(typed_o)) + for(auto const &e : make_sequence_range(typed_o)) { if(i == index) { @@ -843,7 +843,7 @@ namespace jank::runtime o); } - object_ref nth(object_ref const o, object_ref const idx, object_ref const fallback) + object_ref nth(object_ref const &o, object_ref const &idx, object_ref const &fallback) { auto const index(to_int(idx)); if(index < 0 || o == jank_nil()) @@ -852,8 +852,8 @@ namespace jank::runtime } return visit_object( - [&](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [&](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::indexable) { @@ -862,7 +862,7 @@ namespace jank::runtime else if constexpr(behavior::seqable && behavior::sequential) { i64 i{}; - for(auto const e : make_sequence_range(typed_o)) + for(auto const &e : make_sequence_range(typed_o)) { if(i == index) { @@ -880,7 +880,7 @@ namespace jank::runtime o); } - object_ref peek(object_ref const o) + object_ref peek(object_ref const &o) { if(o == jank_nil()) { @@ -888,8 +888,8 @@ namespace jank::runtime } return visit_object( - [&](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [&](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::stackable) { @@ -903,7 +903,7 @@ namespace jank::runtime o); } - object_ref pop(object_ref const o) + object_ref pop(object_ref const &o) { if(o == jank_nil()) { @@ -911,8 +911,8 @@ namespace jank::runtime } return visit_object( - [&](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [&](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::stackable) { @@ -926,15 +926,15 @@ namespace jank::runtime o); } - object_ref empty(object_ref const o) + object_ref empty(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::collection_like) { - auto const empty{ T::empty() }; + auto const &empty{ T::empty() }; return with_meta(empty, meta(typed_o)); } else @@ -945,12 +945,12 @@ namespace jank::runtime o); } - jtl::immutable_string str(object_ref const o) + jtl::immutable_string str(object_ref const &o) { return runtime::to_string(o); } - jtl::immutable_string str(object_ref const o, object_ref const args) + jtl::immutable_string str(object_ref const &o, object_ref const &args) { jtl::string_builder buff; buff.reserve(16); @@ -959,8 +959,8 @@ namespace jank::runtime runtime::to_string(o, buff); } return visit_seqable( - [](auto const typed_args, jtl::string_builder &buff) -> jtl::immutable_string { - for(auto const e : make_sequence_range(typed_args)) + [](auto const &typed_args, jtl::string_builder &buff) -> jtl::immutable_string { + for(auto const &e : make_sequence_range(typed_args)) { if(is_nil(e)) { @@ -974,30 +974,30 @@ namespace jank::runtime buff); } - obj::persistent_list_ref list(object_ref const s) + obj::persistent_list_ref list(object_ref const &s) { return visit_seqable( - [](auto const typed_s) -> obj::persistent_list_ref { + [](auto const &typed_s) -> obj::persistent_list_ref { return obj::persistent_list::create(typed_s); }, s); } - obj::persistent_vector_ref vec(object_ref const s) + obj::persistent_vector_ref vec(object_ref const &s) { return visit_seqable( - [](auto const typed_s) -> obj::persistent_vector_ref { + [](auto const &typed_s) -> obj::persistent_vector_ref { return obj::persistent_vector::create(typed_s); }, s); } - usize sequence_length(object_ref const s) + usize sequence_length(object_ref const &s) { return sequence_length(s, std::numeric_limits::max()); } - usize sequence_length(object_ref const s, usize const max) + usize sequence_length(object_ref const &s, usize const max) { if(s.is_nil()) { @@ -1005,8 +1005,8 @@ namespace jank::runtime } return visit_object( - [&](auto const typed_s) -> usize { - using T = typename decltype(typed_s)::value_type; + [&](auto const &typed_s) -> usize { + using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) { @@ -1019,7 +1019,7 @@ namespace jank::runtime else if constexpr(behavior::seqable) { usize length{ 0 }; - auto const r{ make_sequence_range(typed_s) }; + auto const &r{ make_sequence_range(typed_s) }; for(auto i(r.begin()); i != r.end() && length < max; ++i) { ++length; @@ -1034,7 +1034,7 @@ namespace jank::runtime s); } - bool sequence_equal(object_ref const l, object_ref const r) + bool sequence_equal(object_ref const &l, object_ref const &r) { if(l == r) { @@ -1043,11 +1043,11 @@ namespace jank::runtime /* TODO: visit_sequence. */ return visit_seqable( - [](auto const typed_l, object_ref const r) -> bool { + [](auto const &typed_l, object_ref const &r) -> bool { return visit_seqable( - [](auto const typed_r, auto const typed_l) -> bool { - auto const l_range{ make_sequence_range(typed_l) }; - auto const r_range{ make_sequence_range(typed_r) }; + [](auto const &typed_r, auto const &typed_l) -> bool { + auto const &l_range{ make_sequence_range(typed_l) }; + auto const &r_range{ make_sequence_range(typed_r) }; auto r_it(r_range.begin()); for(auto l_it(l_range.begin()); l_it != l_range.end(); ++l_it, ++r_it) { @@ -1067,12 +1067,12 @@ namespace jank::runtime r); } - object_ref reduce(object_ref const f, object_ref const init, object_ref const s) + object_ref reduce(object_ref const &f, object_ref const &init, object_ref const &s) { return visit_seqable( - [](auto const typed_coll, object_ref const f, object_ref const init) -> object_ref { + [](auto const &typed_coll, object_ref const &f, object_ref const &init) -> object_ref { object_ref res{ init }; - for(auto const e : make_sequence_range(typed_coll)) + for(auto const &e : make_sequence_range(typed_coll)) { res = dynamic_call(f, res, e); if(res->type == object_type::reduced) @@ -1088,39 +1088,39 @@ namespace jank::runtime init); } - object_ref reduced(object_ref const o) + object_ref reduced(object_ref const &o) { return make_box(o); } - bool is_reduced(object_ref const o) + bool is_reduced(object_ref const &o) { return o->type == object_type::reduced; } - object_ref chunk_buffer(object_ref const capacity) + object_ref chunk_buffer(object_ref const &capacity) { return make_box(capacity); } - object_ref chunk_append(object_ref const buff, object_ref const val) + object_ref chunk_append(object_ref const &buff, object_ref const &val) { - auto const buffer(try_object(buff)); + auto const &buffer(try_object(buff)); buffer->append(val); return jank_nil(); } - object_ref chunk(object_ref const buff) + object_ref chunk(object_ref const &buff) { - auto const buffer(try_object(buff)); + auto const &buffer(try_object(buff)); return buffer->chunk(); } - object_ref chunk_first(object_ref const o) + object_ref chunk_first(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::chunkable) { @@ -1133,11 +1133,11 @@ namespace jank::runtime o); } - object_ref chunk_next(object_ref const o) + object_ref chunk_next(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::chunkable) { @@ -1150,11 +1150,11 @@ namespace jank::runtime o); } - object_ref chunk_rest(object_ref const o) + object_ref chunk_rest(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> object_ref { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> object_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::chunkable) { @@ -1167,52 +1167,52 @@ namespace jank::runtime o); } - object_ref chunk_cons(object_ref const chunk, object_ref const rest) + object_ref chunk_cons(object_ref const &chunk, object_ref const &rest) { return make_box(chunk, seq(rest)); } - bool is_chunked_seq(object_ref const o) + bool is_chunked_seq(object_ref const &o) { return visit_object( - [=](auto const typed_o) -> bool { - using T = typename decltype(typed_o)::value_type; + [=](auto const &typed_o) -> bool { + using T = typename jtl::decay_t::value_type; return behavior::chunkable; }, o); } - object_ref iterate(object_ref const fn, object_ref const o) + object_ref iterate(object_ref const &fn, object_ref const &o) { return make_box(fn, o); } - object_ref repeat(object_ref const val) + object_ref repeat(object_ref const &val) { return obj::repeat::create(val); } - object_ref repeat(object_ref const n, object_ref const val) + object_ref repeat(object_ref const &n, object_ref const &val) { return obj::repeat::create(n, val); } - object_ref sort(object_ref const coll) + object_ref sort(object_ref const &coll) { return visit_seqable( - [](auto const typed_coll) -> object_ref { + [](auto const &typed_coll) -> object_ref { native_vector vec; - for(auto const e : make_sequence_range(typed_coll)) + for(auto const &e : make_sequence_range(typed_coll)) { vec.push_back(e); } - std::stable_sort(vec.begin(), vec.end(), [](object_ref const a, object_ref const b) { + std::stable_sort(vec.begin(), vec.end(), [](object_ref const &a, object_ref const &b) { return runtime::compare(a, b) < 0; }); - using T = typename decltype(typed_coll)::value_type; + using T = typename jtl::decay_t::value_type; if constexpr(behavior::metadatable) { @@ -1226,12 +1226,12 @@ namespace jank::runtime coll); } - object_ref shuffle(object_ref const coll) + object_ref shuffle(object_ref const &coll) { return visit_seqable( - [](auto const typed_coll) -> object_ref { + [](auto const &typed_coll) -> object_ref { native_vector vec; - for(auto const e : make_sequence_range(typed_coll)) + for(auto const &e : make_sequence_range(typed_coll)) { vec.push_back(e); } diff --git a/compiler+runtime/src/cpp/jank/runtime/core/to_string.cpp b/compiler+runtime/src/cpp/jank/runtime/core/to_string.cpp index ab32d9245..6818495c9 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/to_string.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/to_string.cpp @@ -13,14 +13,14 @@ namespace jank::runtime obj::character{ ch }.to_string(buff); } - void to_string(object_ref const o, jtl::string_builder &buff) + void to_string(object_ref const &o, jtl::string_builder &buff) { - visit_object([&](auto const typed_o) { typed_o->to_string(buff); }, o); + visit_object([&](auto const &typed_o) { typed_o->to_string(buff); }, o); } - jtl::immutable_string to_code_string(object_ref const o) + jtl::immutable_string to_code_string(object_ref const &o) { - return visit_object([](auto const typed_o) { return typed_o->to_code_string(); }, o); + return visit_object([](auto const &typed_o) { return typed_o->to_code_string(); }, o); } void to_code_string(char const ch, jtl::string_builder &buff) @@ -28,9 +28,9 @@ namespace jank::runtime buff(obj::character{ ch }.to_code_string()); } - void to_code_string(object_ref const o, jtl::string_builder &buff) + void to_code_string(object_ref const &o, jtl::string_builder &buff) { - auto const value{ visit_object([](auto const typed_o) { return typed_o->to_code_string(); }, + auto const value{ visit_object([](auto const &typed_o) { return typed_o->to_code_string(); }, o) }; buff(value); } diff --git a/compiler+runtime/src/cpp/jank/runtime/core/truthy.cpp b/compiler+runtime/src/cpp/jank/runtime/core/truthy.cpp index 24228c95d..6bc42d47e 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/truthy.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/truthy.cpp @@ -24,17 +24,17 @@ namespace jank::runtime return true; } - bool truthy(object_ref const o) + bool truthy(object_ref const &o) { return truthy(o.data); } - bool truthy(obj::nil_ref) + bool truthy(obj::nil_ref const &) { return false; } - bool truthy(obj::boolean_ref const o) + bool truthy(obj::boolean_ref const &o) { return o.is_some() && o->data; } diff --git a/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp b/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp index 9f69cb8e3..2c9c15742 100644 --- a/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp @@ -1,5 +1,6 @@ #include #include +#include #include namespace jank::runtime::detail @@ -119,11 +120,12 @@ namespace jank::runtime::detail native_array_map::~native_array_map() { + data = nullptr; /* TODO: data could still be referenced by iterators. shared ptr? */ //delete[] data; } - void native_array_map::insert_unique(object_ref const key, object_ref const val) + void native_array_map::insert_unique(object_ref const &key, object_ref const &val) { data = make_next_array(data, cap, length, key, val); length += 2; @@ -131,7 +133,7 @@ namespace jank::runtime::detail hash = 0; } - void native_array_map::insert_or_assign(object_ref const key, object_ref const val) + void native_array_map::insert_or_assign(object_ref const &key, object_ref const &val) { if(key->type == runtime::object_type::keyword) { @@ -160,7 +162,7 @@ namespace jank::runtime::detail insert_unique(key, val); } - jtl::option native_array_map::find(object_ref const key) const + jtl::option native_array_map::find(object_ref const &key) const { if(key->type == runtime::object_type::keyword) { @@ -185,7 +187,7 @@ namespace jank::runtime::detail return {}; } - void native_array_map::erase(object_ref const key) + void native_array_map::erase(object_ref const &key) { if(key->type == runtime::object_type::keyword) { @@ -298,7 +300,7 @@ namespace jank::runtime::detail auto const new_capacity{ static_cast(size * 2) }; - if(new_capacity < cap) + if(new_capacity <= cap) { return; } @@ -336,7 +338,7 @@ namespace jank::runtime::detail { native_array_map ret{ *this }; ret.data = new object_ref[cap]; - for(usize i{}; i < length; ++i) + for(u8 i{}; i < length; ++i) { ret.data[i] = data[i]; } diff --git a/compiler+runtime/src/cpp/jank/runtime/detail/type.cpp b/compiler+runtime/src/cpp/jank/runtime/detail/type.cpp index b8c4abafd..8ea3d9fa6 100644 --- a/compiler+runtime/src/cpp/jank/runtime/detail/type.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/detail/type.cpp @@ -3,7 +3,7 @@ namespace jank::runtime::detail { - bool object_ref_compare::operator()(object_ref const l, object_ref const r) const + bool object_ref_compare::operator()(object_ref const &l, object_ref const &r) const { return runtime::compare(l, r) < 0; } diff --git a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp index 3ea237e1f..cc6e4fedf 100644 --- a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp @@ -828,13 +828,13 @@ namespace jank::runtime::module auto const loaded_libs_atom{ runtime::try_object( __rt_ctx->loaded_libs_var->deref()) }; - auto const swap_fn{ [&](object_ref const curr_val) { + auto const swap_fn{ [&](object_ref const &curr_val) { return runtime::try_object(curr_val)->conj( make_box(module)); } }; auto const swap_fn_wrapper{ make_box( - std::function{ swap_fn }) }; + std::function{ swap_fn }) }; loaded_libs_atom->swap(swap_fn_wrapper); } diff --git a/compiler+runtime/src/cpp/jank/runtime/ns.cpp b/compiler+runtime/src/cpp/jank/runtime/ns.cpp index 2306fe325..a42966e8b 100644 --- a/compiler+runtime/src/cpp/jank/runtime/ns.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/ns.cpp @@ -8,7 +8,7 @@ namespace jank::runtime { - ns::ns(obj::symbol_ref const name) + ns::ns(obj::symbol_ref const &name) : name{ name } , vars{ obj::persistent_hash_map::empty() } , aliases{ obj::persistent_hash_map::empty() } @@ -20,7 +20,7 @@ namespace jank::runtime return intern_var(make_box(name)); } - var_ref ns::intern_var(obj::symbol_ref const sym) + var_ref ns::intern_var(obj::symbol_ref const &sym) { obj::symbol_ref unqualified_sym{ sym }; if(!unqualified_sym->ns.empty()) @@ -59,7 +59,7 @@ namespace jank::runtime * WARNING 'println' already referred to #'clojure.core/println in namespace 'foo' but has been replaced by #'foo/println * ``` */ - var_ref ns::intern_owned_var(obj::symbol_ref const sym) + var_ref ns::intern_owned_var(obj::symbol_ref const &sym) { obj::symbol_ref unqualified_sym{ sym }; if(!unqualified_sym->ns.empty()) @@ -98,7 +98,7 @@ namespace jank::runtime return new_var; } - jtl::result ns::unmap(obj::symbol_ref const sym) + jtl::result ns::unmap(obj::symbol_ref const &sym) { if(!sym->ns.empty()) { @@ -110,7 +110,7 @@ namespace jank::runtime return ok(); } - var_ref ns::find_var(obj::symbol_ref const sym) + var_ref ns::find_var(obj::symbol_ref const &sym) { if(!sym->ns.empty()) { @@ -128,7 +128,7 @@ namespace jank::runtime } jtl::result - ns::add_alias(obj::symbol_ref const sym, ns_ref const nsp) + ns::add_alias(obj::symbol_ref const &sym, ns_ref const &nsp) { auto locked_aliases(aliases.wlock()); auto const found((*locked_aliases)->data.find(sym)); @@ -149,13 +149,13 @@ namespace jank::runtime return ok(); } - void ns::remove_alias(obj::symbol_ref const sym) + void ns::remove_alias(obj::symbol_ref const &sym) { auto locked_aliases(aliases.wlock()); *locked_aliases = make_box((*locked_aliases)->data.erase(sym)); } - ns_ref ns::find_alias(obj::symbol_ref const sym) const + ns_ref ns::find_alias(obj::symbol_ref const &sym) const { auto locked_aliases(aliases.rlock()); auto const found((*locked_aliases)->data.find(sym)); @@ -166,7 +166,7 @@ namespace jank::runtime return {}; } - jtl::result ns::refer(obj::symbol_ref const sym, var_ref const var) + jtl::result ns::refer(obj::symbol_ref const &sym, var_ref const &var) { auto locked_vars(vars.wlock()); if(auto const found = (*locked_vars)->data.find(sym)) diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/array_chunk.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/array_chunk.cpp index 9b14b3442..755968dbf 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/array_chunk.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/array_chunk.cpp @@ -75,7 +75,7 @@ namespace jank::runtime::obj return buffer.size() - offset; } - object_ref array_chunk::nth(object_ref const index) const + object_ref array_chunk::nth(object_ref const &index) const { if(index->type == object_type::integer) { @@ -97,7 +97,7 @@ namespace jank::runtime::obj } } - object_ref array_chunk::nth(object_ref const index, object_ref const fallback) const + object_ref array_chunk::nth(object_ref const &index, object_ref const &fallback) const { if(index->type == object_type::integer) { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp index 414f2f63c..09e5a312c 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp @@ -7,7 +7,7 @@ namespace jank::runtime::obj { - atom::atom(object_ref const o) + atom::atom(object_ref const &o) : val{ o.data } , watches{ persistent_hash_map::empty() } { @@ -51,7 +51,7 @@ namespace jank::runtime::obj return val.load(); } - static void notify_watches(atom_ref const a, object_ref const old_val, object_ref const new_val) + static void notify_watches(atom_ref const &a, object_ref const &old_val, object_ref const &new_val) { auto const locked_watches(a->watches.rlock()); for(auto const &entry : (*locked_watches)->data) @@ -64,7 +64,7 @@ namespace jank::runtime::obj } } - object_ref atom::reset(object_ref const o) + object_ref atom::reset(object_ref const &o) { jank_debug_assert(o.is_some()); auto const v(val.load()); @@ -75,7 +75,7 @@ namespace jank::runtime::obj return o; } - persistent_vector_ref atom::reset_vals(object_ref const o) + persistent_vector_ref atom::reset_vals(object_ref const &o) { while(true) { @@ -92,7 +92,7 @@ namespace jank::runtime::obj } /* NOLINTNEXTLINE(cppcoreguidelines-noexcept-swap,bugprone-exception-escape) */ - object_ref atom::swap(object_ref const fn) + object_ref atom::swap(object_ref const &fn) { while(true) { @@ -109,7 +109,7 @@ namespace jank::runtime::obj } /* NOLINTNEXTLINE(cppcoreguidelines-noexcept-swap,bugprone-exception-escape) */ - object_ref atom::swap(object_ref const fn, object_ref const a1) + object_ref atom::swap(object_ref const &fn, object_ref const &a1) { while(true) { @@ -126,7 +126,7 @@ namespace jank::runtime::obj } /* NOLINTNEXTLINE(cppcoreguidelines-noexcept-swap,bugprone-exception-escape) */ - object_ref atom::swap(object_ref const fn, object_ref const a1, object_ref const a2) + object_ref atom::swap(object_ref const &fn, object_ref const &a1, object_ref const &a2) { while(true) { @@ -144,7 +144,7 @@ namespace jank::runtime::obj object_ref /* NOLINTNEXTLINE(cppcoreguidelines-noexcept-swap,bugprone-exception-escape) */ - atom::swap(object_ref const fn, object_ref const a1, object_ref const a2, object_ref const rest) + atom::swap(object_ref const &fn, object_ref const &a1, object_ref const &a2, object_ref const &rest) { while(true) { @@ -161,7 +161,7 @@ namespace jank::runtime::obj } } - persistent_vector_ref atom::swap_vals(object_ref const fn) + persistent_vector_ref atom::swap_vals(object_ref const &fn) { while(true) { @@ -178,7 +178,7 @@ namespace jank::runtime::obj } } - persistent_vector_ref atom::swap_vals(object_ref const fn, object_ref const a1) + persistent_vector_ref atom::swap_vals(object_ref const &fn, object_ref const &a1) { while(true) { @@ -196,7 +196,7 @@ namespace jank::runtime::obj } persistent_vector_ref - atom::swap_vals(object_ref const fn, object_ref const a1, object_ref const a2) + atom::swap_vals(object_ref const &fn, object_ref const &a1, object_ref const &a2) { while(true) { @@ -213,10 +213,10 @@ namespace jank::runtime::obj } } - persistent_vector_ref atom::swap_vals(object_ref const fn, - object_ref const a1, - object_ref const a2, - object_ref const rest) + persistent_vector_ref atom::swap_vals(object_ref const &fn, + object_ref const &a1, + object_ref const &a2, + object_ref const &rest) { while(true) { @@ -234,7 +234,7 @@ namespace jank::runtime::obj } } - object_ref atom::compare_and_set(object_ref const old_val, object_ref const new_val) + object_ref atom::compare_and_set(object_ref const &old_val, object_ref const &new_val) { /* NOLINTNEXTLINE(misc-const-correctness): Can't actually be const. */ object *old{ old_val.data }; @@ -248,13 +248,13 @@ namespace jank::runtime::obj return make_box(ret); } - void atom::add_watch(object_ref const key, object_ref const fn) + void atom::add_watch(object_ref const &key, object_ref const &fn) { auto locked_watches(this->watches.wlock()); *locked_watches = (*locked_watches)->assoc(key, fn); } - void atom::remove_watch(object_ref const key) + void atom::remove_watch(object_ref const &key) { auto locked_watches(this->watches.wlock()); *locked_watches = (*locked_watches)->dissoc(key); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/big_decimal.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/big_decimal.cpp index 6339a028c..d534fc1f2 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/big_decimal.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/big_decimal.cpp @@ -4,7 +4,6 @@ namespace jank::runtime { - native_big_decimal operator+(native_big_decimal const &l, native_big_integer const &r) { return l + native_big_decimal(r.str()); @@ -137,7 +136,7 @@ namespace jank::runtime::obj bool big_decimal::equal(object const &o) const { return visit_number_like( - [this](auto const typed_o) -> bool { + [this](auto const &typed_o) -> bool { return abs(data - typed_o->data) < std::numeric_limits::epsilon(); }, [&]() -> bool { return false; }, @@ -167,7 +166,9 @@ namespace jank::runtime::obj i64 big_decimal::compare(object const &o) const { return visit_number_like( - [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, + [this](auto const &typed_o) -> i64 { + return (data > typed_o->data) - (data < typed_o->data); + }, [&]() -> i64 { throw std::runtime_error{ util::format("not comparable: {}", runtime::to_string(&o)) }; }, diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/big_integer.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/big_integer.cpp index 1dd1fd314..db23160ff 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/big_integer.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/big_integer.cpp @@ -7,7 +7,6 @@ namespace jank::runtime { - f64 operator+(native_big_integer const &l, f64 const &r) { return obj::big_integer::to_f64(l) + r; @@ -280,7 +279,9 @@ namespace jank::runtime::obj i64 big_integer::compare(object const &o) const { return visit_number_like( - [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, + [this](auto const &typed_o) -> i64 { + return (data > typed_o->data) - (data < typed_o->data); + }, [&]() -> i64 { throw std::runtime_error{ util::format("not comparable: {}", runtime::to_string(&o)) }; }, diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/chunk_buffer.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/chunk_buffer.cpp index dcdd84cdd..367c1bc33 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/chunk_buffer.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/chunk_buffer.cpp @@ -11,7 +11,7 @@ namespace jank::runtime::obj buffer.reserve(capacity); } - chunk_buffer::chunk_buffer(object_ref const capacity) + chunk_buffer::chunk_buffer(object_ref const &capacity) { auto const c(to_int(capacity)); if(c < 0) @@ -54,7 +54,7 @@ namespace jank::runtime::obj return buffer.size(); } - void chunk_buffer::append(object_ref const o) + void chunk_buffer::append(object_ref const &o) { if(buffer.size() == capacity) { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/chunked_cons.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/chunked_cons.cpp index f6c730922..3911034ee 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/chunked_cons.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/chunked_cons.cpp @@ -7,14 +7,14 @@ namespace jank::runtime::obj { - chunked_cons::chunked_cons(object_ref const head, object_ref const tail) + chunked_cons::chunked_cons(object_ref const &head, object_ref const &tail) : head{ head } , tail{ tail } { jank_debug_assert(head.is_some()); } - chunked_cons::chunked_cons(object_ref const meta, object_ref const head, object_ref const tail) + chunked_cons::chunked_cons(object_ref const &meta, object_ref const &head, object_ref const &tail) : head{ head } , tail{ tail } , meta{ meta } @@ -75,7 +75,7 @@ namespace jank::runtime::obj head); } - static chunked_cons_ref next_in_place_non_chunked(chunked_cons_ref const o) + static chunked_cons_ref next_in_place_non_chunked(chunked_cons_ref const &o) { if(o->tail.is_nil()) { @@ -83,8 +83,8 @@ namespace jank::runtime::obj } return visit_object( - [&](auto const typed_tail) -> chunked_cons_ref { - using T = typename decltype(typed_tail)::value_type; + [&](auto const &typed_tail) -> chunked_cons_ref { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::sequenceable) { @@ -177,12 +177,12 @@ namespace jank::runtime::obj return hash::ordered(&base); } - cons_ref chunked_cons::conj(object_ref const head) const + cons_ref chunked_cons::conj(object_ref const &head) const { return make_box(head, this); } - chunked_cons_ref chunked_cons::with_meta(object_ref const m) const + chunked_cons_ref chunked_cons::with_meta(object_ref const &m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(fresh_seq()); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/cons.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/cons.cpp index 1baff1f0b..0c15c82d9 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/cons.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/cons.cpp @@ -5,7 +5,7 @@ namespace jank::runtime::obj { - cons::cons(object_ref const head, object_ref const tail) + cons::cons(object_ref const &head, object_ref const &tail) : head{ head } , tail{ tail } { @@ -66,12 +66,12 @@ namespace jank::runtime::obj return hash = hash::ordered(&base); } - cons_ref cons::conj(object_ref const head) const + cons_ref cons::conj(object_ref const &head) const { return make_box(head, this); } - cons_ref cons::with_meta(object_ref const m) const + cons_ref cons::with_meta(object_ref const &m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(fresh_seq()); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/delay.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/delay.cpp index 41c425990..edf6dc6ac 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/delay.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/delay.cpp @@ -5,7 +5,7 @@ namespace jank::runtime::obj { - delay::delay(object_ref const fn) + delay::delay(object_ref const &fn) : fn{ fn } { } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map.cpp index 612cdd25d..ab0617717 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map.cpp @@ -23,7 +23,7 @@ namespace jank::runtime::obj::detail } return visit_map_like( - [&](auto const typed_o) -> bool { + [&](auto const &typed_o) -> bool { if(typed_o->count() != count()) { return false; @@ -55,7 +55,7 @@ namespace jank::runtime::obj::detail inserter = '{'; for(auto i(begin); i != end; ++i) { - auto const pair(*i); + auto const &pair(*i); if(to_code) { runtime::to_code_string(pair.first, buff); @@ -158,7 +158,7 @@ namespace jank::runtime::obj::detail } template - object_ref base_persistent_map::conj(object_ref const head) const + object_ref base_persistent_map::conj(object_ref const &head) const { auto const ret(static_cast(this)); if(head.is_nil()) @@ -188,7 +188,7 @@ namespace jank::runtime::obj::detail } template - oref base_persistent_map::with_meta(object_ref const m) const + oref base_persistent_map::with_meta(object_ref const &m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(make_box(static_cast(this)->data)); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.cpp index b42ddcd61..9066ec1fd 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.cpp @@ -5,7 +5,7 @@ namespace jank::runtime::obj::detail { template - base_persistent_map_sequence::base_persistent_map_sequence(object_ref const c, + base_persistent_map_sequence::base_persistent_map_sequence(object_ref const &c, IT const &b, IT const &e) : coll{ c } @@ -138,7 +138,7 @@ namespace jank::runtime::obj::detail } template - obj::cons_ref base_persistent_map_sequence::conj(object_ref const head) + obj::cons_ref base_persistent_map_sequence::conj(object_ref const &head) { return make_box(head, static_cast(this)); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/detail/iterator_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/detail/iterator_sequence.cpp index 130c3ee07..f5d11eef5 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/detail/iterator_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/detail/iterator_sequence.cpp @@ -5,7 +5,7 @@ namespace jank::runtime { - bool equal(object_ref lhs, object_ref rhs); + bool equal(object_ref const &lhs, object_ref const &rhs); } namespace jank::runtime::obj::detail @@ -112,7 +112,7 @@ namespace jank::runtime::obj::detail } template - obj::cons_ref iterator_sequence::conj(object_ref const head) + obj::cons_ref iterator_sequence::conj(object_ref const &head) { return make_box(head, static_cast(this)); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/integer_range.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/integer_range.cpp index de5917f0a..f2406aeb0 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/integer_range.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/integer_range.cpp @@ -7,17 +7,17 @@ namespace jank::runtime::obj { - static bool positive_step_bounds_check(integer_ref const val, integer_ref const end) + static bool positive_step_bounds_check(integer_ref const &val, integer_ref const &end) { return lte(end, val); } - static bool negative_step_bounds_check(integer_ref const val, integer_ref const end) + static bool negative_step_bounds_check(integer_ref const &val, integer_ref const &end) { return lte(val, end); } - integer_range::integer_range(integer_ref const end) + integer_range::integer_range(integer_ref const &end) : start{ make_box(0) } , end{ end } , step{ make_box(1) } @@ -25,7 +25,7 @@ namespace jank::runtime::obj { } - integer_range::integer_range(integer_ref const start, integer_ref const end) + integer_range::integer_range(integer_ref const &start, integer_ref const &end) : start{ start } , end{ end } , step{ make_box(1) } @@ -33,9 +33,9 @@ namespace jank::runtime::obj { } - integer_range::integer_range(integer_ref const start, - integer_ref const end, - integer_ref const step) + integer_range::integer_range(integer_ref const &start, + integer_ref const &end, + integer_ref const &step) : start{ start } , end{ end } , step{ step } @@ -45,9 +45,9 @@ namespace jank::runtime::obj { } - integer_range::integer_range(integer_ref const start, - integer_ref const end, - integer_ref const step, + integer_range::integer_range(integer_ref const &start, + integer_ref const &end, + integer_ref const &step, integer_range::bounds_check_t const bounds_check) : start{ start } , end{ end } @@ -56,7 +56,7 @@ namespace jank::runtime::obj { } - object_ref integer_range::create(integer_ref const end) + object_ref integer_range::create(integer_ref const &end) { if(is_pos(end)) { @@ -68,13 +68,13 @@ namespace jank::runtime::obj return persistent_list::empty(); } - object_ref integer_range::create(integer_ref const start, integer_ref const end) + object_ref integer_range::create(integer_ref const &start, integer_ref const &end) { return create(start, end, make_box(1)); } object_ref - integer_range::create(integer_ref const start, integer_ref const end, integer_ref const step) + integer_range::create(integer_ref const &start, integer_ref const &end, integer_ref const &step) { if((is_pos(step) && lt(end, start)) || (is_neg(step) && lt(start, end)) || is_equiv(start, end)) { @@ -126,7 +126,7 @@ namespace jank::runtime::obj return this; } - cons_ref integer_range::conj(object_ref const head) const + cons_ref integer_range::conj(object_ref const &head) const { return make_box(head, this); } @@ -156,7 +156,7 @@ namespace jank::runtime::obj return hash::ordered(&base); } - integer_range_ref integer_range::with_meta(object_ref const m) const + integer_range_ref integer_range::with_meta(object_ref const &m) const { auto const meta(behavior::detail::validate_meta(m)); auto const ret(fresh_seq()); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/iterator.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/iterator.cpp index ccc3b3fcb..a7bcbeb08 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/iterator.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/iterator.cpp @@ -5,7 +5,7 @@ namespace jank::runtime::obj { - iterator::iterator(object_ref const fn, object_ref const start) + iterator::iterator(object_ref const &fn, object_ref const &start) : fn{ fn } , current{ start } { @@ -81,7 +81,7 @@ namespace jank::runtime::obj return hash::ordered(&base); } - cons_ref iterator::conj(object_ref const head) const + cons_ref iterator::conj(object_ref const &head) const { return make_box(head, this); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/jit_closure.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/jit_closure.cpp index 91dbd0741..1799927a4 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/jit_closure.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/jit_closure.cpp @@ -17,7 +17,7 @@ namespace jank::runtime::obj { } - jit_closure::jit_closure(object_ref const meta) + jit_closure::jit_closure(object_ref const &meta) : meta{ meta } { } @@ -40,7 +40,7 @@ namespace jank::runtime::obj util::format_to( buff, "#object [{} {} {}]", - (name->type == object_type::nil ? "unknown" : expect_object(name)->data), + (name->type == object_type::nil ? "unknown" : try_object(name)->data), object_type_str(base.type), &base); } @@ -55,7 +55,7 @@ namespace jank::runtime::obj return static_cast(reinterpret_cast(this)); } - jit_closure_ref jit_closure::with_meta(object_ref const m) + jit_closure_ref jit_closure::with_meta(object_ref const &m) { auto const new_meta(behavior::detail::validate_meta(m)); meta = new_meta; @@ -71,7 +71,7 @@ namespace jank::runtime::obj return arity_0(&base); } - object_ref jit_closure::call(object_ref const a1) + object_ref jit_closure::call(object_ref const &a1) { if(!arity_1) { @@ -80,7 +80,7 @@ namespace jank::runtime::obj return arity_1(&base, a1.data); } - object_ref jit_closure::call(object_ref const a1, object_ref const a2) + object_ref jit_closure::call(object_ref const &a1, object_ref const &a2) { if(!arity_2) { @@ -89,7 +89,7 @@ namespace jank::runtime::obj return arity_2(&base, a1.data, a2.data); } - object_ref jit_closure::call(object_ref const a1, object_ref const a2, object_ref const a3) + object_ref jit_closure::call(object_ref const &a1, object_ref const &a2, object_ref const &a3) { if(!arity_3) { @@ -98,10 +98,10 @@ namespace jank::runtime::obj return arity_3(&base, a1.data, a2.data, a3.data); } - object_ref jit_closure::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4) + object_ref jit_closure::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4) { if(!arity_4) { @@ -110,11 +110,11 @@ namespace jank::runtime::obj return arity_4(&base, a1.data, a2.data, a3.data, a4.data); } - object_ref jit_closure::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5) + object_ref jit_closure::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5) { if(!arity_5) { @@ -123,12 +123,12 @@ namespace jank::runtime::obj return arity_5(&base, a1.data, a2.data, a3.data, a4.data, a5.data); } - object_ref jit_closure::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6) + object_ref jit_closure::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6) { if(!arity_6) { @@ -137,13 +137,13 @@ namespace jank::runtime::obj return arity_6(&base, a1.data, a2.data, a3.data, a4.data, a5.data, a6.data); } - object_ref jit_closure::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7) + object_ref jit_closure::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7) { if(!arity_7) { @@ -152,14 +152,14 @@ namespace jank::runtime::obj return arity_7(&base, a1.data, a2.data, a3.data, a4.data, a5.data, a6.data, a7.data); } - object_ref jit_closure::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7, - object_ref const a8) + object_ref jit_closure::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7, + object_ref const &a8) { if(!arity_8) { @@ -168,15 +168,15 @@ namespace jank::runtime::obj return arity_8(&base, a1.data, a2.data, a3.data, a4.data, a5.data, a6.data, a7.data, a8.data); } - object_ref jit_closure::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7, - object_ref const a8, - object_ref const a9) + object_ref jit_closure::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7, + object_ref const &a8, + object_ref const &a9) { if(!arity_9) { @@ -194,16 +194,16 @@ namespace jank::runtime::obj a9.data); } - object_ref jit_closure::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7, - object_ref const a8, - object_ref const a9, - object_ref const a10) + object_ref jit_closure::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7, + object_ref const &a8, + object_ref const &a9, + object_ref const &a10) { if(!arity_10) { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/jit_function.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/jit_function.cpp index 6964b681e..fab9ac162 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/jit_function.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/jit_function.cpp @@ -16,7 +16,7 @@ namespace jank::runtime::obj { } - jit_function::jit_function(object_ref const meta) + jit_function::jit_function(object_ref const &meta) : meta{ meta } { } @@ -39,7 +39,7 @@ namespace jank::runtime::obj util::format_to( buff, "#object [{} {} {}]", - (name->type == object_type::nil ? "unknown" : expect_object(name)->data), + (name->type == object_type::nil ? "unknown" : try_object(name)->data), object_type_str(base.type), &base); } @@ -54,7 +54,7 @@ namespace jank::runtime::obj return static_cast(reinterpret_cast(this)); } - jit_function_ref jit_function::with_meta(object_ref const m) + jit_function_ref jit_function::with_meta(object_ref const &m) { auto const new_meta(behavior::detail::validate_meta(m)); meta = new_meta; @@ -70,7 +70,7 @@ namespace jank::runtime::obj return arity_0(&base); } - object_ref jit_function::call(object_ref const a1) + object_ref jit_function::call(object_ref const &a1) { if(!arity_1) { @@ -79,7 +79,7 @@ namespace jank::runtime::obj return arity_1(&base, a1.data); } - object_ref jit_function::call(object_ref const a1, object_ref const a2) + object_ref jit_function::call(object_ref const &a1, object_ref const &a2) { if(!arity_2) { @@ -88,7 +88,7 @@ namespace jank::runtime::obj return arity_2(&base, a1.data, a2.data); } - object_ref jit_function::call(object_ref const a1, object_ref const a2, object_ref const a3) + object_ref jit_function::call(object_ref const &a1, object_ref const &a2, object_ref const &a3) { if(!arity_3) { @@ -97,10 +97,10 @@ namespace jank::runtime::obj return arity_3(&base, a1.data, a2.data, a3.data); } - object_ref jit_function::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4) + object_ref jit_function::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4) { if(!arity_4) { @@ -109,11 +109,11 @@ namespace jank::runtime::obj return arity_4(&base, a1.data, a2.data, a3.data, a4.data); } - object_ref jit_function::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5) + object_ref jit_function::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5) { if(!arity_5) { @@ -122,12 +122,12 @@ namespace jank::runtime::obj return arity_5(&base, a1.data, a2.data, a3.data, a4.data, a5.data); } - object_ref jit_function::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6) + object_ref jit_function::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6) { if(!arity_6) { @@ -136,13 +136,13 @@ namespace jank::runtime::obj return arity_6(&base, a1.data, a2.data, a3.data, a4.data, a5.data, a6.data); } - object_ref jit_function::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7) + object_ref jit_function::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7) { if(!arity_7) { @@ -151,14 +151,14 @@ namespace jank::runtime::obj return arity_7(&base, a1.data, a2.data, a3.data, a4.data, a5.data, a6.data, a7.data); } - object_ref jit_function::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7, - object_ref const a8) + object_ref jit_function::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7, + object_ref const &a8) { if(!arity_8) { @@ -167,15 +167,15 @@ namespace jank::runtime::obj return arity_8(&base, a1.data, a2.data, a3.data, a4.data, a5.data, a6.data, a7.data, a8.data); } - object_ref jit_function::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7, - object_ref const a8, - object_ref const a9) + object_ref jit_function::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7, + object_ref const &a8, + object_ref const &a9) { if(!arity_9) { @@ -193,16 +193,16 @@ namespace jank::runtime::obj a9.data); } - object_ref jit_function::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7, - object_ref const a8, - object_ref const a9, - object_ref const a10) + object_ref jit_function::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7, + object_ref const &a8, + object_ref const &a9, + object_ref const &a10) { if(!arity_10) { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/keyword.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/keyword.cpp index 5feacd4c5..79eca4dcf 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/keyword.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/keyword.cpp @@ -71,12 +71,12 @@ namespace jank::runtime::obj return sym->ns; } - object_ref keyword::call(object_ref const m) + object_ref keyword::call(object_ref const &m) { return runtime::get(m, this); } - object_ref keyword::call(object_ref const m, object_ref const fallback) + object_ref keyword::call(object_ref const &m, object_ref const &fallback) { return runtime::get(m, this, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp index dade9af1a..641cfae7b 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp @@ -11,13 +11,13 @@ namespace jank::runtime::obj { - lazy_sequence::lazy_sequence(object_ref const fn) + lazy_sequence::lazy_sequence(object_ref const &fn) : fn{ fn } { jank_debug_assert(fn.is_some()); } - lazy_sequence::lazy_sequence(object_ref const fn, object_ref const sequence) + lazy_sequence::lazy_sequence(object_ref const &fn, object_ref const &sequence) : fn{ fn } , s{ sequence } { @@ -92,7 +92,7 @@ namespace jank::runtime::obj return hash::ordered(s.erase()); } - cons_ref lazy_sequence::conj(object_ref const head) const + cons_ref lazy_sequence::conj(object_ref const &head) const { return make_box(head, seq()); } @@ -150,7 +150,7 @@ namespace jank::runtime::obj return ls; } - lazy_sequence_ref lazy_sequence::with_meta(object_ref const m) const + lazy_sequence_ref lazy_sequence::with_meta(object_ref const &m) const { auto const ret(make_box(jank_nil(), seq())); auto const meta(behavior::detail::validate_meta(m)); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/multi_function.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/multi_function.cpp index ba1906465..0ba7c2451 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/multi_function.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/multi_function.cpp @@ -9,10 +9,10 @@ namespace jank::runtime::obj { - multi_function::multi_function(object_ref const name, - object_ref const dispatch, - object_ref const default_, - object_ref const hierarchy) + multi_function::multi_function(object_ref const &name, + object_ref const &dispatch, + object_ref const &default_, + object_ref const &hierarchy) : dispatch{ dispatch } , default_dispatch_value{ default_ } , hierarchy{ hierarchy } @@ -59,44 +59,44 @@ namespace jank::runtime::obj return dynamic_call(get_fn(dynamic_call(dispatch))); } - object_ref multi_function::call(object_ref const a1) + object_ref multi_function::call(object_ref const &a1) { return dynamic_call(get_fn(dynamic_call(dispatch, a1)), a1); } - object_ref multi_function::call(object_ref const a1, object_ref const a2) + object_ref multi_function::call(object_ref const &a1, object_ref const &a2) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2)), a1, a2); } - object_ref multi_function::call(object_ref const a1, object_ref const a2, object_ref const a3) + object_ref multi_function::call(object_ref const &a1, object_ref const &a2, object_ref const &a3) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3)), a1, a2, a3); } - object_ref multi_function::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4) + object_ref multi_function::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3, a4)), a1, a2, a3, a4); } - object_ref multi_function::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5) + object_ref multi_function::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3, a4, a5)), a1, a2, a3, a4, a5); } - object_ref multi_function::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6) + object_ref multi_function::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3, a4, a5, a6)), a1, @@ -107,13 +107,13 @@ namespace jank::runtime::obj a6); } - object_ref multi_function::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7) + object_ref multi_function::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3, a4, a5, a6, a7)), a1, @@ -125,14 +125,14 @@ namespace jank::runtime::obj a7); } - object_ref multi_function::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7, - object_ref const a8) + object_ref multi_function::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7, + object_ref const &a8) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3, a4, a5, a6, a7, a8)), a1, @@ -145,15 +145,15 @@ namespace jank::runtime::obj a8); } - object_ref multi_function::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7, - object_ref const a8, - object_ref const a9) + object_ref multi_function::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7, + object_ref const &a8, + object_ref const &a9) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3, a4, a5, a6, a7, a8, a9)), a1, @@ -167,16 +167,16 @@ namespace jank::runtime::obj a9); } - object_ref multi_function::call(object_ref const a1, - object_ref const a2, - object_ref const a3, - object_ref const a4, - object_ref const a5, - object_ref const a6, - object_ref const a7, - object_ref const a8, - object_ref const a9, - object_ref const a10) + object_ref multi_function::call(object_ref const &a1, + object_ref const &a2, + object_ref const &a3, + object_ref const &a4, + object_ref const &a5, + object_ref const &a6, + object_ref const &a7, + object_ref const &a8, + object_ref const &a9, + object_ref const &a10) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)), a1, @@ -213,7 +213,7 @@ namespace jank::runtime::obj } multi_function_ref - multi_function::add_method(object_ref const dispatch_val, object_ref const method) + multi_function::add_method(object_ref const &dispatch_val, object_ref const &method) { std::lock_guard const locked{ data_lock }; @@ -222,7 +222,7 @@ namespace jank::runtime::obj return this; } - multi_function_ref multi_function::remove_method(object_ref const dispatch_val) + multi_function_ref multi_function::remove_method(object_ref const &dispatch_val) { std::lock_guard const locked{ data_lock }; method_table = method_table->dissoc(dispatch_val); @@ -230,7 +230,7 @@ namespace jank::runtime::obj return this; } - multi_function_ref multi_function::prefer_method(object_ref const x, object_ref const y) + multi_function_ref multi_function::prefer_method(object_ref const &x, object_ref const &y) { std::lock_guard const locked{ data_lock }; @@ -250,9 +250,9 @@ namespace jank::runtime::obj return this; } - bool multi_function::is_preferred(object_ref const hierarchy, - object_ref const x, - object_ref const y) const + bool multi_function::is_preferred(object_ref const &hierarchy, + object_ref const &x, + object_ref const &y) const { auto const x_prefs(prefer_table->get(x)); if(x_prefs != jank_nil() && expect_object(x_prefs)->contains(y)) @@ -285,7 +285,7 @@ namespace jank::runtime::obj return false; } - bool multi_function::is_a(object_ref const hierarchy, object_ref const x, object_ref const y) + bool multi_function::is_a(object_ref const &hierarchy, object_ref const &x, object_ref const &y) { static object_ref const isa{ __rt_ctx->intern_var("clojure.core", "isa?").expect_ok()->deref() @@ -293,14 +293,14 @@ namespace jank::runtime::obj return truthy(dynamic_call(isa, deref(hierarchy), x, y)); } - bool multi_function::is_dominant(object_ref const hierarchy, - object_ref const x, - object_ref const y) const + bool multi_function::is_dominant(object_ref const &hierarchy, + object_ref const &x, + object_ref const &y) const { return is_preferred(hierarchy, x, y) || is_a(hierarchy, x, y); } - object_ref multi_function::get_fn(object_ref const dispatch_val) + object_ref multi_function::get_fn(object_ref const &dispatch_val) { auto const target(get_method(dispatch_val)); if(target == jank_nil()) @@ -312,14 +312,14 @@ namespace jank::runtime::obj return target; } - object_ref multi_function::get_method(object_ref const dispatch_val) + object_ref multi_function::get_method(object_ref const &dispatch_val) { if(cached_hierarchy != deref(hierarchy)) { reset_cache(); } - auto const target(method_cache->get(dispatch_val)); + auto target(method_cache->get(dispatch_val)); if(target != jank_nil()) { return target; @@ -328,7 +328,7 @@ namespace jank::runtime::obj return find_and_cache_best_method(dispatch_val); } - object_ref multi_function::find_and_cache_best_method(object_ref const dispatch_val) + object_ref multi_function::find_and_cache_best_method(object_ref const &dispatch_val) { /* TODO: Clojure uses a RW lock here for better parallelism. */ std::lock_guard const locked{ data_lock }; diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/native_array_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/native_array_sequence.cpp index 1bcc265c6..fceeb936a 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/native_array_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/native_array_sequence.cpp @@ -102,7 +102,7 @@ namespace jank::runtime::obj return this; } - cons_ref native_array_sequence::conj(object_ref const head) + cons_ref native_array_sequence::conj(object_ref const &head) { return make_box(head, this); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp index a70fea469..cc2a0e262 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp @@ -1,9 +1,11 @@ #include #include #include +#include #include #include #include +#include #include namespace jank::runtime::obj @@ -25,7 +27,12 @@ namespace jank::runtime::obj void native_function_wrapper::to_string(jtl::string_builder &buff) const { - util::format_to(buff, "#object [{} {}]", object_type_str(base.type), &base); + auto const name(get(meta.unwrap_or(jank_nil()), __rt_ctx->intern_keyword("name").expect_ok())); + util::format_to(buff, + "#object [{} {} {}]", + (name.is_nil() ? "unknown" : try_object(name)->data), + object_type_str(base.type), + &base); } jtl::immutable_string native_function_wrapper::to_string() const @@ -48,7 +55,7 @@ namespace jank::runtime::obj template struct build_arity { - using type = typename build_arity::type; + using type = typename build_arity::type; }; template @@ -88,97 +95,101 @@ namespace jank::runtime::obj return apply_function(*this); } - object_ref native_function_wrapper::call(object_ref arg1) + object_ref native_function_wrapper::call(object_ref const &arg1) { return apply_function(*this, arg1); } - object_ref native_function_wrapper::call(object_ref arg1, object_ref arg2) + object_ref native_function_wrapper::call(object_ref const &arg1, object_ref const &arg2) { return apply_function(*this, arg1, arg2); } - object_ref native_function_wrapper::call(object_ref arg1, object_ref arg2, object_ref arg3) + object_ref native_function_wrapper::call(object_ref const &arg1, + object_ref const &arg2, + object_ref const &arg3) { return apply_function(*this, arg1, arg2, arg3); } - object_ref - native_function_wrapper::call(object_ref arg1, object_ref arg2, object_ref arg3, object_ref arg4) + object_ref native_function_wrapper::call(object_ref const &arg1, + object_ref const &arg2, + object_ref const &arg3, + object_ref const &arg4) { return apply_function(*this, arg1, arg2, arg3, arg4); } - object_ref native_function_wrapper::call(object_ref arg1, - object_ref arg2, - object_ref arg3, - object_ref arg4, - object_ref arg5) + object_ref native_function_wrapper::call(object_ref const &arg1, + object_ref const &arg2, + object_ref const &arg3, + object_ref const &arg4, + object_ref const &arg5) { return apply_function(*this, arg1, arg2, arg3, arg4, arg5); } - object_ref native_function_wrapper::call(object_ref arg1, - object_ref arg2, - object_ref arg3, - object_ref arg4, - object_ref arg5, - object_ref arg6) + object_ref native_function_wrapper::call(object_ref const &arg1, + object_ref const &arg2, + object_ref const &arg3, + object_ref const &arg4, + object_ref const &arg5, + object_ref const &arg6) { return apply_function(*this, arg1, arg2, arg3, arg4, arg5, arg6); } - object_ref native_function_wrapper::call(object_ref arg1, - object_ref arg2, - object_ref arg3, - object_ref arg4, - object_ref arg5, - object_ref arg6, - object_ref arg7) + object_ref native_function_wrapper::call(object_ref const &arg1, + object_ref const &arg2, + object_ref const &arg3, + object_ref const &arg4, + object_ref const &arg5, + object_ref const &arg6, + object_ref const &arg7) { return apply_function(*this, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } - object_ref native_function_wrapper::call(object_ref arg1, - object_ref arg2, - object_ref arg3, - object_ref arg4, - object_ref arg5, - object_ref arg6, - object_ref arg7, - object_ref arg8) + object_ref native_function_wrapper::call(object_ref const &arg1, + object_ref const &arg2, + object_ref const &arg3, + object_ref const &arg4, + object_ref const &arg5, + object_ref const &arg6, + object_ref const &arg7, + object_ref const &arg8) { return apply_function(*this, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } - object_ref native_function_wrapper::call(object_ref arg1, - object_ref arg2, - object_ref arg3, - object_ref arg4, - object_ref arg5, - object_ref arg6, - object_ref arg7, - object_ref arg8, - object_ref arg9) + object_ref native_function_wrapper::call(object_ref const &arg1, + object_ref const &arg2, + object_ref const &arg3, + object_ref const &arg4, + object_ref const &arg5, + object_ref const &arg6, + object_ref const &arg7, + object_ref const &arg8, + object_ref const &arg9) { return apply_function(*this, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); } - object_ref native_function_wrapper::call(object_ref arg1, - object_ref arg2, - object_ref arg3, - object_ref arg4, - object_ref arg5, - object_ref arg6, - object_ref arg7, - object_ref arg8, - object_ref arg9, - object_ref arg10) + object_ref native_function_wrapper::call(object_ref const &arg1, + object_ref const &arg2, + object_ref const &arg3, + object_ref const &arg4, + object_ref const &arg5, + object_ref const &arg6, + object_ref const &arg7, + object_ref const &arg8, + object_ref const &arg9, + object_ref const &arg10) { return apply_function(*this, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); } - native_function_wrapper_ref native_function_wrapper::with_meta(object_ref const m) const + native_function_wrapper_ref native_function_wrapper::with_meta(object_ref const &m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(make_box(data)); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/native_vector_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/native_vector_sequence.cpp index cea169687..b48f748a5 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/native_vector_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/native_vector_sequence.cpp @@ -111,12 +111,12 @@ namespace jank::runtime::obj return this; } - cons_ref native_vector_sequence::conj(object_ref const head) + cons_ref native_vector_sequence::conj(object_ref const &head) { return make_box(head, data.empty() ? nullptr : this); } - native_vector_sequence_ref native_vector_sequence::with_meta(object_ref const m) const + native_vector_sequence_ref native_vector_sequence::with_meta(object_ref const &m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(fresh_seq()); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp index 2c4719dde..4d253416b 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp @@ -40,32 +40,32 @@ namespace jank::runtime::obj return 0; } - object_ref nil::get(object_ref const) + object_ref nil::get(object_ref const &) { return &base; } - object_ref nil::get(object_ref const, object_ref const fallback) + object_ref nil::get(object_ref const &, object_ref const &fallback) { return fallback; } - object_ref nil::get_entry(object_ref) + object_ref nil::get_entry(object_ref const &) { return &base; } - bool nil::contains(object_ref) const + bool nil::contains(object_ref const &) const { return false; } - persistent_array_map_ref nil::assoc(object_ref const key, object_ref const val) const + persistent_array_map_ref nil::assoc(object_ref const &key, object_ref const &val) const { return persistent_array_map::create_unique(key, val); } - nil_ref nil::dissoc(object_ref const) const + nil_ref nil::dissoc(object_ref const &) const { return this; } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp index 6913750d8..c2ad18714 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp @@ -48,7 +48,9 @@ namespace jank::runtime::obj i64 boolean::compare(object const &o) const { return visit_number_like( - [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, + [this](auto const &typed_o) -> i64 { + return (data > typed_o->data) - (data < typed_o->data); + }, [&]() -> i64 { throw std::runtime_error{ util::format("not comparable: {}", runtime::to_string(&o)) }; }, @@ -101,7 +103,9 @@ namespace jank::runtime::obj i64 integer::compare(object const &o) const { return visit_number_like( - [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, + [this](auto const &typed_o) -> i64 { + return (data > typed_o->data) - (data < typed_o->data); + }, [&]() -> i64 { throw std::runtime_error{ util::format("not comparable: {}", runtime::to_string(&o)) }; }, @@ -184,7 +188,9 @@ namespace jank::runtime::obj i64 real::compare(object const &o) const { return visit_number_like( - [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, + [this](auto const &typed_o) -> i64 { + return (data > typed_o->data) - (data < typed_o->data); + }, [&]() -> i64 { throw std::runtime_error{ util::format("not comparable: {}", runtime::to_string(&o)) }; }, diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/opaque_box.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/opaque_box.cpp index f3133cacd..b0b6a22e4 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/opaque_box.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/opaque_box.cpp @@ -44,7 +44,7 @@ namespace jank::runtime::obj return static_cast(reinterpret_cast(data.data)); } - opaque_box_ref opaque_box::with_meta(object_ref const m) + opaque_box_ref opaque_box::with_meta(object_ref const &m) { meta = behavior::detail::validate_meta(m); return this; diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_array_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_array_map.cpp index 6bee67e1a..7a6013e5e 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_array_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_array_map.cpp @@ -27,17 +27,17 @@ namespace jank::runtime::obj { } - object_ref persistent_array_map::get(object_ref const key) const + object_ref persistent_array_map::get(object_ref const &key) const { return data.find(key).unwrap_or(jank_nil()); } - object_ref persistent_array_map::get(object_ref const key, object_ref const fallback) const + object_ref persistent_array_map::get(object_ref const &key, object_ref const &fallback) const { return data.find(key).unwrap_or(fallback); } - object_ref persistent_array_map::get_entry(object_ref const key) const + object_ref persistent_array_map::get_entry(object_ref const &key) const { auto const res(data.find(key)); if(res.is_some()) @@ -47,12 +47,12 @@ namespace jank::runtime::obj return jank_nil(); } - bool persistent_array_map::contains(object_ref const key) const + bool persistent_array_map::contains(object_ref const &key) const { return data.find(key).is_some(); } - object_ref persistent_array_map::assoc(object_ref const key, object_ref const val) const + object_ref persistent_array_map::assoc(object_ref const &key, object_ref const &val) const { /* If we've hit the max array map size, it's time to promote to a hash map. * @@ -73,19 +73,19 @@ namespace jank::runtime::obj } } - persistent_array_map_ref persistent_array_map::dissoc(object_ref const key) const + persistent_array_map_ref persistent_array_map::dissoc(object_ref const &key) const { auto copy(data.clone()); copy.erase(key); return make_box(meta, std::move(copy)); } - object_ref persistent_array_map::call(object_ref const o) const + object_ref persistent_array_map::call(object_ref const &o) const { return get(o); } - object_ref persistent_array_map::call(object_ref const o, object_ref const fallback) const + object_ref persistent_array_map::call(object_ref const &o, object_ref const &fallback) const { return get(o, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp index c3f0e5d8b..9cd43500b 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp @@ -11,8 +11,8 @@ namespace jank::runtime::obj { persistent_hash_map::persistent_hash_map(jtl::option const &meta, runtime::detail::native_array_map const &m, - object_ref const key, - object_ref const val) + object_ref const &key, + object_ref const &val) : parent_type{ meta } { runtime::detail::native_transient_hash_map transient; @@ -46,10 +46,10 @@ namespace jank::runtime::obj return ret; } - persistent_hash_map_ref persistent_hash_map::create_from_seq(object_ref const seq) + persistent_hash_map_ref persistent_hash_map::create_from_seq(object_ref const &seq) { return make_box(visit_seqable( - [](auto const typed_seq) -> persistent_hash_map::value_type { + [](auto const &typed_seq) -> persistent_hash_map::value_type { runtime::detail::native_transient_hash_map transient; auto const r{ make_sequence_range(typed_seq) }; for(auto it(r.begin()); it != r.end(); ++it) @@ -72,7 +72,7 @@ namespace jank::runtime::obj seq)); } - object_ref persistent_hash_map::get(object_ref const key) const + object_ref persistent_hash_map::get(object_ref const &key) const { auto const res(data.find(key)); if(res) @@ -82,7 +82,7 @@ namespace jank::runtime::obj return jank_nil(); } - object_ref persistent_hash_map::get(object_ref const key, object_ref const fallback) const + object_ref persistent_hash_map::get(object_ref const &key, object_ref const &fallback) const { auto const res(data.find(key)); if(res) @@ -92,7 +92,7 @@ namespace jank::runtime::obj return fallback; } - object_ref persistent_hash_map::get_entry(object_ref const key) const + object_ref persistent_hash_map::get_entry(object_ref const &key) const { auto const res(data.find(key)); if(res) @@ -102,30 +102,30 @@ namespace jank::runtime::obj return jank_nil(); } - bool persistent_hash_map::contains(object_ref const key) const + bool persistent_hash_map::contains(object_ref const &key) const { return data.find(key); } persistent_hash_map_ref - persistent_hash_map::assoc(object_ref const key, object_ref const val) const + persistent_hash_map::assoc(object_ref const &key, object_ref const &val) const { auto copy(data.set(key, val)); return make_box(meta, std::move(copy)); } - persistent_hash_map_ref persistent_hash_map::dissoc(object_ref const key) const + persistent_hash_map_ref persistent_hash_map::dissoc(object_ref const &key) const { auto copy(data.erase(key)); return make_box(meta, std::move(copy)); } - object_ref persistent_hash_map::call(object_ref const o) const + object_ref persistent_hash_map::call(object_ref const &o) const { return get(o); } - object_ref persistent_hash_map::call(object_ref const o, object_ref const fallback) const + object_ref persistent_hash_map::call(object_ref const &o, object_ref const &fallback) const { return get(o, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp index 81eb92527..2a8e79435 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp @@ -27,10 +27,10 @@ namespace jank::runtime::obj return ret; } - persistent_hash_set_ref persistent_hash_set::create_from_seq(object_ref const seq) + persistent_hash_set_ref persistent_hash_set::create_from_seq(object_ref const &seq) { return make_box(visit_seqable( - [](auto const typed_seq) -> persistent_hash_set::value_type { + [](auto const &typed_seq) -> persistent_hash_set::value_type { runtime::detail::native_transient_hash_set transient; for(auto const e : make_sequence_range(typed_seq)) { @@ -113,7 +113,7 @@ namespace jank::runtime::obj return data.size(); } - persistent_hash_set_ref persistent_hash_set::with_meta(object_ref const m) const + persistent_hash_set_ref persistent_hash_set::with_meta(object_ref const &m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(make_box(data)); @@ -121,14 +121,14 @@ namespace jank::runtime::obj return ret; } - persistent_hash_set_ref persistent_hash_set::conj(object_ref const head) const + persistent_hash_set_ref persistent_hash_set::conj(object_ref const &head) const { auto set(data.insert(head)); auto ret(make_box(meta, std::move(set))); return ret; } - object_ref persistent_hash_set::call(object_ref const o) const + object_ref persistent_hash_set::call(object_ref const &o) const { auto const found(data.find(o)); if(!found) @@ -143,12 +143,12 @@ namespace jank::runtime::obj return make_box(data); } - bool persistent_hash_set::contains(object_ref const o) const + bool persistent_hash_set::contains(object_ref const &o) const { return data.find(o); } - persistent_hash_set_ref persistent_hash_set::disj(object_ref const o) const + persistent_hash_set_ref persistent_hash_set::disj(object_ref const &o) const { auto set(data.erase(o)); auto ret(make_box(meta, std::move(set))); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp index 15530a216..0c90bcc83 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp @@ -18,7 +18,7 @@ namespace jank::runtime::obj { } - persistent_list_ref persistent_list::create(object_ref const meta, object_ref const s) + persistent_list_ref persistent_list::create(object_ref const &meta, object_ref const &s) { auto const ret{ create(s) }; auto const m{ behavior::detail::validate_meta(meta) }; @@ -26,7 +26,7 @@ namespace jank::runtime::obj return ret; } - persistent_list_ref persistent_list::create(object_ref const s) + persistent_list_ref persistent_list::create(object_ref const &s) { if(s.is_nil()) { @@ -55,12 +55,12 @@ namespace jank::runtime::obj s); } - persistent_list_ref persistent_list::create(persistent_list_ref const s) + persistent_list_ref persistent_list::create(persistent_list_ref const &s) { return s; } - persistent_list_ref persistent_list::create(nil_ref const) + persistent_list_ref persistent_list::create(nil_ref const &) { return empty(); } @@ -114,7 +114,7 @@ namespace jank::runtime::obj return data.size(); } - persistent_list_ref persistent_list::conj(object_ref head) const + persistent_list_ref persistent_list::conj(object_ref const &head) const { auto l(data.conj(head)); auto ret(make_box(meta, std::move(l))); @@ -151,7 +151,7 @@ namespace jank::runtime::obj return this; } - persistent_list_ref persistent_list::with_meta(object_ref const m) const + persistent_list_ref persistent_list::with_meta(object_ref const &m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(make_box(data)); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp index fcdeaced3..39815e091 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp @@ -18,7 +18,7 @@ namespace jank::runtime::obj { } - persistent_sorted_map::persistent_sorted_map(object_ref const meta, value_type &&d) + persistent_sorted_map::persistent_sorted_map(object_ref const &meta, value_type &&d) : data{ std::move(d) } { this->meta = meta; @@ -36,11 +36,11 @@ namespace jank::runtime::obj return ret; } - persistent_sorted_map_ref persistent_sorted_map::create_from_seq(object_ref const seq) + persistent_sorted_map_ref persistent_sorted_map::create_from_seq(object_ref const &seq) { return make_box(visit_object( - [](auto const typed_seq) -> persistent_sorted_map::value_type { - using T = typename decltype(typed_seq)::value_type; + [](auto const &typed_seq) -> persistent_sorted_map::value_type { + using T = typename jtl::decay_t::value_type; if constexpr(behavior::seqable) { @@ -68,7 +68,7 @@ namespace jank::runtime::obj seq)); } - object_ref persistent_sorted_map::get(object_ref const key) const + object_ref persistent_sorted_map::get(object_ref const &key) const { auto const res(data.find(key)); if(res != data.end()) @@ -78,7 +78,7 @@ namespace jank::runtime::obj return jank_nil(); } - object_ref persistent_sorted_map::get(object_ref const key, object_ref const fallback) const + object_ref persistent_sorted_map::get(object_ref const &key, object_ref const &fallback) const { auto const res(data.find(key)); if(res != data.end()) @@ -88,7 +88,7 @@ namespace jank::runtime::obj return fallback; } - object_ref persistent_sorted_map::get_entry(object_ref const key) const + object_ref persistent_sorted_map::get_entry(object_ref const &key) const { auto const res(data.find(key)); if(res != data.end()) @@ -98,32 +98,32 @@ namespace jank::runtime::obj return jank_nil(); } - bool persistent_sorted_map::contains(object_ref const key) const + bool persistent_sorted_map::contains(object_ref const &key) const { return data.contains(key); } persistent_sorted_map_ref - persistent_sorted_map::assoc(object_ref const key, object_ref const val) const + persistent_sorted_map::assoc(object_ref const &key, object_ref const &val) const { auto copy(data); copy[key] = val; return make_box(meta, std::move(copy)); } - persistent_sorted_map_ref persistent_sorted_map::dissoc(object_ref const key) const + persistent_sorted_map_ref persistent_sorted_map::dissoc(object_ref const &key) const { auto copy(data); copy.erase(key); return make_box(meta, std::move(copy)); } - object_ref persistent_sorted_map::call(object_ref const o) const + object_ref persistent_sorted_map::call(object_ref const &o) const { return get(o); } - object_ref persistent_sorted_map::call(object_ref const o, object_ref const fallback) const + object_ref persistent_sorted_map::call(object_ref const &o, object_ref const &fallback) const { return get(o, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp index aa2c368ed..80ab478b6 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp @@ -16,7 +16,7 @@ namespace jank::runtime::obj { } - persistent_sorted_set::persistent_sorted_set(object_ref const meta, value_type &&d) + persistent_sorted_set::persistent_sorted_set(object_ref const &meta, value_type &&d) : data{ std::move(d) } , meta{ meta } { @@ -34,10 +34,10 @@ namespace jank::runtime::obj return ret; } - persistent_sorted_set_ref persistent_sorted_set::create_from_seq(object_ref const seq) + persistent_sorted_set_ref persistent_sorted_set::create_from_seq(object_ref const &seq) { return make_box(visit_seqable( - [](auto const typed_seq) -> persistent_sorted_set::value_type { + [](auto const &typed_seq) -> persistent_sorted_set::value_type { runtime::detail::native_transient_sorted_set transient; for(auto const e : make_sequence_range(typed_seq)) { @@ -120,7 +120,7 @@ namespace jank::runtime::obj return data.size(); } - persistent_sorted_set_ref persistent_sorted_set::with_meta(object_ref const m) const + persistent_sorted_set_ref persistent_sorted_set::with_meta(object_ref const &m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(make_box(data)); @@ -128,7 +128,7 @@ namespace jank::runtime::obj return ret; } - persistent_sorted_set_ref persistent_sorted_set::conj(object_ref const head) const + persistent_sorted_set_ref persistent_sorted_set::conj(object_ref const &head) const { auto copy(data); copy.insert(head); @@ -136,7 +136,7 @@ namespace jank::runtime::obj return ret; } - object_ref persistent_sorted_set::call(object_ref const o) + object_ref persistent_sorted_set::call(object_ref const &o) { auto const found(data.find(o)); if(found != data.end()) @@ -151,12 +151,12 @@ namespace jank::runtime::obj return make_box(data); } - bool persistent_sorted_set::contains(object_ref const o) const + bool persistent_sorted_set::contains(object_ref const &o) const { return data.contains(o); } - persistent_sorted_set_ref persistent_sorted_set::disj(object_ref const o) const + persistent_sorted_set_ref persistent_sorted_set::disj(object_ref const &o) const { auto copy(data); copy.erase(o); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp index e06d9c195..e16a3bb93 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp @@ -60,12 +60,12 @@ namespace jank::runtime::obj return data.compare(s.data); } - object_ref persistent_string::get(object_ref const key) const + object_ref persistent_string::get(object_ref const &key) const { return get(key, jank_nil()); } - object_ref persistent_string::get(object_ref const key, object_ref const fallback) const + object_ref persistent_string::get(object_ref const &key, object_ref const &fallback) const { if(key->type == object_type::integer) { @@ -82,7 +82,7 @@ namespace jank::runtime::obj } } - bool persistent_string::contains(object_ref const key) const + bool persistent_string::contains(object_ref const &key) const { if(key->type == object_type::integer) { @@ -92,12 +92,12 @@ namespace jank::runtime::obj return false; } - object_ref persistent_string::get_entry(object_ref const) const + object_ref persistent_string::get_entry(object_ref const &) const { throw std::runtime_error{ util::format("get_entry not supported on string") }; } - object_ref persistent_string::nth(object_ref const index) const + object_ref persistent_string::nth(object_ref const &index) const { if(index->type == object_type::integer) { @@ -117,7 +117,7 @@ namespace jank::runtime::obj } } - object_ref persistent_string::nth(object_ref const index, object_ref const fallback) const + object_ref persistent_string::nth(object_ref const &index, object_ref const &fallback) const { return get(index, fallback); } @@ -146,7 +146,7 @@ namespace jank::runtime::obj return ok(make_box(data.substr(start, end - start))); } - i64 persistent_string::first_index_of(object_ref const m) const + i64 persistent_string::first_index_of(object_ref const &m) const { auto const s(runtime::to_string(m)); auto const found(data.find(s)); @@ -157,7 +157,7 @@ namespace jank::runtime::obj return static_cast(found); } - i64 persistent_string::last_index_of(object_ref const m) const + i64 persistent_string::last_index_of(object_ref const &m) const { auto const s(runtime::to_string(m)); auto const found(data.rfind(s)); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string_sequence.cpp index 1ffe3d19a..56a4659a9 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string_sequence.cpp @@ -5,13 +5,13 @@ namespace jank::runtime::obj { - persistent_string_sequence::persistent_string_sequence(persistent_string_ref const s) + persistent_string_sequence::persistent_string_sequence(persistent_string_ref const &s) : str{ s } { jank_debug_assert(!s->data.empty()); } - persistent_string_sequence::persistent_string_sequence(persistent_string_ref const s, + persistent_string_sequence::persistent_string_sequence(persistent_string_ref const &s, usize const i) : str{ s } , index{ i } @@ -97,7 +97,7 @@ namespace jank::runtime::obj return this; } - cons_ref persistent_string_sequence::conj(object_ref const head) + cons_ref persistent_string_sequence::conj(object_ref const &head) { return make_box(head, this); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp index b94956b04..07f3a5969 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp @@ -25,7 +25,7 @@ namespace jank::runtime::obj { } - persistent_vector_ref persistent_vector::create(object_ref const s) + persistent_vector_ref persistent_vector::create(object_ref const &s) { if(s.is_nil()) { @@ -120,7 +120,7 @@ namespace jank::runtime::obj i64 persistent_vector::compare(object const &o) const { - return visit_type([this](auto const typed_o) { return compare(*typed_o); }, + return visit_type([this](auto const &typed_o) { return compare(*typed_o); }, &o); } @@ -169,14 +169,14 @@ namespace jank::runtime::obj return data.size(); } - persistent_vector_ref persistent_vector::conj(object_ref head) const + persistent_vector_ref persistent_vector::conj(object_ref const &head) const { auto vec(data.push_back(head)); auto ret(make_box(meta, std::move(vec))); return ret; } - object_ref persistent_vector::call(object_ref const o) const + object_ref persistent_vector::call(object_ref const &o) const { return get(o); } @@ -186,7 +186,7 @@ namespace jank::runtime::obj return make_box(data); } - persistent_vector_ref persistent_vector::with_meta(object_ref const m) const + persistent_vector_ref persistent_vector::with_meta(object_ref const &m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(make_box(data)); @@ -194,12 +194,12 @@ namespace jank::runtime::obj return ret; } - object_ref persistent_vector::get(object_ref const key) const + object_ref persistent_vector::get(object_ref const &key) const { return get(key, jank_nil()); } - object_ref persistent_vector::get(object_ref const key, object_ref const fallback) const + object_ref persistent_vector::get(object_ref const &key, object_ref const &fallback) const { if(key->type == object_type::integer) { @@ -216,7 +216,7 @@ namespace jank::runtime::obj } } - object_ref persistent_vector::get_entry(object_ref const key) const + object_ref persistent_vector::get_entry(object_ref const &key) const { if(key->type == object_type::integer) { @@ -234,7 +234,7 @@ namespace jank::runtime::obj } } - bool persistent_vector::contains(object_ref const key) const + bool persistent_vector::contains(object_ref const &key) const { if(key->type == object_type::integer) { @@ -247,7 +247,7 @@ namespace jank::runtime::obj } } - persistent_vector_ref persistent_vector::assoc(object_ref const key, object_ref const val) const + persistent_vector_ref persistent_vector::assoc(object_ref const &key, object_ref const &val) const { if(key->type != object_type::integer) { @@ -272,7 +272,7 @@ namespace jank::runtime::obj return make_box(meta, std::move(vec)); } - persistent_vector_ref persistent_vector::dissoc(object_ref const /*key*/) const + persistent_vector_ref persistent_vector::dissoc(object_ref const & /*key*/) const { throw std::runtime_error{ "Type 'persistent_vector' does not support 'dissoc'." }; } @@ -297,7 +297,7 @@ namespace jank::runtime::obj return make_box(meta, data.take(data.size() - 1)); } - object_ref persistent_vector::nth(object_ref const index) const + object_ref persistent_vector::nth(object_ref const &index) const { if(index->type == object_type::integer) { @@ -317,7 +317,7 @@ namespace jank::runtime::obj } } - object_ref persistent_vector::nth(object_ref const index, object_ref const fallback) const + object_ref persistent_vector::nth(object_ref const &index, object_ref const &fallback) const { return get(index, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector_sequence.cpp index 73897a8ea..139b77917 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector_sequence.cpp @@ -5,13 +5,13 @@ namespace jank::runtime::obj { - persistent_vector_sequence::persistent_vector_sequence(persistent_vector_ref const v) + persistent_vector_sequence::persistent_vector_sequence(persistent_vector_ref const &v) : vec{ v } { jank_debug_assert(!v->data.empty()); } - persistent_vector_sequence::persistent_vector_sequence(persistent_vector_ref const v, + persistent_vector_sequence::persistent_vector_sequence(persistent_vector_ref const &v, usize const i) : vec{ v } , index{ i } @@ -118,7 +118,7 @@ namespace jank::runtime::obj return this; } - cons_ref persistent_vector_sequence::conj(object_ref const head) + cons_ref persistent_vector_sequence::conj(object_ref const &head) { return make_box(head, this); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/range.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/range.cpp index 626e9601d..5de0713e5 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/range.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/range.cpp @@ -8,17 +8,17 @@ namespace jank::runtime::obj { - static bool positive_step_bounds_check(object_ref const val, object_ref const end) + static bool positive_step_bounds_check(object_ref const &val, object_ref const &end) { return lte(end, val); } - static bool negative_step_bounds_check(object_ref const val, object_ref const end) + static bool negative_step_bounds_check(object_ref const &val, object_ref const &end) { return lte(val, end); } - range::range(object_ref const end) + range::range(object_ref const &end) : start{ make_box(0) } , end{ end } , step{ make_box(1) } @@ -26,7 +26,7 @@ namespace jank::runtime::obj { } - range::range(object_ref const start, object_ref const end) + range::range(object_ref const &start, object_ref const &end) : start{ start } , end{ end } , step{ make_box(1) } @@ -34,7 +34,7 @@ namespace jank::runtime::obj { } - range::range(object_ref const start, object_ref const end, object_ref const step) + range::range(object_ref const &start, object_ref const &end, object_ref const &step) : start{ start } , end{ end } , step{ step } @@ -43,9 +43,9 @@ namespace jank::runtime::obj { } - range::range(object_ref const start, - object_ref const end, - object_ref const step, + range::range(object_ref const &start, + object_ref const &end, + object_ref const &step, range::bounds_check_t const bounds_check) : start{ start } , end{ end } @@ -54,12 +54,12 @@ namespace jank::runtime::obj { } - range::range(object_ref const start, - object_ref const end, - object_ref const step, + range::range(object_ref const &start, + object_ref const &end, + object_ref const &step, range::bounds_check_t const bounds_check, - array_chunk_ref const chunk, - range_ptr const chunk_next) + array_chunk_ref const &chunk, + range_ref const &chunk_next) : start{ start } , end{ end } , step{ step } @@ -69,7 +69,7 @@ namespace jank::runtime::obj { } - object_ref range::create(object_ref const end) + object_ref range::create(object_ref const &end) { if(is_pos(end)) { @@ -81,12 +81,12 @@ namespace jank::runtime::obj return persistent_list::empty(); } - object_ref range::create(object_ref const start, object_ref const end) + object_ref range::create(object_ref const &start, object_ref const &end) { return create(start, end, make_box(1)); } - object_ref range::create(object_ref const start, object_ref const end, object_ref const step) + object_ref range::create(object_ref const &start, object_ref const &end, object_ref const &step) { if((is_pos(step) && lt(end, start)) || (is_neg(step) && lt(start, end)) || is_equiv(start, end)) { @@ -102,12 +102,12 @@ namespace jank::runtime::obj : static_cast(negative_step_bounds_check)); } - range_ptr range::seq() + range_ref range::seq() { return this; } - range_ptr range::fresh_seq() const + range_ref range::fresh_seq() const { return make_box(start, end, step, bounds_check); } @@ -150,7 +150,7 @@ namespace jank::runtime::obj chunk_next = make_box(val, end, step, bounds_check); } - range_ptr range::next() const + range_ref range::next() const { if(cached_next.is_some()) { @@ -172,7 +172,7 @@ namespace jank::runtime::obj return chunked_next(); } - range_ptr range::next_in_place() + range_ref range::next_in_place() { force_chunk(); if(chunk->count() > 1) @@ -190,7 +190,7 @@ namespace jank::runtime::obj return chunk; } - range_ptr range::chunked_next() const + range_ref range::chunked_next() const { force_chunk(); if(chunk_next.is_nil()) @@ -200,7 +200,7 @@ namespace jank::runtime::obj return chunk_next; } - cons_ref range::conj(object_ref const head) const + cons_ref range::conj(object_ref const &head) const { return make_box(head, this); } @@ -230,7 +230,7 @@ namespace jank::runtime::obj return hash::ordered(&base); } - range_ptr range::with_meta(object_ref const m) const + range_ref range::with_meta(object_ref const &m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(fresh_seq()); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp index 932dcf03c..6bd25e49f 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp @@ -22,7 +22,7 @@ namespace jank::runtime::obj return to_native_big_decimal(r.data); } - static native_big_integer extract_big_integer(object_ref const d) + static native_big_integer extract_big_integer(object_ref const &d) { native_big_integer result{}; if(d->type == object_type::big_integer) @@ -71,7 +71,7 @@ namespace jank::runtime::obj { } - ratio_data::ratio_data(object_ref const numerator, object_ref const denominator) + ratio_data::ratio_data(object_ref const &numerator, object_ref const &denominator) : ratio_data(extract_big_integer(numerator), extract_big_integer(denominator)) { } @@ -168,7 +168,7 @@ namespace jank::runtime::obj i64 ratio::compare(object const &o) const { return visit_number_like( - [this](auto const typed_o) -> i64 { + [this](auto const &typed_o) -> i64 { using T = std::decay_t; if constexpr(std::is_same_v) { @@ -194,22 +194,22 @@ namespace jank::runtime::obj return ratio::create(num, denom); } - ratio_ref operator+(integer_ref const l, ratio_data const &r) + ratio_ref operator+(integer_ref const &l, ratio_data const &r) { return l->data + r; } - ratio_ref operator+(ratio_data const &l, integer_ref const r) + ratio_ref operator+(ratio_data const &l, integer_ref const &r) { return r + l; } - f64 operator+(real_ref const l, ratio_data const &r) + f64 operator+(real_ref const &l, ratio_data const &r) { return l->data + r.to_real(); } - f64 operator+(ratio_data const &l, real_ref const r) + f64 operator+(ratio_data const &l, real_ref const &r) { return l.to_real() + r->data; } @@ -241,22 +241,22 @@ namespace jank::runtime::obj return ratio::create(num, denom); } - ratio_ref operator-(integer_ref const l, ratio_data const &r) + ratio_ref operator-(integer_ref const &l, ratio_data const &r) { return l->data - r; } - ratio_ref operator-(ratio_data const &l, integer_ref const r) + ratio_ref operator-(ratio_data const &l, integer_ref const &r) { return l - r->data; } - f64 operator-(real_ref const l, ratio_data const &r) + f64 operator-(real_ref const &l, ratio_data const &r) { return l->data - r.to_real(); } - f64 operator-(ratio_data const &l, real_ref const r) + f64 operator-(ratio_data const &l, real_ref const &r) { return l.to_real() - r->data; } @@ -286,22 +286,22 @@ namespace jank::runtime::obj return ratio::create(l.numerator * r.numerator, l.denominator * r.denominator); } - object_ref operator*(integer_ref const l, ratio_data const &r) + object_ref operator*(integer_ref const &l, ratio_data const &r) { return ratio_data(l->data, 1ll) * r; } - object_ref operator*(ratio_data const &l, integer_ref const r) + object_ref operator*(ratio_data const &l, integer_ref const &r) { return l * ratio_data(r->data, 1ll); } - f64 operator*(real_ref const l, ratio_data const &r) + f64 operator*(real_ref const &l, ratio_data const &r) { return l->data * r.to_real(); } - f64 operator*(ratio_data const &l, real_ref const r) + f64 operator*(ratio_data const &l, real_ref const &r) { return l.to_real() * r->data; } @@ -331,22 +331,22 @@ namespace jank::runtime::obj return ratio::create(l.numerator * r.denominator, l.denominator * r.numerator); } - object_ref operator/(integer_ref const l, ratio_data const &r) + object_ref operator/(integer_ref const &l, ratio_data const &r) { return ratio_data(l->data, 1ll) / r; } - ratio_ref operator/(ratio_data const &l, integer_ref const r) + ratio_ref operator/(ratio_data const &l, integer_ref const &r) { return l / r->data; } - f64 operator/(real_ref const l, ratio_data const &r) + f64 operator/(real_ref const &l, ratio_data const &r) { return l->data / r.to_real(); } - f64 operator/(ratio_data const &l, real_ref const r) + f64 operator/(ratio_data const &l, real_ref const &r) { return l.to_real() / r->data; } @@ -376,22 +376,22 @@ namespace jank::runtime::obj return l.numerator == r.numerator && l.denominator == r.denominator; } - bool operator==(integer_ref const l, ratio_data const &r) + bool operator==(integer_ref const &l, ratio_data const &r) { return l->data * r.denominator == r.numerator; } - bool operator==(ratio_data const &l, integer_ref const r) + bool operator==(ratio_data const &l, integer_ref const &r) { return l.numerator == r->data * l.denominator; } - bool operator==(real_ref const l, ratio_data const &r) + bool operator==(real_ref const &l, ratio_data const &r) { return std::fabs(l->data - r) < epsilon; } - bool operator==(ratio_data const &l, real_ref const r) + bool operator==(ratio_data const &l, real_ref const &r) { return r == l; } @@ -426,42 +426,42 @@ namespace jank::runtime::obj return l.numerator * r.denominator <= r.numerator * l.denominator; } - bool operator<(integer_ref const l, ratio_data const &r) + bool operator<(integer_ref const &l, ratio_data const &r) { return l->data * r.denominator < r.numerator; } - bool operator<(ratio_data const &l, integer_ref const r) + bool operator<(ratio_data const &l, integer_ref const &r) { return l.numerator < r->data * l.denominator; } - bool operator<=(integer_ref const l, ratio_data const &r) + bool operator<=(integer_ref const &l, ratio_data const &r) { return l->data * r.denominator <= r.numerator; } - bool operator<=(ratio_data const &l, integer_ref const r) + bool operator<=(ratio_data const &l, integer_ref const &r) { return l.numerator <= r->data * l.denominator; } - bool operator<(real_ref const l, ratio_data const &r) + bool operator<(real_ref const &l, ratio_data const &r) { return l->data < r.to_real(); } - bool operator<(ratio_data const &l, real_ref const r) + bool operator<(ratio_data const &l, real_ref const &r) { return l.to_real() < r->data; } - bool operator<=(real_ref const l, ratio_data const &r) + bool operator<=(real_ref const &l, ratio_data const &r) { return l->data <= r.to_real(); } - bool operator<=(ratio_data const &l, real_ref const r) + bool operator<=(ratio_data const &l, real_ref const &r) { return l.to_real() <= r->data; } @@ -511,22 +511,22 @@ namespace jank::runtime::obj return l.numerator * r.denominator > r.numerator * l.denominator; } - bool operator>(integer_ref const l, ratio_data const &r) + bool operator>(integer_ref const &l, ratio_data const &r) { return l->data * r.denominator > r.numerator; } - bool operator>(ratio_data const &l, integer_ref const r) + bool operator>(ratio_data const &l, integer_ref const &r) { return l.numerator > r->data * l.denominator; } - bool operator>(real_ref const l, ratio_data const &r) + bool operator>(real_ref const &l, ratio_data const &r) { return l->data > r.to_real(); } - bool operator>(ratio_data const &l, real_ref const r) + bool operator>(ratio_data const &l, real_ref const &r) { return l.to_real() > r->data; } @@ -556,22 +556,22 @@ namespace jank::runtime::obj return l.numerator * r.denominator >= r.numerator * l.denominator; } - bool operator>=(integer_ref const l, ratio_data const &r) + bool operator>=(integer_ref const &l, ratio_data const &r) { return l->data * r.denominator >= r.numerator; } - bool operator>=(ratio_data const &l, integer_ref const r) + bool operator>=(ratio_data const &l, integer_ref const &r) { return l.numerator >= r->data * l.denominator; } - bool operator>=(real_ref const l, ratio_data const &r) + bool operator>=(real_ref const &l, ratio_data const &r) { return l->data >= r.to_real(); } - bool operator>=(ratio_data const &l, real_ref const r) + bool operator>=(ratio_data const &l, real_ref const &r) { return l.to_real() >= r->data; } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/re_matcher.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/re_matcher.cpp index 57673a760..ede3f080a 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/re_matcher.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/re_matcher.cpp @@ -4,7 +4,7 @@ namespace jank::runtime::obj { - re_matcher::re_matcher(re_pattern_ref const re, jtl::immutable_string const &s) + re_matcher::re_matcher(re_pattern_ref const &re, jtl::immutable_string const &s) : re{ re } , match_input{ s.c_str() } { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/reduced.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/reduced.cpp index 1e9fce965..15a802c14 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/reduced.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/reduced.cpp @@ -3,7 +3,7 @@ namespace jank::runtime::obj { - reduced::reduced(object_ref const o) + reduced::reduced(object_ref const &o) : val{ o } { jank_debug_assert(val.is_some()); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/repeat.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/repeat.cpp index fdd84f7d4..cd31d93de 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/repeat.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/repeat.cpp @@ -6,13 +6,13 @@ namespace jank::runtime::obj { - repeat::repeat(object_ref const value) + repeat::repeat(object_ref const &value) : value{ value } , count{ make_box(infinite) } { } - repeat::repeat(object_ref const count, object_ref const value) + repeat::repeat(object_ref const &count, object_ref const &value) : value{ value } , count{ count } { @@ -23,12 +23,12 @@ namespace jank::runtime::obj } } - object_ref repeat::create(object_ref const value) + object_ref repeat::create(object_ref const &value) { return make_box(value); } - object_ref repeat::create(object_ref const count, object_ref const value) + object_ref repeat::create(object_ref const &count, object_ref const &value) { if(lte(count, make_box(0))) { @@ -83,7 +83,7 @@ namespace jank::runtime::obj return this; } - cons_ref repeat::conj(object_ref const head) const + cons_ref repeat::conj(object_ref const &head) const { return make_box(head, this); } @@ -113,7 +113,7 @@ namespace jank::runtime::obj return hash::ordered(&base); } - repeat_ref repeat::with_meta(object_ref const m) const + repeat_ref repeat::with_meta(object_ref const &m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(fresh_seq()); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/symbol.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/symbol.cpp index 3461decde..0ad038c17 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/symbol.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/symbol.cpp @@ -41,7 +41,7 @@ namespace jank::runtime::obj { } - symbol::symbol(object_ref const meta, + symbol::symbol(object_ref const &meta, jtl::immutable_string const &ns, jtl::immutable_string const &n) : ns{ ns } @@ -50,7 +50,7 @@ namespace jank::runtime::obj { } - symbol::symbol(object_ref const ns, object_ref const n) + symbol::symbol(object_ref const &ns, object_ref const &n) : ns{ runtime::to_string(ns) } , name{ runtime::to_string(n) } { @@ -74,7 +74,7 @@ namespace jank::runtime::obj i64 symbol::compare(object const &o) const { - return visit_type([this](auto const typed_o) { return compare(*typed_o); }, &o); + return visit_type([this](auto const &typed_o) { return compare(*typed_o); }, &o); } i64 symbol::compare(symbol const &s) const @@ -144,7 +144,7 @@ namespace jank::runtime::obj return hash = hash::combine(hash::string(name), hash::string(ns)); } - symbol_ref symbol::with_meta(object_ref const m) const + symbol_ref symbol::with_meta(object_ref const &m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(make_box(ns, name)); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp index 04a5bbd69..07301144a 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp @@ -9,7 +9,7 @@ namespace jank::runtime::obj { - tagged_literal::tagged_literal(object_ref const tag, object_ref const form) + tagged_literal::tagged_literal(object_ref const &tag, object_ref const &form) : tag{ tag } , form{ form } { @@ -62,7 +62,7 @@ namespace jank::runtime::obj return hash = hash::combine(hash::visit(tag.get()), hash::visit(form.get())); } - object_ref tagged_literal::get(object_ref const key, object_ref const fallback) const + object_ref tagged_literal::get(object_ref const &key, object_ref const &fallback) const { auto const tag_kw{ __rt_ctx->intern_keyword("tag").expect_ok() }; auto const form_kw{ __rt_ctx->intern_keyword("form").expect_ok() }; @@ -80,12 +80,12 @@ namespace jank::runtime::obj return fallback; } - object_ref tagged_literal::get(object_ref const key) const + object_ref tagged_literal::get(object_ref const &key) const { return get(key, jank_nil()); } - object_ref tagged_literal::get_entry(object_ref const key) const + object_ref tagged_literal::get_entry(object_ref const &key) const { auto const tag_kw{ __rt_ctx->intern_keyword("tag").expect_ok() }; auto const form_kw{ __rt_ctx->intern_keyword("form").expect_ok() }; @@ -103,7 +103,7 @@ namespace jank::runtime::obj return jank_nil(); } - bool tagged_literal::contains(object_ref const key) const + bool tagged_literal::contains(object_ref const &key) const { auto const tag_kw{ __rt_ctx->intern_keyword("tag").expect_ok() }; auto const form_kw{ __rt_ctx->intern_keyword("form").expect_ok() }; diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_array_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_array_map.cpp index f6a4c9917..9e96e1b4f 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_array_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_array_map.cpp @@ -61,18 +61,18 @@ namespace jank::runtime::obj return data.size(); } - object_ref transient_array_map::get(object_ref const key) const + object_ref transient_array_map::get(object_ref const &key) const { assert_active(); return data.find(key).unwrap_or(jank_nil()); } - object_ref transient_array_map::get(object_ref const key, object_ref const fallback) const + object_ref transient_array_map::get(object_ref const &key, object_ref const &fallback) const { return data.find(key).unwrap_or(fallback); } - object_ref transient_array_map::get_entry(object_ref const key) const + object_ref transient_array_map::get_entry(object_ref const &key) const { auto const res(data.find(key)); if(res.is_some()) @@ -82,12 +82,12 @@ namespace jank::runtime::obj return jank_nil(); } - bool transient_array_map::contains(object_ref const key) const + bool transient_array_map::contains(object_ref const &key) const { return data.find(key).is_some(); } - object_ref transient_array_map::assoc_in_place(object_ref const key, object_ref const value) + object_ref transient_array_map::assoc_in_place(object_ref const &key, object_ref const &value) { assert_active(); /* If we've hit the max array map size, it's time to promote to a hash map. @@ -111,14 +111,14 @@ namespace jank::runtime::obj } } - transient_array_map_ref transient_array_map::dissoc_in_place(object_ref const key) + transient_array_map_ref transient_array_map::dissoc_in_place(object_ref const &key) { assert_active(); data.erase(key); return this; } - object_ref transient_array_map::conj_in_place(object_ref const head) + object_ref transient_array_map::conj_in_place(object_ref const &head) { assert_active(); @@ -155,12 +155,12 @@ namespace jank::runtime::obj return make_box(std::move(data)); } - object_ref transient_array_map::call(object_ref const o) const + object_ref transient_array_map::call(object_ref const &o) const { return get(o); } - object_ref transient_array_map::call(object_ref const o, object_ref const fallback) const + object_ref transient_array_map::call(object_ref const &o, object_ref const &fallback) const { return get(o, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_map.cpp index 9001a44a4..2793f8793 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_map.cpp @@ -73,7 +73,7 @@ namespace jank::runtime::obj return data.size(); } - object_ref transient_hash_map::get(object_ref const key) const + object_ref transient_hash_map::get(object_ref const &key) const { assert_active(); auto const res(data.find(key)); @@ -84,7 +84,7 @@ namespace jank::runtime::obj return jank_nil(); } - object_ref transient_hash_map::get(object_ref const key, object_ref const fallback) const + object_ref transient_hash_map::get(object_ref const &key, object_ref const &fallback) const { assert_active(); auto const res(data.find(key)); @@ -95,7 +95,7 @@ namespace jank::runtime::obj return fallback; } - object_ref transient_hash_map::get_entry(object_ref const key) const + object_ref transient_hash_map::get_entry(object_ref const &key) const { assert_active(); auto const res(data.find(key)); @@ -106,28 +106,28 @@ namespace jank::runtime::obj return jank_nil(); } - bool transient_hash_map::contains(object_ref const key) const + bool transient_hash_map::contains(object_ref const &key) const { assert_active(); return data.find(key); } transient_hash_map_ref - transient_hash_map::assoc_in_place(object_ref const key, object_ref const val) + transient_hash_map::assoc_in_place(object_ref const &key, object_ref const &val) { assert_active(); data.set(key, val); return this; } - transient_hash_map_ref transient_hash_map::dissoc_in_place(object_ref const key) + transient_hash_map_ref transient_hash_map::dissoc_in_place(object_ref const &key) { assert_active(); data.erase(key); return this; } - transient_hash_map_ref transient_hash_map::conj_in_place(object_ref const head) + transient_hash_map_ref transient_hash_map::conj_in_place(object_ref const &head) { assert_active(); @@ -163,12 +163,12 @@ namespace jank::runtime::obj return make_box(std::move(data).persistent()); } - object_ref transient_hash_map::call(object_ref const o) const + object_ref transient_hash_map::call(object_ref const &o) const { return get(o); } - object_ref transient_hash_map::call(object_ref const o, object_ref const fallback) const + object_ref transient_hash_map::call(object_ref const &o, object_ref const &fallback) const { return get(o, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_set.cpp index 9d6e927ba..a03b68fde 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_set.cpp @@ -61,7 +61,7 @@ namespace jank::runtime::obj return data.size(); } - transient_hash_set_ref transient_hash_set::conj_in_place(object_ref const elem) + transient_hash_set_ref transient_hash_set::conj_in_place(object_ref const &elem) { assert_active(); data.insert(elem); @@ -75,7 +75,7 @@ namespace jank::runtime::obj return make_box(data.persistent()); } - object_ref transient_hash_set::call(object_ref const elem) const + object_ref transient_hash_set::call(object_ref const &elem) const { assert_active(); auto const found(data.find(elem)); @@ -86,7 +86,7 @@ namespace jank::runtime::obj return *found; } - object_ref transient_hash_set::call(object_ref const elem, object_ref const fallback) const + object_ref transient_hash_set::call(object_ref const &elem, object_ref const &fallback) const { assert_active(); auto const found(data.find(elem)); @@ -97,17 +97,17 @@ namespace jank::runtime::obj return *found; } - object_ref transient_hash_set::get(object_ref const elem) const + object_ref transient_hash_set::get(object_ref const &elem) const { return call(elem); } - object_ref transient_hash_set::get(object_ref const elem, object_ref const fallback) const + object_ref transient_hash_set::get(object_ref const &elem, object_ref const &fallback) const { return call(elem, fallback); } - object_ref transient_hash_set::get_entry(object_ref const elem) const + object_ref transient_hash_set::get_entry(object_ref const &elem) const { auto const found = call(elem); auto const nil(jank_nil()); @@ -119,13 +119,13 @@ namespace jank::runtime::obj return make_box(std::in_place, found, found); } - bool transient_hash_set::contains(object_ref const elem) const + bool transient_hash_set::contains(object_ref const &elem) const { assert_active(); return data.find(elem); } - transient_hash_set_ref transient_hash_set::disjoin_in_place(object_ref const elem) + transient_hash_set_ref transient_hash_set::disjoin_in_place(object_ref const &elem) { assert_active(); data.erase(elem); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp index 9a7c9f994..25b1caf97 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp @@ -59,7 +59,7 @@ namespace jank::runtime::obj return data.size(); } - object_ref transient_sorted_map::get(object_ref const key) const + object_ref transient_sorted_map::get(object_ref const &key) const { assert_active(); auto const res(data.find(key)); @@ -70,7 +70,7 @@ namespace jank::runtime::obj return jank_nil(); } - object_ref transient_sorted_map::get(object_ref const key, object_ref const fallback) const + object_ref transient_sorted_map::get(object_ref const &key, object_ref const &fallback) const { assert_active(); auto const res(data.find(key)); @@ -81,7 +81,7 @@ namespace jank::runtime::obj return fallback; } - object_ref transient_sorted_map::get_entry(object_ref const key) const + object_ref transient_sorted_map::get_entry(object_ref const &key) const { assert_active(); auto const res(data.find(key)); @@ -92,28 +92,28 @@ namespace jank::runtime::obj return jank_nil(); } - bool transient_sorted_map::contains(object_ref const key) const + bool transient_sorted_map::contains(object_ref const &key) const { assert_active(); return data.contains(key); } transient_sorted_map_ref - transient_sorted_map::assoc_in_place(object_ref const key, object_ref const val) + transient_sorted_map::assoc_in_place(object_ref const &key, object_ref const &val) { assert_active(); data[key] = val; return this; } - transient_sorted_map_ref transient_sorted_map::dissoc_in_place(object_ref const key) + transient_sorted_map_ref transient_sorted_map::dissoc_in_place(object_ref const &key) { assert_active(); data.erase(key); return this; } - transient_sorted_map_ref transient_sorted_map::conj_in_place(object_ref const head) + transient_sorted_map_ref transient_sorted_map::conj_in_place(object_ref const &head) { assert_active(); @@ -149,12 +149,12 @@ namespace jank::runtime::obj return make_box(std::move(data)); } - object_ref transient_sorted_map::call(object_ref const o) const + object_ref transient_sorted_map::call(object_ref const &o) const { return get(o); } - object_ref transient_sorted_map::call(object_ref const o, object_ref const fallback) const + object_ref transient_sorted_map::call(object_ref const &o, object_ref const &fallback) const { return get(o, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp index a18120004..f43d7a0e6 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp @@ -56,7 +56,7 @@ namespace jank::runtime::obj return data.size(); } - transient_sorted_set_ref transient_sorted_set::conj_in_place(object_ref const elem) + transient_sorted_set_ref transient_sorted_set::conj_in_place(object_ref const &elem) { assert_active(); data.insert(elem); @@ -70,7 +70,7 @@ namespace jank::runtime::obj return make_box(data); } - object_ref transient_sorted_set::call(object_ref const elem) + object_ref transient_sorted_set::call(object_ref const &elem) { assert_active(); auto const found(data.find(elem)); @@ -81,7 +81,7 @@ namespace jank::runtime::obj return jank_nil(); } - object_ref transient_sorted_set::call(object_ref const elem, object_ref const fallback) + object_ref transient_sorted_set::call(object_ref const &elem, object_ref const &fallback) { assert_active(); auto const found(data.find(elem)); @@ -92,19 +92,19 @@ namespace jank::runtime::obj return fallback; } - object_ref transient_sorted_set::get(object_ref const elem) + object_ref transient_sorted_set::get(object_ref const &elem) { return call(elem); } - object_ref transient_sorted_set::get(object_ref const elem, object_ref const fallback) + object_ref transient_sorted_set::get(object_ref const &elem, object_ref const &fallback) { return call(elem, fallback); } - object_ref transient_sorted_set::get_entry(object_ref const elem) + object_ref transient_sorted_set::get_entry(object_ref const &elem) { - auto const found{ call(elem) }; + auto found{ call(elem) }; if(found == jank_nil()) { return found; @@ -113,13 +113,13 @@ namespace jank::runtime::obj return make_box(std::in_place, found, found); } - bool transient_sorted_set::contains(object_ref const elem) const + bool transient_sorted_set::contains(object_ref const &elem) const { assert_active(); return data.contains(elem); } - transient_sorted_set_ref transient_sorted_set::disjoin_in_place(object_ref const elem) + transient_sorted_set_ref transient_sorted_set::disjoin_in_place(object_ref const &elem) { assert_active(); data.erase(elem); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_vector.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_vector.cpp index c90ea73d8..18ac426d4 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_vector.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_vector.cpp @@ -63,7 +63,7 @@ namespace jank::runtime::obj return data.size(); } - transient_vector_ref transient_vector::conj_in_place(object_ref const head) + transient_vector_ref transient_vector::conj_in_place(object_ref const &head) { assert_active(); data.push_back(head); @@ -77,7 +77,7 @@ namespace jank::runtime::obj return make_box(data.persistent()); } - object_ref transient_vector::call(object_ref const idx) const + object_ref transient_vector::call(object_ref const &idx) const { assert_active(); if(idx->type == object_type::integer) @@ -99,7 +99,7 @@ namespace jank::runtime::obj } } - object_ref transient_vector::get(object_ref const idx) const + object_ref transient_vector::get(object_ref const &idx) const { assert_active(); if(idx->type == object_type::integer) @@ -119,7 +119,7 @@ namespace jank::runtime::obj } } - object_ref transient_vector::get(object_ref const idx, object_ref const fallback) const + object_ref transient_vector::get(object_ref const &idx, object_ref const &fallback) const { assert_active(); if(idx->type == object_type::integer) @@ -139,7 +139,7 @@ namespace jank::runtime::obj } } - object_ref transient_vector::get_entry(object_ref const idx) const + object_ref transient_vector::get_entry(object_ref const &idx) const { if(idx->type == object_type::integer) { @@ -158,7 +158,7 @@ namespace jank::runtime::obj } } - bool transient_vector::contains(object_ref const elem) const + bool transient_vector::contains(object_ref const &elem) const { if(elem->type == object_type::integer) { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/volatile.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/volatile.cpp index ad26b9787..1018b8dc9 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/volatile.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/volatile.cpp @@ -3,7 +3,7 @@ namespace jank::runtime::obj { - volatile_::volatile_(object_ref const o) + volatile_::volatile_(object_ref const &o) : val{ o } { jank_debug_assert(val.is_some()); @@ -41,7 +41,7 @@ namespace jank::runtime::obj return val; } - object_ref volatile_::reset(object_ref const o) + object_ref volatile_::reset(object_ref const &o) { val = o; jank_debug_assert(val.is_some()); diff --git a/compiler+runtime/src/cpp/jank/runtime/object.cpp b/compiler+runtime/src/cpp/jank/runtime/object.cpp index 0811ec89a..974ef390f 100644 --- a/compiler+runtime/src/cpp/jank/runtime/object.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/object.cpp @@ -64,7 +64,7 @@ namespace jank::runtime return *this; } - bool very_equal_to::operator()(object_ref const lhs, object_ref const rhs) const noexcept + bool very_equal_to::operator()(object_ref const &lhs, object_ref const &rhs) const noexcept { if(lhs->type != rhs->type) { @@ -73,12 +73,12 @@ namespace jank::runtime return equal(lhs, rhs); } - bool operator==(object const * const lhs, object_ref const rhs) + bool operator==(object const * const lhs, object_ref const &rhs) { return lhs == rhs.data; } - bool operator!=(object const * const lhs, object_ref const rhs) + bool operator!=(object const * const lhs, object_ref const &rhs) { return lhs != rhs.data; } @@ -89,7 +89,7 @@ namespace std using namespace jank; using namespace jank::runtime; - size_t hash::operator()(object_ref const o) const noexcept + size_t hash::operator()(object_ref const &o) const noexcept { return jank::hash::visit(o.data); } @@ -101,7 +101,7 @@ namespace std bool // NOLINTNEXTLINE(bugprone-exception-escape): TODO: Sort this out. - equal_to::operator()(object_ref const lhs, object_ref const rhs) const noexcept + equal_to::operator()(object_ref const &lhs, object_ref const &rhs) const noexcept { return equal(lhs, rhs); } diff --git a/compiler+runtime/src/cpp/jank/runtime/perf.cpp b/compiler+runtime/src/cpp/jank/runtime/perf.cpp index 84f9325ed..67214b6de 100644 --- a/compiler+runtime/src/cpp/jank/runtime/perf.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/perf.cpp @@ -8,13 +8,13 @@ namespace jank::runtime::perf { - object_ref benchmark(object_ref const opts, object_ref const f) + object_ref benchmark(object_ref const &opts, object_ref const &f) { auto const label(get(opts, __rt_ctx->intern_keyword("label").expect_ok())); auto const label_str(to_string(label)); visit_object( - [](auto const typed_f, jtl::immutable_string const &label) { - using T = typename decltype(typed_f)::value_type; + [](auto const &typed_f, jtl::immutable_string const &label) { + using T = typename jtl::decay_t::value_type; if constexpr(std::is_base_of_v) { diff --git a/compiler+runtime/src/cpp/jank/runtime/var.cpp b/compiler+runtime/src/cpp/jank/runtime/var.cpp index e00daf26d..fc7ffa72a 100644 --- a/compiler+runtime/src/cpp/jank/runtime/var.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/var.cpp @@ -20,7 +20,7 @@ namespace jank::runtime { } - var::var(weak_ns_ref const &n, obj::symbol_ref const &name, object_ref const root) + var::var(weak_ns_ref const &n, obj::symbol_ref const &name, object_ref const &root) : n{ n } , name{ name } , root{ root } @@ -29,7 +29,7 @@ namespace jank::runtime var::var(weak_ns_ref const &n, obj::symbol_ref const &name, - object_ref const root, + object_ref const &root, bool const dynamic, bool const thread_bound) : n{ n } @@ -88,7 +88,7 @@ namespace jank::runtime return hash = hash::combine(n->to_hash(), name->to_hash()); } - var_ref var::with_meta(object_ref const m) + var_ref var::with_meta(object_ref const &m) { meta = behavior::detail::validate_meta(m); return this; @@ -105,21 +105,21 @@ namespace jank::runtime return *root.rlock(); } - var_ref var::bind_root(object_ref const r) + var_ref var::bind_root(object_ref const &r) { profile::timer const timer{ "var bind_root" }; *root.wlock() = r; return this; } - object_ref var::alter_root(object_ref const f, object_ref const args) + object_ref var::alter_root(object_ref const &f, object_ref const &args) { auto locked_root(root.wlock()); *locked_root = apply_to(f, cons(*locked_root, args)); return *locked_root; } - jtl::string_result var::set(object_ref const r) const + jtl::string_result var::set(object_ref const &r) const { profile::timer const timer{ "var set" }; @@ -187,7 +187,7 @@ namespace jank::runtime return make_box(n, name, get_root(), dynamic.load(), thread_bound.load()); } - var_thread_binding::var_thread_binding(object_ref const value, std::thread::id const id) + var_thread_binding::var_thread_binding(object_ref const &value, std::thread::id const id) : value{ value } , thread_id{ id } { @@ -218,7 +218,7 @@ namespace jank::runtime return hash::visit(value.get()); } - var_unbound_root::var_unbound_root(var_ref const var) + var_unbound_root::var_unbound_root(var_ref const &var) : var{ var } { } @@ -250,3 +250,25 @@ namespace jank::runtime return static_cast(reinterpret_cast(this)); } } + +namespace std +{ + size_t hash::operator()(jank::runtime::var const &o) const noexcept + { + static auto hasher(std::hash{}); + return hasher(*o.name); + } + + size_t hash::operator()(jank::runtime::var_ref const &o) const noexcept + { + static auto hasher(std::hash{}); + return hasher(*o->name); + } + + bool + equal_to::operator()(jank::runtime::var_ref const &lhs, + jank::runtime::var_ref const &rhs) const noexcept + { + return lhs->equal(*rhs); + } +} diff --git a/compiler+runtime/src/cpp/jank/util/try.cpp b/compiler+runtime/src/cpp/jank/util/try.cpp index c50e77d98..0c5bc73f6 100644 --- a/compiler+runtime/src/cpp/jank/util/try.cpp +++ b/compiler+runtime/src/cpp/jank/util/try.cpp @@ -88,7 +88,7 @@ namespace jank::util print_exception_stack_trace(); } - void print_exception(runtime::object_ref const e) + void print_exception(runtime::object_ref const &e) { if(e->type == runtime::object_type::persistent_string) { diff --git a/compiler+runtime/src/cpp/jtl/panic.cpp b/compiler+runtime/src/cpp/jtl/panic.cpp index 54e48705e..c405088af 100644 --- a/compiler+runtime/src/cpp/jtl/panic.cpp +++ b/compiler+runtime/src/cpp/jtl/panic.cpp @@ -5,6 +5,7 @@ namespace jtl::detail { + [[noreturn]] void panic(char const * const msg) { jank::util::println(stderr, "Panic encountered: {}", msg); diff --git a/compiler+runtime/src/cpp/jtl/string_builder.cpp b/compiler+runtime/src/cpp/jtl/string_builder.cpp index c433efd28..783a1e4a0 100644 --- a/compiler+runtime/src/cpp/jtl/string_builder.cpp +++ b/compiler+runtime/src/cpp/jtl/string_builder.cpp @@ -15,8 +15,10 @@ namespace jtl static void realloc(string_builder &sb, usize const required) { auto const new_capacity{ std::bit_ceil(required) }; + /* NOLINTNEXTLINE(cppcoreguidelines-no-malloc) */ auto const new_data{ reinterpret_cast(malloc(new_capacity)) }; string_builder::traits_type::copy(new_data, sb.buffer, sb.pos); + /* NOLINTNEXTLINE(cppcoreguidelines-no-malloc) */ free(sb.buffer); sb.buffer = new_data; sb.capacity = new_capacity; @@ -99,6 +101,7 @@ namespace jtl string_builder::~string_builder() { + /* NOLINTNEXTLINE(cppcoreguidelines-no-malloc) */ free(buffer); } From bb77b5779f54bca83540851c267a1cba98b1cdd9 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 20 Dec 2025 11:53:20 -0800 Subject: [PATCH 079/122] Fix some Linux issues --- .github/workflows/build.yml | 9 +- compiler+runtime/CMakeLists.txt | 2 +- compiler+runtime/bin/build-clang | 1 + .../include/cpp/jank/codegen/processor.hpp | 1 + .../include/cpp/jank/perf_native.hpp | 2 +- .../include/cpp/jank/runtime/oref.hpp | 26 +- .../include/cpp/jank/runtime/weak_oref.hpp | 22 +- .../src/cpp/clojure/core_native.cpp | 314 ------------------ .../src/cpp/jank/analyze/cpp_util.cpp | 15 +- compiler+runtime/src/cpp/jank/c_api.cpp | 90 ++--- .../src/cpp/jank/codegen/processor.cpp | 17 +- compiler+runtime/src/cpp/jank/evaluate.cpp | 4 +- compiler+runtime/src/cpp/jank/perf_native.cpp | 4 +- .../src/cpp/jank/runtime/context.cpp | 4 +- .../src/cpp/jank/runtime/core/seq.cpp | 7 +- .../cpp/jank/runtime/obj/lazy_sequence.cpp | 2 +- .../src/cpp/jank/runtime/obj/nil.cpp | 7 +- .../src/cpp/jank/runtime/object.cpp | 1 - compiler+runtime/src/jank/clojure/core.jank | 2 +- .../clojure-test-suite/clojure-test-suite | 2 +- 20 files changed, 118 insertions(+), 414 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 06e4f89dd..e87c092ac 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -97,11 +97,10 @@ jobs: analyze: on ## Debug + sanitization - # TODO: Fix this. GC issue: https://github.com/bdwgc/bdwgc/issues/772 - #- name: Ubuntu - address sanitizer - # os: ubuntu-24.04 - # build_type: Debug - # sanitize: address + - name: Ubuntu - address sanitizer + os: ubuntu-24.04 + build_type: Debug + sanitize: address - name: Ubuntu - undefined behavior sanitizer os: ubuntu-24.04 diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index c71b83df9..457a3dd6c 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -74,7 +74,7 @@ set( jank_aot_compiler_flags -Wall -Wextra -Wpedantic -Wfloat-equal -Wuninitialized -Wswitch-enum -Wnon-virtual-dtor - -Wold-style-cast -Wno-gnu-case-range -Wno-c99-designator + -Wold-style-cast -Wno-gnu-case-range -Wno-c99-designator -Wno-c2y-extensions -Wno-gnu-conditional-omitted-operand -Wno-implicit-fallthrough -Wno-covered-switch-default diff --git a/compiler+runtime/bin/build-clang b/compiler+runtime/bin/build-clang index b2cb2054c..c583c763d 100755 --- a/compiler+runtime/bin/build-clang +++ b/compiler+runtime/bin/build-clang @@ -52,6 +52,7 @@ srcdir="${PWD}" llvm_url="https://github.com/jank-lang/llvm-project.git" llvm_version=22 llvm_branch="jank-snapshot/llvm${llvm_version}" +# 4e5928689f23..a8f19259e708 jank-snapshot/llvm22 -> jank-snapshot/llvm22 function prepare() { diff --git a/compiler+runtime/include/cpp/jank/codegen/processor.hpp b/compiler+runtime/include/cpp/jank/codegen/processor.hpp index 972160695..f54dcf124 100644 --- a/compiler+runtime/include/cpp/jank/codegen/processor.hpp +++ b/compiler+runtime/include/cpp/jank/codegen/processor.hpp @@ -153,6 +153,7 @@ namespace jank::codegen void build_body(); void build_footer(); jtl::immutable_string expression_str(); + jtl::immutable_string expression_fn_str(); void format_elided_var(jtl::immutable_string const &start, jtl::immutable_string const &end, diff --git a/compiler+runtime/include/cpp/jank/perf_native.hpp b/compiler+runtime/include/cpp/jank/perf_native.hpp index 6c25a70db..d76892c86 100644 --- a/compiler+runtime/include/cpp/jank/perf_native.hpp +++ b/compiler+runtime/include/cpp/jank/perf_native.hpp @@ -2,4 +2,4 @@ #include -jank_object_ref jank_load_jank_perf_native(); +void jank_load_jank_perf_native(); diff --git a/compiler+runtime/include/cpp/jank/runtime/oref.hpp b/compiler+runtime/include/cpp/jank/runtime/oref.hpp index 09d9eddaa..0e4021fdc 100644 --- a/compiler+runtime/include/cpp/jank/runtime/oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/oref.hpp @@ -89,7 +89,7 @@ namespace jank::runtime template requires behavior::object_like oref(oref const &typed_data) noexcept - : data{ typed_data.erase() } + : data{ typed_data.erase().data } { retain(); } @@ -193,7 +193,7 @@ namespace jank::runtime requires behavior::object_like bool operator==(oref const &rhs) const noexcept { - return data == rhs.erase(); + return data == rhs.erase().data; } bool operator!=(oref const &rhs) const noexcept @@ -205,7 +205,7 @@ namespace jank::runtime requires behavior::object_like bool operator!=(oref const &rhs) const noexcept { - return data != rhs.erase(); + return data != rhs.erase().data; } oref &operator=(jtl::nullptr_t) noexcept = delete; @@ -217,7 +217,7 @@ namespace jank::runtime return data; } - value_type *erase() const noexcept + oref erase() const noexcept { return data; } @@ -236,7 +236,7 @@ namespace jank::runtime value_type *data{ std::bit_cast(jank_const_nil()) }; }; - /* This specialization of oref is for fully-typed objects like nil, + /* This specialization of oref is for fully-typed objects like * persistent_list, persistent_array_map, etc. * * It cannot be null, but it can be nil. */ @@ -354,12 +354,12 @@ namespace jank::runtime bool operator==(oref const &rhs) const { - return erase() == rhs; + return erase().data == rhs; } bool operator!=(oref const &rhs) const { - return erase() != rhs; + return erase().data != rhs; } template @@ -451,14 +451,14 @@ namespace jank::runtime object *get() const noexcept { - return erase(); + return &reinterpret_cast(data)->base; } - object *erase() const noexcept + oref erase() const noexcept { if(is_nil()) { - return std::bit_cast(jank_const_nil()); + return {}; } return &reinterpret_cast(data)->base; } @@ -555,12 +555,12 @@ namespace jank::runtime object *get() const noexcept { - return erase(); + return std::bit_cast(data); } - object *erase() const noexcept + oref erase() const noexcept { - return std::bit_cast(data); + return {}; } bool is_some() const noexcept diff --git a/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp b/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp index b37eb5336..c90a60860 100644 --- a/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/weak_oref.hpp @@ -62,14 +62,14 @@ namespace jank::runtime template requires behavior::object_like weak_oref(weak_oref const typed_data) noexcept - : data{ typed_data.erase() } + : data{ typed_data.erase().data } { } template requires behavior::object_like weak_oref(oref const &typed_data) noexcept - : data{ typed_data.erase() } + : data{ typed_data.erase().data } { } @@ -105,7 +105,7 @@ namespace jank::runtime requires behavior::object_like bool operator==(weak_oref const &rhs) const noexcept { - return data == rhs.erase(); + return data == rhs.erase().data; } bool operator!=(weak_oref const &rhs) const noexcept @@ -117,7 +117,7 @@ namespace jank::runtime requires behavior::object_like bool operator!=(weak_oref const &rhs) const noexcept { - return data != rhs.erase(); + return data != rhs.erase().data; } weak_oref &operator=(jtl::nullptr_t) noexcept = delete; @@ -139,7 +139,7 @@ namespace jank::runtime return data; } - value_type *erase() const noexcept + weak_oref erase() const noexcept { return data; } @@ -230,12 +230,12 @@ namespace jank::runtime bool operator==(weak_oref const &rhs) const { - return erase() == rhs.erase(); + return erase().data == rhs.erase().data; } bool operator!=(weak_oref const &rhs) const { - return erase() != rhs.erase(); + return erase().data != rhs.erase().data; } template @@ -302,11 +302,11 @@ namespace jank::runtime return erase(); } - object *erase() const noexcept + weak_oref erase() const noexcept { if(is_nil()) { - return std::bit_cast(jank_const_nil()); + return {}; } return &reinterpret_cast(data)->base; } @@ -426,10 +426,10 @@ namespace jank::runtime object *get() const noexcept { - return erase(); + return std::bit_cast(data); } - object *erase() const noexcept + weak_oref erase() const noexcept { return std::bit_cast(data); } diff --git a/compiler+runtime/src/cpp/clojure/core_native.cpp b/compiler+runtime/src/cpp/clojure/core_native.cpp index f71374251..afde28288 100644 --- a/compiler+runtime/src/cpp/clojure/core_native.cpp +++ b/compiler+runtime/src/cpp/clojure/core_native.cpp @@ -540,318 +540,4 @@ void jank_load_clojure_core_native() intern_fn("tan", static_cast(&runtime::tan)); intern_fn("abs", static_cast(&runtime::abs)); intern_fn("pow", static_cast(&runtime::pow)); - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(0, true, false))); - fn->arity_1 = [](object *, object * const seq) -> object * { return list(seq).erase(); }; - intern_fn_obj("list", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(2, true, true))); - fn->arity_1 = [](object *, object *) -> object * { return jank_true.erase(); }; - fn->arity_2 = [](object *, object * const l, object * const r) -> object * { - return make_box(equal(l, r)).erase(); - }; - fn->arity_3 - = [](object *, object * const l, object * const r, object * const rest) -> object * { - if(!equal(l, r)) - { - return jank_false.erase(); - } - - return visit_seqable( - [](auto const &typed_rest, object_ref const &l) { - for(auto const e : make_sequence_range(typed_rest)) - { - if(!equal(l, e)) - { - return jank_false.erase(); - } - } - - return jank_true.erase(); - }, - rest, - l); - }; - intern_fn_obj("=", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(2, true, true))); - fn->arity_1 = [](object *, object *) -> object * { return jank_true.erase(); }; - fn->arity_2 = [](object *, object * const l, object * const r) -> object * { - return make_box(is_equiv(l, r)).erase(); - }; - fn->arity_3 - = [](object *, object * const l, object * const r, object * const rest) -> object * { - if(!is_equiv(l, r)) - { - return jank_false.erase(); - } - - for(auto it(fresh_seq(rest)); it != jank_nil(); it = next_in_place(it)) - { - if(!is_equiv(l, first(it))) - { - return jank_false.erase(); - } - } - - return jank_true.erase(); - }; - intern_fn_obj("==", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(0, true, false))); - fn->arity_1 = [](object *, object * const seq) -> object * { return println(seq).erase(); }; - intern_fn_obj("println", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(0, true, false))); - fn->arity_1 = [](object *, object * const seq) -> object * { return print(seq).erase(); }; - intern_fn_obj("print", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(0, true, false))); - fn->arity_1 = [](object *, object * const seq) -> object * { return prn(seq).erase(); }; - intern_fn_obj("prn", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(0, true, false))); - fn->arity_1 = [](object *, object * const seq) -> object * { return pr(seq).erase(); }; - intern_fn_obj("pr", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(0, false, false))); - fn->arity_0 = [](object *) -> object * { return gensym(make_box("G__")).erase(); }; - fn->arity_1 - = [](object *, object * const prefix) -> object * { return gensym(prefix).erase(); }; - intern_fn_obj("gensym", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(4, true, true))); - fn->arity_2 = [](object *, object * const atom, object * const fn) -> object * { - return try_object(atom)->swap(fn).erase(); - }; - fn->arity_3 - = [](object *, object * const atom, object * const fn, object * const a1) -> object * { - return try_object(atom)->swap(fn, a1).erase(); - }; - fn->arity_4 - = [](object *, object * const atom, object * const fn, object * const a1, object * const a2) - -> object * { return try_object(atom)->swap(fn, a1, a2).erase(); }; - fn->arity_5 = [](object *, - object * const atom, - object * const fn, - object * const a1, - object * const a2, - object * const rest) -> object * { - return try_object(atom)->swap(fn, a1, a2, rest).erase(); - }; - intern_fn_obj("swap!", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(4, true, true))); - fn->arity_2 = [](object *, object * const atom, object * const fn) -> object * { - return try_object(atom)->swap_vals(fn).erase(); - }; - fn->arity_3 - = [](object *, object * const atom, object * const fn, object * const a1) -> object * { - return try_object(atom)->swap_vals(fn, a1).erase(); - }; - fn->arity_4 - = [](object *, object * const atom, object * const fn, object * const a1, object * const a2) - -> object * { return try_object(atom)->swap_vals(fn, a1, a2).erase(); }; - fn->arity_5 = [](object *, - object * const atom, - object * const fn, - object * const a1, - object * const a2, - object * const rest) -> object * { - return try_object(atom)->swap_vals(fn, a1, a2, rest).erase(); - }; - intern_fn_obj("swap-vals!", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(2, true, true))); - fn->arity_2 = [](object *, object * const vol, object * const fn) -> object * { - return vswap(vol, fn).erase(); - }; - fn->arity_3 - = [](object *, object * const vol, object * const fn, object * const rest) -> object * { - return vswap(vol, fn, rest).erase(); - }; - intern_fn_obj("vswap!", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(0, false, false))); - fn->arity_2 = [](object *, object * const s, object * const start) -> object * { - return subs(s, start).erase(); - }; - fn->arity_3 - = [](object *, object * const s, object * const start, object * const end) -> object * { - return subs(s, start, end).erase(); - }; - intern_fn_obj("subs", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(0, true, true))); - fn->arity_0 = [](object *) -> object * { return obj::persistent_hash_map::empty().erase(); }; - fn->arity_1 = [](object *, object * const kvs) -> object * { - return obj::persistent_hash_map::create_from_seq(kvs).erase(); - }; - intern_fn_obj("hash-map", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(0, true, true))); - fn->arity_0 = [](object *) -> object * { return obj::persistent_sorted_map::empty().erase(); }; - fn->arity_1 = [](object *, object * const kvs) -> object * { - return obj::persistent_sorted_map::create_from_seq(kvs).erase(); - }; - intern_fn_obj("sorted-map", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(0, true, true))); - fn->arity_0 = [](object *) -> object * { return obj::persistent_hash_set::empty().erase(); }; - fn->arity_1 = [](object *, object * const kvs) -> object * { - return obj::persistent_hash_set::create_from_seq(kvs).erase(); - }; - intern_fn_obj("hash-set", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(0, true, true))); - fn->arity_0 = [](object *) -> object * { return obj::persistent_sorted_set::empty().erase(); }; - fn->arity_1 = [](object *, object * const kvs) -> object * { - return obj::persistent_sorted_set::create_from_seq(kvs).erase(); - }; - intern_fn_obj("sorted-set", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(3, false, false))); - fn->arity_2 - = [](object *, object * const o, object * const k) -> object * { return get(o, k).erase(); }; - fn->arity_3 - = [](object *, object * const o, object * const k, object * const fallback) -> object * { - return get(o, k, fallback).erase(); - }; - intern_fn_obj("get", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(3, false, false))); - fn->arity_2 = [](object *, object * const o, object * const k) -> object * { - return get_in(o, k).erase(); - }; - fn->arity_3 - = [](object *, object * const o, object * const k, object * const fallback) -> object * { - return get_in(o, k, fallback).erase(); - }; - intern_fn_obj("get-in", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(3, false, false))); - fn->arity_0 = [](object *) -> object * { - return iterate(__rt_ctx->intern_var("clojure.core", "inc").expect_ok()->deref(), make_box(0)) - .erase(); - }; - fn->arity_1 - = [](object *, object * const end) -> object * { return obj::range::create(end).erase(); }; - fn->arity_2 = [](object *, object * const start, object * const end) -> object * { - return obj::range::create(start, end).erase(); - }; - fn->arity_3 - = [](object *, object * const start, object * const end, object * const step) -> object * { - return obj::range::create(start, end, step).erase(); - }; - intern_fn_obj("range", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(3, false, false))); - fn->arity_0 = [](object *) -> object * { - return iterate(__rt_ctx->intern_var("clojure.core", "inc").expect_ok()->deref(), make_box(0)) - .erase(); - }; - fn->arity_1 = [](object *, object * const end) -> object * { - return obj::integer_range::create(try_object(end)).erase(); - }; - fn->arity_2 = [](object *, object * const start, object * const end) -> object * { - return obj::integer_range::create(try_object(start), - try_object(end)) - .erase(); - }; - fn->arity_3 - = [](object *, object * const start, object * const end, object * const step) -> object * { - return obj::integer_range::create(try_object(start), - try_object(end), - try_object(step)) - .erase(); - }; - intern_fn_obj("integer-range", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(3, false, false))); - fn->arity_0 = [](object *) -> object * { - return iterate(__rt_ctx->intern_var("clojure.core", "inc").expect_ok()->deref(), make_box(0)) - .erase(); - }; - fn->arity_2 = [](object *, object * const coll, object * const index) -> object * { - return nth(coll, index).erase(); - }; - fn->arity_3 = - [](object *, object * const coll, object * const index, object * const fallback) -> object * { - return nth(coll, index, fallback).erase(); - }; - intern_fn_obj("nth", fn); - } - - { - auto const fn( - make_box(behavior::callable::build_arity_flags(2, false, false))); - fn->arity_1 - = [](object *, object * const val) -> object * { return obj::repeat::create(val).erase(); }; - fn->arity_2 = [](object *, object * const n, object * const val) -> object * { - return obj::repeat::create(n, val).erase(); - }; - intern_fn_obj("repeat", fn); - } } diff --git a/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp b/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp index ff883c5a1..a281daea2 100644 --- a/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp @@ -298,6 +298,7 @@ namespace jank::analyze::cpp_util { return "jank::runtime::object_ref"; } + util::println("get_qualified_type_name {}", Cpp::GetTypeAsString(type)); /* TODO: Handle typed object refs, too. */ /* TODO: We probably want a recursive approach to this, for types and scopes. */ @@ -306,29 +307,25 @@ namespace jank::analyze::cpp_util llvm::dyn_cast_or_null(qual_type.getTypePtrOrNull()) }; alias) { + util::println("\t is alias"); if(auto const *alias_decl{ alias->getDecl() }; alias_decl) { - auto alias_name{ alias_decl->getQualifiedNameAsString() }; - if(!alias_name.empty()) - { - if(Cpp::IsPointerType(type)) - { - alias_name += "*"; - } - return alias_name; - } + util::println("\t getting decl name: {}", get_qualified_name(alias_decl)); + return get_qualified_name(alias_decl); } } if(auto const scope{ Cpp::GetScopeFromType(type) }; scope) { auto name{ get_qualified_name(scope) }; + util::println("\t found scope: {}", name); if(Cpp::IsPointerType(type)) { name = name + "*"; } return name; } + return Cpp::GetTypeAsString(type); } diff --git a/compiler+runtime/src/cpp/jank/c_api.cpp b/compiler+runtime/src/cpp/jank/c_api.cpp index 438ddc46f..3c1e0d9b6 100644 --- a/compiler+runtime/src/cpp/jank/c_api.cpp +++ b/compiler+runtime/src/cpp/jank/c_api.cpp @@ -54,29 +54,29 @@ extern "C" jank_object_ref jank_eval(jank_object_ref const s) { auto const s_obj(try_object(reinterpret_cast(s))); - return __rt_ctx->eval_string(s_obj->data).retain().erase(); + return __rt_ctx->eval_string(s_obj->data).retain().erase().data; } jank_object_ref jank_read_string(jank_object_ref const s) { auto const s_obj(try_object(reinterpret_cast(s))); - return __rt_ctx->read_string(s_obj->data).retain().erase(); + return __rt_ctx->read_string(s_obj->data).retain().erase().data; } jank_object_ref jank_read_string_c(char const * const s) { - return __rt_ctx->read_string(s).retain().erase(); + return __rt_ctx->read_string(s).retain().erase().data; } jank_object_ref jank_ns_intern(jank_object_ref const sym) { auto const sym_obj(try_object(reinterpret_cast(sym))); - return __rt_ctx->intern_ns(sym_obj).erase(); + return __rt_ctx->intern_ns(sym_obj).erase().data; } jank_object_ref jank_ns_intern_c(char const * const sym) { - return __rt_ctx->intern_ns(sym).erase(); + return __rt_ctx->intern_ns(sym).erase().data; } void jank_ns_set_symbol_counter(char const * const ns, jank_u64 const count) @@ -91,27 +91,27 @@ extern "C" __rt_ctx->intern_ns(ns_obj->data); auto const name_obj(try_object(reinterpret_cast(name))); - return __rt_ctx->intern_var(ns_obj->data, name_obj->data).expect_ok().retain().erase(); + return __rt_ctx->intern_var(ns_obj->data, name_obj->data).expect_ok().retain().erase().data; } jank_object_ref jank_var_intern_c(char const * const ns, char const * const name) { __rt_ctx->intern_ns(ns); - return __rt_ctx->intern_var(ns, name).expect_ok().retain().erase(); + return __rt_ctx->intern_var(ns, name).expect_ok().retain().erase().data; } jank_object_ref jank_var_bind_root(jank_object_ref const var, jank_object_ref const val) { auto const var_obj(try_object(reinterpret_cast(var))); auto const val_obj(reinterpret_cast(val)); - return var_obj->bind_root(val_obj).retain().erase(); + return var_obj->bind_root(val_obj).retain().erase().data; } jank_object_ref jank_var_set_dynamic(jank_object_ref const var, jank_object_ref const dynamic) { auto const var_obj(try_object(reinterpret_cast(var))); auto const dynamic_obj(reinterpret_cast(dynamic)); - return var_obj->set_dynamic(truthy(dynamic_obj)).retain().erase(); + return var_obj->set_dynamic(truthy(dynamic_obj)).retain().erase().data; } jank_object_ref jank_keyword_intern(jank_object_ref const ns, jank_object_ref const name) @@ -121,26 +121,26 @@ extern "C" return __rt_ctx->intern_keyword(to_string(ns_obj), to_string(name_obj)) .expect_ok() .retain() - .erase(); + .erase().data; } jank_object_ref jank_deref(jank_object_ref const o) { auto const o_obj(reinterpret_cast(o)); - return deref(o_obj).retain().erase(); + return deref(o_obj).retain().erase().data; } jank_object_ref jank_call0(jank_object_ref const f) { auto const f_obj(reinterpret_cast(f)); - return dynamic_call(f_obj).retain().erase(); + return dynamic_call(f_obj).retain().erase().data; } jank_object_ref jank_call1(jank_object_ref const f, jank_object_ref const a1) { auto const f_obj(reinterpret_cast(f)); auto const a1_obj(reinterpret_cast(a1)); - return dynamic_call(f_obj, a1_obj).retain().erase(); + return dynamic_call(f_obj, a1_obj).retain().erase().data; } jank_object_ref @@ -149,7 +149,7 @@ extern "C" auto const f_obj(reinterpret_cast(f)); auto const a1_obj(reinterpret_cast(a1)); auto const a2_obj(reinterpret_cast(a2)); - return dynamic_call(f_obj, a1_obj, a2_obj).retain().erase(); + return dynamic_call(f_obj, a1_obj, a2_obj).retain().erase().data; } jank_object_ref jank_call3(jank_object_ref const f, @@ -161,7 +161,7 @@ extern "C" auto const a1_obj(reinterpret_cast(a1)); auto const a2_obj(reinterpret_cast(a2)); auto const a3_obj(reinterpret_cast(a3)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj).retain().erase(); + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj).retain().erase().data; } jank_object_ref jank_call4(jank_object_ref const f, @@ -175,7 +175,7 @@ extern "C" auto const a2_obj(reinterpret_cast(a2)); auto const a3_obj(reinterpret_cast(a3)); auto const a4_obj(reinterpret_cast(a4)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj).retain().erase(); + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj).retain().erase().data; } jank_object_ref jank_call5(jank_object_ref const f, @@ -191,7 +191,7 @@ extern "C" auto const a3_obj(reinterpret_cast(a3)); auto const a4_obj(reinterpret_cast(a4)); auto const a5_obj(reinterpret_cast(a5)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj).retain().erase(); + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj).retain().erase().data; } jank_object_ref jank_call6(jank_object_ref const f, @@ -209,7 +209,7 @@ extern "C" auto const a4_obj(reinterpret_cast(a4)); auto const a5_obj(reinterpret_cast(a5)); auto const a6_obj(reinterpret_cast(a6)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj).retain().erase(); + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj).retain().erase().data; } jank_object_ref jank_call7(jank_object_ref const f, @@ -231,7 +231,7 @@ extern "C" auto const a7_obj(reinterpret_cast(a7)); return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj, a7_obj) .retain() - .erase(); + .erase().data; } jank_object_ref jank_call8(jank_object_ref const f, @@ -255,7 +255,7 @@ extern "C" auto const a8_obj(reinterpret_cast(a8)); return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj, a7_obj, a8_obj) .retain() - .erase(); + .erase().data; } jank_object_ref jank_call9(jank_object_ref const f, @@ -290,7 +290,7 @@ extern "C" a8_obj, a9_obj) .retain() - .erase(); + .erase().data; } jank_object_ref jank_call10(jank_object_ref const f, @@ -328,7 +328,7 @@ extern "C" a9_obj, a10_obj) .retain() - .erase(); + .erase().data; } jank_object_ref jank_call11(jank_object_ref const f, @@ -369,44 +369,44 @@ extern "C" a10_obj, try_object(rest_obj)) .retain() - .erase(); + .erase().data; } jank_object_ref jank_const_nil() { - return jank_nil().erase(); + return jank_nil().erase().data; } jank_object_ref jank_const_true() { - return jank_true.retain().erase(); + return jank_true.retain().erase().data; } jank_object_ref jank_const_false() { - return jank_false.retain().erase(); + return jank_false.retain().erase().data; } jank_object_ref jank_integer_create(jank_i64 const i) { - return make_box(i).retain().erase(); + return make_box(i).retain().erase().data; } jank_object_ref jank_big_integer_create(char const * const s) { jank_assert(s); - return make_box(s).retain().erase(); + return make_box(s).retain().erase().data; } jank_object_ref jank_big_decimal_create(char const * const s) { jank_assert(s); - return make_box(s).retain().erase(); + return make_box(s).retain().erase().data; } jank_object_ref jank_real_create(jank_f64 const r) { - return make_box(r).retain().erase(); + return make_box(r).retain().erase().data; } jank_object_ref @@ -415,20 +415,20 @@ extern "C" return make_box(runtime::obj::ratio_data(reinterpret_cast(numerator), reinterpret_cast(denominator))) .retain() - .erase(); + .erase().data; } jank_object_ref jank_string_create(char const *s) { jank_debug_assert(s); - return make_box(s).retain().erase(); + return make_box(s).retain().erase().data; } jank_object_ref jank_symbol_create(jank_object_ref const ns, jank_object_ref const name) { auto const ns_obj(reinterpret_cast(ns)); auto const name_obj(reinterpret_cast(name)); - return make_box(ns_obj, name_obj).retain().erase(); + return make_box(ns_obj, name_obj).retain().erase().data; } jank_object_ref jank_character_create(char const *s) @@ -436,25 +436,25 @@ extern "C" jank_debug_assert(s); return make_box(read::parse::get_char_from_literal(s).unwrap()) .retain() - .erase(); + .erase().data; } jank_object_ref jank_regex_create(char const *s) { jank_debug_assert(s); - return make_box(s).retain().erase(); + return make_box(s).retain().erase().data; } jank_object_ref jank_uuid_create(char const *s) { jank_debug_assert(s); - return make_box(s).retain().erase(); + return make_box(s).retain().erase().data; } jank_object_ref jank_inst_create(char const *s) { jank_debug_assert(s); - return make_box(s).retain().erase(); + return make_box(s).retain().erase().data; } jank_object_ref jank_list_create(jank_u64 const size, ...) @@ -474,7 +474,7 @@ extern "C" va_end(args); runtime::detail::native_persistent_list const npl{ v.rbegin(), v.rend() }; - return make_box(std::move(npl)).retain().erase(); + return make_box(std::move(npl)).retain().erase().data; } jank_object_ref jank_vector_create(jank_u64 const size, ...) @@ -492,7 +492,7 @@ extern "C" } va_end(args); - return trans.to_persistent().retain().erase(); + return trans.to_persistent().retain().erase().data; } /* TODO: Meta for maps, vectors, sets, symbols, and fns. */ @@ -514,7 +514,7 @@ extern "C" } va_end(args); - return trans.to_persistent().retain().erase(); + return trans.to_persistent().retain().erase().data; } jank_object_ref jank_set_create(u64 const size, ...) @@ -532,12 +532,12 @@ extern "C" } va_end(args); - return trans.to_persistent().retain().erase(); + return trans.to_persistent().retain().erase().data; } jank_object_ref jank_box(char const * const type, void const * const o) { - return make_box(o, type).erase(); + return make_box(o, type).erase().data; } void *jank_unbox(char const * const type, jank_object_ref const o) @@ -587,7 +587,7 @@ extern "C" jank_object_ref jank_function_create(jank_arity_flags const arity_flags) { - return make_box(arity_flags).erase(); + return make_box(arity_flags).erase().data; } void @@ -754,7 +754,7 @@ extern "C" jank_object_ref jank_closure_create(jank_arity_flags const arity_flags, void * const context) { - return make_box(arity_flags, context).erase(); + return make_box(arity_flags, context).erase().data; } void @@ -1081,6 +1081,6 @@ extern "C" trans.conj_in_place(make_box(arg)); } - return trans.to_persistent().retain().erase(); + return trans.to_persistent().retain().erase().data; } } diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 30d97c1cf..69d4234a5 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -1926,8 +1926,8 @@ namespace jank::codegen body_buffer, "auto const {}{ jank::runtime::convert<{}>::{}({}) };", ret_tmp, - cpp_util::get_qualified_type_name( - Cpp::GetTypeWithoutCv(Cpp::GetNonReferenceType(expr->conversion_type))), + cpp_util::get_qualified_type_name(Cpp::GetCanonicalType( + Cpp::GetTypeWithoutCv(Cpp::GetNonReferenceType(expr->conversion_type)))), (expr->policy == conversion_policy::into_object ? "into_object" : "from_object"), value_tmp.unwrap().str(true)); @@ -2844,4 +2844,17 @@ namespace jank::codegen } return { expression_buffer.data(), expression_buffer.size() }; } + + jtl::immutable_string processor::expression_fn_str() + { + auto const &expr_str{ expression_str() }; + auto const &fn_name{ runtime::munge(runtime::__rt_ctx->unique_namespaced_string("expr_fn")) }; + jtl::string_builder fn_buffer; + util::format_to(fn_buffer, + "auto {}(){ return {}.retain().erase().data; } {}()", + fn_name, + expr_str, + fn_name); + return fn_buffer.release(); + } } diff --git a/compiler+runtime/src/cpp/jank/evaluate.cpp b/compiler+runtime/src/cpp/jank/evaluate.cpp index 7ede2a152..0917137d2 100644 --- a/compiler+runtime/src/cpp/jank/evaluate.cpp +++ b/compiler+runtime/src/cpp/jank/evaluate.cpp @@ -604,11 +604,11 @@ namespace jank::evaluate } __rt_ctx->jit_prc.eval_string(cg_prc.declaration_str()); - auto const expr_str{ cg_prc.expression_str() + ".retain().erase()" }; + auto const expr_str{ cg_prc.expression_fn_str() }; clang::Value v; __rt_ctx->jit_prc.eval_string({ expr_str.data(), expr_str.size() }, &v); auto ret{ try_object(v.convertTo()) }; - ret->base.release(); + ret.release(); return ret; } } diff --git a/compiler+runtime/src/cpp/jank/perf_native.cpp b/compiler+runtime/src/cpp/jank/perf_native.cpp index 63c0594b2..2a2819c3d 100644 --- a/compiler+runtime/src/cpp/jank/perf_native.cpp +++ b/compiler+runtime/src/cpp/jank/perf_native.cpp @@ -8,7 +8,7 @@ #include #include -jank_object_ref jank_load_jank_perf_native() +void jank_load_jank_perf_native() { using namespace jank; using namespace jank::runtime; @@ -23,6 +23,4 @@ jank_object_ref jank_load_jank_perf_native() make_box(obj::symbol{ __rt_ctx->current_ns()->to_string(), name }.to_string()))))); }); intern_fn("benchmark", &perf::benchmark); - - return jank_nil().erase(); } diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 9fc7f9b43..1d677c6bb 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -402,7 +402,9 @@ namespace jank::runtime "generic", "", opt, - llvm::Reloc::PIC_) }; + llvm::Reloc::PIC_, + llvm::CodeModel::Large, + llvm::CodeGenOptLevel::Default) }; if(!target_machine) { return err(util::format("failed to create target machine for {}", target_triple)); diff --git a/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp b/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp index ae78b19ec..a4e8358b1 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp @@ -1158,7 +1158,12 @@ namespace jank::runtime if constexpr(behavior::chunkable) { - return typed_o->chunked_next().erase() ?: obj::persistent_list::empty().erase(); + auto ret{ typed_o->chunked_next() }; + if(ret.is_nil()) + { + return obj::persistent_list::empty(); + } + return ret; } { throw std::runtime_error{ util::format("not chunkable: {}", typed_o->to_code_string()) }; diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp index 641cfae7b..3f95d473a 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp @@ -89,7 +89,7 @@ namespace jank::runtime::obj { return 1; } - return hash::ordered(s.erase()); + return hash::ordered(s.erase().data); } cons_ref lazy_sequence::conj(object_ref const &head) const diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp index 4d253416b..5001c62aa 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp @@ -110,8 +110,11 @@ namespace jank::runtime obj::weak_nil_ref jank_nil() { - static obj::nil n; - n.base.retain(); + static auto n{ []() { + obj::nil n; + n.base.retain(); + return n; + }() }; return &n; } } diff --git a/compiler+runtime/src/cpp/jank/runtime/object.cpp b/compiler+runtime/src/cpp/jank/runtime/object.cpp index 974ef390f..5232c0bda 100644 --- a/compiler+runtime/src/cpp/jank/runtime/object.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/object.cpp @@ -37,7 +37,6 @@ namespace jank::runtime visit_object( [](auto const typed_this) { using T = typename decltype(typed_this)::value_type; - delete static_cast(typed_this.data); }, this); diff --git a/compiler+runtime/src/jank/clojure/core.jank b/compiler+runtime/src/jank/clojure/core.jank index c614b5efd..2512f899a 100644 --- a/compiler+runtime/src/jank/clojure/core.jank +++ b/compiler+runtime/src/jank/clojure/core.jank @@ -493,7 +493,7 @@ false)))) (def ^:private sigs - (fn* [fdecl] + (fn* sigs [fdecl] (let* [asig (fn* asig [fdecl] (let* [arglist (first fdecl) ;elide implicit macro args diff --git a/compiler+runtime/test/bash/clojure-test-suite/clojure-test-suite b/compiler+runtime/test/bash/clojure-test-suite/clojure-test-suite index 5bd9fd054..b7882f5eb 160000 --- a/compiler+runtime/test/bash/clojure-test-suite/clojure-test-suite +++ b/compiler+runtime/test/bash/clojure-test-suite/clojure-test-suite @@ -1 +1 @@ -Subproject commit 5bd9fd05419aee86d4831cdcf16a762850383517 +Subproject commit b7882f5eb12818ebdf608b9d379839f7a174c811 From 70c1cb2d94d254e49b563a888c57b72c31b556e0 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 20 Dec 2025 12:32:32 -0800 Subject: [PATCH 080/122] Add more erasure to C++ gen --- compiler+runtime/src/cpp/jank/codegen/processor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 69d4234a5..e2391916f 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -1801,7 +1801,7 @@ namespace jank::codegen auto const &value_tmp{ gen(expr->value_expr, fn_arity) }; util::format_to(body_buffer, - "switch(jank_shift_mask_case_integer({}.erase(), {}, {})) {", + "switch(jank_shift_mask_case_integer({}.erase().data, {}, {})) {", value_tmp.unwrap().str(true), expr->shift, expr->mask); @@ -1983,7 +1983,7 @@ namespace jank::codegen util::format_to(body_buffer, "{}", arg_tmp.str(true)); if(param_type && Cpp::IsPointerType(param_type) && cpp_util::is_any_object(arg_type)) { - util::format_to(body_buffer, ".erase()"); + util::format_to(body_buffer, ".erase().data"); } need_comma = true; } From da0b629d28f838886a457820203c0f9227d7917a Mon Sep 17 00:00:00 2001 From: jeaye Date: Sun, 21 Dec 2025 10:54:08 -0800 Subject: [PATCH 081/122] Hard-code nullptr qualification An LLM said that Clang doesn't consider this qualified, so it won't add it automatically. This works fine on libc++, but fails on libstdc++, due to implicit usings, most likely. --- compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp b/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp index a281daea2..3a3fb783f 100644 --- a/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/cpp_util.cpp @@ -298,19 +298,21 @@ namespace jank::analyze::cpp_util { return "jank::runtime::object_ref"; } - util::println("get_qualified_type_name {}", Cpp::GetTypeAsString(type)); /* TODO: Handle typed object refs, too. */ /* TODO: We probably want a recursive approach to this, for types and scopes. */ auto const qual_type{ clang::QualType::getFromOpaquePtr(type) }; + if(qual_type->isNullPtrType()) + { + return "std::nullptr_t"; + } + if(auto const *alias{ llvm::dyn_cast_or_null(qual_type.getTypePtrOrNull()) }; alias) { - util::println("\t is alias"); if(auto const *alias_decl{ alias->getDecl() }; alias_decl) { - util::println("\t getting decl name: {}", get_qualified_name(alias_decl)); return get_qualified_name(alias_decl); } } @@ -318,7 +320,6 @@ namespace jank::analyze::cpp_util if(auto const scope{ Cpp::GetScopeFromType(type) }; scope) { auto name{ get_qualified_name(scope) }; - util::println("\t found scope: {}", name); if(Cpp::IsPointerType(type)) { name = name + "*"; From 664d2c81e859adce97f163d48e0324e8ae073d64 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sun, 21 Dec 2025 10:57:12 -0800 Subject: [PATCH 082/122] Add some cppgen retains, to be safe --- compiler+runtime/src/cpp/jank/codegen/processor.cpp | 6 +++--- compiler+runtime/src/cpp/jank/runtime/object.cpp | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index e2391916f..d01039738 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -1801,7 +1801,7 @@ namespace jank::codegen auto const &value_tmp{ gen(expr->value_expr, fn_arity) }; util::format_to(body_buffer, - "switch(jank_shift_mask_case_integer({}.erase().data, {}, {})) {", + "switch(jank_shift_mask_case_integer({}.retain().get(), {}, {})) {", value_tmp.unwrap().str(true), expr->shift, expr->mask); @@ -1983,7 +1983,7 @@ namespace jank::codegen util::format_to(body_buffer, "{}", arg_tmp.str(true)); if(param_type && Cpp::IsPointerType(param_type) && cpp_util::is_any_object(arg_type)) { - util::format_to(body_buffer, ".erase().data"); + util::format_to(body_buffer, ".retain().get()"); } need_comma = true; } @@ -2851,7 +2851,7 @@ namespace jank::codegen auto const &fn_name{ runtime::munge(runtime::__rt_ctx->unique_namespaced_string("expr_fn")) }; jtl::string_builder fn_buffer; util::format_to(fn_buffer, - "auto {}(){ return {}.retain().erase().data; } {}()", + "auto {}(){ return {}.retain().get(); } {}()", fn_name, expr_str, fn_name); diff --git a/compiler+runtime/src/cpp/jank/runtime/object.cpp b/compiler+runtime/src/cpp/jank/runtime/object.cpp index 5232c0bda..445869564 100644 --- a/compiler+runtime/src/cpp/jank/runtime/object.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/object.cpp @@ -37,6 +37,7 @@ namespace jank::runtime visit_object( [](auto const typed_this) { using T = typename decltype(typed_this)::value_type; + //util::println("\tfreeing {}", typed_this.data); delete static_cast(typed_this.data); }, this); From 7d882c1cc82f7f0d25db27225a8e45d534e2315b Mon Sep 17 00:00:00 2001 From: jeaye Date: Sun, 21 Dec 2025 10:58:04 -0800 Subject: [PATCH 083/122] Switch oref erasure to return an object_ref This allows us to more easily throw `object_ref`, rather than `object*`. --- .../include/cpp/jank/runtime/oref.hpp | 21 ++++++++++---- compiler+runtime/src/cpp/jank/c_api.cpp | 29 +++++++++++++------ 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/runtime/oref.hpp b/compiler+runtime/include/cpp/jank/runtime/oref.hpp index 0e4021fdc..dd4b4d91e 100644 --- a/compiler+runtime/include/cpp/jank/runtime/oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/oref.hpp @@ -99,7 +99,7 @@ namespace jank::runtime release(); } - oref &retain() + oref const &retain() const { if(is_some()) { @@ -108,7 +108,7 @@ namespace jank::runtime return *this; } - void release() + void release() const { if(is_some()) { @@ -217,9 +217,9 @@ namespace jank::runtime return data; } - oref erase() const noexcept + oref const &erase() const noexcept { - return data; + return *this; } bool is_some() const noexcept @@ -295,7 +295,7 @@ namespace jank::runtime release(); } - oref &retain() + oref const &retain() const { if(is_some()) { @@ -304,7 +304,7 @@ namespace jank::runtime return *this; } - void release() + void release() const { if(is_some()) { @@ -511,6 +511,15 @@ namespace jank::runtime { } + oref const &retain() const + { + return *this; + } + + void release() const + { + } + void reset() { } diff --git a/compiler+runtime/src/cpp/jank/c_api.cpp b/compiler+runtime/src/cpp/jank/c_api.cpp index 3c1e0d9b6..8f67df6ed 100644 --- a/compiler+runtime/src/cpp/jank/c_api.cpp +++ b/compiler+runtime/src/cpp/jank/c_api.cpp @@ -121,7 +121,8 @@ extern "C" return __rt_ctx->intern_keyword(to_string(ns_obj), to_string(name_obj)) .expect_ok() .retain() - .erase().data; + .erase() + .data; } jank_object_ref jank_deref(jank_object_ref const o) @@ -209,7 +210,10 @@ extern "C" auto const a4_obj(reinterpret_cast(a4)); auto const a5_obj(reinterpret_cast(a5)); auto const a6_obj(reinterpret_cast(a6)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj).retain().erase().data; + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj) + .retain() + .erase() + .data; } jank_object_ref jank_call7(jank_object_ref const f, @@ -231,7 +235,8 @@ extern "C" auto const a7_obj(reinterpret_cast(a7)); return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj, a7_obj) .retain() - .erase().data; + .erase() + .data; } jank_object_ref jank_call8(jank_object_ref const f, @@ -255,7 +260,8 @@ extern "C" auto const a8_obj(reinterpret_cast(a8)); return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj, a7_obj, a8_obj) .retain() - .erase().data; + .erase() + .data; } jank_object_ref jank_call9(jank_object_ref const f, @@ -290,7 +296,8 @@ extern "C" a8_obj, a9_obj) .retain() - .erase().data; + .erase() + .data; } jank_object_ref jank_call10(jank_object_ref const f, @@ -328,7 +335,8 @@ extern "C" a9_obj, a10_obj) .retain() - .erase().data; + .erase() + .data; } jank_object_ref jank_call11(jank_object_ref const f, @@ -369,7 +377,8 @@ extern "C" a10_obj, try_object(rest_obj)) .retain() - .erase().data; + .erase() + .data; } jank_object_ref jank_const_nil() @@ -415,7 +424,8 @@ extern "C" return make_box(runtime::obj::ratio_data(reinterpret_cast(numerator), reinterpret_cast(denominator))) .retain() - .erase().data; + .erase() + .data; } jank_object_ref jank_string_create(char const *s) @@ -436,7 +446,8 @@ extern "C" jank_debug_assert(s); return make_box(read::parse::get_char_from_literal(s).unwrap()) .retain() - .erase().data; + .erase() + .data; } jank_object_ref jank_regex_create(char const *s) From d8386f94b8aec4aee125c11daf06608032d218c5 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sun, 21 Dec 2025 11:41:24 -0800 Subject: [PATCH 084/122] Remove arc It removed the bdwgc premature GC errors, but it led to Clang JIT compilation bugs instead. There's no way out! --- .../include/cpp/clojure/core_native.hpp | 92 +-- .../include/cpp/clojure/string_native.hpp | 32 +- .../include/cpp/jank/analyze/expr/call.hpp | 2 +- .../cpp/jank/analyze/expr/cpp_type.hpp | 2 +- .../cpp/jank/analyze/expr/cpp_value.hpp | 2 +- .../include/cpp/jank/analyze/expr/def.hpp | 2 +- .../cpp/jank/analyze/expr/function.hpp | 2 +- .../cpp/jank/analyze/expr/local_reference.hpp | 2 +- .../cpp/jank/analyze/expr/named_recursion.hpp | 2 +- .../jank/analyze/expr/primitive_literal.hpp | 2 +- .../include/cpp/jank/analyze/expr/recur.hpp | 2 +- .../cpp/jank/analyze/expr/var_deref.hpp | 4 +- .../include/cpp/jank/analyze/expr/var_ref.hpp | 4 +- .../include/cpp/jank/analyze/local_frame.hpp | 6 +- .../include/cpp/jank/analyze/processor.hpp | 74 +-- .../cpp/jank/analyze/recursive_visitor.hpp | 2 +- .../include/cpp/jank/codegen/processor.hpp | 1 - compiler+runtime/include/cpp/jank/error.hpp | 12 +- .../include/cpp/jank/error/analyze.hpp | 96 +-- compiler+runtime/include/cpp/jank/hash.hpp | 2 +- .../include/cpp/jank/read/parse.hpp | 10 +- .../include/cpp/jank/read/reparse.hpp | 6 +- .../include/cpp/jank/read/source.hpp | 2 +- .../cpp/jank/runtime/behavior/callable.hpp | 250 ++++---- .../cpp/jank/runtime/behavior/metadatable.hpp | 2 +- .../include/cpp/jank/runtime/context.hpp | 30 +- .../cpp/jank/runtime/convert/builtin.hpp | 62 +- .../cpp/jank/runtime/convert/function.hpp | 4 +- .../include/cpp/jank/runtime/core.hpp | 180 +++--- .../include/cpp/jank/runtime/core/equal.hpp | 8 +- .../include/cpp/jank/runtime/core/math.hpp | 376 +++++------ .../include/cpp/jank/runtime/core/meta.hpp | 12 +- .../include/cpp/jank/runtime/core/munge.hpp | 2 +- .../include/cpp/jank/runtime/core/seq.hpp | 166 ++--- .../include/cpp/jank/runtime/core/seq_ext.hpp | 2 +- .../cpp/jank/runtime/core/to_string.hpp | 12 +- .../include/cpp/jank/runtime/core/truthy.hpp | 6 +- .../jank/runtime/detail/native_array_map.hpp | 8 +- .../include/cpp/jank/runtime/detail/type.hpp | 2 +- .../include/cpp/jank/runtime/ns.hpp | 18 +- .../cpp/jank/runtime/obj/array_chunk.hpp | 4 +- .../include/cpp/jank/runtime/obj/atom.hpp | 35 +- .../cpp/jank/runtime/obj/chunk_buffer.hpp | 4 +- .../cpp/jank/runtime/obj/chunked_cons.hpp | 8 +- .../include/cpp/jank/runtime/obj/cons.hpp | 6 +- .../include/cpp/jank/runtime/obj/delay.hpp | 2 +- .../obj/detail/base_persistent_map.hpp | 14 +- .../detail/base_persistent_map_sequence.hpp | 8 +- .../runtime/obj/detail/iterator_sequence.hpp | 4 +- .../cpp/jank/runtime/obj/integer_range.hpp | 28 +- .../include/cpp/jank/runtime/obj/iterator.hpp | 4 +- .../cpp/jank/runtime/obj/jit_closure.hpp | 102 +-- .../cpp/jank/runtime/obj/jit_function.hpp | 102 +-- .../include/cpp/jank/runtime/obj/keyword.hpp | 10 +- .../cpp/jank/runtime/obj/lazy_sequence.hpp | 8 +- .../cpp/jank/runtime/obj/multi_function.hpp | 124 ++-- .../runtime/obj/native_array_sequence.hpp | 4 +- .../runtime/obj/native_function_wrapper.hpp | 100 +-- .../runtime/obj/native_vector_sequence.hpp | 4 +- .../include/cpp/jank/runtime/obj/nil.hpp | 15 +- .../cpp/jank/runtime/obj/opaque_box.hpp | 2 +- .../jank/runtime/obj/persistent_array_map.hpp | 20 +- .../jank/runtime/obj/persistent_hash_map.hpp | 27 +- .../jank/runtime/obj/persistent_hash_set.hpp | 14 +- .../cpp/jank/runtime/obj/persistent_list.hpp | 14 +- .../runtime/obj/persistent_sorted_map.hpp | 24 +- .../runtime/obj/persistent_sorted_set.hpp | 16 +- .../jank/runtime/obj/persistent_string.hpp | 16 +- .../obj/persistent_string_sequence.hpp | 6 +- .../jank/runtime/obj/persistent_vector.hpp | 26 +- .../obj/persistent_vector_sequence.hpp | 6 +- .../include/cpp/jank/runtime/obj/range.hpp | 34 +- .../include/cpp/jank/runtime/obj/ratio.hpp | 74 +-- .../cpp/jank/runtime/obj/re_matcher.hpp | 2 +- .../include/cpp/jank/runtime/obj/reduced.hpp | 2 +- .../include/cpp/jank/runtime/obj/repeat.hpp | 12 +- .../include/cpp/jank/runtime/obj/symbol.hpp | 12 +- .../cpp/jank/runtime/obj/tagged_literal.hpp | 10 +- .../jank/runtime/obj/transient_array_map.hpp | 18 +- .../jank/runtime/obj/transient_hash_map.hpp | 18 +- .../jank/runtime/obj/transient_hash_set.hpp | 16 +- .../jank/runtime/obj/transient_sorted_map.hpp | 18 +- .../jank/runtime/obj/transient_sorted_set.hpp | 16 +- .../cpp/jank/runtime/obj/transient_vector.hpp | 12 +- .../include/cpp/jank/runtime/obj/volatile.hpp | 4 +- .../include/cpp/jank/runtime/object.hpp | 17 +- .../include/cpp/jank/runtime/oref.hpp | 129 +--- .../include/cpp/jank/runtime/perf.hpp | 2 +- .../include/cpp/jank/runtime/rtti.hpp | 19 +- .../cpp/jank/runtime/sequence_range.hpp | 22 +- .../include/cpp/jank/runtime/var.hpp | 30 +- .../include/cpp/jank/runtime/visit.hpp | 22 +- .../include/cpp/jank/util/try.hpp | 4 +- .../src/cpp/clojure/core_native.cpp | 175 +++-- .../src/cpp/clojure/string_native.cpp | 38 +- .../src/cpp/jank/analyze/expr/call.cpp | 2 +- .../src/cpp/jank/analyze/expr/cpp_type.cpp | 2 +- .../src/cpp/jank/analyze/expr/cpp_value.cpp | 2 +- .../src/cpp/jank/analyze/expr/def.cpp | 2 +- .../src/cpp/jank/analyze/expr/function.cpp | 2 +- .../cpp/jank/analyze/expr/local_reference.cpp | 2 +- .../cpp/jank/analyze/expr/named_recursion.cpp | 2 +- .../jank/analyze/expr/primitive_literal.cpp | 2 +- .../src/cpp/jank/analyze/expr/recur.cpp | 2 +- .../src/cpp/jank/analyze/expr/var_deref.cpp | 4 +- .../src/cpp/jank/analyze/expr/var_ref.cpp | 4 +- .../src/cpp/jank/analyze/local_frame.cpp | 8 +- .../src/cpp/jank/analyze/processor.cpp | 88 +-- compiler+runtime/src/cpp/jank/c_api.cpp | 83 +-- .../src/cpp/jank/codegen/llvm_processor.cpp | 74 +-- .../src/cpp/jank/codegen/processor.cpp | 25 +- .../src/cpp/jank/compiler_native.cpp | 2 +- compiler+runtime/src/cpp/jank/error.cpp | 14 +- .../src/cpp/jank/error/analyze.cpp | 96 +-- compiler+runtime/src/cpp/jank/evaluate.cpp | 3 +- compiler+runtime/src/cpp/jank/hash.cpp | 4 +- compiler+runtime/src/cpp/jank/read/parse.cpp | 26 +- .../src/cpp/jank/read/reparse.cpp | 10 +- compiler+runtime/src/cpp/jank/read/source.cpp | 2 +- .../cpp/jank/runtime/behavior/callable.cpp | 276 ++++---- .../cpp/jank/runtime/behavior/metadatable.cpp | 2 +- .../src/cpp/jank/runtime/context.cpp | 32 +- .../src/cpp/jank/runtime/core.cpp | 192 +++--- .../src/cpp/jank/runtime/core/equal.cpp | 12 +- .../src/cpp/jank/runtime/core/math.cpp | 605 +++++++++--------- .../src/cpp/jank/runtime/core/meta.cpp | 20 +- .../src/cpp/jank/runtime/core/munge.cpp | 2 +- .../src/cpp/jank/runtime/core/seq.cpp | 244 +++---- .../src/cpp/jank/runtime/core/to_string.cpp | 14 +- .../src/cpp/jank/runtime/core/truthy.cpp | 6 +- .../jank/runtime/detail/native_array_map.cpp | 12 +- .../src/cpp/jank/runtime/detail/type.cpp | 2 +- .../src/cpp/jank/runtime/module/loader.cpp | 4 +- compiler+runtime/src/cpp/jank/runtime/ns.cpp | 18 +- .../src/cpp/jank/runtime/obj/array_chunk.cpp | 4 +- .../src/cpp/jank/runtime/obj/atom.cpp | 68 +- .../src/cpp/jank/runtime/obj/big_decimal.cpp | 4 +- .../src/cpp/jank/runtime/obj/big_integer.cpp | 2 +- .../src/cpp/jank/runtime/obj/chunk_buffer.cpp | 4 +- .../src/cpp/jank/runtime/obj/chunked_cons.cpp | 12 +- .../src/cpp/jank/runtime/obj/cons.cpp | 6 +- .../src/cpp/jank/runtime/obj/delay.cpp | 2 +- .../obj/detail/base_persistent_map.cpp | 6 +- .../detail/base_persistent_map_sequence.cpp | 4 +- .../runtime/obj/detail/iterator_sequence.cpp | 6 +- .../cpp/jank/runtime/obj/integer_range.cpp | 30 +- .../src/cpp/jank/runtime/obj/iterator.cpp | 4 +- .../src/cpp/jank/runtime/obj/jit_closure.cpp | 108 ++-- .../src/cpp/jank/runtime/obj/jit_function.cpp | 108 ++-- .../src/cpp/jank/runtime/obj/keyword.cpp | 4 +- .../cpp/jank/runtime/obj/lazy_sequence.cpp | 8 +- .../cpp/jank/runtime/obj/multi_function.cpp | 138 ++-- .../runtime/obj/native_array_sequence.cpp | 2 +- .../runtime/obj/native_function_wrapper.cpp | 112 ++-- .../runtime/obj/native_vector_sequence.cpp | 4 +- .../src/cpp/jank/runtime/obj/nil.cpp | 20 +- .../src/cpp/jank/runtime/obj/number.cpp | 8 +- .../src/cpp/jank/runtime/obj/opaque_box.cpp | 2 +- .../jank/runtime/obj/persistent_array_map.cpp | 16 +- .../jank/runtime/obj/persistent_hash_map.cpp | 24 +- .../jank/runtime/obj/persistent_hash_set.cpp | 16 +- .../cpp/jank/runtime/obj/persistent_list.cpp | 12 +- .../runtime/obj/persistent_sorted_map.cpp | 22 +- .../runtime/obj/persistent_sorted_set.cpp | 18 +- .../jank/runtime/obj/persistent_string.cpp | 16 +- .../obj/persistent_string_sequence.cpp | 6 +- .../jank/runtime/obj/persistent_vector.cpp | 26 +- .../obj/persistent_vector_sequence.cpp | 6 +- .../src/cpp/jank/runtime/obj/range.cpp | 36 +- .../src/cpp/jank/runtime/obj/ratio.cpp | 78 +-- .../src/cpp/jank/runtime/obj/re_matcher.cpp | 2 +- .../src/cpp/jank/runtime/obj/reduced.cpp | 2 +- .../src/cpp/jank/runtime/obj/repeat.cpp | 12 +- .../src/cpp/jank/runtime/obj/symbol.cpp | 14 +- .../cpp/jank/runtime/obj/tagged_literal.cpp | 12 +- .../jank/runtime/obj/transient_array_map.cpp | 18 +- .../jank/runtime/obj/transient_hash_map.cpp | 18 +- .../jank/runtime/obj/transient_hash_set.cpp | 16 +- .../jank/runtime/obj/transient_sorted_map.cpp | 18 +- .../jank/runtime/obj/transient_sorted_set.cpp | 16 +- .../cpp/jank/runtime/obj/transient_vector.cpp | 12 +- .../src/cpp/jank/runtime/obj/volatile.cpp | 4 +- .../src/cpp/jank/runtime/object.cpp | 33 +- .../src/cpp/jank/runtime/perf.cpp | 4 +- compiler+runtime/src/cpp/jank/runtime/var.cpp | 32 +- compiler+runtime/src/cpp/jank/util/try.cpp | 2 +- 186 files changed, 2875 insertions(+), 3148 deletions(-) diff --git a/compiler+runtime/include/cpp/clojure/core_native.hpp b/compiler+runtime/include/cpp/clojure/core_native.hpp index af7948cf2..5f9c903f9 100644 --- a/compiler+runtime/include/cpp/clojure/core_native.hpp +++ b/compiler+runtime/include/cpp/clojure/core_native.hpp @@ -9,62 +9,62 @@ namespace clojure::core_native { using namespace jank::runtime; - object_ref is_var(object_ref const &o); - object_ref var_get(object_ref const &o); - object_ref alter_var_root(object_ref const &o, object_ref const &fn, object_ref const &args); - object_ref is_var_bound(object_ref const &o); - object_ref is_var_thread_bound(object_ref const &o); - object_ref var_bind_root(object_ref const &v, object_ref const &o); - object_ref var_get_root(object_ref const &o); - object_ref intern_var(object_ref const &sym); + object_ref is_var(object_ref const o); + object_ref var_get(object_ref const o); + object_ref alter_var_root(object_ref const o, object_ref const fn, object_ref const args); + object_ref is_var_bound(object_ref const o); + object_ref is_var_thread_bound(object_ref const o); + object_ref var_bind_root(object_ref const v, object_ref const o); + object_ref var_get_root(object_ref const o); + object_ref intern_var(object_ref const sym); - object_ref ns_unalias(object_ref const ¤t_ns, object_ref const &alias); - object_ref ns_unmap(object_ref const ¤t_ns, object_ref const &sym); - object_ref in_ns(object_ref const &sym); - object_ref intern_ns(object_ref const &sym); - object_ref find_ns(object_ref const &sym); - object_ref find_var(object_ref const &sym); - object_ref remove_ns(object_ref const &sym); - object_ref is_ns(object_ref const &ns_or_sym); - object_ref ns_name(object_ref const &ns); - object_ref ns_map(object_ref const &ns); - object_ref var_ns(object_ref const &v); - object_ref ns_resolve(object_ref const &ns, object_ref const &sym); + object_ref ns_unalias(object_ref const current_ns, object_ref const alias); + object_ref ns_unmap(object_ref const current_ns, object_ref const sym); + object_ref in_ns(object_ref const sym); + object_ref intern_ns(object_ref const sym); + object_ref find_ns(object_ref const sym); + object_ref find_var(object_ref const sym); + object_ref remove_ns(object_ref const sym); + object_ref is_ns(object_ref const ns_or_sym); + object_ref ns_name(object_ref const ns); + object_ref ns_map(object_ref const ns); + object_ref var_ns(object_ref const v); + object_ref ns_resolve(object_ref const ns, object_ref const sym); object_ref - alias(object_ref const ¤t_ns, object_ref const &remote_ns, object_ref const &alias); - object_ref refer(object_ref const ¤t_ns, object_ref const &sym, object_ref const &var); - object_ref load_module(object_ref const &path); - object_ref compile(object_ref const &path); + alias(object_ref const current_ns, object_ref const remote_ns, object_ref const alias); + object_ref refer(object_ref const current_ns, object_ref const sym, object_ref const var); + object_ref load_module(object_ref const path); + object_ref compile(object_ref const path); - object_ref not_(object_ref const &o); + object_ref not_(object_ref const o); - object_ref is_fn(object_ref const &o); - object_ref is_multi_fn(object_ref const &o); - object_ref multi_fn(object_ref const &name, - object_ref const &dispatch_fn, - object_ref const &default_, - object_ref const &hierarchy); + object_ref is_fn(object_ref const o); + object_ref is_multi_fn(object_ref const o); + object_ref multi_fn(object_ref const name, + object_ref const dispatch_fn, + object_ref const default_, + object_ref const hierarchy); object_ref - defmethod(object_ref const &multifn, object_ref const &dispatch_val, object_ref const &fn); - object_ref remove_all_methods(object_ref const &multifn); - object_ref remove_method(object_ref const &multifn, object_ref const &dispatch_val); - object_ref prefer_method(object_ref const &multifn, - object_ref const &dispatch_val_x, - object_ref const &ispatch_val_y); - object_ref methods(object_ref const &multifn); - object_ref get_method(object_ref const &multifn, object_ref const &dispatch_val); - object_ref prefers(object_ref const &multifn); + defmethod(object_ref const multifn, object_ref const dispatch_val, object_ref const fn); + object_ref remove_all_methods(object_ref const multifn); + object_ref remove_method(object_ref const multifn, object_ref const dispatch_val); + object_ref prefer_method(object_ref const multifn, + object_ref const dispatch_val_x, + object_ref const ispatch_val_y); + object_ref methods(object_ref const multifn); + object_ref get_method(object_ref const multifn, object_ref const dispatch_val); + object_ref prefers(object_ref const multifn); - object_ref sleep(object_ref const &ms); + object_ref sleep(object_ref const ms); object_ref current_time(); - object_ref eval(object_ref const &expr); - object_ref read_string(object_ref const & /* opts */, object_ref const &str); + object_ref eval(object_ref const expr); + object_ref read_string(object_ref const /* opts */, object_ref const str); - object_ref lazy_seq(object_ref const &o); + object_ref lazy_seq(object_ref const o); - object_ref hash_unordered(object_ref const &coll); + object_ref hash_unordered(object_ref const coll); object_ref jank_version(); - object_ref delay(object_ref const &fn); + object_ref delay(object_ref const fn); } diff --git a/compiler+runtime/include/cpp/clojure/string_native.hpp b/compiler+runtime/include/cpp/clojure/string_native.hpp index 44b475b0d..4412d6c5e 100644 --- a/compiler+runtime/include/cpp/clojure/string_native.hpp +++ b/compiler+runtime/include/cpp/clojure/string_native.hpp @@ -7,24 +7,24 @@ namespace clojure::string_native using namespace jank; using namespace jank::runtime; - object_ref blank(object_ref const &s); - object_ref reverse(object_ref const &s); - object_ref lower_case(object_ref const &s); - object_ref starts_with(object_ref const &s, object_ref const &substr); - object_ref ends_with(object_ref const &s, object_ref const &substr); - object_ref includes(object_ref const &s, object_ref const &substr); - object_ref upper_case(object_ref const &s); + object_ref blank(object_ref const s); + object_ref reverse(object_ref const s); + object_ref lower_case(object_ref const s); + object_ref starts_with(object_ref const s, object_ref const substr); + object_ref ends_with(object_ref const s, object_ref const substr); + object_ref includes(object_ref const s, object_ref const substr); + object_ref upper_case(object_ref const s); object_ref - replace_first(object_ref const &s, object_ref const &match, object_ref const &replacement); + replace_first(object_ref const s, object_ref const match, object_ref const replacement); - i64 index_of(object_ref const &s, object_ref const &value, object_ref const &from_index); - i64 last_index_of(object_ref const &s, object_ref const &value, object_ref const &from_index); + i64 index_of(object_ref const s, object_ref const value, object_ref const from_index); + i64 last_index_of(object_ref const s, object_ref const value, object_ref const from_index); - object_ref triml(object_ref const &s); - object_ref trimr(object_ref const &s); - object_ref trim(object_ref const &s); - object_ref trim_newline(object_ref const &s); + object_ref triml(object_ref const s); + object_ref trimr(object_ref const s); + object_ref trim(object_ref const s); + object_ref trim_newline(object_ref const s); - object_ref split(object_ref const &s, object_ref const &re); - object_ref split(object_ref const &s, object_ref const &re, object_ref const &limit); + object_ref split(object_ref const s, object_ref const re); + object_ref split(object_ref const s, object_ref const re, object_ref const limit); } diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/call.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/call.hpp index dcc9074e9..00ba72d51 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/call.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/call.hpp @@ -20,7 +20,7 @@ namespace jank::analyze::expr bool needs_box, expression_ref source, native_vector &&arg_exprs, - runtime::obj::persistent_list_ref const &form); + runtime::obj::persistent_list_ref const form); runtime::object_ref to_runtime_data() const override; void walk(std::function)> const &f) override; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/cpp_type.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/cpp_type.hpp index 15f154845..714ca9585 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/cpp_type.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/cpp_type.hpp @@ -18,7 +18,7 @@ namespace jank::analyze::expr cpp_type(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::obj::symbol_ref const &sym, + runtime::obj::symbol_ref const sym, jtl::ptr type); void propagate_position(expression_position const pos) override; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/cpp_value.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/cpp_value.hpp index af7b23826..4d0ac8825 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/cpp_value.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/cpp_value.hpp @@ -32,7 +32,7 @@ namespace jank::analyze::expr cpp_value(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::obj::symbol_ref const &sym, + runtime::obj::symbol_ref const sym, jtl::ptr type, jtl::ptr scope, value_kind val_kind); diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/def.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/def.hpp index 19ef19252..251428d1d 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/def.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/def.hpp @@ -20,7 +20,7 @@ namespace jank::analyze::expr def(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::obj::symbol_ref const &name, + runtime::obj::symbol_ref const name, jtl::option const &value); runtime::object_ref to_runtime_data() const override; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp index a4bc74e17..890de0a14 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/function.hpp @@ -61,7 +61,7 @@ namespace jank::analyze::expr jtl::immutable_string const &name, jtl::immutable_string const &unique_name, native_vector &&arities, - runtime::obj::persistent_hash_map_ref const &meta); + runtime::obj::persistent_hash_map_ref const meta); /* Aggregates all `frame->captures` from each arity so that we can know the overall * captures for all arities of this fn. This is necessary for codegen to IR, since we diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/local_reference.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/local_reference.hpp index fc566fa24..b88faa7ab 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/local_reference.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/local_reference.hpp @@ -19,7 +19,7 @@ namespace jank::analyze::expr local_reference(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::obj::symbol_ref const &name, + runtime::obj::symbol_ref const name, local_binding_ptr binding); runtime::object_ref to_runtime_data() const override; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/named_recursion.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/named_recursion.hpp index 7d4726e41..90db262ae 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/named_recursion.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/named_recursion.hpp @@ -19,7 +19,7 @@ namespace jank::analyze::expr local_frame_ptr frame, bool needs_box, recursion_reference &&recursion_ref, - runtime::obj::persistent_list_ref const &args, + runtime::obj::persistent_list_ref const args, native_vector &&arg_exprs); runtime::object_ref to_runtime_data() const override; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/primitive_literal.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/primitive_literal.hpp index 33278f538..b850730c6 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/primitive_literal.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/primitive_literal.hpp @@ -13,7 +13,7 @@ namespace jank::analyze::expr primitive_literal(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::object_ref const &data); + runtime::object_ref const data); runtime::object_ref to_runtime_data() const override; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/recur.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/recur.hpp index 7fb33f729..1e1056754 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/recur.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/recur.hpp @@ -24,7 +24,7 @@ namespace jank::analyze::expr recur(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::obj::persistent_list_ref const &args, + runtime::obj::persistent_list_ref const args, native_vector &&arg_exprs, jtl::option const &loop_target); diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/var_deref.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/var_deref.hpp index 9f5b160fa..ae3656ad3 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/var_deref.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/var_deref.hpp @@ -23,8 +23,8 @@ namespace jank::analyze::expr var_deref(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::obj::symbol_ref const &qualified_name, - runtime::var_ref const &var); + runtime::obj::symbol_ref const qualified_name, + runtime::var_ref const var); runtime::object_ref to_runtime_data() const override; diff --git a/compiler+runtime/include/cpp/jank/analyze/expr/var_ref.hpp b/compiler+runtime/include/cpp/jank/analyze/expr/var_ref.hpp index c75577aa5..4ffcc2dce 100644 --- a/compiler+runtime/include/cpp/jank/analyze/expr/var_ref.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/expr/var_ref.hpp @@ -21,8 +21,8 @@ namespace jank::analyze::expr var_ref(expression_position position, local_frame_ptr frame, bool needs_box, - runtime::obj::symbol_ref const &qualified_name, - runtime::var_ref const &var); + runtime::obj::symbol_ref const qualified_name, + runtime::var_ref const var); runtime::object_ref to_runtime_data() const override; diff --git a/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp b/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp index 0390478b7..c8b16607c 100644 --- a/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/local_frame.hpp @@ -104,17 +104,17 @@ namespace jank::analyze /* This is used to find both captures and regular locals, since it's * impossible to know which one a sym is without finding it. */ - jtl::option find_local_or_capture(runtime::obj::symbol_ref const &sym); + jtl::option find_local_or_capture(runtime::obj::symbol_ref const sym); static void register_captures(binding_find_result const &result); static void register_captures(jtl::ptr frame, named_recursion_find_result const &result); /* This can be used when you have a capture, but you want to trace it back to the * originating local. */ - jtl::option find_originating_local(runtime::obj::symbol_ref const &sym); + jtl::option find_originating_local(runtime::obj::symbol_ref const sym); jtl::option - find_named_recursion(runtime::obj::symbol_ref const &sym); + find_named_recursion(runtime::obj::symbol_ref const sym); static bool within_same_fn(jtl::ptr, jtl::ptr); diff --git a/compiler+runtime/include/cpp/jank/analyze/processor.hpp b/compiler+runtime/include/cpp/jank/analyze/processor.hpp index da3c2480a..71ee1b02b 100644 --- a/compiler+runtime/include/cpp/jank/analyze/processor.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/processor.hpp @@ -49,175 +49,175 @@ namespace jank::analyze expression_result analyze(read::parse::processor::iterator, read::parse::processor::iterator const &); - expression_result analyze(runtime::object_ref const &, expression_position); - expression_result analyze(runtime::object_ref const &, + expression_result analyze(runtime::object_ref const , expression_position); + expression_result analyze(runtime::object_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_call(runtime::obj::persistent_list_ref const &, + expression_result analyze_call(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_def(runtime::obj::persistent_list_ref const &, + expression_result analyze_def(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_symbol(runtime::obj::symbol_ref const &, + expression_result analyze_symbol(runtime::obj::symbol_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_fn(runtime::obj::persistent_list_ref const &, + expression_result analyze_fn(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_recur(runtime::obj::persistent_list_ref const &, + expression_result analyze_recur(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_do(runtime::obj::persistent_list_ref const &, + expression_result analyze_do(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); jtl::result - analyze_fn_arity(runtime::obj::persistent_list_ref const &, + analyze_fn_arity(runtime::obj::persistent_list_ref const , jtl::immutable_string const &name, local_frame_ptr); - expression_result analyze_let(runtime::obj::persistent_list_ref const &, + expression_result analyze_let(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_letfn(runtime::obj::persistent_list_ref const &, + expression_result analyze_letfn(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_loop(runtime::obj::persistent_list_ref const &, + expression_result analyze_loop(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_if(runtime::obj::persistent_list_ref const &, + expression_result analyze_if(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_quote(runtime::obj::persistent_list_ref const &, + expression_result analyze_quote(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_var_call(runtime::obj::persistent_list_ref const &, + expression_result analyze_var_call(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_var_val(runtime::var_ref const &, + expression_result analyze_var_val(runtime::var_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_throw(runtime::obj::persistent_list_ref const &, + expression_result analyze_throw(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_try(runtime::obj::persistent_list_ref const &, + expression_result analyze_try(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_primitive_literal(runtime::object_ref const &, + expression_result analyze_primitive_literal(runtime::object_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_vector(runtime::obj::persistent_vector_ref const &, + expression_result analyze_vector(runtime::obj::persistent_vector_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_map(runtime::object_ref const &, + expression_result analyze_map(runtime::object_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_set(runtime::object_ref const &, + expression_result analyze_set(runtime::object_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_case(runtime::obj::persistent_list_ref const &, + expression_result analyze_case(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_symbol(runtime::obj::symbol_ref const &, + expression_result analyze_cpp_symbol(runtime::obj::symbol_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_call(runtime::obj::persistent_list_ref const &, + expression_result analyze_cpp_call(runtime::obj::persistent_list_ref const , expression_ref, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_raw(runtime::obj::persistent_list_ref const &, + expression_result analyze_cpp_raw(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_literal(runtime::obj::persistent_list_ref const &, + expression_result analyze_cpp_literal(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box, literal_kind kind); - expression_result analyze_cpp_type(runtime::obj::persistent_list_ref const &, + expression_result analyze_cpp_type(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_value(runtime::obj::persistent_list_ref const &, + expression_result analyze_cpp_value(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_cast(runtime::obj::persistent_list_ref const &, + expression_result analyze_cpp_cast(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_box(runtime::obj::persistent_list_ref const &, + expression_result analyze_cpp_box(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_unbox(runtime::obj::persistent_list_ref const &, + expression_result analyze_cpp_unbox(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_new(runtime::obj::persistent_list_ref const &, + expression_result analyze_cpp_new(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_delete(runtime::obj::persistent_list_ref const &, + expression_result analyze_cpp_delete(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_member_access(runtime::obj::persistent_list_ref const &, + expression_result analyze_cpp_member_access(runtime::obj::persistent_list_ref const , expr::cpp_value_ref, local_frame_ptr, expression_position, @@ -225,10 +225,10 @@ namespace jank::analyze bool needs_box); /* Returns whether the form is a special symbol. */ - bool is_special(runtime::object_ref const &form); + bool is_special(runtime::object_ref const form); using special_function_type - = expression_result (processor::*)(runtime::obj::persistent_list_ref const &, + = expression_result (processor::*)(runtime::obj::persistent_list_ref const , local_frame_ptr, expression_position, jtl::option const &, diff --git a/compiler+runtime/include/cpp/jank/analyze/recursive_visitor.hpp b/compiler+runtime/include/cpp/jank/analyze/recursive_visitor.hpp index 1c281afc9..713bbc1c8 100644 --- a/compiler+runtime/include/cpp/jank/analyze/recursive_visitor.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/recursive_visitor.hpp @@ -62,7 +62,7 @@ namespace jank::analyze virtual result_type visit(expr::def const &expr); virtual result_type visit(expr::var_deref const &expr); - virtual result_type visit(expr::var_ref const &expr); + virtual result_type visit(expr::var_ref const expr); virtual result_type visit(expr::call const &expr); virtual result_type visit(expr::primitive_literal const &expr); virtual result_type visit(expr::list const &expr); diff --git a/compiler+runtime/include/cpp/jank/codegen/processor.hpp b/compiler+runtime/include/cpp/jank/codegen/processor.hpp index f54dcf124..972160695 100644 --- a/compiler+runtime/include/cpp/jank/codegen/processor.hpp +++ b/compiler+runtime/include/cpp/jank/codegen/processor.hpp @@ -153,7 +153,6 @@ namespace jank::codegen void build_body(); void build_footer(); jtl::immutable_string expression_str(); - jtl::immutable_string expression_fn_str(); void format_elided_var(jtl::immutable_string const &start, jtl::immutable_string const &end, diff --git a/compiler+runtime/include/cpp/jank/error.hpp b/compiler+runtime/include/cpp/jank/error.hpp index c7fd37d44..949fb64e1 100644 --- a/compiler+runtime/include/cpp/jank/error.hpp +++ b/compiler+runtime/include/cpp/jank/error.hpp @@ -392,17 +392,17 @@ namespace jank::error base(kind k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); base(kind k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion, + runtime::object_ref const expansion, std::unique_ptr trace); base(kind k, jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const ¬e_message, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); base(kind k, read::source const &source, jtl::immutable_string const ¬e_message); base(kind k, jtl::immutable_string const &message, @@ -417,7 +417,7 @@ namespace jank::error jtl::immutable_string const &message, read::source const &source, note const ¬e, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); base(kind k, jtl::immutable_string const &message, read::source const &source, @@ -425,12 +425,12 @@ namespace jank::error base(kind k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion, + runtime::object_ref const expansion, jtl::ref cause); base(kind k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion, + runtime::object_ref const expansion, jtl::ref cause, std::unique_ptr trace); diff --git a/compiler+runtime/include/cpp/jank/error/analyze.hpp b/compiler+runtime/include/cpp/jank/error/analyze.hpp index 33708e3fc..b67323af1 100644 --- a/compiler+runtime/include/cpp/jank/error/analyze.hpp +++ b/compiler+runtime/include/cpp/jank/error/analyze.hpp @@ -11,151 +11,151 @@ namespace jank::error { error_ref analyze_invalid_case(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_def(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_def(jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const ¬e, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_fn(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_fn_parameters(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_fn_parameters(jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const &error_note_message, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_recur_position(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_recur_from_try(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_recur_args(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_let(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_letfn(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_loop(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_if(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_if(jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const &error_note_message, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_quote(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_var_reference(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_throw(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_try(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_try(jtl::immutable_string const &message, read::source const &source, note &&extra, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_unresolved_var(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_unresolved_symbol(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_macro_expansion_exception(std::exception const &e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref const &expansion); - error_ref analyze_macro_expansion_exception(runtime::object_ref const &e, + runtime::object_ref const expansion); + error_ref analyze_macro_expansion_exception(runtime::object_ref const e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_macro_expansion_exception(jtl::immutable_string const &e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_macro_expansion_exception(error_ref e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_conversion(jtl::immutable_string const &message); error_ref analyze_invalid_cpp_operator_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_constructor_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_member_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_capture(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_mismatched_if_types(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_function_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_conversion(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_symbol(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_unresolved_cpp_symbol(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_raw(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_type(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_value(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_cast(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_box(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_unbox(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_new(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_delete(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_invalid_cpp_member_access(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref analyze_known_issue(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref internal_analyze_failure(jtl::immutable_string const &message, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); error_ref internal_analyze_failure(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion); + runtime::object_ref const expansion); } diff --git a/compiler+runtime/include/cpp/jank/hash.hpp b/compiler+runtime/include/cpp/jank/hash.hpp index 46133f98c..452224760 100644 --- a/compiler+runtime/include/cpp/jank/hash.hpp +++ b/compiler+runtime/include/cpp/jank/hash.hpp @@ -38,7 +38,7 @@ namespace jank::hash u32 string(jtl::immutable_string_view const &input); - u32 visit(runtime::oref const &o); + u32 visit(runtime::oref const o); u32 visit(char const ch); u32 ordered(runtime::object const * const sequence); diff --git a/compiler+runtime/include/cpp/jank/read/parse.hpp b/compiler+runtime/include/cpp/jank/read/parse.hpp index 3408623e6..a3e27a54e 100644 --- a/compiler+runtime/include/cpp/jank/read/parse.hpp +++ b/compiler+runtime/include/cpp/jank/read/parse.hpp @@ -100,14 +100,14 @@ namespace jank::read::parse iterator end(); private: - jtl::result syntax_quote(runtime::object_ref const &form); + jtl::result syntax_quote(runtime::object_ref const form); jtl::result - syntax_quote_expand_seq(runtime::object_ref const &seq); + syntax_quote_expand_seq(runtime::object_ref const seq); jtl::result - syntax_quote_expand_set(runtime::object_ref const &seq); + syntax_quote_expand_set(runtime::object_ref const seq); static jtl::result - syntax_quote_flatten_map(runtime::object_ref const &seq); - static bool syntax_quote_is_unquote(runtime::object_ref const &form, bool splice); + syntax_quote_flatten_map(runtime::object_ref const seq); + static bool syntax_quote_is_unquote(runtime::object_ref const form, bool splice); public: lex::processor::iterator token_current, token_end; diff --git a/compiler+runtime/include/cpp/jank/read/reparse.hpp b/compiler+runtime/include/cpp/jank/read/reparse.hpp index ddc49526d..1a791d1cd 100644 --- a/compiler+runtime/include/cpp/jank/read/reparse.hpp +++ b/compiler+runtime/include/cpp/jank/read/reparse.hpp @@ -20,7 +20,7 @@ namespace jank::runtime::obj * to parse the nth form inside that list. That gives us the source for `:foo`. */ namespace jank::read::parse { - source reparse_nth(runtime::obj::persistent_list_ref const &o, usize n); - source reparse_nth(runtime::obj::persistent_vector_ref const &o, usize n); - source reparse_nth(runtime::object_ref const &o, usize n); + source reparse_nth(runtime::obj::persistent_list_ref const o, usize n); + source reparse_nth(runtime::obj::persistent_vector_ref const o, usize n); + source reparse_nth(runtime::object_ref const o, usize n); } diff --git a/compiler+runtime/include/cpp/jank/read/source.hpp b/compiler+runtime/include/cpp/jank/read/source.hpp index f4435d7d6..c1db7d41a 100644 --- a/compiler+runtime/include/cpp/jank/read/source.hpp +++ b/compiler+runtime/include/cpp/jank/read/source.hpp @@ -38,7 +38,7 @@ namespace jank::read jtl::immutable_string const &module, source_position const &start, source_position const &end, - runtime::object_ref const ¯o_expansion); + runtime::object_ref const macro_expansion); source &operator=(source const &rhs) = default; source &operator=(source &&rhs) = default; diff --git a/compiler+runtime/include/cpp/jank/runtime/behavior/callable.hpp b/compiler+runtime/include/cpp/jank/runtime/behavior/callable.hpp index b7784c187..e6dcc6607 100644 --- a/compiler+runtime/include/cpp/jank/runtime/behavior/callable.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/behavior/callable.hpp @@ -21,83 +21,83 @@ namespace jank::runtime * supported arities at compile-time, but that's not always the case in * dynamic code. We may not every know if the source is callable at all, so * codegen will use this suite of fns instead. */ - object_ref dynamic_call(object_ref const &source); - object_ref dynamic_call(object_ref const &source, object_ref const &); - object_ref dynamic_call(object_ref const &source, object_ref const &, object_ref const &); - object_ref dynamic_call(object_ref const &source, - object_ref const &, - object_ref const &, - object_ref const &); - object_ref dynamic_call(object_ref const &source, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &); - object_ref dynamic_call(object_ref const &source, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &); - object_ref dynamic_call(object_ref const &source, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &); - object_ref dynamic_call(object_ref const &source, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &); - object_ref dynamic_call(object_ref const &source, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &); - object_ref dynamic_call(object_ref const &source, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &); - object_ref dynamic_call(object_ref const &source, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &); - object_ref dynamic_call(object_ref const &source, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - obj::persistent_list_ref const &); + object_ref dynamic_call(object_ref const source); + object_ref dynamic_call(object_ref const source, object_ref const ); + object_ref dynamic_call(object_ref const source, object_ref const , object_ref const ); + object_ref dynamic_call(object_ref const source, + object_ref const , + object_ref const , + object_ref const ); + object_ref dynamic_call(object_ref const source, + object_ref const , + object_ref const , + object_ref const , + object_ref const ); + object_ref dynamic_call(object_ref const source, + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ); + object_ref dynamic_call(object_ref const source, + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ); + object_ref dynamic_call(object_ref const source, + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ); + object_ref dynamic_call(object_ref const source, + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ); + object_ref dynamic_call(object_ref const source, + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ); + object_ref dynamic_call(object_ref const source, + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ); + object_ref dynamic_call(object_ref const source, + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + obj::persistent_list_ref const ); - object_ref apply_to(object_ref const &source, object_ref const &args); + object_ref apply_to(object_ref const source, object_ref const args); namespace behavior { @@ -109,56 +109,56 @@ namespace jank::runtime virtual ~callable() = default; virtual object_ref call(); - virtual object_ref call(object_ref const &); - virtual object_ref call(object_ref const &, object_ref const &); - virtual object_ref call(object_ref const &, object_ref const &, object_ref const &); + virtual object_ref call(object_ref const ); + virtual object_ref call(object_ref const , object_ref const ); + virtual object_ref call(object_ref const , object_ref const , object_ref const ); virtual object_ref - call(object_ref const &, object_ref const &, object_ref const &, object_ref const &); - virtual object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &); - virtual object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &); - virtual object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &); - virtual object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &); - virtual object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &); - virtual object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &); + call(object_ref const , object_ref const , object_ref const , object_ref const ); + virtual object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ); + virtual object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ); + virtual object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ); + virtual object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ); + virtual object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ); + virtual object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ); /* Callables need a way to get back to the root object so we can do helpful * error reporting on failed calls. */ diff --git a/compiler+runtime/include/cpp/jank/runtime/behavior/metadatable.hpp b/compiler+runtime/include/cpp/jank/runtime/behavior/metadatable.hpp index 633da4eae..3233abe38 100644 --- a/compiler+runtime/include/cpp/jank/runtime/behavior/metadatable.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/behavior/metadatable.hpp @@ -14,6 +14,6 @@ namespace jank::runtime::behavior namespace detail { - object_ref validate_meta(object_ref const &m); + object_ref validate_meta(object_ref const m); } } diff --git a/compiler+runtime/include/cpp/jank/runtime/context.hpp b/compiler+runtime/include/cpp/jank/runtime/context.hpp index b1253aeb3..eff008e7b 100644 --- a/compiler+runtime/include/cpp/jank/runtime/context.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/context.hpp @@ -45,29 +45,29 @@ namespace jank::runtime context(context &&) noexcept = delete; ns_ref intern_ns(jtl::immutable_string const &); - ns_ref intern_ns(obj::symbol_ref const &); - ns_ref remove_ns(obj::symbol_ref const &); + ns_ref intern_ns(obj::symbol_ref const ); + ns_ref remove_ns(obj::symbol_ref const ); /* Looks up a ns by its symbol. Does not resolve aliases. Does not intern. */ - ns_ref find_ns(obj::symbol_ref const &); + ns_ref find_ns(obj::symbol_ref const ); /* Resolves a symbol which could be an alias to its ns, based on the aliases * in the current ns. Does not intern. */ - ns_ref resolve_ns(obj::symbol_ref const &); + ns_ref resolve_ns(obj::symbol_ref const ); ns_ref current_ns() const; /* Adds the current ns to unqualified symbols and resolves the ns of qualified symbols. * Does not intern. */ - obj::symbol_ref qualify_symbol(obj::symbol_ref const &) const; - jtl::option find_local(obj::symbol_ref const &); + obj::symbol_ref qualify_symbol(obj::symbol_ref const ) const; + jtl::option find_local(obj::symbol_ref const ); - jtl::result intern_var(obj::symbol_ref const &qualified_name); + jtl::result intern_var(obj::symbol_ref const qualified_name); jtl::result intern_var(jtl::immutable_string const &); jtl::result intern_var(jtl::immutable_string const &ns, jtl::immutable_string const &name); - jtl::result intern_owned_var(obj::symbol_ref const &); + jtl::result intern_owned_var(obj::symbol_ref const ); jtl::result intern_owned_var(jtl::immutable_string const &); jtl::result intern_owned_var(jtl::immutable_string const &ns, jtl::immutable_string const &name); - var_ref find_var(obj::symbol_ref const &); + var_ref find_var(obj::symbol_ref const ); var_ref find_var(jtl::immutable_string const &ns, jtl::immutable_string const &name); jtl::result @@ -77,8 +77,8 @@ namespace jank::runtime jtl::result intern_keyword(jtl::immutable_string const &s); - object_ref macroexpand1(object_ref const &o); - object_ref macroexpand(object_ref const &o); + object_ref macroexpand1(object_ref const o); + object_ref macroexpand(object_ref const o); object_ref eval_file(jtl::immutable_string const &path); object_ref eval_string(jtl::immutable_string const &code); @@ -104,7 +104,7 @@ namespace jank::runtime /* Does all the same work as load_module, but also writes compiled files to the file system. */ jtl::result compile_module(jtl::immutable_string const &module); - object_ref eval(object_ref const &o); + object_ref eval(object_ref const o); jtl::string_result write_module(jtl::immutable_string const &module_name, jtl::ref const &module) const; @@ -124,13 +124,13 @@ namespace jank::runtime struct binding_scope { binding_scope(); - binding_scope(obj::persistent_hash_map_ref const &bindings); + binding_scope(obj::persistent_hash_map_ref const bindings); ~binding_scope(); }; jtl::string_result push_thread_bindings(); - jtl::string_result push_thread_bindings(object_ref const &bindings); - jtl::string_result push_thread_bindings(obj::persistent_hash_map_ref const &bindings); + jtl::string_result push_thread_bindings(object_ref const bindings); + jtl::string_result push_thread_bindings(obj::persistent_hash_map_ref const bindings); jtl::string_result pop_thread_bindings(); obj::persistent_hash_map_ref get_thread_bindings() const; jtl::option current_thread_binding_frame(); diff --git a/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp b/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp index 1b8366217..991a2a1ce 100644 --- a/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/convert/builtin.hpp @@ -15,26 +15,12 @@ namespace jank::runtime template <> struct convert { - static object_ref into_object(object_ref const &t) + static object_ref into_object(object_ref const t) { return t; } - static object_ref from_object(object_ref const &t) - { - return t; - } - }; - - template <> - struct convert - { - static weak_object_ref into_object(weak_object_ref const t) - { - return t; - } - - static weak_object_ref from_object(weak_object_ref const t) + static object_ref from_object(object_ref const t) { return t; } @@ -49,7 +35,7 @@ namespace jank::runtime return const_cast(t); } - static object_ref into_object(object_ref const &t) + static object_ref into_object(object_ref const t) { return t.erase(); } @@ -59,7 +45,7 @@ namespace jank::runtime return const_cast(t); } - static object_ref from_object(object_ref const &t) + static object_ref from_object(object_ref const t) { return t.erase(); } @@ -110,7 +96,7 @@ namespace jank::runtime return jank_nil(); } - static void from_object(object_ref const &) + static void from_object(object_ref const) { } }; @@ -123,7 +109,7 @@ namespace jank::runtime return jank_nil(); } - static jtl::nullptr_t from_object(object_ref const &) + static jtl::nullptr_t from_object(object_ref const) { return nullptr; } @@ -137,12 +123,12 @@ namespace jank::runtime return make_box(o); } - static bool from_object(object_ref const &o) + static bool from_object(object_ref const o) { return try_object(o)->data; } - static bool from_object(obj::boolean_ref const &o) + static bool from_object(obj::boolean_ref const o) { return o->data; } @@ -156,12 +142,12 @@ namespace jank::runtime return make_box(o); } - static char from_object(object_ref const &o) + static char from_object(object_ref const o) { return try_object(o)->data[0]; } - static char from_object(obj::character_ref const &o) + static char from_object(obj::character_ref const o) { return o->data[0]; } @@ -176,12 +162,12 @@ namespace jank::runtime return make_box(static_cast(o)); } - static T from_object(object_ref const &o) + static T from_object(object_ref const o) { return try_object(o); } - static T from_object(obj::integer_ref const &o) + static T from_object(obj::integer_ref const o) { return o->data; } @@ -198,12 +184,12 @@ namespace jank::runtime return make_box(static_cast(o)); } - static T from_object(object_ref const &o) + static T from_object(object_ref const o) { return static_cast(try_object(o)->data); } - static T from_object(obj::integer_ref const &o) + static T from_object(obj::integer_ref const o) { return static_cast(o->data); } @@ -218,12 +204,12 @@ namespace jank::runtime return make_box(o); } - static native_big_integer from_object(object_ref const &o) + static native_big_integer from_object(object_ref const o) { return try_object(o)->data; } - static native_big_integer from_object(obj::big_integer_ref const &o) + static native_big_integer from_object(obj::big_integer_ref const o) { return o->data; } @@ -239,12 +225,12 @@ namespace jank::runtime return make_box(static_cast(o)); } - static T from_object(object_ref const &o) + static T from_object(object_ref const o) { return static_cast(try_object(o)->data); } - static T from_object(obj::real_ref const &o) + static T from_object(obj::real_ref const o) { return static_cast(o->data); } @@ -264,12 +250,12 @@ namespace jank::runtime return make_box(o); } - static char const *from_object(object_ref const &o) + static char const *from_object(object_ref const o) { return try_object(o)->data.c_str(); } - static char const *from_object(obj::persistent_string_ref const &o) + static char const *from_object(obj::persistent_string_ref const o) { return o->data.c_str(); } @@ -285,12 +271,12 @@ namespace jank::runtime return make_box(o); } - static T from_object(object_ref const &o) + static T from_object(object_ref const o) { return try_object(o)->data; } - static T from_object(obj::persistent_string_ref const &o) + static T from_object(obj::persistent_string_ref const o) { return o->data; } @@ -312,12 +298,12 @@ namespace jank::runtime return make_box(trans); } - static V from_object(object_ref const &o) + static V from_object(object_ref const o) { return from_object(try_object(o)); } - static V from_object(obj::persistent_vector_ref const &o) + static V from_object(obj::persistent_vector_ref const o) { V ret; for(auto const &e : o->data) diff --git a/compiler+runtime/include/cpp/jank/runtime/convert/function.hpp b/compiler+runtime/include/cpp/jank/runtime/convert/function.hpp index 4c630bf90..adceb7f3e 100644 --- a/compiler+runtime/include/cpp/jank/runtime/convert/function.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/convert/function.hpp @@ -7,14 +7,14 @@ namespace jank::runtime template struct always_object_ref { - using type = object_ref const &; + using type = object_ref const ; }; template auto convert_function(R (* const fn)(Args...)) { if constexpr(std::conjunction_v, - std::is_same...>) + std::is_same...>) { return fn; } diff --git a/compiler+runtime/include/cpp/jank/runtime/core.hpp b/compiler+runtime/include/cpp/jank/runtime/core.hpp index 295b348ab..d8f588494 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core.hpp @@ -12,108 +12,108 @@ namespace jank::runtime { - jtl::immutable_string type(object_ref const &o); - bool is_nil(object_ref const &o); - bool is_true(object_ref const &o); - bool is_false(object_ref const &o); - bool is_some(object_ref const &o); - bool is_string(object_ref const &o); - bool is_char(object_ref const &o); - - bool is_symbol(object_ref const &o); - bool is_simple_symbol(object_ref const &o); - bool is_qualified_symbol(object_ref const &o); - - object_ref to_unqualified_symbol(object_ref const &o); - object_ref to_qualified_symbol(object_ref const &ns, object_ref const &name); - - object_ref print(object_ref const &args); - object_ref println(object_ref const &args); - object_ref pr(object_ref const &args); - object_ref prn(object_ref const &args); - - obj::persistent_string_ref subs(object_ref const &s, object_ref const &start); + jtl::immutable_string type(object_ref const o); + bool is_nil(object_ref const o); + bool is_true(object_ref const o); + bool is_false(object_ref const o); + bool is_some(object_ref const o); + bool is_string(object_ref const o); + bool is_char(object_ref const o); + + bool is_symbol(object_ref const o); + bool is_simple_symbol(object_ref const o); + bool is_qualified_symbol(object_ref const o); + + object_ref to_unqualified_symbol(object_ref const o); + object_ref to_qualified_symbol(object_ref const ns, object_ref const name); + + object_ref print(object_ref const args); + object_ref println(object_ref const args); + object_ref pr(object_ref const args); + object_ref prn(object_ref const args); + + obj::persistent_string_ref subs(object_ref const s, object_ref const start); obj::persistent_string_ref - subs(object_ref const &s, object_ref const &start, object_ref const &end); - i64 first_index_of(object_ref const &s, object_ref const &m); - i64 last_index_of(object_ref const &s, object_ref const &m); - - bool is_named(object_ref const &o); - jtl::immutable_string name(object_ref const &o); - object_ref namespace_(object_ref const &o); - - object_ref keyword(object_ref const &ns, object_ref const &name); - bool is_keyword(object_ref const &o); - bool is_simple_keyword(object_ref const &o); - bool is_qualified_keyword(object_ref const &o); - - bool is_callable(object_ref const &o); - - uhash to_hash(object_ref const &o); - - object_ref macroexpand1(object_ref const &o); - object_ref macroexpand(object_ref const &o); - - object_ref gensym(object_ref const &o); - - object_ref atom(object_ref const &o); - object_ref deref(object_ref const &o); - object_ref swap_atom(object_ref const &atom, object_ref const &fn); - object_ref swap_atom(object_ref const &atom, object_ref const &fn, object_ref const &a1); - object_ref swap_atom(object_ref const &atom, - object_ref const &fn, - object_ref const &a1, - object_ref const &a2); - object_ref swap_atom(object_ref const &atom, - object_ref const &fn, - object_ref const &a1, - object_ref const &a2, - object_ref const &rest); - object_ref swap_vals(object_ref const &atom, object_ref const &fn); - object_ref swap_vals(object_ref const &atom, object_ref const &fn, object_ref const &a1); - object_ref swap_vals(object_ref const &atom, - object_ref const &fn, - object_ref const &a1, - object_ref const &a2); - object_ref swap_vals(object_ref const &atom, - object_ref const &fn, - object_ref const &a1, - object_ref const &a2, - object_ref const &rest); + subs(object_ref const s, object_ref const start, object_ref const end); + i64 first_index_of(object_ref const s, object_ref const m); + i64 last_index_of(object_ref const s, object_ref const m); + + bool is_named(object_ref const o); + jtl::immutable_string name(object_ref const o); + object_ref namespace_(object_ref const o); + + object_ref keyword(object_ref const ns, object_ref const name); + bool is_keyword(object_ref const o); + bool is_simple_keyword(object_ref const o); + bool is_qualified_keyword(object_ref const o); + + bool is_callable(object_ref const o); + + uhash to_hash(object_ref const o); + + object_ref macroexpand1(object_ref const o); + object_ref macroexpand(object_ref const o); + + object_ref gensym(object_ref const o); + + object_ref atom(object_ref const o); + object_ref deref(object_ref const o); + object_ref swap_atom(object_ref const atom, object_ref const fn); + object_ref swap_atom(object_ref const atom, object_ref const fn, object_ref const a1); + object_ref swap_atom(object_ref const atom, + object_ref const fn, + object_ref const a1, + object_ref const a2); + object_ref swap_atom(object_ref const atom, + object_ref const fn, + object_ref const a1, + object_ref const a2, + object_ref const rest); + object_ref swap_vals(object_ref const atom, object_ref const fn); + object_ref swap_vals(object_ref const atom, object_ref const fn, object_ref const a1); + object_ref swap_vals(object_ref const atom, + object_ref const fn, + object_ref const a1, + object_ref const a2); + object_ref swap_vals(object_ref const atom, + object_ref const fn, + object_ref const a1, + object_ref const a2, + object_ref const rest); object_ref - compare_and_set(object_ref const &atom, object_ref const &old_val, object_ref const &new_val); - object_ref reset(object_ref const &atom, object_ref const &new_val); - object_ref reset_vals(object_ref const &atom, object_ref const &new_val); + compare_and_set(object_ref const atom, object_ref const old_val, object_ref const new_val); + object_ref reset(object_ref const atom, object_ref const new_val); + object_ref reset_vals(object_ref const atom, object_ref const new_val); - object_ref volatile_(object_ref const &o); - bool is_volatile(object_ref const &o); - object_ref vswap(object_ref const &v, object_ref const &fn); - object_ref vswap(object_ref const &v, object_ref const &fn, object_ref const &args); - object_ref vreset(object_ref const &v, object_ref const &new_val); + object_ref volatile_(object_ref const o); + bool is_volatile(object_ref const o); + object_ref vswap(object_ref const v, object_ref const fn); + object_ref vswap(object_ref const v, object_ref const fn, object_ref const args); + object_ref vreset(object_ref const v, object_ref const new_val); - void push_thread_bindings(object_ref const &o); + void push_thread_bindings(object_ref const o); void pop_thread_bindings(); object_ref get_thread_bindings(); - object_ref force(object_ref const &o); + object_ref force(object_ref const o); - object_ref tagged_literal(object_ref const &tag, object_ref const &form); - bool is_tagged_literal(object_ref const &o); + object_ref tagged_literal(object_ref const tag, object_ref const form); + bool is_tagged_literal(object_ref const o); - object_ref parse_uuid(object_ref const &o); - bool is_uuid(object_ref const &o); + object_ref parse_uuid(object_ref const o); + bool is_uuid(object_ref const o); object_ref random_uuid(); - bool is_inst(object_ref const &o); - i64 inst_ms(object_ref const &o); + bool is_inst(object_ref const o); + i64 inst_ms(object_ref const o); - object_ref re_pattern(object_ref const &o); - object_ref re_matcher(object_ref const &re, object_ref const &s); - object_ref re_find(object_ref const &m); - object_ref re_groups(object_ref const &m); - object_ref re_matches(object_ref const &re, object_ref const &s); + object_ref re_pattern(object_ref const o); + object_ref re_matcher(object_ref const re, object_ref const s); + object_ref re_find(object_ref const m); + object_ref re_groups(object_ref const m); + object_ref re_matches(object_ref const re, object_ref const s); object_ref smatch_to_vector(std::smatch const &match_results); - object_ref add_watch(object_ref const &reference, object_ref const &key, object_ref const &fn); - object_ref remove_watch(object_ref const &reference, object_ref const &key); + object_ref add_watch(object_ref const reference, object_ref const key, object_ref const fn); + object_ref remove_watch(object_ref const reference, object_ref const key); } diff --git a/compiler+runtime/include/cpp/jank/runtime/core/equal.hpp b/compiler+runtime/include/cpp/jank/runtime/core/equal.hpp index 34bfb71c1..82167351d 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/equal.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/equal.hpp @@ -4,8 +4,8 @@ namespace jank::runtime { - bool equal(char lhs, object_ref const &rhs); - bool equal(object_ref const &lhs, object_ref const &rhs); - i64 compare(object_ref const &, object_ref const &); - bool is_identical(object_ref const &lhs, object_ref const &rhs); + bool equal(char lhs, object_ref const rhs); + bool equal(object_ref const lhs, object_ref const rhs); + i64 compare(object_ref const , object_ref const ); + bool is_identical(object_ref const lhs, object_ref const rhs); } diff --git a/compiler+runtime/include/cpp/jank/runtime/core/math.hpp b/compiler+runtime/include/cpp/jank/runtime/core/math.hpp index ff4bad927..8d7a3f8f2 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/math.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/math.hpp @@ -12,272 +12,272 @@ namespace jank::runtime using big_decimal_ref = oref; } - object_ref add(object_ref const &l, object_ref const &r); - object_ref add(obj::integer_ref const &l, object_ref const &r); - object_ref add(object_ref const &l, obj::integer_ref const &r); - object_ref add(object_ref const &l, obj::ratio_ref const &r); - object_ref add(obj::big_decimal_ref const &l, object_ref const &r); - object_ref add(object_ref const &l, obj::big_decimal_ref const &r); - i64 add(obj::integer_ref const &l, obj::integer_ref const &r); - f64 add(obj::real_ref const &l, obj::real_ref const &r); - object_ref add(obj::real_ref const &l, object_ref const &r); - object_ref add(object_ref const &l, obj::real_ref const &r); - f64 add(obj::real_ref const &l, obj::integer_ref const &r); - f64 add(obj::integer_ref const &l, obj::real_ref const &r); - - object_ref add(object_ref const &l, f64 r); - object_ref add(f64 l, object_ref const &r); + object_ref add(object_ref const l, object_ref const r); + object_ref add(obj::integer_ref const l, object_ref const r); + object_ref add(object_ref const l, obj::integer_ref const r); + object_ref add(object_ref const l, obj::ratio_ref const r); + object_ref add(obj::big_decimal_ref const l, object_ref const r); + object_ref add(object_ref const l, obj::big_decimal_ref const r); + i64 add(obj::integer_ref const l, obj::integer_ref const r); + f64 add(obj::real_ref const l, obj::real_ref const r); + object_ref add(obj::real_ref const l, object_ref const r); + object_ref add(object_ref const l, obj::real_ref const r); + f64 add(obj::real_ref const l, obj::integer_ref const r); + f64 add(obj::integer_ref const l, obj::real_ref const r); + + object_ref add(object_ref const l, f64 r); + object_ref add(f64 l, object_ref const r); f64 add(f64 l, f64 r); f64 add(i64 l, f64 r); f64 add(f64 l, i64 r); - object_ref add(object_ref const &l, i64 r); - object_ref add(i64 l, object_ref const &r); + object_ref add(object_ref const l, i64 r); + object_ref add(i64 l, object_ref const r); i64 add(i64 l, i64 r); - obj::ratio_ref add(obj::ratio_ref const &l, obj::ratio_ref const &r); - object_ref add(obj::ratio_ref const &l, obj::integer_ref const &r); - obj::ratio_ref add(obj::integer_ref const &l, obj::ratio_ref const &r); - - object_ref sub(object_ref const &l, object_ref const &r); - object_ref sub(obj::integer_ref const &l, object_ref const &r); - object_ref sub(object_ref const &l, obj::integer_ref const &r); - object_ref sub(obj::big_decimal_ref const &l, object_ref const &r); - object_ref sub(object_ref const &l, obj::big_decimal_ref const &r); - i64 sub(obj::integer_ref const &l, obj::integer_ref const &r); - f64 sub(obj::real_ref const &l, obj::real_ref const &r); - object_ref sub(obj::real_ref const &l, object_ref const &r); - object_ref sub(object_ref const &l, obj::real_ref const &r); - f64 sub(obj::real_ref const &l, obj::integer_ref const &r); - f64 sub(obj::integer_ref const &l, obj::real_ref const &r); - - object_ref sub(object_ref const &l, f64 r); - object_ref sub(f64 l, object_ref const &r); + obj::ratio_ref add(obj::ratio_ref const l, obj::ratio_ref const r); + object_ref add(obj::ratio_ref const l, obj::integer_ref const r); + obj::ratio_ref add(obj::integer_ref const l, obj::ratio_ref const r); + + object_ref sub(object_ref const l, object_ref const r); + object_ref sub(obj::integer_ref const l, object_ref const r); + object_ref sub(object_ref const l, obj::integer_ref const r); + object_ref sub(obj::big_decimal_ref const l, object_ref const r); + object_ref sub(object_ref const l, obj::big_decimal_ref const r); + i64 sub(obj::integer_ref const l, obj::integer_ref const r); + f64 sub(obj::real_ref const l, obj::real_ref const r); + object_ref sub(obj::real_ref const l, object_ref const r); + object_ref sub(object_ref const l, obj::real_ref const r); + f64 sub(obj::real_ref const l, obj::integer_ref const r); + f64 sub(obj::integer_ref const l, obj::real_ref const r); + + object_ref sub(object_ref const l, f64 r); + object_ref sub(f64 l, object_ref const r); f64 sub(f64 l, f64 r); f64 sub(i64 l, f64 r); f64 sub(f64 l, i64 r); - object_ref sub(object_ref const &l, i64 r); - object_ref sub(i64 l, object_ref const &r); + object_ref sub(object_ref const l, i64 r); + object_ref sub(i64 l, object_ref const r); i64 sub(i64 l, i64 r); - object_ref div(object_ref const &l, object_ref const &r); - object_ref div(obj::integer_ref const &l, object_ref const &r); - object_ref div(object_ref const &l, obj::integer_ref const &r); - object_ref div(obj::big_decimal_ref const &l, object_ref const &r); - object_ref div(object_ref const &l, obj::big_decimal_ref const &r); - i64 div(obj::integer_ref const &l, obj::integer_ref const &r); - f64 div(obj::real_ref const &l, obj::real_ref const &r); - object_ref div(obj::real_ref const &l, object_ref const &r); - object_ref div(object_ref const &l, obj::real_ref const &r); - f64 div(obj::real_ref const &l, obj::integer_ref const &r); - f64 div(obj::integer_ref const &l, obj::real_ref const &r); - - object_ref div(object_ref const &l, f64 r); - object_ref div(f64 l, object_ref const &r); + object_ref div(object_ref const l, object_ref const r); + object_ref div(obj::integer_ref const l, object_ref const r); + object_ref div(object_ref const l, obj::integer_ref const r); + object_ref div(obj::big_decimal_ref const l, object_ref const r); + object_ref div(object_ref const l, obj::big_decimal_ref const r); + i64 div(obj::integer_ref const l, obj::integer_ref const r); + f64 div(obj::real_ref const l, obj::real_ref const r); + object_ref div(obj::real_ref const l, object_ref const r); + object_ref div(object_ref const l, obj::real_ref const r); + f64 div(obj::real_ref const l, obj::integer_ref const r); + f64 div(obj::integer_ref const l, obj::real_ref const r); + + object_ref div(object_ref const l, f64 r); + object_ref div(f64 l, object_ref const r); f64 div(f64 l, f64 r); f64 div(i64 l, f64 r); f64 div(f64 l, i64 r); - object_ref div(object_ref const &l, i64 r); - object_ref div(i64 l, object_ref const &r); + object_ref div(object_ref const l, i64 r); + object_ref div(i64 l, object_ref const r); i64 div(i64 l, i64 r); - object_ref mul(object_ref const &l, object_ref const &r); - object_ref mul(obj::integer_ref const &l, object_ref const &r); - object_ref mul(object_ref const &l, obj::integer_ref const &r); - object_ref mul(obj::big_decimal_ref const &l, object_ref const &r); - object_ref mul(object_ref const &l, obj::big_decimal_ref const &r); - i64 mul(obj::integer_ref const &l, obj::integer_ref const &r); - f64 mul(obj::real_ref const &l, obj::real_ref const &r); - object_ref mul(obj::real_ref const &l, object_ref const &r); - object_ref mul(object_ref const &l, obj::real_ref const &r); - f64 mul(obj::real_ref const &l, obj::integer_ref const &r); - f64 mul(obj::integer_ref const &l, obj::real_ref const &r); - - object_ref mul(object_ref const &l, f64 r); - object_ref mul(f64 l, object_ref const &r); + object_ref mul(object_ref const l, object_ref const r); + object_ref mul(obj::integer_ref const l, object_ref const r); + object_ref mul(object_ref const l, obj::integer_ref const r); + object_ref mul(obj::big_decimal_ref const l, object_ref const r); + object_ref mul(object_ref const l, obj::big_decimal_ref const r); + i64 mul(obj::integer_ref const l, obj::integer_ref const r); + f64 mul(obj::real_ref const l, obj::real_ref const r); + object_ref mul(obj::real_ref const l, object_ref const r); + object_ref mul(object_ref const l, obj::real_ref const r); + f64 mul(obj::real_ref const l, obj::integer_ref const r); + f64 mul(obj::integer_ref const l, obj::real_ref const r); + + object_ref mul(object_ref const l, f64 r); + object_ref mul(f64 l, object_ref const r); f64 mul(f64 l, f64 r); f64 mul(i64 l, f64 r); f64 mul(f64 l, i64 r); - object_ref mul(object_ref const &l, i64 r); - object_ref mul(i64 l, object_ref const &r); + object_ref mul(object_ref const l, i64 r); + object_ref mul(i64 l, object_ref const r); i64 mul(i64 l, i64 r); - bool lt(object_ref const &l, object_ref const &r); - bool lt(obj::integer_ref const &l, object_ref const &r); - bool lt(object_ref const &l, obj::integer_ref const &r); - bool lt(obj::integer_ref const &l, obj::integer_ref const &r); - bool lt(obj::real_ref const &l, obj::real_ref const &r); - bool lt(obj::real_ref const &l, object_ref const &r); - bool lt(object_ref const &l, obj::real_ref const &r); - bool lt(obj::real_ref const &l, obj::integer_ref const &r); - bool lt(obj::integer_ref const &l, obj::real_ref const &r); - - bool lt(object_ref const &l, f64 r); - bool lt(f64 l, object_ref const &r); + bool lt(object_ref const l, object_ref const r); + bool lt(obj::integer_ref const l, object_ref const r); + bool lt(object_ref const l, obj::integer_ref const r); + bool lt(obj::integer_ref const l, obj::integer_ref const r); + bool lt(obj::real_ref const l, obj::real_ref const r); + bool lt(obj::real_ref const l, object_ref const r); + bool lt(object_ref const l, obj::real_ref const r); + bool lt(obj::real_ref const l, obj::integer_ref const r); + bool lt(obj::integer_ref const l, obj::real_ref const r); + + bool lt(object_ref const l, f64 r); + bool lt(f64 l, object_ref const r); bool lt(f64 l, f64 r); bool lt(i64 l, f64 r); bool lt(f64 l, i64 r); - bool lt(object_ref const &l, i64 r); - bool lt(i64 l, object_ref const &r); + bool lt(object_ref const l, i64 r); + bool lt(i64 l, object_ref const r); bool lt(i64 l, i64 r); - bool lte(object_ref const &l, object_ref const &r); - bool lte(obj::integer_ref const &l, object_ref const &r); - bool lte(object_ref const &l, obj::integer_ref const &r); - bool lte(obj::integer_ref const &l, obj::integer_ref const &r); - bool lte(obj::real_ref const &l, obj::real_ref const &r); - bool lte(obj::real_ref const &l, object_ref const &r); - bool lte(object_ref const &l, obj::real_ref const &r); - bool lte(obj::real_ref const &l, obj::integer_ref const &r); - bool lte(obj::integer_ref const &l, obj::real_ref const &r); - - bool lte(object_ref const &l, f64 r); - bool lte(f64 l, object_ref const &r); + bool lte(object_ref const l, object_ref const r); + bool lte(obj::integer_ref const l, object_ref const r); + bool lte(object_ref const l, obj::integer_ref const r); + bool lte(obj::integer_ref const l, obj::integer_ref const r); + bool lte(obj::real_ref const l, obj::real_ref const r); + bool lte(obj::real_ref const l, object_ref const r); + bool lte(object_ref const l, obj::real_ref const r); + bool lte(obj::real_ref const l, obj::integer_ref const r); + bool lte(obj::integer_ref const l, obj::real_ref const r); + + bool lte(object_ref const l, f64 r); + bool lte(f64 l, object_ref const r); bool lte(f64 l, f64 r); bool lte(i64 l, f64 r); bool lte(f64 l, i64 r); - bool lte(object_ref const &l, i64 r); - bool lte(i64 l, object_ref const &r); + bool lte(object_ref const l, i64 r); + bool lte(i64 l, object_ref const r); bool lte(i64 l, i64 r); - object_ref min(object_ref const &l, object_ref const &r); - object_ref min(obj::integer_ref const &l, object_ref const &r); - object_ref min(object_ref const &l, obj::integer_ref const &r); - i64 min(obj::integer_ref const &l, obj::integer_ref const &r); - f64 min(obj::real_ref const &l, obj::real_ref const &r); - f64 min(obj::real_ref const &l, object_ref const &r); - f64 min(object_ref const &l, obj::real_ref const &r); - f64 min(obj::real_ref const &l, obj::integer_ref const &r); - f64 min(obj::integer_ref const &l, obj::real_ref const &r); - - f64 min(object_ref const &l, f64 r); - f64 min(f64 l, object_ref const &r); + object_ref min(object_ref const l, object_ref const r); + object_ref min(obj::integer_ref const l, object_ref const r); + object_ref min(object_ref const l, obj::integer_ref const r); + i64 min(obj::integer_ref const l, obj::integer_ref const r); + f64 min(obj::real_ref const l, obj::real_ref const r); + f64 min(obj::real_ref const l, object_ref const r); + f64 min(object_ref const l, obj::real_ref const r); + f64 min(obj::real_ref const l, obj::integer_ref const r); + f64 min(obj::integer_ref const l, obj::real_ref const r); + + f64 min(object_ref const l, f64 r); + f64 min(f64 l, object_ref const r); f64 min(f64 l, f64 r); f64 min(i64 l, f64 r); f64 min(f64 l, i64 r); - object_ref min(object_ref const &l, i64 r); - object_ref min(i64 l, object_ref const &r); + object_ref min(object_ref const l, i64 r); + object_ref min(i64 l, object_ref const r); i64 min(i64 l, i64 r); - object_ref max(object_ref const &l, object_ref const &r); - object_ref max(obj::integer_ref const &l, object_ref const &r); - object_ref max(object_ref const &l, obj::integer_ref const &r); - i64 max(obj::integer_ref const &l, obj::integer_ref const &r); - f64 max(obj::real_ref const &l, obj::real_ref const &r); - f64 max(obj::real_ref const &l, object_ref const &r); - f64 max(object_ref const &l, obj::real_ref const &r); - f64 max(obj::real_ref const &l, obj::integer_ref const &r); - f64 max(obj::integer_ref const &l, obj::real_ref const &r); - - object_ref max(object_ref const &l, f64 r); - object_ref max(f64 l, object_ref const &r); + object_ref max(object_ref const l, object_ref const r); + object_ref max(obj::integer_ref const l, object_ref const r); + object_ref max(object_ref const l, obj::integer_ref const r); + i64 max(obj::integer_ref const l, obj::integer_ref const r); + f64 max(obj::real_ref const l, obj::real_ref const r); + f64 max(obj::real_ref const l, object_ref const r); + f64 max(object_ref const l, obj::real_ref const r); + f64 max(obj::real_ref const l, obj::integer_ref const r); + f64 max(obj::integer_ref const l, obj::real_ref const r); + + object_ref max(object_ref const l, f64 r); + object_ref max(f64 l, object_ref const r); f64 max(f64 l, f64 r); f64 max(i64 l, f64 r); f64 max(f64 l, i64 r); - object_ref max(object_ref const &l, i64 r); - object_ref max(i64 l, object_ref const &r); + object_ref max(object_ref const l, i64 r); + object_ref max(i64 l, object_ref const r); i64 max(i64 l, i64 r); - object_ref abs(object_ref const &l); - i64 abs(obj::integer_ref const &l); - f64 abs(obj::real_ref const &l); + object_ref abs(object_ref const l); + i64 abs(obj::integer_ref const l); + f64 abs(obj::real_ref const l); i64 abs(i64 l); f64 abs(f64 l); - f64 tan(object_ref const &l); + f64 tan(object_ref const l); - f64 sqrt(object_ref const &l); - f64 sqrt(obj::integer_ref const &l); - f64 sqrt(obj::real_ref const &l); + f64 sqrt(object_ref const l); + f64 sqrt(obj::integer_ref const l); + f64 sqrt(obj::real_ref const l); f64 sqrt(i64 l); f64 sqrt(f64 l); - f64 pow(object_ref const &l, object_ref const &r); - f64 pow(obj::integer_ref const &l, object_ref const &r); - f64 pow(object_ref const &l, obj::integer_ref const &r); - f64 pow(obj::integer_ref const &l, obj::integer_ref const &r); - f64 pow(obj::real_ref const &l, obj::real_ref const &r); - f64 pow(obj::real_ref const &l, object_ref const &r); - f64 pow(object_ref const &l, obj::real_ref const &r); - f64 pow(obj::real_ref const &l, obj::integer_ref const &r); - f64 pow(obj::integer_ref const &l, obj::real_ref const &r); - - object_ref pow(object_ref const &l, f64 r); - object_ref pow(f64 l, object_ref const &r); + f64 pow(object_ref const l, object_ref const r); + f64 pow(obj::integer_ref const l, object_ref const r); + f64 pow(object_ref const l, obj::integer_ref const r); + f64 pow(obj::integer_ref const l, obj::integer_ref const r); + f64 pow(obj::real_ref const l, obj::real_ref const r); + f64 pow(obj::real_ref const l, object_ref const r); + f64 pow(object_ref const l, obj::real_ref const r); + f64 pow(obj::real_ref const l, obj::integer_ref const r); + f64 pow(obj::integer_ref const l, obj::real_ref const r); + + object_ref pow(object_ref const l, f64 r); + object_ref pow(f64 l, object_ref const r); f64 pow(f64 l, f64 r); f64 pow(i64 l, f64 r); f64 pow(f64 l, i64 r); - f64 pow(object_ref const &l, i64 r); - f64 pow(i64 l, object_ref const &r); + f64 pow(object_ref const l, i64 r); + f64 pow(i64 l, object_ref const r); f64 pow(i64 l, i64 r); - object_ref rem(object_ref const &l, object_ref const &r); - object_ref quot(object_ref const &l, object_ref const &r); - object_ref inc(object_ref const &l); - object_ref dec(object_ref const &l); - - bool is_zero(object_ref const &l); - bool is_pos(object_ref const &l); - bool is_neg(object_ref const &l); - bool is_even(object_ref const &l); - bool is_odd(object_ref const &l); - - bool is_equiv(object_ref const &l, object_ref const &r); - - i64 bit_not(object_ref const &l); - i64 bit_and(object_ref const &l, object_ref const &r); - i64 bit_or(object_ref const &l, object_ref const &r); - i64 bit_xor(object_ref const &l, object_ref const &r); - i64 bit_and_not(object_ref const &l, object_ref const &r); - i64 bit_clear(object_ref const &l, object_ref const &r); - i64 bit_set(object_ref const &l, object_ref const &r); - i64 bit_flip(object_ref const &l, object_ref const &r); - bool bit_test(object_ref const &l, object_ref const &r); - i64 bit_shift_left(object_ref const &l, object_ref const &r); - i64 bit_shift_right(object_ref const &l, object_ref const &r); - i64 bit_unsigned_shift_right(object_ref const &l, object_ref const &r); + object_ref rem(object_ref const l, object_ref const r); + object_ref quot(object_ref const l, object_ref const r); + object_ref inc(object_ref const l); + object_ref dec(object_ref const l); + + bool is_zero(object_ref const l); + bool is_pos(object_ref const l); + bool is_neg(object_ref const l); + bool is_even(object_ref const l); + bool is_odd(object_ref const l); + + bool is_equiv(object_ref const l, object_ref const r); + + i64 bit_not(object_ref const l); + i64 bit_and(object_ref const l, object_ref const r); + i64 bit_or(object_ref const l, object_ref const r); + i64 bit_xor(object_ref const l, object_ref const r); + i64 bit_and_not(object_ref const l, object_ref const r); + i64 bit_clear(object_ref const l, object_ref const r); + i64 bit_set(object_ref const l, object_ref const r); + i64 bit_flip(object_ref const l, object_ref const r); + bool bit_test(object_ref const l, object_ref const r); + i64 bit_shift_left(object_ref const l, object_ref const r); + i64 bit_shift_right(object_ref const l, object_ref const r); + i64 bit_unsigned_shift_right(object_ref const l, object_ref const r); f64 rand(); - native_big_integer numerator(object_ref const &o); - native_big_integer denominator(object_ref const &o); + native_big_integer numerator(object_ref const o); + native_big_integer denominator(object_ref const o); - i64 to_int(object_ref const &l); - i64 to_int(obj::integer_ref const &l); - i64 to_int(obj::real_ref const &l); + i64 to_int(object_ref const l); + i64 to_int(obj::integer_ref const l); + i64 to_int(obj::real_ref const l); i64 to_int(i64 l); i64 to_int(f64 l); - f64 to_real(object_ref const &o); + f64 to_real(object_ref const o); - bool is_number(object_ref const &o); - bool is_integer(object_ref const &o); - bool is_real(object_ref const &o); - bool is_ratio(object_ref const &o); - bool is_boolean(object_ref const &o); - bool is_nan(object_ref const &o); - bool is_infinite(object_ref const &o); + bool is_number(object_ref const o); + bool is_integer(object_ref const o); + bool is_real(object_ref const o); + bool is_ratio(object_ref const o); + bool is_boolean(object_ref const o); + bool is_nan(object_ref const o); + bool is_infinite(object_ref const o); - i64 parse_long(object_ref const &o); - f64 parse_double(object_ref const &o); + i64 parse_long(object_ref const o); + f64 parse_double(object_ref const o); - bool is_big_decimal(object_ref const &o); - obj::big_decimal_ref to_big_decimal(object_ref const &o); + bool is_big_decimal(object_ref const o); + obj::big_decimal_ref to_big_decimal(object_ref const o); } diff --git a/compiler+runtime/include/cpp/jank/runtime/core/meta.hpp b/compiler+runtime/include/cpp/jank/runtime/core/meta.hpp index abc403ba9..1481eaf8d 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/meta.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/meta.hpp @@ -12,16 +12,16 @@ namespace jank::runtime using persistent_hash_map_ref = oref; } - object_ref meta(object_ref const &m); - object_ref with_meta(object_ref const &o, object_ref const &m); - object_ref with_meta_graceful(object_ref const &o, object_ref const &m); - object_ref reset_meta(object_ref const &o, object_ref const &m); + object_ref meta(object_ref const m); + object_ref with_meta(object_ref const o, object_ref const m); + object_ref with_meta_graceful(object_ref const o, object_ref const m); + object_ref reset_meta(object_ref const o, object_ref const m); read::source meta_source(jtl::option const &o); - read::source object_source(object_ref const &o); + read::source object_source(object_ref const o); obj::persistent_hash_map_ref source_to_meta(read::source const &source); obj::persistent_hash_map_ref source_to_meta(read::source_position const &start, read::source_position const &end); - object_ref strip_source_from_meta(object_ref const &meta); + object_ref strip_source_from_meta(object_ref const meta); jtl::option strip_source_from_meta_opt(jtl::option const &meta); } diff --git a/compiler+runtime/include/cpp/jank/runtime/core/munge.hpp b/compiler+runtime/include/cpp/jank/runtime/core/munge.hpp index d20123ed9..6f6177e18 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/munge.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/munge.hpp @@ -8,6 +8,6 @@ namespace jank::runtime jtl::immutable_string munge_and_replace(jtl::immutable_string const &o, jtl::immutable_string const &search, char const * const replace); - object_ref munge(object_ref const &o); + object_ref munge(object_ref const o); jtl::immutable_string demunge(jtl::immutable_string const &o); } diff --git a/compiler+runtime/include/cpp/jank/runtime/core/seq.hpp b/compiler+runtime/include/cpp/jank/runtime/core/seq.hpp index 0e8ec1b66..a3bb3a50f 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/seq.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/seq.hpp @@ -19,7 +19,7 @@ namespace jank::runtime return s->seq(); } - object_ref seq(object_ref const &s); + object_ref seq(object_ref const s); template requires behavior::seqable @@ -28,7 +28,7 @@ namespace jank::runtime return s->fresh_seq(); } - object_ref fresh_seq(object_ref const &s); + object_ref fresh_seq(object_ref const s); template requires behavior::sequenceable @@ -37,7 +37,7 @@ namespace jank::runtime return s->next(); } - object_ref next(object_ref const &s); + object_ref next(object_ref const s); template requires behavior::sequenceable_in_place @@ -55,9 +55,9 @@ namespace jank::runtime return s->next(); } - object_ref next_in_place(object_ref const &s); + object_ref next_in_place(object_ref const s); - object_ref rest(object_ref const &s); + object_ref rest(object_ref const s); template requires behavior::sequenceable @@ -66,7 +66,7 @@ namespace jank::runtime return s->first(); } - object_ref first(object_ref const &s); + object_ref first(object_ref const s); template requires behavior::sequenceable @@ -75,96 +75,96 @@ namespace jank::runtime return next(s)->first(); } - object_ref second(object_ref const &s); - - bool is_empty(object_ref const &o); - bool is_seq(object_ref const &o); - bool is_sequential(object_ref const &o); - bool is_seqable(object_ref const &o); - bool is_collection(object_ref const &o); - bool is_list(object_ref const &o); - bool is_vector(object_ref const &o); - bool is_map(object_ref const &o); - bool is_associative(object_ref const &o); - bool is_set(object_ref const &o); - bool is_counted(object_ref const &o); - bool is_transientable(object_ref const &o); - bool is_sorted(object_ref const &o); - - object_ref transient(object_ref const &o); - object_ref persistent(object_ref const &o); - object_ref conj_in_place(object_ref const &coll, object_ref const &o); - object_ref disj_in_place(object_ref const &coll, object_ref const &o); + object_ref second(object_ref const s); + + bool is_empty(object_ref const o); + bool is_seq(object_ref const o); + bool is_sequential(object_ref const o); + bool is_seqable(object_ref const o); + bool is_collection(object_ref const o); + bool is_list(object_ref const o); + bool is_vector(object_ref const o); + bool is_map(object_ref const o); + bool is_associative(object_ref const o); + bool is_set(object_ref const o); + bool is_counted(object_ref const o); + bool is_transientable(object_ref const o); + bool is_sorted(object_ref const o); + + object_ref transient(object_ref const o); + object_ref persistent(object_ref const o); + object_ref conj_in_place(object_ref const coll, object_ref const o); + object_ref disj_in_place(object_ref const coll, object_ref const o); template requires behavior::associatively_writable_in_place - auto assoc_in_place(oref const &m, object_ref const &k, object_ref const &v) + auto assoc_in_place(oref const &m, object_ref const k, object_ref const v) { return m->assoc_in_place(k, v); } - object_ref assoc_in_place(object_ref const &coll, object_ref const &k, object_ref const &v); - object_ref dissoc_in_place(object_ref const &coll, object_ref const &k); - object_ref pop_in_place(object_ref const &coll); + object_ref assoc_in_place(object_ref const coll, object_ref const k, object_ref const v); + object_ref dissoc_in_place(object_ref const coll, object_ref const k); + object_ref pop_in_place(object_ref const coll); - object_ref cons(object_ref const &head, object_ref const &tail); - object_ref conj(object_ref const &s, object_ref const &o); - object_ref disj(object_ref const &s, object_ref const &o); + object_ref cons(object_ref const head, object_ref const tail); + object_ref conj(object_ref const s, object_ref const o); + object_ref disj(object_ref const s, object_ref const o); template requires behavior::associatively_writable - auto assoc(oref const &m, object_ref const &k, object_ref const &v) + auto assoc(oref const &m, object_ref const k, object_ref const v) { return m->assoc(k, v); } - object_ref assoc(object_ref const &m, object_ref const &k, object_ref const &v); - object_ref dissoc(object_ref const &m, object_ref const &k); - object_ref get(object_ref const &m, object_ref const &key); - object_ref get(object_ref const &m, object_ref const &key, object_ref const &fallback); - object_ref get_in(object_ref const &m, object_ref const &keys); - object_ref get_in(object_ref const &m, object_ref const &keys, object_ref const &fallback); - object_ref find(object_ref const &s, object_ref const &key); - bool contains(object_ref const &s, object_ref const &key); - object_ref merge(object_ref const &m, object_ref const &other); - object_ref merge_in_place(object_ref const &m, object_ref const &other); - object_ref subvec(object_ref const &o, i64 start, i64 end); - object_ref nth(object_ref const &o, object_ref const &idx); - object_ref nth(object_ref const &o, object_ref const &idx, object_ref const &fallback); - object_ref peek(object_ref const &o); - object_ref pop(object_ref const &o); - object_ref empty(object_ref const &o); - - jtl::immutable_string str(object_ref const &o); - jtl::immutable_string str(object_ref const &o, object_ref const &args); - - obj::persistent_list_ref list(object_ref const &s); - obj::persistent_vector_ref vec(object_ref const &s); - - bool sequence_equal(object_ref const &l, object_ref const &r); - - usize sequence_length(object_ref const &s); - usize sequence_length(object_ref const &s, usize const max); - - object_ref reduce(object_ref const &f, object_ref const &init, object_ref const &s); - object_ref reduced(object_ref const &o); - bool is_reduced(object_ref const &o); - - object_ref chunk_buffer(object_ref const &capacity); - object_ref chunk_append(object_ref const &buff, object_ref const &val); - object_ref chunk(object_ref const &buff); - object_ref chunk_first(object_ref const &o); - object_ref chunk_next(object_ref const &o); - object_ref chunk_rest(object_ref const &o); - object_ref chunk_cons(object_ref const &chunk, object_ref const &rest); - bool is_chunked_seq(object_ref const &o); - - object_ref iterate(object_ref const &fn, object_ref const &o); - - object_ref repeat(object_ref const &val); - object_ref repeat(object_ref const &n, object_ref const &val); - - object_ref sort(object_ref const &coll); - - object_ref shuffle(object_ref const &coll); + object_ref assoc(object_ref const m, object_ref const k, object_ref const v); + object_ref dissoc(object_ref const m, object_ref const k); + object_ref get(object_ref const m, object_ref const key); + object_ref get(object_ref const m, object_ref const key, object_ref const fallback); + object_ref get_in(object_ref const m, object_ref const keys); + object_ref get_in(object_ref const m, object_ref const keys, object_ref const fallback); + object_ref find(object_ref const s, object_ref const key); + bool contains(object_ref const s, object_ref const key); + object_ref merge(object_ref const m, object_ref const other); + object_ref merge_in_place(object_ref const m, object_ref const other); + object_ref subvec(object_ref const o, i64 start, i64 end); + object_ref nth(object_ref const o, object_ref const idx); + object_ref nth(object_ref const o, object_ref const idx, object_ref const fallback); + object_ref peek(object_ref const o); + object_ref pop(object_ref const o); + object_ref empty(object_ref const o); + + jtl::immutable_string str(object_ref const o); + jtl::immutable_string str(object_ref const o, object_ref const args); + + obj::persistent_list_ref list(object_ref const s); + obj::persistent_vector_ref vec(object_ref const s); + + bool sequence_equal(object_ref const l, object_ref const r); + + usize sequence_length(object_ref const s); + usize sequence_length(object_ref const s, usize const max); + + object_ref reduce(object_ref const f, object_ref const init, object_ref const s); + object_ref reduced(object_ref const o); + bool is_reduced(object_ref const o); + + object_ref chunk_buffer(object_ref const capacity); + object_ref chunk_append(object_ref const buff, object_ref const val); + object_ref chunk(object_ref const buff); + object_ref chunk_first(object_ref const o); + object_ref chunk_next(object_ref const o); + object_ref chunk_rest(object_ref const o); + object_ref chunk_cons(object_ref const chunk, object_ref const rest); + bool is_chunked_seq(object_ref const o); + + object_ref iterate(object_ref const fn, object_ref const o); + + object_ref repeat(object_ref const val); + object_ref repeat(object_ref const n, object_ref const val); + + object_ref sort(object_ref const coll); + + object_ref shuffle(object_ref const coll); } diff --git a/compiler+runtime/include/cpp/jank/runtime/core/seq_ext.hpp b/compiler+runtime/include/cpp/jank/runtime/core/seq_ext.hpp index 89bf6fa78..887e1afe6 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/seq_ext.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/seq_ext.hpp @@ -13,7 +13,7 @@ namespace jank::runtime bool equal(object const &o, It const &begin, It const &end) { return visit_seqable( - [](auto const &typed_o, auto const &begin, auto const &end) -> bool { + [](auto const typed_o, auto const &begin, auto const &end) -> bool { using T = typename jtl::decay_t::value_type; /* nil is seqable, but we don't want it to be equal to an empty collection. diff --git a/compiler+runtime/include/cpp/jank/runtime/core/to_string.hpp b/compiler+runtime/include/cpp/jank/runtime/core/to_string.hpp index 4b8ddba51..a976f2e99 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/to_string.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/to_string.hpp @@ -5,16 +5,16 @@ namespace jank::runtime { - object_ref first(object_ref const &s); - object_ref next(object_ref const &s); + object_ref first(object_ref const s); + object_ref next(object_ref const s); - jtl::immutable_string to_string(weak_object_ref const o); + jtl::immutable_string to_string(object_ref const o); void to_string(char ch, jtl::string_builder &buff); - void to_string(object_ref const &o, jtl::string_builder &buff); + void to_string(object_ref const o, jtl::string_builder &buff); - jtl::immutable_string to_code_string(object_ref const &o); + jtl::immutable_string to_code_string(object_ref const o); void to_code_string(char ch, jtl::string_builder &buff); - void to_code_string(object_ref const &o, jtl::string_builder &buff); + void to_code_string(object_ref const o, jtl::string_builder &buff); template requires(behavior::object_like && !behavior::sequenceable) diff --git a/compiler+runtime/include/cpp/jank/runtime/core/truthy.hpp b/compiler+runtime/include/cpp/jank/runtime/core/truthy.hpp index 0ee4d0e41..f954502ae 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/truthy.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/truthy.hpp @@ -6,9 +6,9 @@ namespace jank::runtime { bool truthy(object const *o); - bool truthy(object_ref const &o); - bool truthy(obj::nil_ref const &); - bool truthy(obj::boolean_ref const &o); + bool truthy(object_ref const o); + bool truthy(obj::nil_ref const ); + bool truthy(obj::boolean_ref const o); bool truthy(bool const o); template diff --git a/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp b/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp index d08e06f09..f9aaaaea6 100644 --- a/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/detail/native_array_map.hpp @@ -37,13 +37,13 @@ namespace jank::runtime::detail ~native_array_map(); - void insert_unique(object_ref const &key, object_ref const &val); + void insert_unique(object_ref const key, object_ref const val); - void insert_or_assign(object_ref const &key, object_ref const &val); + void insert_or_assign(object_ref const key, object_ref const val); - void erase(object_ref const &key); + void erase(object_ref const key); - jtl::option find(object_ref const &key) const; + jtl::option find(object_ref const key) const; uhash to_hash() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/detail/type.hpp b/compiler+runtime/include/cpp/jank/runtime/detail/type.hpp index b22808aa4..a115e6602 100644 --- a/compiler+runtime/include/cpp/jank/runtime/detail/type.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/detail/type.hpp @@ -15,7 +15,7 @@ namespace jank::runtime::detail { struct object_ref_compare { - bool operator()(object_ref const &l, object_ref const &r) const; + bool operator()(object_ref const l, object_ref const r) const; }; } diff --git a/compiler+runtime/include/cpp/jank/runtime/ns.hpp b/compiler+runtime/include/cpp/jank/runtime/ns.hpp index f985f5ce3..94553fcab 100644 --- a/compiler+runtime/include/cpp/jank/runtime/ns.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/ns.hpp @@ -21,21 +21,21 @@ namespace jank::runtime static constexpr bool pointer_free{ false }; ns() = delete; - ns(obj::symbol_ref const &name); + ns(obj::symbol_ref const name); var_ref intern_var(jtl::immutable_string_view const &); - var_ref intern_var(obj::symbol_ref const &); + var_ref intern_var(obj::symbol_ref const ); var_ref intern_owned_var(jtl::immutable_string_view const &); - var_ref intern_owned_var(obj::symbol_ref const &); - var_ref find_var(obj::symbol_ref const &); - jtl::result unmap(obj::symbol_ref const &sym); + var_ref intern_owned_var(obj::symbol_ref const ); + var_ref find_var(obj::symbol_ref const ); + jtl::result unmap(obj::symbol_ref const sym); jtl::result - add_alias(obj::symbol_ref const &sym, ns_ref const &ns); - void remove_alias(obj::symbol_ref const &sym); - ns_ref find_alias(obj::symbol_ref const &sym) const; + add_alias(obj::symbol_ref const sym, ns_ref const ns); + void remove_alias(obj::symbol_ref const sym); + ns_ref find_alias(obj::symbol_ref const sym) const; - jtl::result refer(obj::symbol_ref const &sym, var_ref const &var); + jtl::result refer(obj::symbol_ref const sym, var_ref const var); obj::persistent_hash_map_ref get_mappings() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/array_chunk.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/array_chunk.hpp index 4af7cfd89..9c65eeea9 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/array_chunk.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/array_chunk.hpp @@ -27,8 +27,8 @@ namespace jank::runtime::obj array_chunk_ref chunk_next() const; array_chunk_ref chunk_next_in_place(); usize count() const; - object_ref nth(object_ref const &index) const; - object_ref nth(object_ref const &index, object_ref const &fallback) const; + object_ref nth(object_ref const index) const; + object_ref nth(object_ref const index, object_ref const fallback) const; object base{ obj_type }; native_vector buffer; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp index 7969fd0f1..f084c7d7b 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp @@ -16,8 +16,7 @@ namespace jank::runtime::obj static constexpr bool pointer_free{ false }; atom() = default; - atom(object_ref const &o); - ~atom(); + atom(object_ref const o); /* behavior::object_like */ bool equal(object const &) const; @@ -30,32 +29,32 @@ namespace jank::runtime::obj object_ref deref() const; /* Replaces the old value with the specified value. Returns the new value. */ - object_ref reset(object_ref const &o); + object_ref reset(object_ref const o); /* Same as reset, but returns a vector of the old value and the new value. */ - persistent_vector_ref reset_vals(object_ref const &o); + persistent_vector_ref reset_vals(object_ref const o); /* Atomically updates the value of the atom with the specified fn. Returns the new value. */ - object_ref swap(object_ref const &fn); - object_ref swap(object_ref const &fn, object_ref const &a1); - object_ref swap(object_ref const &fn, object_ref const &a1, object_ref const &a2); + object_ref swap(object_ref const fn); + object_ref swap(object_ref const fn, object_ref const a1); + object_ref swap(object_ref const fn, object_ref const a1, object_ref const a2); object_ref - swap(object_ref const &fn, object_ref const &a1, object_ref const &a2, object_ref const &rest); + swap(object_ref const fn, object_ref const a1, object_ref const a2, object_ref const rest); /* Same as swap, but returns a vector of the old value and the new value. */ - persistent_vector_ref swap_vals(object_ref const &fn); - persistent_vector_ref swap_vals(object_ref const &fn, object_ref const &a1); + persistent_vector_ref swap_vals(object_ref const fn); + persistent_vector_ref swap_vals(object_ref const fn, object_ref const a1); persistent_vector_ref - swap_vals(object_ref const &fn, object_ref const &a1, object_ref const &a2); - persistent_vector_ref swap_vals(object_ref const &fn, - object_ref const &a1, - object_ref const &a2, - object_ref const &rest); + swap_vals(object_ref const fn, object_ref const a1, object_ref const a2); + persistent_vector_ref swap_vals(object_ref const fn, + object_ref const a1, + object_ref const a2, + object_ref const rest); - object_ref compare_and_set(object_ref const &old_val, object_ref const &new_val); + object_ref compare_and_set(object_ref const old_val, object_ref const new_val); /* behavior::ref_like */ - void add_watch(object_ref const &key, object_ref const &fn); - void remove_watch(object_ref const &key); + void add_watch(object_ref const key, object_ref const fn); + void remove_watch(object_ref const key); object base{ obj_type }; /* We have to hold only a raw pointer here, since std::atomic doesn't diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/chunk_buffer.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/chunk_buffer.hpp index 106496bae..d13274750 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/chunk_buffer.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/chunk_buffer.hpp @@ -14,7 +14,7 @@ namespace jank::runtime::obj chunk_buffer() = default; chunk_buffer(usize capacity); - chunk_buffer(object_ref const &capacity); + chunk_buffer(object_ref const capacity); /* behavior::object_like */ bool equal(object const &) const; @@ -26,7 +26,7 @@ namespace jank::runtime::obj /* behavior::countable */ usize count() const; - void append(object_ref const &o); + void append(object_ref const o); obj::array_chunk_ref chunk(); object base{ obj_type }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/chunked_cons.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/chunked_cons.hpp index d033ada83..ab49f1fa5 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/chunked_cons.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/chunked_cons.hpp @@ -18,8 +18,8 @@ namespace jank::runtime::obj chunked_cons() = default; chunked_cons(chunked_cons &&) noexcept = default; chunked_cons(chunked_cons const &) = default; - chunked_cons(object_ref const &head, object_ref const &tail); - chunked_cons(object_ref const &meta, object_ref const &head, object_ref const &tail); + chunked_cons(object_ref const head, object_ref const tail); + chunked_cons(object_ref const meta, object_ref const head, object_ref const tail); /* behavior::object_like */ bool equal(object const &) const; @@ -29,7 +29,7 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - chunked_cons_ref with_meta(object_ref const &m) const; + chunked_cons_ref with_meta(object_ref const m) const; /* behavior::seqable */ chunked_cons_ref seq() const; @@ -38,7 +38,7 @@ namespace jank::runtime::obj /* behavior::sequenceable */ object_ref first() const; object_ref next() const; - obj::cons_ref conj(object_ref const &head) const; + obj::cons_ref conj(object_ref const head) const; /* behavior::sequenceable_in_place */ chunked_cons_ref next_in_place(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/cons.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/cons.hpp index 2fb461bb1..9264f6885 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/cons.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/cons.hpp @@ -17,7 +17,7 @@ namespace jank::runtime::obj cons() = default; cons(cons &&) noexcept = default; cons(cons const &) = default; - cons(object_ref const &head, object_ref const &tail); + cons(object_ref const head, object_ref const tail); /* behavior::object_like */ bool equal(object const &) const; @@ -27,7 +27,7 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - cons_ref with_meta(object_ref const &m) const; + cons_ref with_meta(object_ref const m) const; /* behavior::seqable */ cons_ref seq() const; @@ -38,7 +38,7 @@ namespace jank::runtime::obj object_ref next() const; /* behavior::conjable */ - cons_ref conj(object_ref const &head) const; + cons_ref conj(object_ref const head) const; object base{ obj_type }; object_ref head{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/delay.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/delay.hpp index 2415504b9..e3d93fdb6 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/delay.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/delay.hpp @@ -12,7 +12,7 @@ namespace jank::runtime::obj static constexpr bool pointer_free{ false }; delay() = default; - delay(object_ref const &fn); + delay(object_ref const fn); /* behavior::object_like */ bool equal(object const &) const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map.hpp index 85f55f6c5..0bdcd0b52 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map.hpp @@ -6,14 +6,14 @@ namespace jank::runtime { - bool is_map(object_ref const &o); - bool equal(object_ref const &l, object_ref const &r); - void to_string(object_ref const &o, jtl::string_builder &buff); - void to_code_string(object_ref const &o, jtl::string_builder &buff); + bool is_map(object_ref const o); + bool equal(object_ref const l, object_ref const r); + void to_string(object_ref const o, jtl::string_builder &buff); + void to_code_string(object_ref const o, jtl::string_builder &buff); namespace behavior::detail { - object_ref validate_meta(object_ref const &m); + object_ref validate_meta(object_ref const m); } } @@ -52,10 +52,10 @@ namespace jank::runtime::obj::detail usize count() const; /* behavior::metadatable */ - oref with_meta(object_ref const &m) const; + oref with_meta(object_ref const m) const; /* behavior::conjable */ - object_ref conj(object_ref const &head) const; + object_ref conj(object_ref const head) const; object base{ PT::obj_type }; jtl::option meta; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.hpp index 8f7536efe..b6ba03c67 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.hpp @@ -5,8 +5,8 @@ namespace jank::runtime { - void to_string(object_ref const &o, jtl::string_builder &buff); - void to_code_string(object_ref const &o, jtl::string_builder &buff); + void to_string(object_ref const o, jtl::string_builder &buff); + void to_code_string(object_ref const o, jtl::string_builder &buff); namespace obj { @@ -25,7 +25,7 @@ namespace jank::runtime::obj::detail base_persistent_map_sequence() = default; base_persistent_map_sequence(base_persistent_map_sequence &&) = default; base_persistent_map_sequence(base_persistent_map_sequence const &) = default; - base_persistent_map_sequence(object_ref const &c, IT const &b, IT const &e); + base_persistent_map_sequence(object_ref const c, IT const &b, IT const &e); /* behavior::object_like */ bool equal(object const &o) const; @@ -50,7 +50,7 @@ namespace jank::runtime::obj::detail oref next_in_place(); /* behavior::conjable */ - obj::cons_ref conj(object_ref const &head); + obj::cons_ref conj(object_ref const head); object base{ PT::obj_type }; object_ref coll{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/detail/iterator_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/detail/iterator_sequence.hpp index 63bf373e3..a0672c7ea 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/detail/iterator_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/detail/iterator_sequence.hpp @@ -16,7 +16,7 @@ namespace jank::runtime::obj::detail iterator_sequence() = default; /* NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility) */ - iterator_sequence(object_ref const &c, It const &b, It const &e, usize const s); + iterator_sequence(object_ref const c, It const &b, It const &e, usize const s); /* behavior::object_like */ bool equal(object const &o) const; @@ -41,7 +41,7 @@ namespace jank::runtime::obj::detail oref next_in_place(); /* behavior::conjable */ - obj::cons_ref conj(object_ref const &head); + obj::cons_ref conj(object_ref const head); object_ref coll{}; /* Not default constructible. */ diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/integer_range.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/integer_range.hpp index 0128138c6..13124e0cd 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/integer_range.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/integer_range.hpp @@ -18,20 +18,20 @@ namespace jank::runtime::obj static constexpr bool pointer_free{ false }; static constexpr bool is_sequential{ true }; - using bounds_check_t = bool (*)(integer_ref const &, integer_ref const &); + using bounds_check_t = bool (*)(integer_ref const , integer_ref const ); /* Constructors are only to be used within integer_range.cpp. Prefer integer_range::create. */ integer_range() = default; integer_range(integer_range &&) noexcept = default; integer_range(integer_range const &) = default; - integer_range(integer_ref const &end); - integer_range(integer_ref const &start, obj::integer_ref const &end); - integer_range(integer_ref const &start, - obj::integer_ref const &end, - obj::integer_ref const &step); - integer_range(integer_ref const &start, - integer_ref const &end, - integer_ref const &step, + integer_range(integer_ref const end); + integer_range(integer_ref const start, obj::integer_ref const end); + integer_range(integer_ref const start, + obj::integer_ref const end, + obj::integer_ref const step); + integer_range(integer_ref const start, + integer_ref const end, + integer_ref const step, bounds_check_t bounds_check); //integer_range(integer_ptr start, // integer_ptr end, @@ -40,10 +40,10 @@ namespace jank::runtime::obj // array_chunk_ptr chunk, // integer_range_ptr chunk_next); - static object_ref create(integer_ref const &end); - static object_ref create(integer_ref const &start, obj::integer_ref const &end); + static object_ref create(integer_ref const end); + static object_ref create(integer_ref const start, obj::integer_ref const end); static object_ref - create(integer_ref const &start, obj::integer_ref const &end, obj::integer_ref const &step); + create(integer_ref const start, obj::integer_ref const end, obj::integer_ref const step); /* behavior::object_like */ bool equal(object const &) const; @@ -69,10 +69,10 @@ namespace jank::runtime::obj /* void force_chunk() const; */ /* behavior::conjable */ - cons_ref conj(object_ref const &head) const; + cons_ref conj(object_ref const head) const; /* behavior::metadatable */ - integer_range_ref with_meta(object_ref const &m) const; + integer_range_ref with_meta(object_ref const m) const; /* behavior::countable */ usize count() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/iterator.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/iterator.hpp index 048d25256..857bf0f33 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/iterator.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/iterator.hpp @@ -18,7 +18,7 @@ namespace jank::runtime::obj iterator() = default; iterator(iterator &&) noexcept = default; iterator(iterator const &) = default; - iterator(object_ref const &fn, object_ref const &start); + iterator(object_ref const fn, object_ref const start); /* behavior::object_like */ bool equal(object const &) const; @@ -34,7 +34,7 @@ namespace jank::runtime::obj /* behavior::sequenceable */ object_ref first() const; iterator_ref next() const; - obj::cons_ref conj(object_ref const &head) const; + obj::cons_ref conj(object_ref const head) const; /* behavior::sequenceable_in_place */ iterator_ref next_in_place(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp index 52818d2e8..e07b8e479 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp @@ -16,7 +16,7 @@ namespace jank::runtime::obj jit_closure(jit_closure &&) noexcept = default; jit_closure(jit_closure const &) = default; jit_closure(arity_flag_t arity_flags, void *context); - jit_closure(object_ref const &meta); + jit_closure(object_ref const meta); /* behavior::object_like */ bool equal(object const &) const; @@ -26,60 +26,60 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - jit_closure_ref with_meta(object_ref const &m); + jit_closure_ref with_meta(object_ref const m); /* behavior::callable */ object_ref call() final; - object_ref call(object_ref const &) final; - object_ref call(object_ref const &, object_ref const &) final; - object_ref call(object_ref const &, object_ref const &, object_ref const &) final; + object_ref call(object_ref const ) final; + object_ref call(object_ref const , object_ref const ) final; + object_ref call(object_ref const , object_ref const , object_ref const ) final; object_ref - call(object_ref const &, object_ref const &, object_ref const &, object_ref const &) final; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) final; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) final; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) final; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) final; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) final; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) final; + call(object_ref const , object_ref const , object_ref const , object_ref const ) final; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) final; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) final; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) final; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) final; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) final; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) final; arity_flag_t get_arity_flags() const final; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp index 9773e80c2..1e5399dbc 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp @@ -16,7 +16,7 @@ namespace jank::runtime::obj jit_function(jit_function &&) noexcept = default; jit_function(jit_function const &) = default; jit_function(arity_flag_t arity_flags); - jit_function(object_ref const &meta); + jit_function(object_ref const meta); /* behavior::object_like */ bool equal(object const &) const; @@ -26,60 +26,60 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - jit_function_ref with_meta(object_ref const &m); + jit_function_ref with_meta(object_ref const m); /* behavior::callable */ object_ref call() override; - object_ref call(object_ref const &) override; - object_ref call(object_ref const &, object_ref const &) override; - object_ref call(object_ref const &, object_ref const &, object_ref const &) override; + object_ref call(object_ref const ) override; + object_ref call(object_ref const , object_ref const ) override; + object_ref call(object_ref const , object_ref const , object_ref const ) override; object_ref - call(object_ref const &, object_ref const &, object_ref const &, object_ref const &) override; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) override; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) override; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) override; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) override; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) override; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) override; + call(object_ref const , object_ref const , object_ref const , object_ref const ) override; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) override; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) override; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) override; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) override; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) override; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) override; arity_flag_t get_arity_flags() const override; object_ref this_object_ref() override; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp index ebfc65eef..57be5a60f 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp @@ -40,8 +40,8 @@ namespace jank::runtime::obj jtl::immutable_string const &get_namespace() const; /* behavior::callable */ - object_ref call(object_ref const &); - object_ref call(object_ref const &, object_ref const &); + object_ref call(object_ref const ); + object_ref call(object_ref const , object_ref const ); bool operator==(keyword const &rhs) const; @@ -58,7 +58,7 @@ namespace std template <> struct hash { - size_t operator()(jank::runtime::obj::keyword_ref const &o) const noexcept + size_t operator()(jank::runtime::obj::keyword_ref const o) const noexcept { return o->to_hash(); } @@ -77,8 +77,8 @@ namespace std template <> struct equal_to { - bool operator()(jank::runtime::obj::keyword_ref const &lhs, - jank::runtime::obj::keyword_ref const &rhs) const noexcept + bool operator()(jank::runtime::obj::keyword_ref const lhs, + jank::runtime::obj::keyword_ref const rhs) const noexcept { return lhs == rhs; } diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/lazy_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/lazy_sequence.hpp index 4172b6da1..ed1ff4483 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/lazy_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/lazy_sequence.hpp @@ -20,8 +20,8 @@ namespace jank::runtime::obj lazy_sequence() = default; lazy_sequence(lazy_sequence &&) noexcept = default; lazy_sequence(lazy_sequence const &) = default; - lazy_sequence(object_ref const &fn); - lazy_sequence(object_ref const &fn, object_ref const &sequence); + lazy_sequence(object_ref const fn); + lazy_sequence(object_ref const fn, object_ref const sequence); /* behavior::object_like */ bool equal(object const &) const; @@ -37,13 +37,13 @@ namespace jank::runtime::obj /* behavior::sequenceable */ object_ref first() const; object_ref next() const; - obj::cons_ref conj(object_ref const &head) const; + obj::cons_ref conj(object_ref const head) const; /* behavior::sequenceable_in_place */ //lazy_sequence_ref next_in_place(); /* behavior::metadatable */ - lazy_sequence_ref with_meta(object_ref const &m) const; + lazy_sequence_ref with_meta(object_ref const m) const; private: object_ref resolve_fn() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp index 3f4de87c2..d603427e0 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp @@ -17,10 +17,10 @@ namespace jank::runtime::obj static constexpr bool pointer_free{ false }; multi_function() = delete; - multi_function(object_ref const &name, - object_ref const &dispatch, - object_ref const &default_, - object_ref const &hierarchy); + multi_function(object_ref const name, + object_ref const dispatch, + object_ref const default_, + object_ref const hierarchy); /* behavior::object_like */ bool equal(object const &) const; @@ -31,71 +31,71 @@ namespace jank::runtime::obj /* behavior::callable */ object_ref call() override; - object_ref call(object_ref const &) override; - object_ref call(object_ref const &, object_ref const &) override; - object_ref call(object_ref const &, object_ref const &, object_ref const &) override; + object_ref call(object_ref const ) override; + object_ref call(object_ref const , object_ref const ) override; + object_ref call(object_ref const , object_ref const , object_ref const ) override; object_ref - call(object_ref const &, object_ref const &, object_ref const &, object_ref const &) override; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) override; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) override; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) override; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) override; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) override; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) override; + call(object_ref const , object_ref const , object_ref const , object_ref const ) override; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) override; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) override; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) override; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) override; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) override; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) override; object_ref this_object_ref() final; multi_function_ref reset(); persistent_hash_map_ref reset_cache(); - multi_function_ref add_method(object_ref const &dispatch_val, object_ref const &method); - multi_function_ref remove_method(object_ref const &dispatch_val); - multi_function_ref prefer_method(object_ref const &x, object_ref const &y); - bool is_preferred(object_ref const &hierarchy, object_ref const &x, object_ref const &y) const; + multi_function_ref add_method(object_ref const dispatch_val, object_ref const method); + multi_function_ref remove_method(object_ref const dispatch_val); + multi_function_ref prefer_method(object_ref const x, object_ref const y); + bool is_preferred(object_ref const hierarchy, object_ref const x, object_ref const y) const; - static bool is_a(object_ref const &hierarchy, object_ref const &x, object_ref const &y); - bool is_dominant(object_ref const &hierarchy, object_ref const &x, object_ref const &y) const; + static bool is_a(object_ref const hierarchy, object_ref const x, object_ref const y); + bool is_dominant(object_ref const hierarchy, object_ref const x, object_ref const y) const; - object_ref get_fn(object_ref const &dispatch_val); - object_ref get_method(object_ref const &dispatch_val); - object_ref find_and_cache_best_method(object_ref const &dispatch_val); + object_ref get_fn(object_ref const dispatch_val); + object_ref get_method(object_ref const dispatch_val); + object_ref find_and_cache_best_method(object_ref const dispatch_val); object base{ obj_type }; object_ref dispatch{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/native_array_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/native_array_sequence.hpp index f361fdd82..77e74a519 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/native_array_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/native_array_sequence.hpp @@ -20,7 +20,7 @@ namespace jank::runtime::obj native_array_sequence(object_ref * const arr, usize const index, usize const size); template - native_array_sequence(object_ref const &first, Args const &...rest) + native_array_sequence(object_ref const first, Args const &...rest) : arr{ make_array_box(first, rest...) } , size{ sizeof...(Args) + 1 } { @@ -43,7 +43,7 @@ namespace jank::runtime::obj /* behavior::sequence */ object_ref first() const; native_array_sequence_ref next() const; - obj::cons_ref conj(object_ref const &head); + obj::cons_ref conj(object_ref const head); /* behavior::sequenceable_in_place */ native_array_sequence_ref next_in_place(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp index 0396ee185..25afe1da8 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp @@ -84,61 +84,61 @@ namespace jank::runtime /* behavior::callable */ object_ref call() final; - object_ref call(object_ref const &) final; - object_ref call(object_ref const &, object_ref const &) final; - object_ref call(object_ref const &, object_ref const &, object_ref const &) final; + object_ref call(object_ref const ) final; + object_ref call(object_ref const , object_ref const ) final; + object_ref call(object_ref const , object_ref const , object_ref const ) final; object_ref - call(object_ref const &, object_ref const &, object_ref const &, object_ref const &) final; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) final; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) final; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) final; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) final; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) final; - object_ref call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) final; + call(object_ref const , object_ref const , object_ref const , object_ref const ) final; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) final; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) final; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) final; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) final; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) final; + object_ref call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) final; object_ref this_object_ref() final; /* behavior::metadatable */ - native_function_wrapper_ref with_meta(object_ref const &m) const; + native_function_wrapper_ref with_meta(object_ref const m) const; object base{ obj_type }; obj::detail::function_type data{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/native_vector_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/native_vector_sequence.hpp index 75c6e55d3..14ecdafcd 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/native_vector_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/native_vector_sequence.hpp @@ -40,13 +40,13 @@ namespace jank::runtime::obj /* behavior::sequence */ object_ref first() const; native_vector_sequence_ref next() const; - obj::cons_ref conj(object_ref const &head); + obj::cons_ref conj(object_ref const head); /* behavior::sequenceable_in_place */ native_vector_sequence_ref next_in_place(); /* behavior::metadatable */ - native_vector_sequence_ref with_meta(object_ref const &m) const; + native_vector_sequence_ref with_meta(object_ref const m) const; object base{ obj_type }; native_vector data{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp index f74e23e1e..5f5c727c4 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/nil.hpp @@ -7,7 +7,6 @@ namespace jank::runtime::obj using persistent_array_map_ref = oref; using cons_ref = oref; using nil_ref = oref; - using weak_nil_ref = weak_oref; struct nil { @@ -30,14 +29,14 @@ namespace jank::runtime::obj i64 compare(nil const &) const; /* behavior::associatively_readable */ - object_ref get(object_ref const &key); - object_ref get(object_ref const &key, object_ref const &fallback); - object_ref get_entry(object_ref const &key); - bool contains(object_ref const &key) const; + object_ref get(object_ref const key); + object_ref get(object_ref const key, object_ref const fallback); + object_ref get_entry(object_ref const key); + bool contains(object_ref const key) const; /* behavior::associatively_writable */ - obj::persistent_array_map_ref assoc(object_ref const &key, object_ref const &val) const; - nil_ref dissoc(object_ref const &key) const; + obj::persistent_array_map_ref assoc(object_ref const key, object_ref const val) const; + nil_ref dissoc(object_ref const key) const; /* behavior::seqable */ nil_ref seq(); @@ -59,5 +58,5 @@ namespace jank::runtime bool operator==(object *, obj::nil_ref); bool operator!=(object *, obj::nil_ref); - obj::weak_nil_ref jank_nil(); + obj::nil_ref jank_nil(); } diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/opaque_box.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/opaque_box.hpp index 2a324bfc1..2c1ddc4ad 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/opaque_box.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/opaque_box.hpp @@ -23,7 +23,7 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - opaque_box_ref with_meta(object_ref const &m); + opaque_box_ref with_meta(object_ref const m); object base{ obj_type }; jtl::ptr data{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_array_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_array_map.hpp index 12117b247..05acb123b 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_array_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_array_map.hpp @@ -36,7 +36,7 @@ namespace jank::runtime::obj } template - persistent_array_map(object_ref const &meta, runtime::detail::in_place_unique, Args &&...args) + persistent_array_map(object_ref const meta, runtime::detail::in_place_unique, Args &&...args) : data{ runtime::detail::in_place_unique{}, std::forward(args)... } { this->meta = meta; @@ -59,7 +59,7 @@ namespace jank::runtime::obj } template - static persistent_array_map_ref create_unique_with_meta(object_ref const &meta, Args &&...args) + static persistent_array_map_ref create_unique_with_meta(object_ref const meta, Args &&...args) { return make_box(meta, runtime::detail::in_place_unique{}, @@ -68,18 +68,18 @@ namespace jank::runtime::obj } /* behavior::associatively_readable */ - object_ref get(object_ref const &key) const; - object_ref get(object_ref const &key, object_ref const &fallback) const; - object_ref get_entry(object_ref const &key) const; - bool contains(object_ref const &key) const; + object_ref get(object_ref const key) const; + object_ref get(object_ref const key, object_ref const fallback) const; + object_ref get_entry(object_ref const key) const; + bool contains(object_ref const key) const; /* behavior::associatively_writable */ - object_ref assoc(object_ref const &key, object_ref const &val) const; - persistent_array_map_ref dissoc(object_ref const &key) const; + object_ref assoc(object_ref const key, object_ref const val) const; + persistent_array_map_ref dissoc(object_ref const key) const; /* behavior::callable */ - object_ref call(object_ref const &) const; - object_ref call(object_ref const &, object_ref const &) const; + object_ref call(object_ref const ) const; + object_ref call(object_ref const , object_ref const ) const; /* behavior::transientable */ transient_array_map_ref to_transient() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp index e1e8ba2fd..5a91e40b5 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_map.hpp @@ -10,7 +10,6 @@ namespace jank::runtime::obj using persistent_array_map_ref = oref; using transient_hash_map_ref = oref; using persistent_hash_map_ref = oref; - using weak_persistent_hash_map_ref = weak_oref; struct persistent_hash_map : obj::detail::base_persistent_map const &meta, runtime::detail::native_array_map const &m, - object_ref const &key, - object_ref const &val); + object_ref const key, + object_ref const val); persistent_hash_map(value_type &&d); persistent_hash_map(value_type const &d); persistent_hash_map(jtl::option const &meta, value_type &&d); @@ -43,7 +42,7 @@ namespace jank::runtime::obj } template - persistent_hash_map(object_ref const &meta, runtime::detail::in_place_unique, Args &&...args) + persistent_hash_map(object_ref const meta, runtime::detail::in_place_unique, Args &&...args) : data{ std::forward(args)... } { this->meta = meta; @@ -61,28 +60,28 @@ namespace jank::runtime::obj } template - static persistent_hash_map_ref create_unique_with_meta(object_ref const &meta, Args &&...pairs) + static persistent_hash_map_ref create_unique_with_meta(object_ref const meta, Args &&...pairs) { return make_box(meta, runtime::detail::in_place_unique{}, std::forward(pairs)...); } - static persistent_hash_map_ref create_from_seq(object_ref const &seq); + static persistent_hash_map_ref create_from_seq(object_ref const seq); /* behavior::associatively_readable */ - object_ref get(object_ref const &key) const; - object_ref get(object_ref const &key, object_ref const &fallback) const; - object_ref get_entry(object_ref const &key) const; - bool contains(object_ref const &key) const; + object_ref get(object_ref const key) const; + object_ref get(object_ref const key, object_ref const fallback) const; + object_ref get_entry(object_ref const key) const; + bool contains(object_ref const key) const; /* behavior::associatively_writable */ - persistent_hash_map_ref assoc(object_ref const &key, object_ref const &val) const; - persistent_hash_map_ref dissoc(object_ref const &key) const; + persistent_hash_map_ref assoc(object_ref const key, object_ref const val) const; + persistent_hash_map_ref dissoc(object_ref const key) const; /* behavior::callable */ - object_ref call(object_ref const &) const; - object_ref call(object_ref const &, object_ref const &) const; + object_ref call(object_ref const) const; + object_ref call(object_ref const, object_ref const) const; /* behavior::transientable */ obj::transient_hash_map_ref to_transient() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp index b5c3c82f1..2c9fbaec5 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp @@ -31,7 +31,7 @@ namespace jank::runtime::obj } template - persistent_hash_set(object_ref const &meta, std::in_place_t, Args &&...args) + persistent_hash_set(object_ref const meta, std::in_place_t, Args &&...args) : data{ std::forward(args)... } , meta{ meta } { @@ -39,7 +39,7 @@ namespace jank::runtime::obj static persistent_hash_set_ref empty(); - static persistent_hash_set_ref create_from_seq(object_ref const &seq); + static persistent_hash_set_ref create_from_seq(object_ref const seq); /* behavior::object_like */ bool equal(object const &) const; @@ -49,7 +49,7 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - persistent_hash_set_ref with_meta(object_ref const &m) const; + persistent_hash_set_ref with_meta(object_ref const m) const; /* behavior::seqable */ obj::persistent_hash_set_sequence_ref seq() const; @@ -59,16 +59,16 @@ namespace jank::runtime::obj usize count() const; /* behavior::conjable */ - persistent_hash_set_ref conj(object_ref const &head) const; + persistent_hash_set_ref conj(object_ref const head) const; /* behavior::callable */ - object_ref call(object_ref const &) const; + object_ref call(object_ref const ) const; /* behavior::transientable */ obj::transient_hash_set_ref to_transient() const; - bool contains(object_ref const &o) const; - persistent_hash_set_ref disj(object_ref const &o) const; + bool contains(object_ref const o) const; + persistent_hash_set_ref disj(object_ref const o) const; object base{ obj_type }; value_type data; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_list.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_list.hpp index 96bb4d599..1719decae 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_list.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_list.hpp @@ -17,10 +17,10 @@ namespace jank::runtime::obj static constexpr bool is_sequential{ true }; /* Create from a sequence. */ - static persistent_list_ref create(object_ref const &meta, object_ref const &s); - static persistent_list_ref create(object_ref const &s); - static persistent_list_ref create(persistent_list_ref const &s); - static persistent_list_ref create(nil_ref const &s); + static persistent_list_ref create(object_ref const meta, object_ref const s); + static persistent_list_ref create(object_ref const s); + static persistent_list_ref create(persistent_list_ref const s); + static persistent_list_ref create(nil_ref const s); persistent_list() = default; persistent_list(persistent_list &&) noexcept = default; @@ -37,7 +37,7 @@ namespace jank::runtime::obj } template - persistent_list(object_ref const &meta, std::in_place_t, Args &&...args) + persistent_list(object_ref const meta, std::in_place_t, Args &&...args) : data{ std::forward(args)... } , meta{ meta } { @@ -57,7 +57,7 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - persistent_list_ref with_meta(object_ref const &m) const; + persistent_list_ref with_meta(object_ref const m) const; /* behavior::seqable */ obj::persistent_list_ref seq() const; @@ -67,7 +67,7 @@ namespace jank::runtime::obj usize count() const; /* behavior::conjable */ - persistent_list_ref conj(object_ref const &head) const; + persistent_list_ref conj(object_ref const head) const; /* behavior::sequenceable */ object_ref first() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_map.hpp index 5df60095e..5b20feb63 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_map.hpp @@ -28,7 +28,7 @@ namespace jank::runtime::obj persistent_sorted_map(persistent_sorted_map const &) = default; persistent_sorted_map(value_type &&d); persistent_sorted_map(value_type const &d); - persistent_sorted_map(object_ref const &meta, value_type &&d); + persistent_sorted_map(object_ref const meta, value_type &&d); persistent_sorted_map(jtl::option const &meta, value_type &&d); template @@ -38,7 +38,7 @@ namespace jank::runtime::obj } template - persistent_sorted_map(object_ref const &meta, runtime::detail::in_place_unique, Args &&...args) + persistent_sorted_map(object_ref const meta, runtime::detail::in_place_unique, Args &&...args) : data{ std::forward(args)... } { this->meta = meta; @@ -57,28 +57,28 @@ namespace jank::runtime::obj template static persistent_sorted_map_ref - create_unique_with_meta(object_ref const &meta, Args &&...pairs) + create_unique_with_meta(object_ref const meta, Args &&...pairs) { return make_box(meta, runtime::detail::in_place_unique{}, std::forward(pairs)...); } - static persistent_sorted_map_ref create_from_seq(object_ref const &seq); + static persistent_sorted_map_ref create_from_seq(object_ref const seq); /* behavior::associatively_readable */ - object_ref get(object_ref const &key) const; - object_ref get(object_ref const &key, object_ref const &fallback) const; - object_ref get_entry(object_ref const &key) const; - bool contains(object_ref const &key) const; + object_ref get(object_ref const key) const; + object_ref get(object_ref const key, object_ref const fallback) const; + object_ref get_entry(object_ref const key) const; + bool contains(object_ref const key) const; /* behavior::associatively_writable */ - persistent_sorted_map_ref assoc(object_ref const &key, object_ref const &val) const; - persistent_sorted_map_ref dissoc(object_ref const &key) const; + persistent_sorted_map_ref assoc(object_ref const key, object_ref const val) const; + persistent_sorted_map_ref dissoc(object_ref const key) const; /* behavior::callable */ - object_ref call(object_ref const &) const; - object_ref call(object_ref const &, object_ref const &) const; + object_ref call(object_ref const ) const; + object_ref call(object_ref const , object_ref const ) const; /* behavior::transientable */ obj::transient_sorted_map_ref to_transient() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp index 2992e1ca8..f44ff943d 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp @@ -22,7 +22,7 @@ namespace jank::runtime::obj persistent_sorted_set(persistent_sorted_set const &) = default; persistent_sorted_set(value_type &&d); persistent_sorted_set(value_type const &d); - persistent_sorted_set(object_ref const &meta, value_type &&d); + persistent_sorted_set(object_ref const meta, value_type &&d); persistent_sorted_set(jtl::option const &meta, value_type &&d); template @@ -32,14 +32,14 @@ namespace jank::runtime::obj } template - persistent_sorted_set(object_ref const &meta, std::in_place_t, Args &&...args) + persistent_sorted_set(object_ref const meta, std::in_place_t, Args &&...args) : data{ std::forward(args)... } , meta{ meta } { } static persistent_sorted_set_ref empty(); - static persistent_sorted_set_ref create_from_seq(object_ref const &seq); + static persistent_sorted_set_ref create_from_seq(object_ref const seq); /* behavior::object_like */ bool equal(object const &) const; @@ -49,7 +49,7 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::metadatable */ - persistent_sorted_set_ref with_meta(object_ref const &m) const; + persistent_sorted_set_ref with_meta(object_ref const m) const; /* behavior::seqable */ persistent_sorted_set_sequence_ref seq() const; @@ -59,16 +59,16 @@ namespace jank::runtime::obj usize count() const; /* behavior::conjable */ - persistent_sorted_set_ref conj(object_ref const &head) const; + persistent_sorted_set_ref conj(object_ref const head) const; /* behavior::callable */ - object_ref call(object_ref const &); + object_ref call(object_ref const ); /* behavior::transientable */ obj::transient_sorted_set_ref to_transient() const; - bool contains(object_ref const &o) const; - persistent_sorted_set_ref disj(object_ref const &o) const; + bool contains(object_ref const o) const; + persistent_sorted_set_ref disj(object_ref const o) const; object base{ obj_type }; value_type data; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string.hpp index 003ee7ad1..3068d3a49 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string.hpp @@ -40,22 +40,22 @@ namespace jank::runtime::obj i64 compare(persistent_string const &) const; /* behavior::associatively_readable */ - object_ref get(object_ref const &key) const; - object_ref get(object_ref const &key, object_ref const &fallback) const; - object_ref get_entry(object_ref const &key) const; - bool contains(object_ref const &key) const; + object_ref get(object_ref const key) const; + object_ref get(object_ref const key, object_ref const fallback) const; + object_ref get_entry(object_ref const key) const; + bool contains(object_ref const key) const; /* behavior::indexable */ - object_ref nth(object_ref const &index) const; - object_ref nth(object_ref const &index, object_ref const &fallback) const; + object_ref nth(object_ref const index) const; + object_ref nth(object_ref const index, object_ref const fallback) const; jtl::string_result substring(i64 start) const; jtl::string_result substring(i64 start, i64 end) const; /* Returns -1 when not found. Turns the arg into a string, so it accepts anything. * Searches for the whole string, not just a char. */ - i64 first_index_of(object_ref const &m) const; - i64 last_index_of(object_ref const &m) const; + i64 first_index_of(object_ref const m) const; + i64 last_index_of(object_ref const m) const; /* behavior::countable */ usize count() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string_sequence.hpp index 9ae98c584..f2644a494 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_string_sequence.hpp @@ -17,8 +17,8 @@ namespace jank::runtime::obj persistent_string_sequence() = default; persistent_string_sequence(persistent_string_sequence &&) noexcept = default; persistent_string_sequence(persistent_string_sequence const &) = default; - persistent_string_sequence(obj::persistent_string_ref const &s); - persistent_string_sequence(obj::persistent_string_ref const &s, usize const i); + persistent_string_sequence(obj::persistent_string_ref const s); + persistent_string_sequence(obj::persistent_string_ref const s, usize const i); /* behavior::object_like */ bool equal(object const &) const; @@ -37,7 +37,7 @@ namespace jank::runtime::obj /* behavior::sequenceable */ object_ref first() const; persistent_string_sequence_ref next() const; - obj::cons_ref conj(object_ref const &head); + obj::cons_ref conj(object_ref const head); /* behavior::sequenceable_in_place */ persistent_string_sequence_ref next_in_place(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp index 049eb089d..5a35f3992 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp @@ -32,13 +32,13 @@ namespace jank::runtime::obj } template - persistent_vector(object_ref const &meta, std::in_place_t, Args &&...args) + persistent_vector(object_ref const meta, std::in_place_t, Args &&...args) : data{ std::forward(args)... } , meta{ meta } { } - static persistent_vector_ref create(object_ref const &s); + static persistent_vector_ref create(object_ref const s); static persistent_vector_ref empty(); @@ -56,7 +56,7 @@ namespace jank::runtime::obj i64 compare(persistent_vector const &) const; /* behavior::metadatable */ - persistent_vector_ref with_meta(object_ref const &m) const; + persistent_vector_ref with_meta(object_ref const m) const; /* behavior::seqable */ persistent_vector_sequence_ref seq() const; @@ -66,28 +66,28 @@ namespace jank::runtime::obj usize count() const; /* behavior::associatively_readable */ - object_ref get(object_ref const &key) const; - object_ref get(object_ref const &key, object_ref const &fallback) const; - object_ref get_entry(object_ref const &key) const; - bool contains(object_ref const &key) const; + object_ref get(object_ref const key) const; + object_ref get(object_ref const key, object_ref const fallback) const; + object_ref get_entry(object_ref const key) const; + bool contains(object_ref const key) const; /* behavior::associatively_writable */ - persistent_vector_ref assoc(object_ref const &key, object_ref const &val) const; - persistent_vector_ref dissoc(object_ref const &key) const; + persistent_vector_ref assoc(object_ref const key, object_ref const val) const; + persistent_vector_ref dissoc(object_ref const key) const; /* behavior::conjable */ - persistent_vector_ref conj(object_ref const &head) const; + persistent_vector_ref conj(object_ref const head) const; /* behavior::stackable */ object_ref peek() const; persistent_vector_ref pop() const; /* behavior::indexable */ - object_ref nth(object_ref const &index) const; - object_ref nth(object_ref const &index, object_ref const &fallback) const; + object_ref nth(object_ref const index) const; + object_ref nth(object_ref const index, object_ref const fallback) const; /* behavior::callable */ - object_ref call(object_ref const &) const; + object_ref call(object_ref const ) const; /* behavior::transientable */ obj::transient_vector_ref to_transient() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector_sequence.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector_sequence.hpp index 300076146..6b4914a76 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector_sequence.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector_sequence.hpp @@ -17,8 +17,8 @@ namespace jank::runtime::obj persistent_vector_sequence() = default; persistent_vector_sequence(persistent_vector_sequence &&) noexcept = default; persistent_vector_sequence(persistent_vector_sequence const &) = default; - persistent_vector_sequence(obj::persistent_vector_ref const &v); - persistent_vector_sequence(obj::persistent_vector_ref const &v, usize i); + persistent_vector_sequence(obj::persistent_vector_ref const v); + persistent_vector_sequence(obj::persistent_vector_ref const v, usize i); /* behavior::object_like */ bool equal(object const &) const; @@ -37,7 +37,7 @@ namespace jank::runtime::obj /* behavior::sequenceable */ object_ref first() const; persistent_vector_sequence_ref next() const; - obj::cons_ref conj(object_ref const &head); + obj::cons_ref conj(object_ref const head); /* behavior::sequenceable_in_place */ persistent_vector_sequence_ref next_in_place(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp index 5cf73e0c6..d81beb91c 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp @@ -20,30 +20,30 @@ namespace jank::runtime::obj static constexpr bool is_sequential{ true }; static constexpr i64 chunk_size{ 32 }; - using bounds_check_t = bool (*)(object_ref const &, object_ref const &); + using bounds_check_t = bool (*)(object_ref const , object_ref const ); /* Constructors are only to be used within range.cpp. Prefer range::create. */ range() = default; range(range &&) noexcept = default; range(range const &) = default; - range(object_ref const &end); - range(object_ref const &start, object_ref const &end); - range(object_ref const &start, object_ref const &end, object_ref const &step); - range(object_ref const &start, - object_ref const &end, - object_ref const &step, + range(object_ref const end); + range(object_ref const start, object_ref const end); + range(object_ref const start, object_ref const end, object_ref const step); + range(object_ref const start, + object_ref const end, + object_ref const step, bounds_check_t bounds_check); - range(object_ref const &start, - object_ref const &end, - object_ref const &step, + range(object_ref const start, + object_ref const end, + object_ref const step, bounds_check_t bounds_check, - obj::array_chunk_ref const &chunk, - range_ref const &chunk_next); + obj::array_chunk_ref const chunk, + range_ref const chunk_next); - static object_ref create(object_ref const &end); - static object_ref create(object_ref const &start, object_ref const &end); + static object_ref create(object_ref const end); + static object_ref create(object_ref const start, object_ref const end); static object_ref - create(object_ref const &start, object_ref const &end, object_ref const &step); + create(object_ref const start, object_ref const end, object_ref const step); /* behavior::object_like */ bool equal(object const &) const; @@ -69,10 +69,10 @@ namespace jank::runtime::obj void force_chunk() const; /* behavior::conjable */ - obj::cons_ref conj(object_ref const &head) const; + obj::cons_ref conj(object_ref const head) const; /* behavior::metadatable */ - range_ref with_meta(object_ref const &m) const; + range_ref with_meta(object_ref const m) const; object base{ obj_type }; object_ref start{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp index 66cacce3d..56027543f 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp @@ -10,7 +10,7 @@ namespace jank::runtime::obj ratio_data(i64 const, i64 const); ratio_data(native_big_integer const &, native_big_integer const &); ratio_data(big_integer const &, big_integer const &); - ratio_data(object_ref const &, object_ref const &); + ratio_data(object_ref const , object_ref const ); ratio_data(ratio_data const &) = default; f64 to_real() const; @@ -58,55 +58,55 @@ namespace jank::runtime::obj }; object_ref operator+(ratio_data const &l, ratio_data const &r); - ratio_ref operator+(integer_ref const &l, ratio_data const &r); - ratio_ref operator+(ratio_data const &l, integer_ref const &r); - f64 operator+(real_ref const &l, ratio_data const &r); - f64 operator+(ratio_data const &l, real_ref const &r); + ratio_ref operator+(integer_ref const l, ratio_data const &r); + ratio_ref operator+(ratio_data const &l, integer_ref const r); + f64 operator+(real_ref const l, ratio_data const &r); + f64 operator+(ratio_data const &l, real_ref const r); f64 operator+(ratio_data const &l, f64 r); f64 operator+(f64 l, ratio_data const &r); ratio_ref operator+(ratio_data const &l, i64 r); ratio_ref operator+(i64 l, ratio_data const &r); object_ref operator-(ratio_data const &l, ratio_data const &r); - ratio_ref operator-(integer_ref const &l, ratio_data const &r); - ratio_ref operator-(ratio_data const &l, integer_ref const &r); - f64 operator-(real_ref const &l, ratio_data const &r); - f64 operator-(ratio_data const &l, real_ref const &r); + ratio_ref operator-(integer_ref const l, ratio_data const &r); + ratio_ref operator-(ratio_data const &l, integer_ref const r); + f64 operator-(real_ref const l, ratio_data const &r); + f64 operator-(ratio_data const &l, real_ref const r); f64 operator-(ratio_data const &l, f64 r); f64 operator-(f64 l, ratio_data const &r); ratio_ref operator-(ratio_data const &l, i64 r); ratio_ref operator-(i64 l, ratio_data const &r); object_ref operator*(ratio_data const &l, ratio_data const &r); - object_ref operator*(integer_ref const &l, ratio_data const &r); - object_ref operator*(ratio_data const &l, integer_ref const &r); - f64 operator*(real_ref const &l, ratio_data const &r); - f64 operator*(ratio_data const &l, real_ref const &r); + object_ref operator*(integer_ref const l, ratio_data const &r); + object_ref operator*(ratio_data const &l, integer_ref const r); + f64 operator*(real_ref const l, ratio_data const &r); + f64 operator*(ratio_data const &l, real_ref const r); f64 operator*(ratio_data const &l, f64 r); f64 operator*(f64 l, ratio_data const &r); object_ref operator*(ratio_data const &l, i64 r); object_ref operator*(i64 l, ratio_data const &r); object_ref operator/(ratio_data const &l, ratio_data const &r); - object_ref operator/(integer_ref const &l, ratio_data const &r); - ratio_ref operator/(ratio_data const &l, integer_ref const &r); - f64 operator/(real_ref const &l, ratio_data const &r); - f64 operator/(ratio_data const &l, real_ref const &r); + object_ref operator/(integer_ref const l, ratio_data const &r); + ratio_ref operator/(ratio_data const &l, integer_ref const r); + f64 operator/(real_ref const l, ratio_data const &r); + f64 operator/(ratio_data const &l, real_ref const r); f64 operator/(ratio_data const &l, f64 r); f64 operator/(f64 l, ratio_data const &r); ratio_ref operator/(ratio_data const &l, i64 r); object_ref operator/(i64 l, ratio_data const &r); bool operator==(ratio_data const &l, ratio_data const &r); - bool operator==(integer_ref const &l, ratio_data const &r); - bool operator==(ratio_data const &l, integer_ref const &r); - bool operator==(real_ref const &l, ratio_data const &r); - bool operator==(ratio_data const &l, real_ref const &r); + bool operator==(integer_ref const l, ratio_data const &r); + bool operator==(ratio_data const &l, integer_ref const r); + bool operator==(real_ref const l, ratio_data const &r); + bool operator==(ratio_data const &l, real_ref const r); bool operator==(ratio_data const &l, f64 r); bool operator==(f64 l, ratio_data const &r); bool operator==(ratio_data const &l, i64 r); bool operator==(i64 l, ratio_data const &r); bool operator<(ratio_data const &l, ratio_data const &r); - bool operator<(integer_ref const &l, ratio_data const &r); - bool operator<(ratio_data const &l, integer_ref const &r); - bool operator<(real_ref const &l, ratio_data const &r); - bool operator<(ratio_data const &l, real_ref const &r); + bool operator<(integer_ref const l, ratio_data const &r); + bool operator<(ratio_data const &l, integer_ref const r); + bool operator<(real_ref const l, ratio_data const &r); + bool operator<(ratio_data const &l, real_ref const r); bool operator<(ratio_data const &l, f64 r); bool operator<(f64 l, ratio_data const &r); bool operator<(ratio_data const &l, i64 r); @@ -114,19 +114,19 @@ namespace jank::runtime::obj bool operator<(bool l, ratio_data const &r); bool operator<(ratio_data const &l, bool r); bool operator<=(ratio_data const &l, ratio_data const &r); - bool operator<=(integer_ref const &l, ratio_data const &r); - bool operator<=(ratio_data const &l, integer_ref const &r); - bool operator<=(real_ref const &l, ratio_data const &r); - bool operator<=(ratio_data const &l, real_ref const &r); + bool operator<=(integer_ref const l, ratio_data const &r); + bool operator<=(ratio_data const &l, integer_ref const r); + bool operator<=(real_ref const l, ratio_data const &r); + bool operator<=(ratio_data const &l, real_ref const r); bool operator<=(ratio_data const &l, f64 r); bool operator<=(f64 l, ratio_data const &r); bool operator<=(ratio_data const &l, i64 r); bool operator<=(i64 l, ratio_data const &r); bool operator>(ratio_data const &l, ratio_data const &r); - bool operator>(integer_ref const &l, ratio_data const &r); - bool operator>(ratio_data const &l, integer_ref const &r); - bool operator>(real_ref const &l, ratio_data const &r); - bool operator>(ratio_data const &l, real_ref const &r); + bool operator>(integer_ref const l, ratio_data const &r); + bool operator>(ratio_data const &l, integer_ref const r); + bool operator>(real_ref const l, ratio_data const &r); + bool operator>(ratio_data const &l, real_ref const r); bool operator>(ratio_data const &l, f64 r); bool operator>(f64 l, ratio_data const &r); bool operator>(ratio_data const &l, i64 r); @@ -134,10 +134,10 @@ namespace jank::runtime::obj bool operator>(bool l, ratio_data const &r); bool operator>(ratio_data const &l, bool r); bool operator>=(ratio_data const &l, ratio_data const &r); - bool operator>=(integer_ref const &l, ratio_data const &r); - bool operator>=(ratio_data const &l, integer_ref const &r); - bool operator>=(real_ref const &l, ratio_data const &r); - bool operator>=(ratio_data const &l, real_ref const &r); + bool operator>=(integer_ref const l, ratio_data const &r); + bool operator>=(ratio_data const &l, integer_ref const r); + bool operator>=(real_ref const l, ratio_data const &r); + bool operator>=(ratio_data const &l, real_ref const r); bool operator>=(ratio_data const &l, f64 r); bool operator>=(f64 l, ratio_data const &r); bool operator>=(ratio_data const &l, i64 r); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/re_matcher.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/re_matcher.hpp index 5808831dd..c0e2d7b71 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/re_matcher.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/re_matcher.hpp @@ -15,7 +15,7 @@ namespace jank::runtime::obj static constexpr object_type obj_type{ object_type::re_matcher }; static constexpr bool pointer_free{ false }; - re_matcher(re_pattern_ref const &re, jtl::immutable_string const &s); + re_matcher(re_pattern_ref const re, jtl::immutable_string const &s); /* behavior::object_like */ bool equal(object const &) const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/reduced.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/reduced.hpp index a6e46babb..32ab49db0 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/reduced.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/reduced.hpp @@ -12,7 +12,7 @@ namespace jank::runtime::obj static constexpr bool pointer_free{ false }; reduced() = default; - reduced(object_ref const &o); + reduced(object_ref const o); /* behavior::object_like */ bool equal(object const &) const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/repeat.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/repeat.hpp index 03793fb3c..fb34aae75 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/repeat.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/repeat.hpp @@ -17,11 +17,11 @@ namespace jank::runtime::obj static constexpr i64 infinite{ -1 }; repeat() = default; - repeat(object_ref const &value); - repeat(object_ref const &count, object_ref const &value); + repeat(object_ref const value); + repeat(object_ref const count, object_ref const value); - static object_ref create(object_ref const &value); - static object_ref create(object_ref const &count, object_ref const &value); + static object_ref create(object_ref const value); + static object_ref create(object_ref const count, object_ref const value); /* behavior::object_like */ bool equal(object const &) const; @@ -42,10 +42,10 @@ namespace jank::runtime::obj repeat_ref next_in_place(); /* behavior::conjable */ - obj::cons_ref conj(object_ref const &head) const; + obj::cons_ref conj(object_ref const head) const; /* behavior::metadatable */ - repeat_ref with_meta(object_ref const &m) const; + repeat_ref with_meta(object_ref const m) const; object base{ obj_type }; object_ref value{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/symbol.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/symbol.hpp index d1659572a..b406b64d9 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/symbol.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/symbol.hpp @@ -21,8 +21,8 @@ namespace jank::runtime::obj symbol(jtl::immutable_string &&d); symbol(jtl::immutable_string const &ns, jtl::immutable_string const &n); symbol(jtl::immutable_string &&ns, jtl::immutable_string &&n); - symbol(object_ref const &meta, jtl::immutable_string const &ns, jtl::immutable_string const &n); - symbol(object_ref const &ns, object_ref const &n); + symbol(object_ref const meta, jtl::immutable_string const &ns, jtl::immutable_string const &n); + symbol(object_ref const ns, object_ref const n); symbol &operator=(symbol const &) = default; symbol &operator=(symbol &&) = default; @@ -44,7 +44,7 @@ namespace jank::runtime::obj i64 compare(symbol const &) const; /* behavior::metadatable */ - symbol_ref with_meta(object_ref const &m) const; + symbol_ref with_meta(object_ref const m) const; /* behavior::nameable */ jtl::immutable_string const &get_name() const; @@ -78,13 +78,13 @@ namespace std template <> struct hash { - size_t operator()(jank::runtime::obj::symbol_ref const &o) const noexcept; + size_t operator()(jank::runtime::obj::symbol_ref const o) const noexcept; }; template <> struct equal_to { - bool operator()(jank::runtime::obj::symbol_ref const &lhs, - jank::runtime::obj::symbol_ref const &rhs) const noexcept; + bool operator()(jank::runtime::obj::symbol_ref const lhs, + jank::runtime::obj::symbol_ref const rhs) const noexcept; }; } diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/tagged_literal.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/tagged_literal.hpp index f42bf8303..104ffc73b 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/tagged_literal.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/tagged_literal.hpp @@ -11,7 +11,7 @@ namespace jank::runtime::obj static constexpr object_type obj_type{ object_type::tagged_literal }; static constexpr bool pointer_free{ false }; - tagged_literal(object_ref const &tag, object_ref const &form); + tagged_literal(object_ref const tag, object_ref const form); /* behavior::object_like */ bool equal(object const &) const; @@ -21,10 +21,10 @@ namespace jank::runtime::obj uhash to_hash() const; /* behavior::associatively_readable */ - object_ref get(object_ref const &key) const; - object_ref get(object_ref const &key, object_ref const &fallback) const; - object_ref get_entry(object_ref const &key) const; - bool contains(object_ref const &key) const; + object_ref get(object_ref const key) const; + object_ref get(object_ref const key, object_ref const fallback) const; + object_ref get_entry(object_ref const key) const; + bool contains(object_ref const key) const; object base{ obj_type }; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp index fb2a07649..7a388acad 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp @@ -35,24 +35,24 @@ namespace jank::runtime::obj u8 count() const; /* behavior::associatively_readable */ - object_ref get(object_ref const &key) const; - object_ref get(object_ref const &key, object_ref const &fallback) const; - object_ref get_entry(object_ref const &key) const; - bool contains(object_ref const &key) const; + object_ref get(object_ref const key) const; + object_ref get(object_ref const key, object_ref const fallback) const; + object_ref get_entry(object_ref const key) const; + bool contains(object_ref const key) const; /* behavior::associatively_writable_in_place */ - object_ref assoc_in_place(object_ref const &key, object_ref const &val); - transient_array_map_ref dissoc_in_place(object_ref const &key); + object_ref assoc_in_place(object_ref const key, object_ref const val); + transient_array_map_ref dissoc_in_place(object_ref const key); /* behavior::conjable_in_place */ - object_ref conj_in_place(object_ref const &head); + object_ref conj_in_place(object_ref const head); /* behavior::persistentable */ persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const &) const; - object_ref call(object_ref const &, object_ref const &) const; + object_ref call(object_ref const ) const; + object_ref call(object_ref const , object_ref const ) const; void assert_active() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp index 06b66ed50..a9aeebd5b 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp @@ -41,24 +41,24 @@ namespace jank::runtime::obj usize count() const; /* behavior::associatively_readable */ - object_ref get(object_ref const &key) const; - object_ref get(object_ref const &key, object_ref const &fallback) const; - object_ref get_entry(object_ref const &key) const; - bool contains(object_ref const &key) const; + object_ref get(object_ref const key) const; + object_ref get(object_ref const key, object_ref const fallback) const; + object_ref get_entry(object_ref const key) const; + bool contains(object_ref const key) const; /* behavior::associatively_writable_in_place */ - transient_hash_map_ref assoc_in_place(object_ref const &key, object_ref const &val); - transient_hash_map_ref dissoc_in_place(object_ref const &key); + transient_hash_map_ref assoc_in_place(object_ref const key, object_ref const val); + transient_hash_map_ref dissoc_in_place(object_ref const key); /* behavior::conjable_in_place */ - transient_hash_map_ref conj_in_place(object_ref const &head); + transient_hash_map_ref conj_in_place(object_ref const head); /* behavior::persistentable */ persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const &) const; - object_ref call(object_ref const &, object_ref const &) const; + object_ref call(object_ref const ) const; + object_ref call(object_ref const , object_ref const ) const; void assert_active() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp index 6993c2224..b657140f3 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp @@ -35,22 +35,22 @@ namespace jank::runtime::obj usize count() const; /* behavior::conjable_in_place */ - transient_hash_set_ref conj_in_place(object_ref const &elem); + transient_hash_set_ref conj_in_place(object_ref const elem); /* behavior::persistentable */ persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const &) const; - object_ref call(object_ref const &, object_ref const &fallback) const; + object_ref call(object_ref const ) const; + object_ref call(object_ref const , object_ref const fallback) const; /* behavior::associatively_readable */ - object_ref get(object_ref const &elem) const; - object_ref get(object_ref const &elem, object_ref const &fallback) const; - object_ref get_entry(object_ref const &elem) const; - bool contains(object_ref const &elem) const; + object_ref get(object_ref const elem) const; + object_ref get(object_ref const elem, object_ref const fallback) const; + object_ref get_entry(object_ref const elem) const; + bool contains(object_ref const elem) const; - transient_hash_set_ref disjoin_in_place(object_ref const &elem); + transient_hash_set_ref disjoin_in_place(object_ref const elem); void assert_active() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp index 6d0542b97..cb367f550 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp @@ -34,24 +34,24 @@ namespace jank::runtime::obj usize count() const; /* behavior::associatively_readable */ - object_ref get(object_ref const &key) const; - object_ref get(object_ref const &key, object_ref const &fallback) const; - object_ref get_entry(object_ref const &key) const; - bool contains(object_ref const &key) const; + object_ref get(object_ref const key) const; + object_ref get(object_ref const key, object_ref const fallback) const; + object_ref get_entry(object_ref const key) const; + bool contains(object_ref const key) const; /* behavior::associatively_writable_in_place */ - transient_sorted_map_ref assoc_in_place(object_ref const &key, object_ref const &val); - transient_sorted_map_ref dissoc_in_place(object_ref const &key); + transient_sorted_map_ref assoc_in_place(object_ref const key, object_ref const val); + transient_sorted_map_ref dissoc_in_place(object_ref const key); /* behavior::conjable_in_place */ - transient_sorted_map_ref conj_in_place(object_ref const &head); + transient_sorted_map_ref conj_in_place(object_ref const head); /* behavior::persistentable */ persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const &) const; - object_ref call(object_ref const &, object_ref const &) const; + object_ref call(object_ref const ) const; + object_ref call(object_ref const , object_ref const ) const; void assert_active() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp index cc229d397..a47d5a214 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp @@ -34,22 +34,22 @@ namespace jank::runtime::obj usize count() const; /* behavior::conjable_in_place */ - transient_sorted_set_ref conj_in_place(object_ref const &elem); + transient_sorted_set_ref conj_in_place(object_ref const elem); /* behavior::persistentable */ persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const &); - object_ref call(object_ref const &, object_ref const &fallback); + object_ref call(object_ref const ); + object_ref call(object_ref const , object_ref const fallback); /* behavior::associatively_readable */ - object_ref get(object_ref const &elem); - object_ref get(object_ref const &elem, object_ref const &fallback); - object_ref get_entry(object_ref const &elem); - bool contains(object_ref const &elem) const; + object_ref get(object_ref const elem); + object_ref get(object_ref const elem, object_ref const fallback); + object_ref get_entry(object_ref const elem); + bool contains(object_ref const elem) const; - transient_sorted_set_ref disjoin_in_place(object_ref const &elem); + transient_sorted_set_ref disjoin_in_place(object_ref const elem); void assert_active() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp index b5c0135d6..d515ebc59 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp @@ -35,19 +35,19 @@ namespace jank::runtime::obj usize count() const; /* behavior::conjable_in_place */ - transient_vector_ref conj_in_place(object_ref const &head); + transient_vector_ref conj_in_place(object_ref const head); /* behavior::persistentable */ persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const &) const; + object_ref call(object_ref const ) const; /* behavior::associatively_readable */ - object_ref get(object_ref const &idx) const; - object_ref get(object_ref const &idx, object_ref const &fallback) const; - object_ref get_entry(object_ref const &idx) const; - bool contains(object_ref const &elem) const; + object_ref get(object_ref const idx) const; + object_ref get(object_ref const idx, object_ref const fallback) const; + object_ref get_entry(object_ref const idx) const; + bool contains(object_ref const elem) const; transient_vector_ref pop_in_place(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/volatile.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/volatile.hpp index b3f0daa6a..17ae5e38a 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/volatile.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/volatile.hpp @@ -12,7 +12,7 @@ namespace jank::runtime::obj static constexpr bool pointer_free{ false }; volatile_() = default; - volatile_(object_ref const &o); + volatile_(object_ref const o); /* behavior::object_like */ bool equal(object const &) const; @@ -24,7 +24,7 @@ namespace jank::runtime::obj /* behavior::derefable */ object_ref deref() const; - object_ref reset(object_ref const &o); + object_ref reset(object_ref const o); object base{ obj_type }; object_ref val{}; diff --git a/compiler+runtime/include/cpp/jank/runtime/object.hpp b/compiler+runtime/include/cpp/jank/runtime/object.hpp index 6427c2e35..2550f786a 100644 --- a/compiler+runtime/include/cpp/jank/runtime/object.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/object.hpp @@ -248,9 +248,6 @@ namespace jank::runtime object(object &&) noexcept; object(object_type) noexcept; - void retain(); - void release(); - object &operator=(object const &) noexcept; object &operator=(object &&) noexcept; @@ -303,23 +300,21 @@ namespace jank::runtime::behavior } #include -#include namespace jank::runtime { using object_ref = oref; - using weak_object_ref = weak_oref; /* This isn't a great name, but it represents more than just value equality, since it * also includes type equality. Otherwise, [] equals '(). This is important when deduping * constants during codegen, since we don't want to be lossy in how we generate values. */ struct very_equal_to { - bool operator()(object_ref const &lhs, object_ref const &rhs) const noexcept; + bool operator()(object_ref const lhs, object_ref const rhs) const noexcept; }; - bool operator==(object const *, object_ref const &); - bool operator!=(object const *, object_ref const &); + bool operator==(object const *, object_ref const); + bool operator!=(object const *, object_ref const); } namespace std @@ -327,7 +322,7 @@ namespace std template <> struct hash { - size_t operator()(jank::runtime::object_ref const &o) const noexcept; + size_t operator()(jank::runtime::object_ref const o) const noexcept; }; template <> @@ -339,7 +334,7 @@ namespace std template <> struct equal_to { - bool operator()(jank::runtime::object_ref const &lhs, - jank::runtime::object_ref const &rhs) const noexcept; + bool operator()(jank::runtime::object_ref const lhs, + jank::runtime::object_ref const rhs) const noexcept; }; } diff --git a/compiler+runtime/include/cpp/jank/runtime/oref.hpp b/compiler+runtime/include/cpp/jank/runtime/oref.hpp index dd4b4d91e..ef40aecae 100644 --- a/compiler+runtime/include/cpp/jank/runtime/oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/oref.hpp @@ -42,14 +42,12 @@ namespace jank::runtime : data{ rhs.data } { jank_assert_throw(data); - retain(); } oref(oref &&rhs) noexcept : data{ jtl::move(rhs.data) } { jank_assert_throw(data); - retain(); } oref(nullptr_t) noexcept = delete; @@ -58,14 +56,12 @@ namespace jank::runtime : data{ data } { jank_assert_throw(data); - retain(); } oref(value_type const * const data) : data{ const_cast(data) } { jank_assert_throw(data); - retain(); } template @@ -74,7 +70,6 @@ namespace jank::runtime : data{ &typed_data->base } { jank_assert_throw(this->data); - retain(); } template @@ -83,7 +78,6 @@ namespace jank::runtime : data{ const_cast(&typed_data->base) } { jank_assert_throw(this->data); - retain(); } template @@ -91,30 +85,9 @@ namespace jank::runtime oref(oref const &typed_data) noexcept : data{ typed_data.erase().data } { - retain(); } - ~oref() - { - release(); - } - - oref const &retain() const - { - if(is_some()) - { - data->retain(); - } - return *this; - } - - void release() const - { - if(is_some()) - { - data->release(); - } - } + ~oref() = default; void reset() { @@ -143,31 +116,8 @@ namespace jank::runtime return *data; } - oref &operator=(oref const &rhs) noexcept - { - if(this == &rhs) - { - return *this; - } - - release(); - data = rhs.data; - retain(); - return *this; - } - - oref &operator=(oref &&rhs) noexcept - { - if(this == &rhs) - { - return *this; - } - - release(); - data = rhs.data; - retain(); - return *this; - } + oref &operator=(oref const &rhs) noexcept = default; + oref &operator=(oref &&rhs) noexcept = default; template requires behavior::object_like @@ -178,9 +128,7 @@ namespace jank::runtime return *this; } - release(); data = &rhs->base; - retain(); return *this; } @@ -250,13 +198,11 @@ namespace jank::runtime oref(oref const &rhs) noexcept : data{ rhs.data } { - retain(); } oref(oref &&rhs) noexcept : data{ rhs.data } { - retain(); } oref(nullptr_t) = delete; @@ -265,14 +211,12 @@ namespace jank::runtime : data{ data } { jank_assert_throw(this->data); - retain(); } oref(T const * const data) : data{ const_cast(data) } { jank_assert_throw(this->data); - retain(); } template @@ -280,7 +224,6 @@ namespace jank::runtime oref(oref const &data) noexcept : data{ data.data } { - retain(); } template @@ -290,27 +233,7 @@ namespace jank::runtime { } - ~oref() - { - release(); - } - - oref const &retain() const - { - if(is_some()) - { - (*this)->base.retain(); - } - return *this; - } - - void release() const - { - if(is_some()) - { - (*this)->base.release(); - } - } + ~oref() = default; void reset() { @@ -376,31 +299,8 @@ namespace jank::runtime return data != rhs.data; } - oref &operator=(oref const &rhs) noexcept - { - if(this == &rhs) - { - return *this; - } - - release(); - data = rhs.data; - retain(); - return *this; - } - - oref &operator=(oref &&rhs) noexcept - { - if(this == &rhs) - { - return *this; - } - - release(); - data = rhs.data; - retain(); - return *this; - } + oref &operator=(oref const &rhs) noexcept = default; + oref &operator=(oref &&rhs) noexcept = default; oref &operator=(std::remove_cv_t> * const rhs) { @@ -409,10 +309,8 @@ namespace jank::runtime return *this; } - release(); data = rhs; jank_assert_throw(data); - retain(); return *this; } @@ -423,10 +321,8 @@ namespace jank::runtime return *this; } - release(); data = const_cast(rhs); jank_assert_throw(data); - retain(); return *this; } @@ -439,9 +335,7 @@ namespace jank::runtime return *this; } - release(); data = std::bit_cast(jank_const_nil()); - retain(); return *this; } @@ -511,15 +405,6 @@ namespace jank::runtime { } - oref const &retain() const - { - return *this; - } - - void release() const - { - } - void reset() { } @@ -569,7 +454,7 @@ namespace jank::runtime oref erase() const noexcept { - return {}; + return { std::bit_cast(jank_const_nil()) }; } bool is_some() const noexcept diff --git a/compiler+runtime/include/cpp/jank/runtime/perf.hpp b/compiler+runtime/include/cpp/jank/runtime/perf.hpp index c7c412e0e..a4418986c 100644 --- a/compiler+runtime/include/cpp/jank/runtime/perf.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/perf.hpp @@ -4,5 +4,5 @@ namespace jank::runtime::perf { - object_ref benchmark(object_ref const &opts, object_ref const &f); + object_ref benchmark(object_ref const opts, object_ref const f); } diff --git a/compiler+runtime/include/cpp/jank/runtime/rtti.hpp b/compiler+runtime/include/cpp/jank/runtime/rtti.hpp index 7582c3371..0576f3217 100644 --- a/compiler+runtime/include/cpp/jank/runtime/rtti.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/rtti.hpp @@ -16,7 +16,7 @@ namespace jank::runtime template requires behavior::object_like [[gnu::always_inline, gnu::flatten, gnu::hot]] - constexpr oref dyn_cast(object_ref const &o) + constexpr oref dyn_cast(object_ref const o) { if(o->type != T::obj_type) { @@ -28,7 +28,7 @@ namespace jank::runtime template requires behavior::object_like [[gnu::always_inline, gnu::flatten, gnu::hot]] - oref try_object(object_ref const &o) + oref try_object(object_ref const o) { if(o->type != T::obj_type) { @@ -49,20 +49,7 @@ namespace jank::runtime template requires behavior::object_like [[gnu::always_inline, gnu::flatten, gnu::hot]] - constexpr oref expect_object(object_ref const &o) - { - if constexpr(T::obj_type != object_type::nil) - { - jank_debug_assert(o.is_some()); - } - jank_debug_assert(o->type == T::obj_type); - return reinterpret_cast(reinterpret_cast(o.data) - offsetof(T, base)); - } - - template - requires behavior::object_like - [[gnu::always_inline, gnu::flatten, gnu::hot]] - constexpr weak_oref expect_object(weak_object_ref const &o) + constexpr oref expect_object(object_ref const o) { if constexpr(T::obj_type != object_type::nil) { diff --git a/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp b/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp index 252e38bf7..8b6a311a0 100644 --- a/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/sequence_range.hpp @@ -21,7 +21,7 @@ namespace jank::runtime iterator(iterator const &) noexcept = default; iterator(iterator &&) noexcept = default; - iterator(object_ref const &data) + iterator(object_ref const data) : data{ data } { } @@ -176,24 +176,4 @@ namespace jank::runtime return sequence_range{ s.is_some() ? s->seq() : s }; } } - - template - requires behavior::seqable - auto make_sequence_range(weak_oref const s) - { - using S = typename decltype(s->seq())::value_type; - - if constexpr(jtl::is_same) - { - return sequence_range{ s }; - } - else if constexpr(behavior::sequenceable_in_place) - { - return sequence_range{ s.is_some() ? weak_oref{ s->fresh_seq() } : weak_oref{} }; - } - else - { - return sequence_range{ s.is_some() ? weak_oref{ s->seq() } : s }; - } - } } diff --git a/compiler+runtime/include/cpp/jank/runtime/var.hpp b/compiler+runtime/include/cpp/jank/runtime/var.hpp index 2176f0052..01424e4db 100644 --- a/compiler+runtime/include/cpp/jank/runtime/var.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/var.hpp @@ -12,7 +12,7 @@ namespace jank::runtime { - using weak_ns_ref = weak_oref; + using ns_ref = oref; using var_ref = oref; using var_thread_binding_ref = oref; using var_unbound_root_ref = oref; @@ -23,11 +23,11 @@ namespace jank::runtime static constexpr bool pointer_free{ false }; var() = delete; - var(weak_ns_ref const &n, obj::symbol_ref const &name); - var(weak_ns_ref const &n, obj::symbol_ref const &name, object_ref const &root); - var(weak_ns_ref const &n, - obj::symbol_ref const &name, - object_ref const &root, + var(ns_ref const n, obj::symbol_ref const name); + var(ns_ref const n, obj::symbol_ref const name, object_ref const root); + var(ns_ref const n, + obj::symbol_ref const name, + object_ref const root, bool dynamic, bool thread_bound); @@ -42,16 +42,16 @@ namespace jank::runtime bool equal(var const &) const; /* behavior::metadatable */ - var_ref with_meta(object_ref const &m); + var_ref with_meta(object_ref const m); bool is_bound() const; object_ref get_root() const; /* Binding a root changes it for all threads. */ - var_ref bind_root(object_ref const &r); - object_ref alter_root(object_ref const &f, object_ref const &args); + var_ref bind_root(object_ref const r); + object_ref alter_root(object_ref const f, object_ref const args); /* Setting a var does not change its root, it only affects the current thread * binding. If there is no thread binding, a var cannot be set. */ - jtl::string_result set(object_ref const &r) const; + jtl::string_result set(object_ref const r) const; var_ref set_dynamic(bool dyn); @@ -66,7 +66,7 @@ namespace jank::runtime var_ref clone() const; object base{ obj_type }; - weak_ns_ref n; + ns_ref n; /* Unqualified. */ obj::symbol_ref name{}; jtl::option meta; @@ -85,7 +85,7 @@ namespace jank::runtime static constexpr object_type obj_type{ object_type::var_thread_binding }; static constexpr bool pointer_free{ false }; - var_thread_binding(object_ref const &value, std::thread::id id); + var_thread_binding(object_ref const value, std::thread::id id); /* behavior::object_like */ bool equal(object const &) const; @@ -109,7 +109,7 @@ namespace jank::runtime static constexpr object_type obj_type{ object_type::var_unbound_root }; static constexpr bool pointer_free{ true }; - var_unbound_root(var_ref const &var); + var_unbound_root(var_ref const var); /* behavior::object_like */ bool equal(object const &) const; @@ -134,13 +134,13 @@ namespace std template <> struct hash { - size_t operator()(jank::runtime::var_ref const &o) const noexcept; + size_t operator()(jank::runtime::var_ref const o) const noexcept; }; template <> struct equal_to { bool - operator()(jank::runtime::var_ref const &lhs, jank::runtime::var_ref const &rhs) const noexcept; + operator()(jank::runtime::var_ref const lhs, jank::runtime::var_ref const rhs) const noexcept; }; } diff --git a/compiler+runtime/include/cpp/jank/runtime/visit.hpp b/compiler+runtime/include/cpp/jank/runtime/visit.hpp index 3fe2fa95b..4cb2327d9 100644 --- a/compiler+runtime/include/cpp/jank/runtime/visit.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/visit.hpp @@ -69,7 +69,7 @@ namespace jank::runtime template requires behavior::object_like [[gnu::hot]] - auto visit_object(F const &fn, weak_oref const not_erased, Args &&...args) + auto visit_object(F const &fn, oref const not_erased, Args &&...args) { return fn(const_cast(¬_erased->base), std::forward(args)...); } @@ -80,7 +80,7 @@ namespace jank::runtime template requires visitable [[gnu::hot]] - auto visit_object(F const &fn, weak_object_ref const erased, Args &&...args) + auto visit_object(F const &fn, object_ref const erased, Args &&...args) { switch(erased->type) { @@ -223,7 +223,7 @@ namespace jank::runtime /* Allows the visiting of a single type. */ template [[gnu::hot]] - auto visit_type(F const &fn, object_ref const &erased, Args &&...args) + auto visit_type(F const &fn, object_ref const erased, Args &&...args) { if(erased->type == T::obj_type) { @@ -240,7 +240,7 @@ namespace jank::runtime template requires(visitable && !std::convertible_to) [[gnu::hot]] - auto visit_seqable(F1 const &fn, F2 const &else_fn, object_ref const &erased, Args &&...args) + auto visit_seqable(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -314,7 +314,7 @@ namespace jank::runtime /* Throws if the object isn't seqable. */ template [[gnu::hot]] - auto visit_seqable(F1 const &fn, object_ref const &erased, Args &&...args) + auto visit_seqable(F1 const &fn, object_ref const erased, Args &&...args) { return visit_seqable( fn, @@ -332,7 +332,7 @@ namespace jank::runtime template requires(map_visitable && !std::convertible_to) [[gnu::hot]] - auto visit_map_like(F1 const &fn, F2 const &else_fn, object_ref const &erased, Args &&...args) + auto visit_map_like(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -354,7 +354,7 @@ namespace jank::runtime /* Throws if the object isn't map-like. */ template [[gnu::hot]] - auto visit_map_like(F1 const &fn, object_ref const &erased, Args &&...args) + auto visit_map_like(F1 const &fn, object_ref const erased, Args &&...args) { return visit_map_like( fn, @@ -368,7 +368,7 @@ namespace jank::runtime template requires(visitable && !std::convertible_to) [[gnu::hot]] - auto visit_set_like(F1 const &fn, F2 const &else_fn, object_ref const &erased, Args &&...args) + auto visit_set_like(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -388,7 +388,7 @@ namespace jank::runtime /* Throws if the object isn't set-like. */ template [[gnu::hot]] - auto visit_set_like(F1 const &fn, object_ref const &erased, Args &&...args) + auto visit_set_like(F1 const &fn, object_ref const erased, Args &&...args) { return visit_set_like( fn, @@ -402,7 +402,7 @@ namespace jank::runtime template requires(!std::convertible_to) [[gnu::hot]] - auto visit_number_like(F1 const &fn, F2 const &else_fn, object_ref const &erased, Args &&...args) + auto visit_number_like(F1 const &fn, F2 const &else_fn, object_ref const erased, Args &&...args) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -427,7 +427,7 @@ namespace jank::runtime /* Throws if the object isn't number-like. */ template [[gnu::hot]] - auto visit_number_like(F1 const &fn, object_ref const &erased, Args &&...args) + auto visit_number_like(F1 const &fn, object_ref const erased, Args &&...args) { return visit_number_like( fn, diff --git a/compiler+runtime/include/cpp/jank/util/try.hpp b/compiler+runtime/include/cpp/jank/util/try.hpp index 1e34bb330..c2a7c2352 100644 --- a/compiler+runtime/include/cpp/jank/util/try.hpp +++ b/compiler+runtime/include/cpp/jank/util/try.hpp @@ -17,7 +17,7 @@ namespace jank namespace jank::util { void print_exception(std::exception const &e); - void print_exception(runtime::object_ref const &e); + void print_exception(runtime::object_ref const e); void print_exception(jtl::immutable_string const &e); void print_exception(error_ref e); } @@ -69,7 +69,7 @@ namespace jank::util fun(e); \ then; \ } \ - catch(jank::error_ref const &e) \ + catch(jank::error_ref const e) \ { \ fun(e); \ then; \ diff --git a/compiler+runtime/src/cpp/clojure/core_native.cpp b/compiler+runtime/src/cpp/clojure/core_native.cpp index afde28288..39b03cea7 100644 --- a/compiler+runtime/src/cpp/clojure/core_native.cpp +++ b/compiler+runtime/src/cpp/clojure/core_native.cpp @@ -14,12 +14,12 @@ namespace clojure::core_native using namespace jank; using namespace jank::runtime; - static object_ref subvec(object_ref const &o, object_ref const &start, object_ref const &end) + static object_ref subvec(object_ref const o, object_ref const start, object_ref const end) { return runtime::subvec(o, runtime::to_int(start), runtime::to_int(end)); } - object_ref not_(object_ref const &o) + object_ref not_(object_ref const o) { if(runtime::is_nil(o)) { @@ -28,10 +28,10 @@ namespace clojure::core_native return make_box(runtime::is_false(o)); } - static object_ref to_unqualified_symbol(object_ref const &o) + static object_ref to_unqualified_symbol(object_ref const o) { return runtime::visit_object( - [&](auto const &typed_o) -> object_ref { + [&](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -59,119 +59,118 @@ namespace clojure::core_native o); } - static object_ref to_qualified_symbol(object_ref const &ns, object_ref const &name) + static object_ref to_qualified_symbol(object_ref const ns, object_ref const name) { return make_box(ns, name); } - object_ref lazy_seq(object_ref const &o) + object_ref lazy_seq(object_ref const o) { return make_box(o); } - object_ref is_var(object_ref const &o) + object_ref is_var(object_ref const o) { return make_box(o->type == object_type::var); } - object_ref var_get(object_ref const &o) + object_ref var_get(object_ref const o) { return try_object(o)->deref(); } - object_ref intern_var(object_ref const &sym) + object_ref intern_var(object_ref const sym) { return __rt_ctx->intern_var(try_object(sym)).expect_ok(); } - object_ref var_get_root(object_ref const &o) + object_ref var_get_root(object_ref const o) { return try_object(o)->get_root(); } - object_ref var_bind_root(object_ref const &v, object_ref const &o) + object_ref var_bind_root(object_ref const v, object_ref const o) { return try_object(v)->bind_root(o); } - object_ref alter_var_root(object_ref const &o, object_ref const &fn, object_ref const &args) + object_ref alter_var_root(object_ref const o, object_ref const fn, object_ref const args) { return try_object(o)->alter_root(fn, args); } - object_ref is_var_bound(object_ref const &o) + object_ref is_var_bound(object_ref const o) { return make_box(try_object(o)->is_bound()); } - object_ref is_var_thread_bound(object_ref const &o) + object_ref is_var_thread_bound(object_ref const o) { return make_box(try_object(o)->get_thread_binding().is_some()); } - object_ref delay(object_ref const &fn) + object_ref delay(object_ref const fn) { return make_box(fn); } - object_ref is_fn(object_ref const &o) + object_ref is_fn(object_ref const o) { return make_box(o->type == object_type::native_function_wrapper || o->type == object_type::jit_function); } - object_ref is_multi_fn(object_ref const &o) + object_ref is_multi_fn(object_ref const o) { return make_box(o->type == object_type::multi_function); } - object_ref multi_fn(object_ref const &name, - object_ref const &dispatch_fn, - object_ref const &default_, - object_ref const &hierarchy) + object_ref multi_fn(object_ref const name, + object_ref const dispatch_fn, + object_ref const default_, + object_ref const hierarchy) { return make_box(name, dispatch_fn, default_, hierarchy); } - object_ref - defmethod(object_ref const &multifn, object_ref const &dispatch_val, object_ref const &fn) + object_ref defmethod(object_ref const multifn, object_ref const dispatch_val, object_ref const fn) { return try_object(multifn)->add_method(dispatch_val, fn); } - object_ref remove_all_methods(object_ref const &multifn) + object_ref remove_all_methods(object_ref const multifn) { return try_object(multifn)->reset(); } - object_ref remove_method(object_ref const &multifn, object_ref const &dispatch_val) + object_ref remove_method(object_ref const multifn, object_ref const dispatch_val) { return try_object(multifn)->remove_method(dispatch_val); } - object_ref prefer_method(object_ref const &multifn, - object_ref const &dispatch_val_x, - object_ref const &dispatch_val_y) + object_ref prefer_method(object_ref const multifn, + object_ref const dispatch_val_x, + object_ref const dispatch_val_y) { return try_object(multifn)->prefer_method(dispatch_val_x, dispatch_val_y); } - object_ref methods(object_ref const &multifn) + object_ref methods(object_ref const multifn) { return try_object(multifn)->method_table; } - object_ref get_method(object_ref const &multifn, object_ref const &dispatch_val) + object_ref get_method(object_ref const multifn, object_ref const dispatch_val) { return try_object(multifn)->get_fn(dispatch_val); } - object_ref prefers(object_ref const &multifn) + object_ref prefers(object_ref const multifn) { return try_object(multifn)->prefer_table; } - object_ref sleep(object_ref const &ms) + object_ref sleep(object_ref const ms) { std::this_thread::sleep_for(std::chrono::milliseconds(to_int(ms))); return jank_nil(); @@ -184,61 +183,60 @@ namespace clojure::core_native return make_box(duration_cast(t.time_since_epoch()).count()); } - object_ref in_ns(object_ref const &sym) + object_ref in_ns(object_ref const sym) { __rt_ctx->current_ns_var->set(__rt_ctx->intern_ns(try_object(sym))).expect_ok(); return jank_nil(); } - object_ref intern_ns(object_ref const &sym) + object_ref intern_ns(object_ref const sym) { return __rt_ctx->intern_ns(try_object(sym)); } - object_ref find_ns(object_ref const &sym) + object_ref find_ns(object_ref const sym) { return __rt_ctx->find_ns(try_object(sym)); } - object_ref find_var(object_ref const &sym) + object_ref find_var(object_ref const sym) { return __rt_ctx->find_var(try_object(sym)); } - object_ref remove_ns(object_ref const &sym) + object_ref remove_ns(object_ref const sym) { return __rt_ctx->remove_ns(try_object(sym)); } - object_ref is_ns(object_ref const &ns_or_sym) + object_ref is_ns(object_ref const ns_or_sym) { return make_box(ns_or_sym->type == object_type::ns); } - object_ref ns_name(object_ref const &ns) + object_ref ns_name(object_ref const ns) { return try_object(ns)->name; } - object_ref ns_map(object_ref const &ns) + object_ref ns_map(object_ref const ns) { return try_object(ns)->get_mappings(); } - object_ref var_ns(object_ref const &v) + object_ref var_ns(object_ref const v) { return try_object(v)->n; } - object_ref ns_resolve(object_ref const &ns, object_ref const &sym) + object_ref ns_resolve(object_ref const ns, object_ref const sym) { auto const n(try_object(ns)); auto const found(n->find_var(try_object(sym))); return found; } - object_ref - alias(object_ref const ¤t_ns, object_ref const &remote_ns, object_ref const &alias) + object_ref alias(object_ref const current_ns, object_ref const remote_ns, object_ref const alias) { try_object(current_ns) ->add_alias(try_object(alias), try_object(remote_ns)) @@ -246,19 +244,19 @@ namespace clojure::core_native return jank_nil(); } - object_ref ns_unalias(object_ref const ¤t_ns, object_ref const &alias) + object_ref ns_unalias(object_ref const current_ns, object_ref const alias) { try_object(current_ns)->remove_alias(try_object(alias)); return jank_nil(); } - object_ref ns_unmap(object_ref const ¤t_ns, object_ref const &sym) + object_ref ns_unmap(object_ref const current_ns, object_ref const sym) { try_object(current_ns)->unmap(try_object(sym)).expect_ok(); return jank_nil(); } - object_ref refer(object_ref const ¤t_ns, object_ref const &sym, object_ref const &var) + object_ref refer(object_ref const current_ns, object_ref const sym, object_ref const var) { expect_object(current_ns) ->refer(try_object(sym), expect_object(var)) @@ -266,30 +264,30 @@ namespace clojure::core_native return jank_nil(); } - object_ref load_module(object_ref const &path) + object_ref load_module(object_ref const path) { __rt_ctx->load_module(runtime::to_string(path), module::origin::latest).expect_ok(); return jank_nil(); } - object_ref compile(object_ref const &path) + object_ref compile(object_ref const path) { __rt_ctx->compile_module(runtime::to_string(path)).expect_ok(); return jank_nil(); } - object_ref eval(object_ref const &expr) + object_ref eval(object_ref const expr) { return __rt_ctx->eval(expr); } - object_ref hash_unordered(object_ref const &coll) + object_ref hash_unordered(object_ref const coll) { return make_box(hash::unordered(coll.data)).erase(); } /* TODO: implement opts for `read-string` */ - object_ref read_string(object_ref const & /* opts */, object_ref const &str) + object_ref read_string(object_ref const /* opts */, object_ref const str) { return __rt_ctx->read_string(runtime::to_string(str)); } @@ -318,30 +316,23 @@ void jank_load_clojure_core_native() __rt_ctx->intern_keyword("name").expect_ok(), make_box(obj::symbol{ __rt_ctx->current_ns()->to_string(), name }.to_string()))))); }); - auto const intern_fn_obj([=](jtl::immutable_string const &name, object_ref const &fn) { - ns->intern_var(name)->bind_root(with_meta( - fn, - obj::persistent_hash_map::create_unique(std::make_pair( - __rt_ctx->intern_keyword("name").expect_ok(), - make_box(obj::symbol{ __rt_ctx->current_ns()->to_string(), name }.to_string()))))); - }); intern_fn("type", &type); intern_fn("nil?", &is_nil); intern_fn("identical?", &is_identical); intern_fn("empty?", &is_empty); intern_fn("empty", &empty); - intern_fn("count", static_cast(&sequence_length)); - intern_fn("boolean", static_cast(&truthy)); - intern_fn("integer", static_cast(&to_int)); - intern_fn("real", static_cast(&to_real)); - intern_fn("seq", static_cast(&seq)); - intern_fn("fresh-seq", static_cast(&fresh_seq)); - intern_fn("first", static_cast(&first)); - intern_fn("second", static_cast(&second)); - intern_fn("next", static_cast(&next)); - intern_fn("next-in-place", static_cast(&next_in_place)); - intern_fn("rest", static_cast(&rest)); + intern_fn("count", static_cast(&sequence_length)); + intern_fn("boolean", static_cast(&truthy)); + intern_fn("integer", static_cast(&to_int)); + intern_fn("real", static_cast(&to_real)); + intern_fn("seq", static_cast(&seq)); + intern_fn("fresh-seq", static_cast(&fresh_seq)); + intern_fn("first", static_cast(&first)); + intern_fn("second", static_cast(&second)); + intern_fn("next", static_cast(&next)); + intern_fn("next-in-place", static_cast(&next_in_place)); + intern_fn("rest", static_cast(&rest)); intern_fn("cons", &cons); intern_fn("coll?", &is_collection); intern_fn("seq?", &is_seq); @@ -353,14 +344,14 @@ void jank_load_clojure_core_native() intern_fn("conj", &conj); intern_fn("map?", &is_map); intern_fn("associative?", &is_associative); - intern_fn("assoc", - static_cast( - &assoc)); - intern_fn("pr-str", static_cast(&to_code_string)); + intern_fn( + "assoc", + static_cast(&assoc)); + intern_fn("pr-str", static_cast(&to_code_string)); intern_fn("string?", &is_string); intern_fn("char?", &is_char); intern_fn("str", - static_cast(&str)); + static_cast(&str)); intern_fn("symbol?", &is_symbol); intern_fn("true?", &is_true); intern_fn("false?", &is_false); @@ -380,7 +371,7 @@ void jank_load_clojure_core_native() intern_fn("persistent!", &persistent); intern_fn("conj-in-place!", &conj_in_place); intern_fn("assoc-in-place!", - static_cast( + static_cast( &assoc_in_place)); intern_fn("dissoc-in-place!", &dissoc_in_place); intern_fn("pop-in-place!", &pop_in_place); @@ -398,10 +389,10 @@ void jank_load_clojure_core_native() intern_fn("volatile!", &volatile_); intern_fn("volatile?", &is_volatile); intern_fn("vreset!", &vreset); - intern_fn("+", static_cast(&add)); - intern_fn("-", static_cast(&sub)); - intern_fn("/", static_cast(&div)); - intern_fn("*", static_cast(&mul)); + intern_fn("+", static_cast(&add)); + intern_fn("-", static_cast(&sub)); + intern_fn("/", static_cast(&div)); + intern_fn("*", static_cast(&mul)); intern_fn("bit-not", &bit_not); intern_fn("bit-and", &bit_and); intern_fn("bit-or", &bit_or); @@ -414,20 +405,20 @@ void jank_load_clojure_core_native() intern_fn("bit-shift-left", &bit_shift_left); intern_fn("bit-shift-right", &bit_shift_right); intern_fn("unsigned-bit-shift-right", &bit_unsigned_shift_right); - intern_fn("<", static_cast(<)); - intern_fn("<=", static_cast(<e)); + intern_fn("<", static_cast(<)); + intern_fn("<=", static_cast(<e)); intern_fn("compare", &runtime::compare); - intern_fn("min", static_cast(&min)); - intern_fn("max", static_cast(&max)); - intern_fn("inc", static_cast(&inc)); - intern_fn("dec", static_cast(&dec)); + intern_fn("min", static_cast(&min)); + intern_fn("max", static_cast(&max)); + intern_fn("inc", static_cast(&inc)); + intern_fn("dec", static_cast(&dec)); intern_fn("numerator", &numerator); intern_fn("denominator", &denominator); intern_fn("pos?", &is_pos); intern_fn("neg?", &is_neg); intern_fn("zero?", &is_zero); - intern_fn("rem", static_cast(&rem)); - intern_fn("quot", static_cast(")); + intern_fn("rem", static_cast(&rem)); + intern_fn("quot", static_cast(")); intern_fn("integer?", &is_integer); intern_fn("real?", &is_real); intern_fn("ratio?", &is_ratio); @@ -536,8 +527,8 @@ void jank_load_clojure_core_native() intern_fn("re-matches", &re_matches); /* TODO: jank.math? */ - intern_fn("sqrt", static_cast(&runtime::sqrt)); - intern_fn("tan", static_cast(&runtime::tan)); - intern_fn("abs", static_cast(&runtime::abs)); - intern_fn("pow", static_cast(&runtime::pow)); + intern_fn("sqrt", static_cast(&runtime::sqrt)); + intern_fn("tan", static_cast(&runtime::tan)); + intern_fn("abs", static_cast(&runtime::abs)); + intern_fn("pow", static_cast(&runtime::pow)); } diff --git a/compiler+runtime/src/cpp/clojure/string_native.cpp b/compiler+runtime/src/cpp/clojure/string_native.cpp index eeedace97..8a18fde4c 100644 --- a/compiler+runtime/src/cpp/clojure/string_native.cpp +++ b/compiler+runtime/src/cpp/clojure/string_native.cpp @@ -13,7 +13,7 @@ namespace clojure::string_native using namespace jank; using namespace jank::runtime; - object_ref blank(object_ref const &s) + object_ref blank(object_ref const s) { if(runtime::is_nil(s)) { @@ -23,40 +23,40 @@ namespace clojure::string_native return make_box(s_str.is_blank()); } - object_ref reverse(object_ref const &s) + object_ref reverse(object_ref const s) { auto const s_str(runtime::to_string(s)); return make_box(jtl::immutable_string{ s_str.rbegin(), s_str.rend() }); } - object_ref lower_case(object_ref const &s) + object_ref lower_case(object_ref const s) { auto const s_str(runtime::to_string(s)); return make_box(util::to_lowercase(s_str)); } - object_ref starts_with(object_ref const &s, object_ref const &substr) + object_ref starts_with(object_ref const s, object_ref const substr) { auto const s_str(runtime::to_string(s)); auto const substr_str(runtime::to_string(substr)); return make_box(s_str.starts_with(substr_str)); } - object_ref ends_with(object_ref const &s, object_ref const &substr) + object_ref ends_with(object_ref const s, object_ref const substr) { auto const s_str(runtime::to_string(s)); auto const substr_str(runtime::to_string(substr)); return make_box(s_str.ends_with(substr_str)); } - object_ref includes(object_ref const &s, object_ref const &substr) + object_ref includes(object_ref const s, object_ref const substr) { auto const s_str(runtime::to_string(s)); auto const substr_str(runtime::to_string(substr)); return make_box(s_str.contains(substr_str)); } - object_ref upper_case(object_ref const &s) + object_ref upper_case(object_ref const s) { auto const s_str(runtime::to_string(s)); return make_box(util::to_uppercase(s_str)); @@ -105,7 +105,7 @@ namespace clojure::string_native static jtl::immutable_string replace_first(jtl::immutable_string const &s, std::regex const &match, - object_ref const &replacement) + object_ref const replacement) { std::smatch match_results{}; std::string const search_str{ s.c_str() }; @@ -136,8 +136,8 @@ namespace clojure::string_native } static jtl::immutable_string replace_first(jtl::immutable_string const &s, - object_ref const &match, - object_ref const &replacement) + object_ref const match, + object_ref const replacement) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -167,7 +167,7 @@ namespace clojure::string_native #pragma clang diagnostic pop } - object_ref replace_first(object_ref const &s, object_ref const &match, object_ref const &replacement) + object_ref replace_first(object_ref const s, object_ref const match, object_ref const replacement) { auto const is_string(s->type == object_type::persistent_string); auto const &s_str(is_string ? try_object(s)->data @@ -178,7 +178,7 @@ namespace clojure::string_native return is_string && output_str == s_str ? s : make_box(output_str); } - i64 index_of(object_ref const &s, object_ref const &value, object_ref const &from_index) + i64 index_of(object_ref const s, object_ref const value, object_ref const from_index) { auto const s_str(runtime::to_string(s)); auto const value_str(runtime::to_string(value)); @@ -186,7 +186,7 @@ namespace clojure::string_native return static_cast(s_str.find(value_str, pos)); } - i64 last_index_of(object_ref const &s, object_ref const &value, object_ref const &from_index) + i64 last_index_of(object_ref const s, object_ref const value, object_ref const from_index) { auto const s_str(runtime::to_string(s)); auto const value_str(runtime::to_string(value)); @@ -216,7 +216,7 @@ namespace clojure::string_native return i; } - object_ref triml(object_ref const &s) + object_ref triml(object_ref const s) { auto const s_str(runtime::to_string(s)); auto const l(triml_index(s_str)); @@ -250,7 +250,7 @@ namespace clojure::string_native return i; } - object_ref trimr(object_ref const &s) + object_ref trimr(object_ref const s) { auto const s_str(try_object(s)->data); auto const r(trimr_index(s_str)); @@ -268,7 +268,7 @@ namespace clojure::string_native return make_box(s_str.substr(0, r)); } - object_ref trim(object_ref const &s) + object_ref trim(object_ref const s) { auto const s_str(try_object(s)->data); auto const r(trimr_index(s_str)); @@ -305,7 +305,7 @@ namespace clojure::string_native return i; } - object_ref trim_newline(object_ref const &s) + object_ref trim_newline(object_ref const s) { auto const s_str(try_object(s)->data); auto const r(trim_newline_index(s_str)); @@ -318,7 +318,7 @@ namespace clojure::string_native return make_box(s_str.substr(0, r)); } - object_ref split(object_ref const &s, object_ref const &re) + object_ref split(object_ref const s, object_ref const re) { auto const s_str(try_object(s)->data); auto const regex(try_object(re)->regex); @@ -343,7 +343,7 @@ namespace clojure::string_native runtime::detail::native_persistent_vector{ vec.begin(), vec.end() }); } - object_ref split(object_ref const &s, object_ref const &re, object_ref const &limit) + object_ref split(object_ref const s, object_ref const re, object_ref const limit) { auto const limit_int(try_object(limit)->data); diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/call.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/call.cpp index 8da1f4108..cd1789bc7 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/call.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/call.cpp @@ -10,7 +10,7 @@ namespace jank::analyze::expr bool const needs_box, expression_ref const source, native_vector &&arg_exprs, - runtime::obj::persistent_list_ref const &form) + runtime::obj::persistent_list_ref const form) : expression{ expr_kind, position, frame, needs_box } , source_expr{ source } , arg_exprs{ std::move(arg_exprs) } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/cpp_type.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/cpp_type.cpp index 85ae57214..c8ff94ed5 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/cpp_type.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/cpp_type.cpp @@ -8,7 +8,7 @@ namespace jank::analyze::expr cpp_type::cpp_type(expression_position const position, local_frame_ptr const frame, bool const needs_box, - runtime::obj::symbol_ref const &sym, + runtime::obj::symbol_ref const sym, jtl::ptr const type) : expression{ expr_kind, position, frame, needs_box } , sym{ sym } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/cpp_value.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/cpp_value.cpp index 92cb9a780..db71d1787 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/cpp_value.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/cpp_value.cpp @@ -8,7 +8,7 @@ namespace jank::analyze::expr cpp_value::cpp_value(expression_position const position, local_frame_ptr const frame, bool const needs_box, - obj::symbol_ref const &sym, + obj::symbol_ref const sym, jtl::ptr const type, jtl::ptr const scope, value_kind const val_kind) diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/def.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/def.cpp index 177064f53..ab2f14154 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/def.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/def.cpp @@ -8,7 +8,7 @@ namespace jank::analyze::expr def::def(expression_position const position, local_frame_ptr const frame, bool const needs_box, - runtime::obj::symbol_ref const &name, + runtime::obj::symbol_ref const name, jtl::option const &value) : expression{ expr_kind, position, frame, needs_box } , name{ name } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/function.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/function.cpp index caec2e4b4..388adbc89 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/function.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/function.cpp @@ -17,7 +17,7 @@ namespace jank::analyze::expr jtl::immutable_string const &name, jtl::immutable_string const &unique_name, native_vector &&arities, - runtime::obj::persistent_hash_map_ref const &meta) + runtime::obj::persistent_hash_map_ref const meta) : expression{ expr_kind, position, frame, needs_box } , name{ name } , unique_name{ unique_name } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/local_reference.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/local_reference.cpp index 6ff8ad1bf..ee78a12f5 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/local_reference.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/local_reference.cpp @@ -9,7 +9,7 @@ namespace jank::analyze::expr local_reference::local_reference(expression_position const position, local_frame_ptr const frame, bool const needs_box, - runtime::obj::symbol_ref const &name, + runtime::obj::symbol_ref const name, local_binding_ptr const binding) : expression{ expr_kind, position, frame, needs_box } , name{ name } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/named_recursion.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/named_recursion.cpp index 9890b5fa3..1729b9c0d 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/named_recursion.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/named_recursion.cpp @@ -9,7 +9,7 @@ namespace jank::analyze::expr local_frame_ptr const frame, bool const needs_box, recursion_reference &&recursion_ref, - runtime::obj::persistent_list_ref const &args, + runtime::obj::persistent_list_ref const args, native_vector &&arg_exprs) : expression{ expr_kind, position, frame, needs_box } , recursion_ref{ std::move(recursion_ref) } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/primitive_literal.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/primitive_literal.cpp index 2bdc4b5df..6c2fae1c0 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/primitive_literal.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/primitive_literal.cpp @@ -8,7 +8,7 @@ namespace jank::analyze::expr primitive_literal::primitive_literal(expression_position const position, local_frame_ptr const frame, bool const needs_box, - runtime::object_ref const &data) + runtime::object_ref const data) : expression{ expr_kind, position, frame, needs_box } , data{ data } { diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/recur.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/recur.cpp index 9a495054c..83a8ce0ed 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/recur.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/recur.cpp @@ -8,7 +8,7 @@ namespace jank::analyze::expr recur::recur(expression_position const position, local_frame_ptr const frame, bool const needs_box, - runtime::obj::persistent_list_ref const &args, + runtime::obj::persistent_list_ref const args, native_vector &&arg_exprs, jtl::option const &loop_target) : expression{ expr_kind, position, frame, needs_box } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/var_deref.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/var_deref.cpp index 75fe2a321..0942dbb3b 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/var_deref.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/var_deref.cpp @@ -9,8 +9,8 @@ namespace jank::analyze::expr var_deref::var_deref(expression_position const position, local_frame_ptr const frame, bool const needs_box, - runtime::obj::symbol_ref const &qualified_name, - runtime::var_ref const &var) + runtime::obj::symbol_ref const qualified_name, + runtime::var_ref const var) : expression{ expr_kind, position, frame, needs_box } , qualified_name{ qualified_name } , var{ var } diff --git a/compiler+runtime/src/cpp/jank/analyze/expr/var_ref.cpp b/compiler+runtime/src/cpp/jank/analyze/expr/var_ref.cpp index 079f3ef88..aed26e4a5 100644 --- a/compiler+runtime/src/cpp/jank/analyze/expr/var_ref.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/expr/var_ref.cpp @@ -9,8 +9,8 @@ namespace jank::analyze::expr var_ref::var_ref(expression_position const position, local_frame_ptr const frame, bool const needs_box, - runtime::obj::symbol_ref const &qualified_name, - runtime::var_ref const &var) + runtime::obj::symbol_ref const qualified_name, + runtime::var_ref const var) : expression{ expr_kind, position, frame, needs_box } , qualified_name{ qualified_name } , var{ var } diff --git a/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp b/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp index be0e8d31b..f4d0a0ea4 100644 --- a/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp @@ -38,7 +38,7 @@ namespace jank::analyze } static jtl::option find_local_impl(local_frame_ptr const start, - obj::symbol_ref const &sym, + obj::symbol_ref const sym, bool const allow_captures) { decltype(local_frame::binding_find_result::crossed_fns) crossed_fns; @@ -79,7 +79,7 @@ namespace jank::analyze } jtl::option - local_frame::find_local_or_capture(obj::symbol_ref const &sym) + local_frame::find_local_or_capture(obj::symbol_ref const sym) { return find_local_impl(this, sym, true); } @@ -120,13 +120,13 @@ namespace jank::analyze } jtl::option - local_frame::find_originating_local(obj::symbol_ref const &sym) + local_frame::find_originating_local(obj::symbol_ref const sym) { return find_local_impl(this, sym, false); } jtl::option - local_frame::find_named_recursion(obj::symbol_ref const &sym) + local_frame::find_named_recursion(obj::symbol_ref const sym) { decltype(local_frame::named_recursion_find_result::crossed_fns) crossed_fns; diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index 7fd44ebfb..d38c34199 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -72,7 +72,7 @@ namespace jank::analyze * a scope_exit which will do so. Since we don't always push something, we lift this * up into a nullable pointer. */ static std::unique_ptr - push_macro_expansions(processor &proc, object_ref const &o) + push_macro_expansions(processor &proc, object_ref const o) { auto const meta(runtime::meta(o)); auto const expansion( @@ -980,7 +980,7 @@ namespace jank::analyze * function pointers and custom functor objects. Function pointers have no * overloads and no Clang decl/scope. Custom functors use the call operator. */ static processor::expression_result - build_indirect_cpp_call(obj::persistent_list_ref const &o, + build_indirect_cpp_call(obj::persistent_list_ref const o, expression_ref const source, native_vector arg_exprs, std::vector arg_types, @@ -1243,7 +1243,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_def(runtime::obj::persistent_list_ref const &l, + processor::analyze_def(runtime::obj::persistent_list_ref const l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -1341,7 +1341,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_case(obj::persistent_list_ref const &o, + processor::analyze_case(obj::persistent_list_ref const o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -1441,7 +1441,7 @@ namespace jank::analyze }; auto keys_exprs{ visit_map_like( - [&](auto const &typed_imap_obj) -> jtl::string_result { + [&](auto const typed_imap_obj) -> jtl::string_result { keys_and_exprs ret{}; for(auto seq{ typed_imap_obj->fresh_seq() }; seq.is_some(); seq = seq->next_in_place()) { @@ -1489,7 +1489,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_symbol(runtime::obj::symbol_ref const &sym, + processor::analyze_symbol(runtime::obj::symbol_ref const sym, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fc, @@ -1596,7 +1596,7 @@ namespace jank::analyze } jtl::result - processor::analyze_fn_arity(runtime::obj::persistent_list_ref const &list, + processor::analyze_fn_arity(runtime::obj::persistent_list_ref const list, jtl::immutable_string const &name, local_frame_ptr const current_frame) { @@ -1766,7 +1766,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_fn(runtime::obj::persistent_list_ref const &full_list, + processor::analyze_fn(runtime::obj::persistent_list_ref const full_list, local_frame_ptr const current_frame, expression_position const position, jtl::option const &, @@ -1830,7 +1830,7 @@ namespace jank::analyze if constexpr(runtime::behavior::sequenceable) { - auto arity_list(runtime::obj::persistent_list::create(typed_arity_list.strong())); + auto arity_list(runtime::obj::persistent_list::create(typed_arity_list)); auto result(analyze_fn_arity(arity_list, name, current_frame)); if(result.is_err()) @@ -1939,7 +1939,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_recur(runtime::obj::persistent_list_ref const &list, + processor::analyze_recur(runtime::obj::persistent_list_ref const list, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2039,7 +2039,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_do(runtime::obj::persistent_list_ref const &list, + processor::analyze_do(runtime::obj::persistent_list_ref const list, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2088,7 +2088,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_let(runtime::obj::persistent_list_ref const &o, + processor::analyze_let(runtime::obj::persistent_list_ref const o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2210,7 +2210,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_letfn(runtime::obj::persistent_list_ref const &o, + processor::analyze_letfn(runtime::obj::persistent_list_ref const o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2343,7 +2343,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_loop(runtime::obj::persistent_list_ref const &list, + processor::analyze_loop(runtime::obj::persistent_list_ref const list, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2371,7 +2371,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_if(runtime::obj::persistent_list_ref const &o, + processor::analyze_if(runtime::obj::persistent_list_ref const o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2486,7 +2486,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_quote(runtime::obj::persistent_list_ref const &o, + processor::analyze_quote(runtime::obj::persistent_list_ref const o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2509,7 +2509,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_var_call(runtime::obj::persistent_list_ref const &o, + processor::analyze_var_call(runtime::obj::persistent_list_ref const o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &, @@ -2553,7 +2553,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_var_val(runtime::var_ref const &o, + processor::analyze_var_val(runtime::var_ref const o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &, @@ -2566,7 +2566,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_throw(runtime::obj::persistent_list_ref const &o, + processor::analyze_throw(runtime::obj::persistent_list_ref const o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2599,7 +2599,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_try(runtime::obj::persistent_list_ref const &list, + processor::analyze_try(runtime::obj::persistent_list_ref const list, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2636,7 +2636,7 @@ namespace jank::analyze { auto const item(it->first()); auto const type(runtime::visit_seqable( - [](auto const &typed_item) { + [](auto const typed_item) { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -2805,7 +2805,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_primitive_literal(runtime::object_ref const &o, + processor::analyze_primitive_literal(runtime::object_ref const o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &, @@ -2817,7 +2817,7 @@ namespace jank::analyze /* TODO: Test for this. */ processor::expression_result - processor::analyze_vector(runtime::obj::persistent_vector_ref const &o, + processor::analyze_vector(runtime::obj::persistent_vector_ref const o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2863,7 +2863,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_map(object_ref const &o, + processor::analyze_map(object_ref const o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2873,7 +2873,7 @@ namespace jank::analyze /* TODO: Detect literal and act accordingly. */ return visit_map_like( - [&](auto const &typed_o) -> processor::expression_result { + [&](auto const typed_o) -> processor::expression_result { native_vector> exprs; exprs.reserve(typed_o->data.size()); @@ -2920,7 +2920,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_set(object_ref const &o, + processor::analyze_set(object_ref const o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -2929,7 +2929,7 @@ namespace jank::analyze auto const pop_macro_expansions{ push_macro_expansions(*this, o) }; return visit_set_like( - [&](auto const &typed_o) -> processor::expression_result { + [&](auto const typed_o) -> processor::expression_result { native_vector exprs; exprs.reserve(typed_o->count()); bool literal{ true }; @@ -2977,7 +2977,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_call(runtime::obj::persistent_list_ref const &o, + processor::analyze_call(runtime::obj::persistent_list_ref const o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -3215,7 +3215,7 @@ namespace jank::analyze } static processor::expression_result - build_cpp_value(runtime::obj::symbol_ref const &sym, + build_cpp_value(runtime::obj::symbol_ref const sym, jtl::ptr const scope, bool const is_ctor, u8 const ptr_count, @@ -3372,7 +3372,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_symbol(obj::symbol_ref const &sym, + processor::analyze_cpp_symbol(obj::symbol_ref const sym, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -3537,7 +3537,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_call(obj::persistent_list_ref const &o, + processor::analyze_cpp_call(obj::persistent_list_ref const o, expression_ref const source, local_frame_ptr const current_frame, expression_position const position, @@ -3601,7 +3601,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_raw(obj::persistent_list_ref const &l, + processor::analyze_cpp_raw(obj::persistent_list_ref const l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -3665,7 +3665,7 @@ namespace jank::analyze }; processor::expression_result - processor::analyze_cpp_literal(obj::persistent_list_ref const &l, + processor::analyze_cpp_literal(obj::persistent_list_ref const l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -3834,7 +3834,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_type(obj::persistent_list_ref const &l, + processor::analyze_cpp_type(obj::persistent_list_ref const l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -3844,7 +3844,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_value(obj::persistent_list_ref const &l, + processor::analyze_cpp_value(obj::persistent_list_ref const l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -3854,7 +3854,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_cast(obj::persistent_list_ref const &l, + processor::analyze_cpp_cast(obj::persistent_list_ref const l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -3967,7 +3967,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_box(obj::persistent_list_ref const &l, + processor::analyze_cpp_box(obj::persistent_list_ref const l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -4034,7 +4034,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_unbox(obj::persistent_list_ref const &l, + processor::analyze_cpp_unbox(obj::persistent_list_ref const l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -4129,7 +4129,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_new(obj::persistent_list_ref const &l, + processor::analyze_cpp_new(obj::persistent_list_ref const l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -4193,7 +4193,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_delete(obj::persistent_list_ref const &l, + processor::analyze_cpp_delete(obj::persistent_list_ref const l, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -4241,7 +4241,7 @@ namespace jank::analyze } processor::expression_result - processor::analyze_cpp_member_access(obj::persistent_list_ref const &l, + processor::analyze_cpp_member_access(obj::persistent_list_ref const l, expr::cpp_value_ref const val, local_frame_ptr const current_frame, expression_position const position, @@ -4355,13 +4355,13 @@ namespace jank::analyze } processor::expression_result - processor::analyze(object_ref const &o, expression_position const position) + processor::analyze(object_ref const o, expression_position const position) { return analyze(o, root_frame, position, none, true); } processor::expression_result - processor::analyze(object_ref const &o, + processor::analyze(object_ref const o, local_frame_ptr const current_frame, expression_position const position, jtl::option const &fn_ctx, @@ -4429,7 +4429,7 @@ namespace jank::analyze o); } - bool processor::is_special(runtime::object_ref const &form) + bool processor::is_special(runtime::object_ref const form) { if(form->type != runtime::object_type::symbol) { diff --git a/compiler+runtime/src/cpp/jank/c_api.cpp b/compiler+runtime/src/cpp/jank/c_api.cpp index 8f67df6ed..c9b2c4190 100644 --- a/compiler+runtime/src/cpp/jank/c_api.cpp +++ b/compiler+runtime/src/cpp/jank/c_api.cpp @@ -54,18 +54,18 @@ extern "C" jank_object_ref jank_eval(jank_object_ref const s) { auto const s_obj(try_object(reinterpret_cast(s))); - return __rt_ctx->eval_string(s_obj->data).retain().erase().data; + return __rt_ctx->eval_string(s_obj->data).erase().data; } jank_object_ref jank_read_string(jank_object_ref const s) { auto const s_obj(try_object(reinterpret_cast(s))); - return __rt_ctx->read_string(s_obj->data).retain().erase().data; + return __rt_ctx->read_string(s_obj->data).erase().data; } jank_object_ref jank_read_string_c(char const * const s) { - return __rt_ctx->read_string(s).retain().erase().data; + return __rt_ctx->read_string(s).erase().data; } jank_object_ref jank_ns_intern(jank_object_ref const sym) @@ -91,27 +91,27 @@ extern "C" __rt_ctx->intern_ns(ns_obj->data); auto const name_obj(try_object(reinterpret_cast(name))); - return __rt_ctx->intern_var(ns_obj->data, name_obj->data).expect_ok().retain().erase().data; + return __rt_ctx->intern_var(ns_obj->data, name_obj->data).expect_ok().erase().data; } jank_object_ref jank_var_intern_c(char const * const ns, char const * const name) { __rt_ctx->intern_ns(ns); - return __rt_ctx->intern_var(ns, name).expect_ok().retain().erase().data; + return __rt_ctx->intern_var(ns, name).expect_ok().erase().data; } jank_object_ref jank_var_bind_root(jank_object_ref const var, jank_object_ref const val) { auto const var_obj(try_object(reinterpret_cast(var))); auto const val_obj(reinterpret_cast(val)); - return var_obj->bind_root(val_obj).retain().erase().data; + return var_obj->bind_root(val_obj).erase().data; } jank_object_ref jank_var_set_dynamic(jank_object_ref const var, jank_object_ref const dynamic) { auto const var_obj(try_object(reinterpret_cast(var))); auto const dynamic_obj(reinterpret_cast(dynamic)); - return var_obj->set_dynamic(truthy(dynamic_obj)).retain().erase().data; + return var_obj->set_dynamic(truthy(dynamic_obj)).erase().data; } jank_object_ref jank_keyword_intern(jank_object_ref const ns, jank_object_ref const name) @@ -120,7 +120,6 @@ extern "C" auto const name_obj(reinterpret_cast(name)); return __rt_ctx->intern_keyword(to_string(ns_obj), to_string(name_obj)) .expect_ok() - .retain() .erase() .data; } @@ -128,20 +127,20 @@ extern "C" jank_object_ref jank_deref(jank_object_ref const o) { auto const o_obj(reinterpret_cast(o)); - return deref(o_obj).retain().erase().data; + return deref(o_obj).erase().data; } jank_object_ref jank_call0(jank_object_ref const f) { auto const f_obj(reinterpret_cast(f)); - return dynamic_call(f_obj).retain().erase().data; + return dynamic_call(f_obj).erase().data; } jank_object_ref jank_call1(jank_object_ref const f, jank_object_ref const a1) { auto const f_obj(reinterpret_cast(f)); auto const a1_obj(reinterpret_cast(a1)); - return dynamic_call(f_obj, a1_obj).retain().erase().data; + return dynamic_call(f_obj, a1_obj).erase().data; } jank_object_ref @@ -150,7 +149,7 @@ extern "C" auto const f_obj(reinterpret_cast(f)); auto const a1_obj(reinterpret_cast(a1)); auto const a2_obj(reinterpret_cast(a2)); - return dynamic_call(f_obj, a1_obj, a2_obj).retain().erase().data; + return dynamic_call(f_obj, a1_obj, a2_obj).erase().data; } jank_object_ref jank_call3(jank_object_ref const f, @@ -162,7 +161,7 @@ extern "C" auto const a1_obj(reinterpret_cast(a1)); auto const a2_obj(reinterpret_cast(a2)); auto const a3_obj(reinterpret_cast(a3)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj).retain().erase().data; + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj).erase().data; } jank_object_ref jank_call4(jank_object_ref const f, @@ -176,7 +175,7 @@ extern "C" auto const a2_obj(reinterpret_cast(a2)); auto const a3_obj(reinterpret_cast(a3)); auto const a4_obj(reinterpret_cast(a4)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj).retain().erase().data; + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj).erase().data; } jank_object_ref jank_call5(jank_object_ref const f, @@ -192,7 +191,7 @@ extern "C" auto const a3_obj(reinterpret_cast(a3)); auto const a4_obj(reinterpret_cast(a4)); auto const a5_obj(reinterpret_cast(a5)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj).retain().erase().data; + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj).erase().data; } jank_object_ref jank_call6(jank_object_ref const f, @@ -210,10 +209,7 @@ extern "C" auto const a4_obj(reinterpret_cast(a4)); auto const a5_obj(reinterpret_cast(a5)); auto const a6_obj(reinterpret_cast(a6)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj) - .retain() - .erase() - .data; + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj).erase().data; } jank_object_ref jank_call7(jank_object_ref const f, @@ -233,10 +229,7 @@ extern "C" auto const a5_obj(reinterpret_cast(a5)); auto const a6_obj(reinterpret_cast(a6)); auto const a7_obj(reinterpret_cast(a7)); - return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj, a7_obj) - .retain() - .erase() - .data; + return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj, a7_obj).erase().data; } jank_object_ref jank_call8(jank_object_ref const f, @@ -259,7 +252,6 @@ extern "C" auto const a7_obj(reinterpret_cast(a7)); auto const a8_obj(reinterpret_cast(a8)); return dynamic_call(f_obj, a1_obj, a2_obj, a3_obj, a4_obj, a5_obj, a6_obj, a7_obj, a8_obj) - .retain() .erase() .data; } @@ -295,7 +287,6 @@ extern "C" a7_obj, a8_obj, a9_obj) - .retain() .erase() .data; } @@ -334,7 +325,6 @@ extern "C" a8_obj, a9_obj, a10_obj) - .retain() .erase() .data; } @@ -376,46 +366,45 @@ extern "C" a9_obj, a10_obj, try_object(rest_obj)) - .retain() .erase() .data; } jank_object_ref jank_const_nil() { - return jank_nil().erase().data; + return jank_nil().data; } jank_object_ref jank_const_true() { - return jank_true.retain().erase().data; + return jank_true.erase().data; } jank_object_ref jank_const_false() { - return jank_false.retain().erase().data; + return jank_false.erase().data; } jank_object_ref jank_integer_create(jank_i64 const i) { - return make_box(i).retain().erase().data; + return make_box(i).erase().data; } jank_object_ref jank_big_integer_create(char const * const s) { jank_assert(s); - return make_box(s).retain().erase().data; + return make_box(s).erase().data; } jank_object_ref jank_big_decimal_create(char const * const s) { jank_assert(s); - return make_box(s).retain().erase().data; + return make_box(s).erase().data; } jank_object_ref jank_real_create(jank_f64 const r) { - return make_box(r).retain().erase().data; + return make_box(r).erase().data; } jank_object_ref @@ -423,7 +412,6 @@ extern "C" { return make_box(runtime::obj::ratio_data(reinterpret_cast(numerator), reinterpret_cast(denominator))) - .retain() .erase() .data; } @@ -431,41 +419,38 @@ extern "C" jank_object_ref jank_string_create(char const *s) { jank_debug_assert(s); - return make_box(s).retain().erase().data; + return make_box(s).erase().data; } jank_object_ref jank_symbol_create(jank_object_ref const ns, jank_object_ref const name) { auto const ns_obj(reinterpret_cast(ns)); auto const name_obj(reinterpret_cast(name)); - return make_box(ns_obj, name_obj).retain().erase().data; + return make_box(ns_obj, name_obj).erase().data; } jank_object_ref jank_character_create(char const *s) { jank_debug_assert(s); - return make_box(read::parse::get_char_from_literal(s).unwrap()) - .retain() - .erase() - .data; + return make_box(read::parse::get_char_from_literal(s).unwrap()).erase().data; } jank_object_ref jank_regex_create(char const *s) { jank_debug_assert(s); - return make_box(s).retain().erase().data; + return make_box(s).erase().data; } jank_object_ref jank_uuid_create(char const *s) { jank_debug_assert(s); - return make_box(s).retain().erase().data; + return make_box(s).erase().data; } jank_object_ref jank_inst_create(char const *s) { jank_debug_assert(s); - return make_box(s).retain().erase().data; + return make_box(s).erase().data; } jank_object_ref jank_list_create(jank_u64 const size, ...) @@ -485,7 +470,7 @@ extern "C" va_end(args); runtime::detail::native_persistent_list const npl{ v.rbegin(), v.rend() }; - return make_box(std::move(npl)).retain().erase().data; + return make_box(std::move(npl)).erase().data; } jank_object_ref jank_vector_create(jank_u64 const size, ...) @@ -503,7 +488,7 @@ extern "C" } va_end(args); - return trans.to_persistent().retain().erase().data; + return trans.to_persistent().erase().data; } /* TODO: Meta for maps, vectors, sets, symbols, and fns. */ @@ -525,7 +510,7 @@ extern "C" } va_end(args); - return trans.to_persistent().retain().erase().data; + return trans.to_persistent().erase().data; } jank_object_ref jank_set_create(u64 const size, ...) @@ -543,7 +528,7 @@ extern "C" } va_end(args); - return trans.to_persistent().retain().erase().data; + return trans.to_persistent().erase().data; } jank_object_ref jank_box(char const * const type, void const * const o) @@ -1092,6 +1077,6 @@ extern "C" trans.conj_in_place(make_box(arg)); } - return trans.to_persistent().retain().erase().data; + return trans.to_persistent().erase().data; } } diff --git a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp index 0d317a373..fde156db5 100644 --- a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp @@ -126,8 +126,8 @@ namespace jank::codegen llvm::Value *gen(analyze::expr::cpp_new_ref, analyze::expr::function_arity const &); llvm::Value *gen(analyze::expr::cpp_delete_ref, analyze::expr::function_arity const &); - llvm::Value *gen_var(obj::symbol_ref const &qualified_name) const; - llvm::Value *gen_var_root(obj::symbol_ref const &qualified_name, var_root_kind kind) const; + llvm::Value *gen_var(obj::symbol_ref const qualified_name) const; + llvm::Value *gen_var_root(obj::symbol_ref const qualified_name, var_root_kind kind) const; llvm::Value *gen_c_string(jtl::immutable_string const &s) const; void create_function(); @@ -135,22 +135,21 @@ namespace jank::codegen void create_global_ctor() const; llvm::GlobalVariable *create_global_var(jtl::immutable_string const &name) const; - llvm::Value *gen_global(runtime::obj::weak_nil_ref) const; - llvm::Value *gen_global(runtime::obj::nil_ref const &) const; - llvm::Value *gen_global(runtime::obj::boolean_ref const &b) const; - llvm::Value *gen_global(runtime::obj::integer_ref const &i) const; - llvm::Value *gen_global(runtime::obj::big_integer_ref const &i) const; - llvm::Value *gen_global(runtime::obj::big_decimal_ref const &i) const; - llvm::Value *gen_global(runtime::obj::real_ref const &r) const; - llvm::Value *gen_global(runtime::obj::ratio_ref const &r) const; - llvm::Value *gen_global(runtime::obj::persistent_string_ref const &s) const; - llvm::Value *gen_global(runtime::obj::symbol_ref const &s) const; - llvm::Value *gen_global(runtime::obj::keyword_ref const &k) const; - llvm::Value *gen_global(runtime::obj::character_ref const &c) const; - llvm::Value *gen_global(runtime::obj::re_pattern_ref const &re) const; - llvm::Value *gen_global(runtime::obj::uuid_ref const &u) const; - llvm::Value *gen_global(runtime::obj::inst_ref const &i) const; - llvm::Value *gen_global_from_read_string(runtime::object_ref const &o) const; + llvm::Value *gen_global(runtime::obj::nil_ref const ) const; + llvm::Value *gen_global(runtime::obj::boolean_ref const b) const; + llvm::Value *gen_global(runtime::obj::integer_ref const i) const; + llvm::Value *gen_global(runtime::obj::big_integer_ref const i) const; + llvm::Value *gen_global(runtime::obj::big_decimal_ref const i) const; + llvm::Value *gen_global(runtime::obj::real_ref const r) const; + llvm::Value *gen_global(runtime::obj::ratio_ref const r) const; + llvm::Value *gen_global(runtime::obj::persistent_string_ref const s) const; + llvm::Value *gen_global(runtime::obj::symbol_ref const s) const; + llvm::Value *gen_global(runtime::obj::keyword_ref const k) const; + llvm::Value *gen_global(runtime::obj::character_ref const c) const; + llvm::Value *gen_global(runtime::obj::re_pattern_ref const re) const; + llvm::Value *gen_global(runtime::obj::uuid_ref const u) const; + llvm::Value *gen_global(runtime::obj::inst_ref const i) const; + llvm::Value *gen_global_from_read_string(runtime::object_ref const o) const; llvm::Value *gen_function_instance(analyze::expr::function_ref expr, analyze::expr::function_arity const &fn_arity); llvm::Value *gen_aot_call(Cpp::AotCall const &call, @@ -2840,7 +2839,7 @@ namespace jank::codegen return ret; } - llvm::Value *llvm_processor::impl::gen_var(obj::symbol_ref const &qualified_name) const + llvm::Value *llvm_processor::impl::gen_var(obj::symbol_ref const qualified_name) const { auto const found(ctx->var_globals.find(qualified_name)); if(found != ctx->var_globals.end()) @@ -2878,7 +2877,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_var_root(obj::symbol_ref const &qualified_name, + llvm::Value *llvm_processor::impl::gen_var_root(obj::symbol_ref const qualified_name, var_root_kind const kind) const { auto it(ctx->var_root_globals.find(qualified_name)); @@ -2954,12 +2953,7 @@ namespace jank::codegen return ctx->c_string_globals[s] = ctx->builder->CreateGlobalString(s.c_str()); } - llvm::Value *llvm_processor::impl::gen_global(obj::weak_nil_ref const nil) const - { - return gen_global(obj::nil_ref{ nil }); - } - - llvm::Value *llvm_processor::impl::gen_global(obj::nil_ref const &nil) const + llvm::Value *llvm_processor::impl::gen_global(obj::nil_ref const nil) const { auto const found(ctx->literal_globals.find(nil)); if(found != ctx->literal_globals.end()) @@ -2992,7 +2986,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::boolean_ref const &b) const + llvm::Value *llvm_processor::impl::gen_global(obj::boolean_ref const b) const { auto const found(ctx->literal_globals.find(b)); if(found != ctx->literal_globals.end()) @@ -3027,7 +3021,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::integer_ref const &i) const + llvm::Value *llvm_processor::impl::gen_global(obj::integer_ref const i) const { auto const found(ctx->literal_globals.find(i)); if(found != ctx->literal_globals.end()) @@ -3062,7 +3056,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::big_integer_ref const &i) const + llvm::Value *llvm_processor::impl::gen_global(obj::big_integer_ref const i) const { auto const found(ctx->literal_globals.find(i)); if(found != ctx->literal_globals.end()) @@ -3102,7 +3096,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::big_decimal_ref const &i) const + llvm::Value *llvm_processor::impl::gen_global(obj::big_decimal_ref const i) const { auto const found(ctx->literal_globals.find(i)); if(found != ctx->literal_globals.end()) @@ -3139,7 +3133,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::real_ref const &r) const + llvm::Value *llvm_processor::impl::gen_global(obj::real_ref const r) const { auto const found(ctx->literal_globals.find(r)); if(found != ctx->literal_globals.end()) @@ -3174,7 +3168,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::ratio_ref const &r) const + llvm::Value *llvm_processor::impl::gen_global(obj::ratio_ref const r) const { if(auto const found(ctx->literal_globals.find(r)); found != ctx->literal_globals.end()) { @@ -3211,7 +3205,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::persistent_string_ref const &s) const + llvm::Value *llvm_processor::impl::gen_global(obj::persistent_string_ref const s) const { auto const found(ctx->literal_globals.find(s)); if(found != ctx->literal_globals.end()) @@ -3247,7 +3241,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::re_pattern_ref const &re) const + llvm::Value *llvm_processor::impl::gen_global(obj::re_pattern_ref const re) const { auto const found(ctx->literal_globals.find(re)); if(found != ctx->literal_globals.end()) @@ -3283,7 +3277,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::uuid_ref const &u) const + llvm::Value *llvm_processor::impl::gen_global(obj::uuid_ref const u) const { auto const found(ctx->literal_globals.find(u)); if(found != ctx->literal_globals.end()) @@ -3319,7 +3313,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::inst_ref const &i) const + llvm::Value *llvm_processor::impl::gen_global(obj::inst_ref const i) const { auto const found(ctx->literal_globals.find(i)); if(found != ctx->literal_globals.end()) @@ -3355,7 +3349,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::symbol_ref const &s) const + llvm::Value *llvm_processor::impl::gen_global(obj::symbol_ref const s) const { auto const found(ctx->literal_globals.find(s)); if(found != ctx->literal_globals.end()) @@ -3408,7 +3402,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::keyword_ref const &k) const + llvm::Value *llvm_processor::impl::gen_global(obj::keyword_ref const k) const { auto const found(ctx->literal_globals.find(k)); if(found != ctx->literal_globals.end()) @@ -3447,7 +3441,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global(obj::character_ref const &c) const + llvm::Value *llvm_processor::impl::gen_global(obj::character_ref const c) const { auto const found(ctx->literal_globals.find(c)); if(found != ctx->literal_globals.end()) @@ -3484,7 +3478,7 @@ namespace jank::codegen return ctx->builder->CreateLoad(ctx->builder->getPtrTy(), global); } - llvm::Value *llvm_processor::impl::gen_global_from_read_string(object_ref const &o) const + llvm::Value *llvm_processor::impl::gen_global_from_read_string(object_ref const o) const { auto const found(ctx->literal_globals.find(o)); if(found != ctx->literal_globals.end()) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index d01039738..36b76ba77 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -77,7 +77,7 @@ namespace jank::codegen jtl::immutable_string, std::hash, runtime::very_equal_to> &lifted_constants, - object_ref const &o) + object_ref const o) { auto const existing{ lifted_constants.find(o) }; if(existing != lifted_constants.end()) @@ -90,7 +90,7 @@ namespace jank::codegen return native_name; } - static jtl::immutable_string gen_constant_type(runtime::object_ref const &o, bool const boxed) + static jtl::immutable_string gen_constant_type(runtime::object_ref const o, bool const boxed) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" @@ -146,7 +146,7 @@ namespace jank::codegen } static void - gen_constant(runtime::object_ref const &o, jtl::string_builder &buffer, bool const boxed) + gen_constant(runtime::object_ref const o, jtl::string_builder &buffer, bool const boxed) { if(!boxed) { @@ -1801,7 +1801,7 @@ namespace jank::codegen auto const &value_tmp{ gen(expr->value_expr, fn_arity) }; util::format_to(body_buffer, - "switch(jank_shift_mask_case_integer({}.retain().get(), {}, {})) {", + "switch(jank_shift_mask_case_integer({}.get(), {}, {})) {", value_tmp.unwrap().str(true), expr->shift, expr->mask); @@ -1983,7 +1983,7 @@ namespace jank::codegen util::format_to(body_buffer, "{}", arg_tmp.str(true)); if(param_type && Cpp::IsPointerType(param_type) && cpp_util::is_any_object(arg_type)) { - util::format_to(body_buffer, ".retain().get()"); + util::format_to(body_buffer, ".get()"); } need_comma = true; } @@ -2624,7 +2624,7 @@ namespace jank::codegen for(auto const ¶m : arity.params) { util::format_to(body_buffer, - "{} jank::runtime::object_ref const &{}{}", + "{} jank::runtime::object_ref const {}{}", (param_comma ? ", " : ""), runtime::munge(param->name), recur_suffix); @@ -2844,17 +2844,4 @@ namespace jank::codegen } return { expression_buffer.data(), expression_buffer.size() }; } - - jtl::immutable_string processor::expression_fn_str() - { - auto const &expr_str{ expression_str() }; - auto const &fn_name{ runtime::munge(runtime::__rt_ctx->unique_namespaced_string("expr_fn")) }; - jtl::string_builder fn_buffer; - util::format_to(fn_buffer, - "auto {}(){ return {}.retain().get(); } {}()", - fn_name, - expr_str, - fn_name); - return fn_buffer.release(); - } } diff --git a/compiler+runtime/src/cpp/jank/compiler_native.cpp b/compiler+runtime/src/cpp/jank/compiler_native.cpp index 30a87a547..a18aad6e1 100644 --- a/compiler+runtime/src/cpp/jank/compiler_native.cpp +++ b/compiler+runtime/src/cpp/jank/compiler_native.cpp @@ -19,7 +19,7 @@ namespace jank::compiler_native using namespace jank; using namespace jank::runtime; - static object_ref native_source(object_ref const &form) + static object_ref native_source(object_ref const form) { /* We use a clean analyze::processor so we don't share lifted items from other REPL * evaluations. */ diff --git a/compiler+runtime/src/cpp/jank/error.cpp b/compiler+runtime/src/cpp/jank/error.cpp index 087a7d37c..ab54ddba8 100644 --- a/compiler+runtime/src/cpp/jank/error.cpp +++ b/compiler+runtime/src/cpp/jank/error.cpp @@ -234,7 +234,7 @@ namespace jank::error .release(); } - static void add_expansion_note(base &e, runtime::object_ref const &expansion) + static void add_expansion_note(base &e, runtime::object_ref const expansion) { auto source{ runtime::object_source(expansion) }; /* We just want to point at the start of the expansion, not underline the @@ -274,7 +274,7 @@ namespace jank::error base::base(enum kind const k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) : kind{ k } @@ -288,7 +288,7 @@ namespace jank::error base::base(enum kind const k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion, + runtime::object_ref const expansion, std::unique_ptr trace) : kind{ k @@ -330,7 +330,7 @@ namespace jank::error jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const ¬e_message, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) : kind{ k } @@ -364,7 +364,7 @@ namespace jank::error jtl::immutable_string const &message, read::source const &source, note const ¬e, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) : kind{ k } , message{ message } , source{ source } @@ -387,7 +387,7 @@ namespace jank::error base::base(enum kind const k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion, + runtime::object_ref const expansion, jtl::ref const cause) : kind{ k @@ -403,7 +403,7 @@ namespace jank::error base::base(enum kind const k, jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion, + runtime::object_ref const expansion, jtl::ref const cause, std::unique_ptr trace) : kind{ diff --git a/compiler+runtime/src/cpp/jank/error/analyze.cpp b/compiler+runtime/src/cpp/jank/error/analyze.cpp index 48fe128aa..2d04d1d02 100644 --- a/compiler+runtime/src/cpp/jank/error/analyze.cpp +++ b/compiler+runtime/src/cpp/jank/error/analyze.cpp @@ -12,7 +12,7 @@ namespace jank::error { error_ref analyze_invalid_case(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error( kind::analyze_invalid_case, @@ -24,7 +24,7 @@ namespace jank::error error_ref analyze_invalid_def(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_def, message, source, expansion); } @@ -32,21 +32,21 @@ namespace jank::error error_ref analyze_invalid_def(jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const ¬e, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_def, message, source, note, expansion); } error_ref analyze_invalid_fn(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_fn, message, source, expansion); } error_ref analyze_invalid_fn_parameters(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_fn_parameters, message, source, expansion); } @@ -54,7 +54,7 @@ namespace jank::error error_ref analyze_invalid_fn_parameters(jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const &error_note_message, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_fn_parameters, message, @@ -65,49 +65,49 @@ namespace jank::error error_ref analyze_invalid_recur_position(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_recur_position, message, source, expansion); } error_ref analyze_invalid_recur_from_try(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_recur_from_try, message, source, expansion); } error_ref analyze_invalid_recur_args(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_recur_args, message, source, expansion); } error_ref analyze_invalid_let(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_let, message, source, expansion); } error_ref analyze_invalid_letfn(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_letfn, message, source, expansion); } error_ref analyze_invalid_loop(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_loop, message, source, expansion); } error_ref analyze_invalid_if(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_if, message, source, expansion); } @@ -115,35 +115,35 @@ namespace jank::error error_ref analyze_invalid_if(jtl::immutable_string const &message, read::source const &source, jtl::immutable_string const &error_note_message, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_if, message, source, error_note_message, expansion); } error_ref analyze_invalid_quote(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_quote, message, source, expansion); } error_ref analyze_invalid_var_reference(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_var_reference, message, source, expansion); } error_ref analyze_invalid_throw(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_throw, message, source, expansion); } error_ref analyze_invalid_try(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_try, message, source, expansion); } @@ -151,21 +151,21 @@ namespace jank::error error_ref analyze_invalid_try(jtl::immutable_string const &message, read::source const &source, note &&extra, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_try, message, source, jtl::move(extra), expansion); } error_ref analyze_unresolved_var(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_unresolved_var, message, source, expansion); } error_ref analyze_unresolved_symbol(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_unresolved_symbol, message, source, expansion); } @@ -173,7 +173,7 @@ namespace jank::error error_ref analyze_macro_expansion_exception(std::exception const &e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_macro_expansion_exception, e.what(), @@ -182,10 +182,10 @@ namespace jank::error std::make_unique(trace)); } - error_ref analyze_macro_expansion_exception(runtime::object_ref const &e, + error_ref analyze_macro_expansion_exception(runtime::object_ref const e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_macro_expansion_exception, e->type == runtime::object_type::persistent_string @@ -199,7 +199,7 @@ namespace jank::error error_ref analyze_macro_expansion_exception(jtl::immutable_string const &e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_macro_expansion_exception, e, @@ -211,7 +211,7 @@ namespace jank::error error_ref analyze_macro_expansion_exception(error_ref const e, cpptrace::stacktrace const &trace, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_macro_expansion_exception, /* TODO: Macro name. */ @@ -229,28 +229,28 @@ namespace jank::error error_ref analyze_invalid_cpp_operator_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_operator_call, message, source, expansion); } error_ref analyze_invalid_cpp_constructor_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_constructor_call, message, source, expansion); } error_ref analyze_invalid_cpp_member_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_member_call, message, source, expansion); } error_ref analyze_invalid_cpp_capture(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_capture, message, @@ -261,125 +261,125 @@ namespace jank::error error_ref analyze_mismatched_if_types(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_mismatched_if_types, message, source, expansion); } error_ref analyze_invalid_cpp_function_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_function_call, message, source, expansion); } error_ref analyze_invalid_cpp_call(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_call, message, source, expansion); } error_ref analyze_invalid_cpp_conversion(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_conversion, message, source, expansion); } error_ref analyze_invalid_cpp_symbol(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_symbol, message, source, expansion); } error_ref analyze_unresolved_cpp_symbol(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_unresolved_cpp_symbol, message, source, expansion); } error_ref analyze_invalid_cpp_raw(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_raw, message, source, expansion); } error_ref analyze_invalid_cpp_type(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_type, message, source, expansion); } error_ref analyze_invalid_cpp_value(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_value, message, source, expansion); } error_ref analyze_invalid_cpp_cast(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_cast, message, source, expansion); } error_ref analyze_invalid_cpp_box(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_box, message, source, expansion); } error_ref analyze_invalid_cpp_unbox(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_unbox, message, source, expansion); } error_ref analyze_invalid_cpp_new(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_new, message, source, expansion); } error_ref analyze_invalid_cpp_delete(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_delete, message, source, expansion); } error_ref analyze_invalid_cpp_member_access(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_invalid_cpp_member_access, message, source, expansion); } error_ref analyze_known_issue(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::analyze_known_issue, message, source, expansion); } error_ref internal_analyze_failure(jtl::immutable_string const &message, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::internal_analyze_failure, message, read::source::unknown(), expansion); } error_ref internal_analyze_failure(jtl::immutable_string const &message, read::source const &source, - runtime::object_ref const &expansion) + runtime::object_ref const expansion) { return make_error(kind::internal_analyze_failure, message, source, expansion); } diff --git a/compiler+runtime/src/cpp/jank/evaluate.cpp b/compiler+runtime/src/cpp/jank/evaluate.cpp index 0917137d2..ba79af473 100644 --- a/compiler+runtime/src/cpp/jank/evaluate.cpp +++ b/compiler+runtime/src/cpp/jank/evaluate.cpp @@ -604,11 +604,10 @@ namespace jank::evaluate } __rt_ctx->jit_prc.eval_string(cg_prc.declaration_str()); - auto const expr_str{ cg_prc.expression_fn_str() }; + auto const expr_str{ cg_prc.expression_str() + ".erase().data" }; clang::Value v; __rt_ctx->jit_prc.eval_string({ expr_str.data(), expr_str.size() }, &v); auto ret{ try_object(v.convertTo()) }; - ret.release(); return ret; } } diff --git a/compiler+runtime/src/cpp/jank/hash.cpp b/compiler+runtime/src/cpp/jank/hash.cpp index 965e311db..c222e8f01 100644 --- a/compiler+runtime/src/cpp/jank/hash.cpp +++ b/compiler+runtime/src/cpp/jank/hash.cpp @@ -153,14 +153,14 @@ namespace jank::hash return static_cast(ch); } - u32 visit(runtime::object_ref const &o) + u32 visit(runtime::object_ref const o) { return runtime::visit_object([](auto const typed_o) -> u32 { return typed_o->to_hash(); }, o); } template requires runtime::behavior::object_like - static u32 visit(runtime::oref const &o) + static u32 visit(runtime::oref const o) { return o->to_hash(); } diff --git a/compiler+runtime/src/cpp/jank/read/parse.cpp b/compiler+runtime/src/cpp/jank/read/parse.cpp index f3121cba0..07bde35b0 100644 --- a/compiler+runtime/src/cpp/jank/read/parse.cpp +++ b/compiler+runtime/src/cpp/jank/read/parse.cpp @@ -536,7 +536,7 @@ namespace jank::read::parse } auto meta_result(visit_object( - [&](auto const &typed_val) -> processor::object_result { + [&](auto const typed_val) -> processor::object_result { using T = typename jtl::decay_t::value_type; if constexpr(jtl::is_same) { @@ -571,7 +571,7 @@ namespace jank::read::parse } return visit_object( - [&](auto const &typed_val) -> processor::object_result { + [&](auto const typed_val) -> processor::object_result { using T = typename jtl::decay_t::value_type; if constexpr(behavior::metadatable) { @@ -1082,7 +1082,7 @@ namespace jank::read::parse auto const s(*(++it)); return visit_seqable( - [&](auto const &typed_s) -> processor::object_result { + [&](auto const typed_s) -> processor::object_result { auto const r{ make_sequence_range(typed_s) }; if(r.begin() == r.end()) { @@ -1115,7 +1115,7 @@ namespace jank::read::parse return ok(none); } - jtl::result processor::syntax_quote_expand_seq(object_ref const &seq) + jtl::result processor::syntax_quote_expand_seq(object_ref const seq) { if(seq.is_nil()) { @@ -1123,7 +1123,7 @@ namespace jank::read::parse } return visit_seqable( - [this](auto const &typed_seq) -> jtl::result { + [this](auto const typed_seq) -> jtl::result { runtime::detail::native_transient_vector ret; for(auto const item : make_sequence_range(typed_seq)) { @@ -1160,7 +1160,7 @@ namespace jank::read::parse seq); } - jtl::result processor::syntax_quote_flatten_map(object_ref const &seq) + jtl::result processor::syntax_quote_flatten_map(object_ref const seq) { if(seq.is_nil()) { @@ -1168,7 +1168,7 @@ namespace jank::read::parse } return visit_seqable( - [](auto const &typed_seq) -> jtl::result { + [](auto const typed_seq) -> jtl::result { runtime::detail::native_transient_vector ret; for(auto const item : make_sequence_range(typed_seq)) { @@ -1184,7 +1184,7 @@ namespace jank::read::parse seq); } - jtl::result processor::syntax_quote_expand_set(object_ref const &seq) + jtl::result processor::syntax_quote_expand_set(object_ref const seq) { if(seq.is_nil()) { @@ -1192,7 +1192,7 @@ namespace jank::read::parse } return visit_seqable( - [this](auto const &typed_seq) -> jtl::result { + [this](auto const typed_seq) -> jtl::result { runtime::detail::native_transient_vector ret; for(auto const item : make_sequence_range(typed_seq)) { @@ -1229,10 +1229,10 @@ namespace jank::read::parse seq); } - bool processor::syntax_quote_is_unquote(object_ref const &form, bool const splice) + bool processor::syntax_quote_is_unquote(object_ref const form, bool const splice) { return visit_seqable( - [splice](auto const &typed_form) { + [splice](auto const typed_form) { auto const s(typed_form->seq()); object_ref const item{ s.is_some() ? first(s).erase() : s.erase() }; @@ -1243,7 +1243,7 @@ namespace jank::read::parse form); } - jtl::result processor::syntax_quote(object_ref const &form) + jtl::result processor::syntax_quote(object_ref const form) { object_ref ret{}; @@ -1311,7 +1311,7 @@ namespace jank::read::parse * flattening them, qualifying the symbols, and then building up code which will * reassemble them. */ auto const res{ visit_seqable( - [&](auto const &typed_form) -> jtl::result { + [&](auto const typed_form) -> jtl::result { using T = typename jtl::decay_t::value_type; if constexpr(jtl::is_same) diff --git a/compiler+runtime/src/cpp/jank/read/reparse.cpp b/compiler+runtime/src/cpp/jank/read/reparse.cpp index 67d02523f..9c28dd06c 100644 --- a/compiler+runtime/src/cpp/jank/read/reparse.cpp +++ b/compiler+runtime/src/cpp/jank/read/reparse.cpp @@ -16,7 +16,7 @@ namespace jank::read::parse jtl::immutable_string const &module, usize const offset, usize const n, - object_ref const ¯o_expansion) + object_ref const macro_expansion) { if(module == no_source_path) { @@ -62,7 +62,7 @@ namespace jank::read::parse return source{ file, module, res.start.start, res.end.end, macro_expansion }; } - source reparse_nth(obj::persistent_list_ref const &o, usize const n) + source reparse_nth(obj::persistent_list_ref const o, usize const n) { auto source(object_source(o)); if(source == source::unknown()) @@ -81,7 +81,7 @@ namespace jank::read::parse return res.expect_ok(); } - source reparse_nth(runtime::obj::persistent_vector_ref const &o, usize const n) + source reparse_nth(runtime::obj::persistent_vector_ref const o, usize const n) { auto source(object_source(o)); if(source == source::unknown()) @@ -100,14 +100,14 @@ namespace jank::read::parse return res.expect_ok(); } - source reparse_nth(runtime::object_ref const &o, usize const n) + source reparse_nth(runtime::object_ref const o, usize const n) { /* When we have an object, but we're not sure of the type, let's just * see if it's one of the types we support. If not, we'll error out. * We can do more here, going forward, by supporting various sequences and such, * but this will be fine for now. */ return visit_seqable( - [](auto const &typed_o, usize const n) -> source { + [](auto const typed_o, usize const n) -> source { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as diff --git a/compiler+runtime/src/cpp/jank/read/source.cpp b/compiler+runtime/src/cpp/jank/read/source.cpp index fc666cb40..b4457208a 100644 --- a/compiler+runtime/src/cpp/jank/read/source.cpp +++ b/compiler+runtime/src/cpp/jank/read/source.cpp @@ -45,7 +45,7 @@ namespace jank::read jtl::immutable_string const &module, source_position const &start, source_position const &end, - runtime::object_ref const ¯o_expansion) + runtime::object_ref const macro_expansion) : file{ file } , module{ module } , start{ start } diff --git a/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp b/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp index 7607775c8..bc5a5c261 100644 --- a/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp @@ -19,11 +19,11 @@ namespace jank::runtime return source; } - object_ref dynamic_call(object_ref const &source) + object_ref dynamic_call(object_ref const source) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const &typed_source) -> object_ref { + [=](auto const typed_source) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) @@ -47,11 +47,11 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const &source, object_ref const &a1) + object_ref dynamic_call(object_ref const source, object_ref const a1) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const &typed_source) -> object_ref { + [=](auto const typed_source) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) @@ -91,11 +91,11 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const &source, object_ref const &a1, object_ref const &a2) + object_ref dynamic_call(object_ref const source, object_ref const a1, object_ref const a2) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const &typed_source) -> object_ref { + [=](auto const typed_source) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) @@ -134,14 +134,14 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const &source, - object_ref const &a1, - object_ref const &a2, - object_ref const &a3) + object_ref dynamic_call(object_ref const source, + object_ref const a1, + object_ref const a2, + object_ref const a3) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const &typed_source) -> object_ref { + [=](auto const typed_source) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) @@ -175,15 +175,15 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const &source, - object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4) + object_ref dynamic_call(object_ref const source, + object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const &typed_source) -> object_ref { + [=](auto const typed_source) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) @@ -219,16 +219,16 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const &source, - object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5) + object_ref dynamic_call(object_ref const source, + object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const &typed_source) -> object_ref { + [=](auto const typed_source) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) @@ -266,17 +266,17 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const &source, - object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6) + object_ref dynamic_call(object_ref const source, + object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const &typed_source) -> object_ref { + [=](auto const typed_source) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) @@ -328,18 +328,18 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const &source, - object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7) + object_ref dynamic_call(object_ref const source, + object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const &typed_source) -> object_ref { + [=](auto const typed_source) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) @@ -395,19 +395,19 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const &source, - object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7, - object_ref const &a8) + object_ref dynamic_call(object_ref const source, + object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7, + object_ref const a8) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const &typed_source) -> object_ref { + [=](auto const typed_source) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) @@ -467,20 +467,20 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const &source, - object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7, - object_ref const &a8, - object_ref const &a9) + object_ref dynamic_call(object_ref const source, + object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7, + object_ref const a8, + object_ref const a9) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const &typed_source) -> object_ref { + [=](auto const typed_source) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) @@ -541,21 +541,21 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const &source, - object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7, - object_ref const &a8, - object_ref const &a9, - object_ref const &a10) + object_ref dynamic_call(object_ref const source, + object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7, + object_ref const a8, + object_ref const a9, + object_ref const a10) { auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const &typed_source) -> object_ref { + [=](auto const typed_source) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) @@ -662,23 +662,23 @@ namespace jank::runtime processed_source); } - object_ref dynamic_call(object_ref const &source, - object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7, - object_ref const &a8, - object_ref const &a9, - object_ref const &a10, - obj::persistent_list_ref const &rest) + object_ref dynamic_call(object_ref const source, + object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7, + object_ref const a8, + object_ref const a9, + object_ref const a10, + obj::persistent_list_ref const rest) { /* TODO: Move call fns into var so we can remove these checks. */ auto const processed_source(pass_through_vars(source)); return visit_object( - [=](auto const &typed_source) -> object_ref { + [=](auto const typed_source) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(function_like || std::is_base_of_v) @@ -827,10 +827,10 @@ namespace jank::runtime processed_source); } - object_ref apply_to(object_ref const &source, object_ref const &args) + object_ref apply_to(object_ref const source, object_ref const args) { return visit_seqable( - [=](auto const &typed_args) -> object_ref { + [=](auto const typed_args) -> object_ref { auto const s(typed_args->fresh_seq()); auto const length(sequence_length(s, max_params + 1)); auto const r{ make_sequence_range(s) }; @@ -975,92 +975,92 @@ namespace jank::runtime throw invalid_arity<0>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const &) + object_ref callable::call(object_ref const ) { throw invalid_arity<1>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const &, object_ref const &) + object_ref callable::call(object_ref const , object_ref const ) { throw invalid_arity<2>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const &, object_ref const &, object_ref const &) + object_ref callable::call(object_ref const , object_ref const , object_ref const ) { throw invalid_arity<3>{ runtime::to_code_string(this_object_ref()) }; } object_ref - callable::call(object_ref const &, object_ref const &, object_ref const &, object_ref const &) + callable::call(object_ref const , object_ref const , object_ref const , object_ref const ) { throw invalid_arity<4>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) + object_ref callable::call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) { throw invalid_arity<5>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) + object_ref callable::call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) { throw invalid_arity<6>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) + object_ref callable::call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) { throw invalid_arity<7>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) + object_ref callable::call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) { throw invalid_arity<8>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) + object_ref callable::call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) { throw invalid_arity<9>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &, - object_ref const &) + object_ref callable::call(object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const , + object_ref const ) { throw invalid_arity<10>{ runtime::to_code_string(this_object_ref()) }; } diff --git a/compiler+runtime/src/cpp/jank/runtime/behavior/metadatable.cpp b/compiler+runtime/src/cpp/jank/runtime/behavior/metadatable.cpp index c37aef25b..65c8ca205 100644 --- a/compiler+runtime/src/cpp/jank/runtime/behavior/metadatable.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/behavior/metadatable.cpp @@ -6,7 +6,7 @@ namespace jank::runtime::behavior::detail { - object_ref validate_meta(object_ref const &m) + object_ref validate_meta(object_ref const m) { if(!is_map(m) && m.is_some()) { diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 1d677c6bb..52c77e28e 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -92,7 +92,7 @@ namespace jank::runtime .expect_ok(); } - obj::symbol_ref context::qualify_symbol(obj::symbol_ref const &sym) const + obj::symbol_ref context::qualify_symbol(obj::symbol_ref const sym) const { obj::symbol_ref qualified_sym{ sym }; if(qualified_sym->ns.empty()) @@ -103,7 +103,7 @@ namespace jank::runtime return qualified_sym; } - var_ref context::find_var(obj::symbol_ref const &sym) + var_ref context::find_var(obj::symbol_ref const sym) { profile::timer const timer{ "rt find_var" }; if(!sym->ns.empty()) @@ -133,7 +133,7 @@ namespace jank::runtime return find_var(make_box(ns, name)); } - jtl::option context::find_local(obj::symbol_ref const &) + jtl::option context::find_local(obj::symbol_ref const ) { return none; } @@ -361,7 +361,7 @@ namespace jank::runtime return load_module(util::format("/{}", module), module::origin::latest); } - object_ref context::eval(object_ref const &o) + object_ref context::eval(object_ref const o) { auto const expr( analyze::pass::optimize(an_prc.analyze(o, analyze::expression_position::value).expect_ok())); @@ -462,7 +462,7 @@ namespace jank::runtime return intern_ns(make_box(name)); } - ns_ref context::intern_ns(obj::symbol_ref const &sym) + ns_ref context::intern_ns(obj::symbol_ref const sym) { if(!sym->ns.empty()) { @@ -480,7 +480,7 @@ namespace jank::runtime return result.first->second; } - ns_ref context::remove_ns(obj::symbol_ref const &sym) + ns_ref context::remove_ns(obj::symbol_ref const sym) { auto locked_namespaces(namespaces.wlock()); auto const found(locked_namespaces->find(sym)); @@ -493,7 +493,7 @@ namespace jank::runtime return {}; } - ns_ref context::find_ns(obj::symbol_ref const &sym) + ns_ref context::find_ns(obj::symbol_ref const sym) { auto locked_namespaces(namespaces.rlock()); auto const found(locked_namespaces->find(sym)); @@ -504,7 +504,7 @@ namespace jank::runtime return {}; } - ns_ref context::resolve_ns(obj::symbol_ref const &target) + ns_ref context::resolve_ns(obj::symbol_ref const target) { auto const ns(current_ns()); auto alias(ns->find_alias(target)); @@ -534,7 +534,7 @@ namespace jank::runtime } jtl::result - context::intern_var(obj::symbol_ref const &qualified_name) + context::intern_var(obj::symbol_ref const qualified_name) { profile::timer const timer{ "intern_var" }; if(qualified_name->ns.empty()) @@ -567,7 +567,7 @@ namespace jank::runtime } jtl::result - context::intern_owned_var(obj::symbol_ref const &qualified_sym) + context::intern_owned_var(obj::symbol_ref const qualified_sym) { /* TODO: Clean up duplication between this and intern_var. */ profile::timer const timer{ "intern_var" }; @@ -632,11 +632,11 @@ namespace jank::runtime return res.first->second; } - object_ref context::macroexpand1(object_ref const &o) + object_ref context::macroexpand1(object_ref const o) { profile::timer const timer{ "rt macroexpand1" }; return visit_seqable( - [this](auto const &typed_o) -> object_ref { + [this](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(!behavior::sequenceable) @@ -674,7 +674,7 @@ namespace jank::runtime o); } - object_ref context::macroexpand(object_ref const &o) + object_ref context::macroexpand(object_ref const o) { auto expanded(macroexpand1(o)); if(expanded != o) @@ -701,7 +701,7 @@ namespace jank::runtime __rt_ctx->push_thread_bindings().expect_ok(); } - context::binding_scope::binding_scope(obj::persistent_hash_map_ref const &bindings) + context::binding_scope::binding_scope(obj::persistent_hash_map_ref const bindings) { __rt_ctx->push_thread_bindings(bindings).expect_ok(); } @@ -735,7 +735,7 @@ namespace jank::runtime return push_thread_bindings(bindings); } - jtl::string_result context::push_thread_bindings(object_ref const &bindings) + jtl::string_result context::push_thread_bindings(object_ref const bindings) { if(bindings->type != object_type::persistent_hash_map) { @@ -747,7 +747,7 @@ namespace jank::runtime } jtl::string_result - context::push_thread_bindings(obj::persistent_hash_map_ref const &bindings) + context::push_thread_bindings(obj::persistent_hash_map_ref const bindings) { thread_binding_frame frame{ obj::persistent_hash_map::empty() }; auto &tbfs(thread_binding_frames); diff --git a/compiler+runtime/src/cpp/jank/runtime/core.cpp b/compiler+runtime/src/cpp/jank/runtime/core.cpp index e6c0b1d46..0bafd044d 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core.cpp @@ -9,60 +9,60 @@ namespace jank::runtime { - jtl::immutable_string type(object_ref const &o) + jtl::immutable_string type(object_ref const o) { return object_type_str(o->type); } - bool is_nil(object_ref const &o) + bool is_nil(object_ref const o) { return o == jank_nil(); } - bool is_true(object_ref const &o) + bool is_true(object_ref const o) { return o == jank_true; } - bool is_false(object_ref const &o) + bool is_false(object_ref const o) { return o == jank_false; } - bool is_some(object_ref const &o) + bool is_some(object_ref const o) { return o != jank_nil(); } - bool is_string(object_ref const &o) + bool is_string(object_ref const o) { return o->type == object_type::persistent_string; } - bool is_char(object_ref const &o) + bool is_char(object_ref const o) { return o->type == object_type::character; } - bool is_symbol(object_ref const &o) + bool is_symbol(object_ref const o) { return o->type == object_type::symbol; } - bool is_simple_symbol(object_ref const &o) + bool is_simple_symbol(object_ref const o) { return o->type == object_type::symbol && expect_object(o)->ns.empty(); } - bool is_qualified_symbol(object_ref const &o) + bool is_qualified_symbol(object_ref const o) { return o->type == object_type::symbol && !expect_object(o)->ns.empty(); } - object_ref to_unqualified_symbol(object_ref const &o) + object_ref to_unqualified_symbol(object_ref const o) { return runtime::visit_object( - [&](auto const &typed_o) -> object_ref { + [&](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -90,15 +90,15 @@ namespace jank::runtime o); } - object_ref to_qualified_symbol(object_ref const &ns, object_ref const &name) + object_ref to_qualified_symbol(object_ref const ns, object_ref const name) { return make_box(ns, name); } - object_ref print(object_ref const &args) + object_ref print(object_ref const args) { visit_object( - [](auto const &typed_args) { + [](auto const typed_args) { using T = typename jtl::decay_t::value_type; if constexpr(behavior::sequenceable) @@ -122,10 +122,10 @@ namespace jank::runtime return jank_nil(); } - object_ref println(object_ref const &args) + object_ref println(object_ref const args) { visit_object( - [](auto const &typed_more) { + [](auto const typed_more) { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -154,10 +154,10 @@ namespace jank::runtime return jank_nil(); } - object_ref pr(object_ref const &args) + object_ref pr(object_ref const args) { visit_object( - [](auto const &typed_args) { + [](auto const typed_args) { using T = typename jtl::decay_t::value_type; if constexpr(behavior::sequenceable) @@ -181,10 +181,10 @@ namespace jank::runtime return jank_nil(); } - object_ref prn(object_ref const &args) + object_ref prn(object_ref const args) { visit_object( - [](auto const &typed_args) { + [](auto const typed_args) { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -213,10 +213,10 @@ namespace jank::runtime return jank_nil(); } - obj::persistent_string_ref subs(object_ref const &s, object_ref const &start) + obj::persistent_string_ref subs(object_ref const s, object_ref const start) { return visit_type( - [](auto const &typed_s, i64 const start) -> obj::persistent_string_ref { + [](auto const typed_s, i64 const start) -> obj::persistent_string_ref { return typed_s->substring(start).expect_ok(); }, s, @@ -224,10 +224,10 @@ namespace jank::runtime } obj::persistent_string_ref - subs(object_ref const &s, object_ref const &start, object_ref const &end) + subs(object_ref const s, object_ref const start, object_ref const end) { return visit_type( - [](auto const &typed_s, i64 const start, i64 const end) -> obj::persistent_string_ref { + [](auto const typed_s, i64 const start, i64 const end) -> obj::persistent_string_ref { return typed_s->substring(start, end).expect_ok(); }, s, @@ -235,26 +235,26 @@ namespace jank::runtime to_int(end)); } - i64 first_index_of(object_ref const &s, object_ref const &m) + i64 first_index_of(object_ref const s, object_ref const m) { return visit_type( - [](auto const &typed_s, object_ref const &m) -> i64 { return typed_s->first_index_of(m); }, + [](auto const typed_s, object_ref const m) -> i64 { return typed_s->first_index_of(m); }, s, m); } - i64 last_index_of(object_ref const &s, object_ref const &m) + i64 last_index_of(object_ref const s, object_ref const m) { return visit_type( - [](auto const &typed_s, object_ref const &m) -> i64 { return typed_s->last_index_of(m); }, + [](auto const typed_s, object_ref const m) -> i64 { return typed_s->last_index_of(m); }, s, m); } - bool is_named(object_ref const &o) + bool is_named(object_ref const o) { return visit_object( - [](auto const &typed_o) { + [](auto const typed_o) { using T = typename jtl::decay_t::value_type; return behavior::nameable; @@ -262,10 +262,10 @@ namespace jank::runtime o); } - jtl::immutable_string name(object_ref const &o) + jtl::immutable_string name(object_ref const o) { return visit_object( - [](auto const &typed_o) -> jtl::immutable_string { + [](auto const typed_o) -> jtl::immutable_string { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -284,10 +284,10 @@ namespace jank::runtime o); } - object_ref namespace_(object_ref const &o) + object_ref namespace_(object_ref const o) { return visit_object( - [](auto const &typed_o) -> object_ref { + [](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::nameable) @@ -307,7 +307,7 @@ namespace jank::runtime o); } - object_ref keyword(object_ref const &ns, object_ref const &name) + object_ref keyword(object_ref const ns, object_ref const name) { if(!ns.is_nil() && ns->type != object_type::persistent_string) { @@ -330,25 +330,25 @@ namespace jank::runtime return __rt_ctx->intern_keyword(runtime::to_string(ns), runtime::to_string(name)).expect_ok(); } - bool is_keyword(object_ref const &o) + bool is_keyword(object_ref const o) { return o->type == object_type::keyword; } - bool is_simple_keyword(object_ref const &o) + bool is_simple_keyword(object_ref const o) { return o->type == object_type::keyword && expect_object(o)->sym->ns.empty(); } - bool is_qualified_keyword(object_ref const &o) + bool is_qualified_keyword(object_ref const o) { return o->type == object_type::keyword && !expect_object(o)->sym->ns.empty(); } - bool is_callable(object_ref const &o) + bool is_callable(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> bool { + [=](auto const typed_o) -> bool { using T = typename jtl::decay_t::value_type; return std::is_base_of_v; @@ -356,105 +356,105 @@ namespace jank::runtime o); } - uhash to_hash(object_ref const &o) + uhash to_hash(object_ref const o) { - return visit_object([=](auto const &typed_o) -> uhash { return typed_o->to_hash(); }, o); + return visit_object([=](auto const typed_o) -> uhash { return typed_o->to_hash(); }, o); } - object_ref macroexpand1(object_ref const &o) + object_ref macroexpand1(object_ref const o) { return __rt_ctx->macroexpand1(o); } - object_ref macroexpand(object_ref const &o) + object_ref macroexpand(object_ref const o) { return __rt_ctx->macroexpand(o); } - object_ref gensym(object_ref const &o) + object_ref gensym(object_ref const o) { return __rt_ctx->unique_symbol(to_string(o)); } - object_ref atom(object_ref const &o) + object_ref atom(object_ref const o) { return make_box(o); } - object_ref swap_atom(object_ref const &atom, object_ref const &fn) + object_ref swap_atom(object_ref const atom, object_ref const fn) { return try_object(atom)->swap(fn); } - object_ref swap_atom(object_ref const &atom, object_ref const &fn, object_ref const &a1) + object_ref swap_atom(object_ref const atom, object_ref const fn, object_ref const a1) { return try_object(atom)->swap(fn, a1); } - object_ref swap_atom(object_ref const &atom, - object_ref const &fn, - object_ref const &a1, - object_ref const &a2) + object_ref swap_atom(object_ref const atom, + object_ref const fn, + object_ref const a1, + object_ref const a2) { return try_object(atom)->swap(fn, a1, a2); } - object_ref swap_atom(object_ref const &atom, - object_ref const &fn, - object_ref const &a1, - object_ref const &a2, - object_ref const &rest) + object_ref swap_atom(object_ref const atom, + object_ref const fn, + object_ref const a1, + object_ref const a2, + object_ref const rest) { return try_object(atom)->swap(fn, a1, a2, rest); } - object_ref swap_vals(object_ref const &atom, object_ref const &fn) + object_ref swap_vals(object_ref const atom, object_ref const fn) { return try_object(atom)->swap_vals(fn); } - object_ref swap_vals(object_ref const &atom, object_ref const &fn, object_ref const &a1) + object_ref swap_vals(object_ref const atom, object_ref const fn, object_ref const a1) { return try_object(atom)->swap_vals(fn, a1); } - object_ref swap_vals(object_ref const &atom, - object_ref const &fn, - object_ref const &a1, - object_ref const &a2) + object_ref swap_vals(object_ref const atom, + object_ref const fn, + object_ref const a1, + object_ref const a2) { return try_object(atom)->swap_vals(fn, a1, a2); } - object_ref swap_vals(object_ref const &atom, - object_ref const &fn, - object_ref const &a1, - object_ref const &a2, - object_ref const &rest) + object_ref swap_vals(object_ref const atom, + object_ref const fn, + object_ref const a1, + object_ref const a2, + object_ref const rest) { return try_object(atom)->swap_vals(fn, a1, a2, rest); } object_ref - compare_and_set(object_ref const &atom, object_ref const &old_val, object_ref const &new_val) + compare_and_set(object_ref const atom, object_ref const old_val, object_ref const new_val) { return try_object(atom)->compare_and_set(old_val, new_val); } - object_ref reset(object_ref const &atom, object_ref const &new_val) + object_ref reset(object_ref const atom, object_ref const new_val) { return try_object(atom)->reset(new_val); } - object_ref reset_vals(object_ref const &atom, object_ref const &new_val) + object_ref reset_vals(object_ref const atom, object_ref const new_val) { return try_object(atom)->reset_vals(new_val); } - object_ref deref(object_ref const &o) + object_ref deref(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> object_ref { + [=](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::derefable) @@ -469,34 +469,34 @@ namespace jank::runtime o); } - object_ref volatile_(object_ref const &o) + object_ref volatile_(object_ref const o) { return make_box(o); } - bool is_volatile(object_ref const &o) + bool is_volatile(object_ref const o) { return o->type == object_type::volatile_; } - object_ref vswap(object_ref const &v, object_ref const &fn) + object_ref vswap(object_ref const v, object_ref const fn) { auto const v_obj(try_object(v)); return v_obj->reset(dynamic_call(fn, v_obj->deref())); } - object_ref vswap(object_ref const &v, object_ref const &fn, object_ref const &args) + object_ref vswap(object_ref const v, object_ref const fn, object_ref const args) { auto const v_obj(try_object(v)); return v_obj->reset(apply_to(fn, make_box(v_obj->deref(), args))); } - object_ref vreset(object_ref const &v, object_ref const &new_val) + object_ref vreset(object_ref const v, object_ref const new_val) { return try_object(v)->reset(new_val); } - void push_thread_bindings(object_ref const &o) + void push_thread_bindings(object_ref const o) { __rt_ctx->push_thread_bindings(o).expect_ok(); } @@ -511,7 +511,7 @@ namespace jank::runtime return __rt_ctx->get_thread_bindings(); } - object_ref force(object_ref const &o) + object_ref force(object_ref const o) { if(o->type == object_type::delay) { @@ -520,22 +520,22 @@ namespace jank::runtime return o; } - object_ref tagged_literal(object_ref const &tag, object_ref const &form) + object_ref tagged_literal(object_ref const tag, object_ref const form) { return make_box(tag, form); } - bool is_tagged_literal(object_ref const &o) + bool is_tagged_literal(object_ref const o) { return o->type == object_type::tagged_literal; } - object_ref re_pattern(object_ref const &o) + object_ref re_pattern(object_ref const o) { return make_box(try_object(o)->data); } - object_ref re_matcher(object_ref const &re, object_ref const &s) + object_ref re_matcher(object_ref const re, object_ref const s) { return make_box(try_object(re), try_object(s)->data); @@ -568,7 +568,7 @@ namespace jank::runtime } } - object_ref re_find(object_ref const &m) + object_ref re_find(object_ref const m) { std::smatch match_results{}; auto const matcher(try_object(m)); @@ -586,7 +586,7 @@ namespace jank::runtime return matcher->groups; } - object_ref re_groups(object_ref const &m) + object_ref re_groups(object_ref const m) { auto const matcher(try_object(m)); @@ -598,7 +598,7 @@ namespace jank::runtime return matcher->groups; } - object_ref re_matches(object_ref const &re, object_ref const &s) + object_ref re_matches(object_ref const re, object_ref const s) { std::smatch match_results{}; std::string const search_str{ try_object(s)->data.c_str() }; @@ -616,7 +616,7 @@ namespace jank::runtime return smatch_to_vector(match_results); } - object_ref parse_uuid(object_ref const &o) + object_ref parse_uuid(object_ref const o) { if(o->type == object_type::persistent_string) { @@ -635,7 +635,7 @@ namespace jank::runtime } } - bool is_uuid(object_ref const &o) + bool is_uuid(object_ref const o) { return o->type == object_type::uuid; } @@ -645,12 +645,12 @@ namespace jank::runtime return make_box(); } - bool is_inst(object_ref const &o) + bool is_inst(object_ref const o) { return o->type == object_type::inst; } - i64 inst_ms(object_ref const &o) + i64 inst_ms(object_ref const o) { if(o->type != object_type::inst) { @@ -663,10 +663,10 @@ namespace jank::runtime .count(); } - object_ref add_watch(object_ref const &reference, object_ref const &key, object_ref const &fn) + object_ref add_watch(object_ref const reference, object_ref const key, object_ref const fn) { visit_object( - [=](auto const &typed_reference) -> void { + [=](auto const typed_reference) -> void { using T = typename jtl::decay_t::value_type; if constexpr(behavior::ref_like) @@ -685,10 +685,10 @@ namespace jank::runtime return reference; } - object_ref remove_watch(object_ref const &reference, object_ref const &key) + object_ref remove_watch(object_ref const reference, object_ref const key) { visit_object( - [=](auto const &typed_reference) -> void { + [=](auto const typed_reference) -> void { using T = typename jtl::decay_t::value_type; if constexpr(behavior::ref_like) diff --git a/compiler+runtime/src/cpp/jank/runtime/core/equal.cpp b/compiler+runtime/src/cpp/jank/runtime/core/equal.cpp index a493bf44d..2805af947 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/equal.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/equal.cpp @@ -5,7 +5,7 @@ namespace jank::runtime { - bool equal(char const lhs, object_ref const &rhs) + bool equal(char const lhs, object_ref const rhs) { if(rhs.is_nil() || rhs->type != object_type::character) { @@ -16,7 +16,7 @@ namespace jank::runtime return typed_rhs->to_hash() == static_cast(lhs); } - bool equal(object_ref const &lhs, object_ref const &rhs) + bool equal(object_ref const lhs, object_ref const rhs) { if(lhs.is_nil()) { @@ -27,10 +27,10 @@ namespace jank::runtime return false; } - return visit_object([&](auto const &typed_lhs) { return typed_lhs->equal(*rhs); }, lhs); + return visit_object([&](auto const typed_lhs) { return typed_lhs->equal(*rhs); }, lhs); } - i64 compare(object_ref const &l, object_ref const &r) + i64 compare(object_ref const l, object_ref const r) { if(l == r) { @@ -45,7 +45,7 @@ namespace jank::runtime } return visit_object( - [](auto const &typed_l, auto const &r) -> i64 { + [](auto const typed_l, auto const &r) -> i64 { using L = typename jtl::decay_t::value_type; if constexpr(behavior::comparable) { @@ -63,7 +63,7 @@ namespace jank::runtime return -1; } - bool is_identical(object_ref const &lhs, object_ref const &rhs) + bool is_identical(object_ref const lhs, object_ref const rhs) { return lhs == rhs; } diff --git a/compiler+runtime/src/cpp/jank/runtime/core/math.cpp b/compiler+runtime/src/cpp/jank/runtime/core/math.cpp index 76d842d97..e6bfcbf07 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/math.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/math.cpp @@ -36,12 +36,12 @@ namespace jank::runtime } /* TODO: visit_number_like */ - object_ref add(object_ref const &l, object_ref const &r) + object_ref add(object_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &r) -> object_ref { + [](auto const typed_l, auto const r) -> object_ref { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l + typed_r->data).erase(); }, r, @@ -51,80 +51,80 @@ namespace jank::runtime r); } - object_ref add(obj::integer_ref const &l, object_ref const &r) + object_ref add(obj::integer_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l + typed_r->data); }, r, l->data); } - object_ref add(object_ref const &l, obj::integer_ref const &r) + object_ref add(object_ref const l, obj::integer_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data + typed_r); }, l, r->data); } - i64 add(obj::integer_ref const &l, obj::integer_ref const &r) + i64 add(obj::integer_ref const l, obj::integer_ref const r) { return l->data + r->data; } - f64 add(obj::real_ref const &l, obj::real_ref const &r) + f64 add(obj::real_ref const l, obj::real_ref const r) { return l->data + r->data; } - object_ref add(obj::real_ref const &l, object_ref const &r) + object_ref add(obj::real_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l + typed_r->data); }, r, l->data); } - object_ref add(object_ref const &l, obj::real_ref const &r) + object_ref add(object_ref const l, obj::real_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data + typed_r); }, l, r->data); } - f64 add(obj::real_ref const &l, obj::integer_ref const &r) + f64 add(obj::real_ref const l, obj::integer_ref const r) { return l->data + static_cast(r->data); } - f64 add(obj::integer_ref const &l, obj::real_ref const &r) + f64 add(obj::integer_ref const l, obj::real_ref const r) { return static_cast(l->data) + r->data; } - object_ref add(object_ref const &l, f64 const r) + object_ref add(object_ref const l, f64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data + typed_r); }, l, r); } - object_ref add(f64 const l, object_ref const &r) + object_ref add(f64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l + typed_r->data); }, r, @@ -146,20 +146,20 @@ namespace jank::runtime return l + static_cast(r); } - object_ref add(object_ref const &l, i64 const r) + object_ref add(object_ref const l, i64 const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data + typed_r); }, l, r); } - object_ref add(i64 const l, object_ref const &r) + object_ref add(i64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l + typed_r->data); }, r, @@ -171,12 +171,12 @@ namespace jank::runtime return l + r; } - object_ref sub(object_ref const &l, object_ref const &r) + object_ref sub(object_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &r) -> object_ref { + [](auto const typed_l, auto const r) -> object_ref { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l - typed_r->data).erase(); }, r, @@ -186,80 +186,80 @@ namespace jank::runtime r); } - object_ref sub(obj::integer_ref const &l, object_ref const &r) + object_ref sub(obj::integer_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l - typed_r->data); }, r, l->data); } - object_ref sub(object_ref const &l, obj::integer_ref const &r) + object_ref sub(object_ref const l, obj::integer_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data - typed_r); }, l, r->data); } - i64 sub(obj::integer_ref const &l, obj::integer_ref const &r) + i64 sub(obj::integer_ref const l, obj::integer_ref const r) { return l->data - r->data; } - f64 sub(obj::real_ref const &l, obj::real_ref const &r) + f64 sub(obj::real_ref const l, obj::real_ref const r) { return l->data - r->data; } - object_ref sub(obj::real_ref const &l, object_ref const &r) + object_ref sub(obj::real_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l - typed_r->data); }, r, l->data); } - object_ref sub(object_ref const &l, obj::real_ref const &r) + object_ref sub(object_ref const l, obj::real_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data - typed_r); }, l, r->data); } - f64 sub(obj::real_ref const &l, obj::integer_ref const &r) + f64 sub(obj::real_ref const l, obj::integer_ref const r) { return l->data - static_cast(r->data); } - f64 sub(obj::integer_ref const &l, obj::real_ref const &r) + f64 sub(obj::integer_ref const l, obj::real_ref const r) { return static_cast(l->data) - r->data; } - object_ref sub(object_ref const &l, f64 const r) + object_ref sub(object_ref const l, f64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data - typed_r); }, l, r); } - object_ref sub(f64 const l, object_ref const &r) + object_ref sub(f64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l - typed_r->data); }, r, @@ -281,20 +281,20 @@ namespace jank::runtime return l - static_cast(r); } - object_ref sub(object_ref const &l, i64 const r) + object_ref sub(object_ref const l, i64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data - typed_r); }, l, r); } - object_ref sub(i64 const l, object_ref const &r) + object_ref sub(i64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l - typed_r->data); }, r, @@ -306,12 +306,12 @@ namespace jank::runtime return l - r; } - object_ref div(object_ref const &l, object_ref const &r) + object_ref div(object_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &r) -> object_ref { + [](auto const typed_l, auto const r) -> object_ref { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l / typed_r->data).erase(); }, r, @@ -321,80 +321,80 @@ namespace jank::runtime r); } - object_ref div(obj::integer_ref const &l, object_ref const &r) + object_ref div(obj::integer_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l / typed_r->data); }, r, l->data); } - object_ref div(object_ref const &l, obj::integer_ref const &r) + object_ref div(object_ref const l, obj::integer_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data / typed_r); }, l, r->data); } - i64 div(obj::integer_ref const &l, obj::integer_ref const &r) + i64 div(obj::integer_ref const l, obj::integer_ref const r) { return l->data / r->data; } - f64 div(obj::real_ref const &l, obj::real_ref const &r) + f64 div(obj::real_ref const l, obj::real_ref const r) { return l->data / r->data; } - object_ref div(obj::real_ref const &l, object_ref const &r) + object_ref div(obj::real_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l / typed_r->data); }, r, l->data); } - object_ref div(object_ref const &l, obj::real_ref const &r) + object_ref div(object_ref const l, obj::real_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data / typed_r); }, l, r->data); } - f64 div(obj::real_ref const &l, obj::integer_ref const &r) + f64 div(obj::real_ref const l, obj::integer_ref const r) { return l->data / static_cast(r->data); } - f64 div(obj::integer_ref const &l, obj::real_ref const &r) + f64 div(obj::integer_ref const l, obj::real_ref const r) { return static_cast(l->data) / r->data; } - object_ref div(object_ref const &l, f64 const r) + object_ref div(object_ref const l, f64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data / typed_r); }, l, r); } - object_ref div(f64 const l, object_ref const &r) + object_ref div(f64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l / typed_r->data); }, r, @@ -416,20 +416,20 @@ namespace jank::runtime return l / static_cast(r); } - object_ref div(object_ref const &l, i64 const r) + object_ref div(object_ref const l, i64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data / typed_r); }, l, r); } - object_ref div(i64 const l, object_ref const &r) + object_ref div(i64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l / typed_r->data); }, r, @@ -441,12 +441,12 @@ namespace jank::runtime return l / r; } - object_ref mul(object_ref const &l, object_ref const &r) + object_ref mul(object_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &r) -> object_ref { + [](auto const typed_l, auto const r) -> object_ref { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l * typed_r->data).erase(); }, r, @@ -456,80 +456,80 @@ namespace jank::runtime r); } - object_ref mul(obj::integer_ref const &l, object_ref const &r) + object_ref mul(obj::integer_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l * typed_r->data); }, r, l->data); } - object_ref mul(object_ref const &l, obj::integer_ref const &r) + object_ref mul(object_ref const l, obj::integer_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data * typed_r); }, l, r->data); } - i64 mul(obj::integer_ref const &l, obj::integer_ref const &r) + i64 mul(obj::integer_ref const l, obj::integer_ref const r) { return l->data * r->data; } - f64 mul(obj::real_ref const &l, obj::real_ref const &r) + f64 mul(obj::real_ref const l, obj::real_ref const r) { return l->data * r->data; } - object_ref mul(obj::real_ref const &l, object_ref const &r) + object_ref mul(obj::real_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l * typed_r->data); }, r, l->data); } - object_ref mul(object_ref const &l, obj::real_ref const &r) + object_ref mul(object_ref const l, obj::real_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data * typed_r); }, l, r->data); } - f64 mul(obj::real_ref const &l, obj::integer_ref const &r) + f64 mul(obj::real_ref const l, obj::integer_ref const r) { return l->data * static_cast(r->data); } - f64 mul(obj::integer_ref const &l, obj::real_ref const &r) + f64 mul(obj::integer_ref const l, obj::real_ref const r) { return static_cast(l->data) * r->data; } - object_ref mul(object_ref const &l, f64 const r) + object_ref mul(object_ref const l, f64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data * typed_r); }, l, r); } - object_ref mul(f64 const l, object_ref const &r) + object_ref mul(f64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l * typed_r->data); }, r, @@ -551,20 +551,20 @@ namespace jank::runtime return l * static_cast(r); } - object_ref mul(object_ref const &l, i64 const r) + object_ref mul(object_ref const l, i64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return make_box(typed_l->data * typed_r); }, l, r); } - object_ref mul(i64 const l, object_ref const &r) + object_ref mul(i64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return make_box(typed_l * typed_r->data); }, r, @@ -576,12 +576,12 @@ namespace jank::runtime return l * r; } - object_ref rem(object_ref const &l, object_ref const &r) + object_ref rem(object_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &r_obj) -> object_ref { + [](auto const typed_l, auto const r_obj) -> object_ref { return visit_number_like( - [](auto const &typed_r, T const &typed_l_data) -> object_ref { + [](auto const typed_r, T const &typed_l_data) -> object_ref { using LeftType = std::decay_t; using RightType = std::decay_tdata)>; @@ -621,13 +621,13 @@ namespace jank::runtime r); } - object_ref quot(object_ref const &l, object_ref const &r) + object_ref quot(object_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &r) -> object_ref { + [](auto const typed_l, auto const r) -> object_ref { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { - auto const &typed_l_data{ to_real(typed_l) }; + [](auto const typed_r, auto const typed_l) -> object_ref { + auto const typed_l_data{ to_real(typed_l) }; auto const typed_r_data{ to_real(typed_r->data) }; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" @@ -648,10 +648,10 @@ namespace jank::runtime r); } - object_ref inc(object_ref const &l) + object_ref inc(object_ref const l) { return visit_number_like( - [](auto const &typed_l) -> object_ref { + [](auto const typed_l) -> object_ref { auto const ret{ make_box(typed_l->data + 1ll) }; object_ref r{ ret }; return r; @@ -659,17 +659,17 @@ namespace jank::runtime l); } - object_ref dec(object_ref const &l) + object_ref dec(object_ref const l) { return visit_number_like( - [](auto const &typed_l) -> object_ref { return make_box(typed_l->data - 1ll).erase(); }, + [](auto const typed_l) -> object_ref { return make_box(typed_l->data - 1ll).erase(); }, l); } - bool is_zero(object_ref const &l) + bool is_zero(object_ref const l) { return visit_number_like( - [](auto const &typed_l) -> bool { + [](auto const typed_l) -> bool { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" { @@ -680,10 +680,10 @@ namespace jank::runtime l); } - bool is_pos(object_ref const &l) + bool is_pos(object_ref const l) { return visit_number_like( - [](auto const &typed_l) -> bool { + [](auto const typed_l) -> bool { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" { @@ -694,10 +694,10 @@ namespace jank::runtime l); } - bool is_neg(object_ref const &l) + bool is_neg(object_ref const l) { return visit_number_like( - [](auto const &typed_l) -> bool { + [](auto const typed_l) -> bool { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" { @@ -708,26 +708,26 @@ namespace jank::runtime l); } - bool is_even(object_ref const &l) + bool is_even(object_ref const l) { return visit_type( - [=](auto const &typed_l) -> bool { return typed_l->data % 2 == 0; }, + [=](auto const typed_l) -> bool { return typed_l->data % 2 == 0; }, l); } - bool is_odd(object_ref const &l) + bool is_odd(object_ref const l) { return visit_type( - [=](auto const &typed_l) -> bool { return typed_l->data % 2 == 1; }, + [=](auto const typed_l) -> bool { return typed_l->data % 2 == 1; }, l); } - bool is_equiv(object_ref const &l, object_ref const &r) + bool is_equiv(object_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_l, object_ref const &r) -> bool { + [](auto const typed_l, object_ref const r) -> bool { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> bool { + [](auto const typed_r, auto const typed_l) -> bool { auto const data_l{ to_real(typed_l) }; auto const data_r{ to_real(typed_r->data) }; @@ -745,17 +745,17 @@ namespace jank::runtime r); } - i64 bit_not(object_ref const &l) + i64 bit_not(object_ref const l) { - return visit_type([](auto const &typed_l) -> i64 { return ~typed_l->data; }, l); + return visit_type([](auto const typed_l) -> i64 { return ~typed_l->data; }, l); } - i64 bit_and(object_ref const &l, object_ref const &r) + i64 bit_and(object_ref const l, object_ref const r) { return visit_type( - [](auto const &typed_l, auto const &r) -> i64 { + [](auto const typed_l, auto const r) -> i64 { return visit_type( - [](auto const &typed_r, auto const &typed_l) -> i64 { return typed_l & typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> i64 { return typed_l & typed_r->data; }, r, typed_l->data); }, @@ -763,12 +763,12 @@ namespace jank::runtime r); } - i64 bit_or(object_ref const &l, object_ref const &r) + i64 bit_or(object_ref const l, object_ref const r) { return visit_type( - [](auto const &typed_l, auto const &r) -> i64 { + [](auto const typed_l, auto const r) -> i64 { return visit_type( - [](auto const &typed_r, auto const &typed_l) -> i64 { return typed_l | typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> i64 { return typed_l | typed_r->data; }, r, typed_l->data); }, @@ -776,12 +776,12 @@ namespace jank::runtime r); } - i64 bit_xor(object_ref const &l, object_ref const &r) + i64 bit_xor(object_ref const l, object_ref const r) { return visit_type( - [](auto const &typed_l, auto const &r) -> i64 { + [](auto const typed_l, auto const r) -> i64 { return visit_type( - [](auto const &typed_r, auto const &typed_l) -> i64 { return typed_l ^ typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> i64 { return typed_l ^ typed_r->data; }, r, typed_l->data); }, @@ -789,14 +789,12 @@ namespace jank::runtime r); } - i64 bit_and_not(object_ref const &l, object_ref const &r) + i64 bit_and_not(object_ref const l, object_ref const r) { return visit_type( - [](auto const &typed_l, auto const &r) -> i64 { + [](auto const typed_l, auto const r) -> i64 { return visit_type( - [](auto const &typed_r, auto const &typed_l) -> i64 { - return typed_l & (~typed_r->data); - }, + [](auto const typed_r, auto const typed_l) -> i64 { return typed_l & (~typed_r->data); }, r, typed_l->data); }, @@ -804,12 +802,12 @@ namespace jank::runtime r); } - i64 bit_clear(object_ref const &l, object_ref const &r) + i64 bit_clear(object_ref const l, object_ref const r) { return visit_type( - [](auto const &typed_l, auto const &r) -> i64 { + [](auto const typed_l, auto const r) -> i64 { return visit_type( - [](auto const &typed_r, auto const &typed_l) -> i64 { + [](auto const typed_r, auto const typed_l) -> i64 { return typed_l & ~(static_cast(1) << typed_r->data); }, r, @@ -819,12 +817,12 @@ namespace jank::runtime r); } - i64 bit_set(object_ref const &l, object_ref const &r) + i64 bit_set(object_ref const l, object_ref const r) { return visit_type( - [](auto const &typed_l, auto const &r) -> i64 { + [](auto const typed_l, auto const r) -> i64 { return visit_type( - [](auto const &typed_r, auto const &typed_l) -> i64 { + [](auto const typed_r, auto const typed_l) -> i64 { return typed_l | (static_cast(1) << typed_r->data); }, r, @@ -834,12 +832,12 @@ namespace jank::runtime r); } - i64 bit_flip(object_ref const &l, object_ref const &r) + i64 bit_flip(object_ref const l, object_ref const r) { return visit_type( - [](auto const &typed_l, auto const &r) -> i64 { + [](auto const typed_l, auto const r) -> i64 { return visit_type( - [](auto const &typed_r, auto const &typed_l) -> i64 { + [](auto const typed_r, auto const typed_l) -> i64 { return typed_l ^ (static_cast(1) << typed_r->data); }, r, @@ -849,12 +847,12 @@ namespace jank::runtime r); } - bool bit_test(object_ref const &l, object_ref const &r) + bool bit_test(object_ref const l, object_ref const r) { return visit_type( - [](auto const &typed_l, auto const &r) -> bool { + [](auto const typed_l, auto const r) -> bool { return visit_type( - [](auto const &typed_r, auto const &typed_l) -> bool { + [](auto const typed_r, auto const typed_l) -> bool { return (typed_l >> typed_r->data) & static_cast(1); }, r, @@ -864,12 +862,12 @@ namespace jank::runtime r); } - i64 bit_shift_left(object_ref const &l, object_ref const &r) + i64 bit_shift_left(object_ref const l, object_ref const r) { return visit_type( - [](auto const &typed_l, auto const &r) -> i64 { + [](auto const typed_l, auto const r) -> i64 { return visit_type( - [](auto const &typed_r, auto const &typed_l) -> i64 { return typed_l << typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> i64 { return typed_l << typed_r->data; }, r, typed_l->data); }, @@ -877,12 +875,12 @@ namespace jank::runtime r); } - i64 bit_shift_right(object_ref const &l, object_ref const &r) + i64 bit_shift_right(object_ref const l, object_ref const r) { return visit_type( - [](auto const &typed_l, auto const &r) -> i64 { + [](auto const typed_l, auto const r) -> i64 { return visit_type( - [](auto const &typed_r, auto const &typed_l) -> i64 { return typed_l >> typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> i64 { return typed_l >> typed_r->data; }, r, typed_l->data); }, @@ -890,12 +888,12 @@ namespace jank::runtime r); } - i64 bit_unsigned_shift_right(object_ref const &l, object_ref const &r) + i64 bit_unsigned_shift_right(object_ref const l, object_ref const r) { return visit_type( - [](auto const &typed_l, auto const &r) -> i64 { + [](auto const typed_l, auto const r) -> i64 { return visit_type( - [](auto const &typed_r, auto const &typed_l) -> i64 { + [](auto const typed_r, auto const typed_l) -> i64 { using uni = std::make_unsigned_t; return static_cast(typed_l) >> static_cast(typed_r->data); }, @@ -913,12 +911,12 @@ namespace jank::runtime return dis(gen); } - bool lt(object_ref const &l, object_ref const &r) + bool lt(object_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &r) -> bool { + [](auto const typed_l, auto const r) -> bool { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> bool { return typed_l < typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> bool { return typed_l < typed_r->data; }, r, typed_l->data); }, @@ -926,70 +924,70 @@ namespace jank::runtime r); } - bool lt(obj::integer_ref const &l, object_ref const &r) + bool lt(obj::integer_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> bool { return typed_l < typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> bool { return typed_l < typed_r->data; }, r, l->data); } - bool lt(object_ref const &l, obj::integer_ref const &r) + bool lt(object_ref const l, obj::integer_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> bool { return typed_l->data < typed_r; }, + [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data < typed_r; }, l, r->data); } - bool lt(obj::integer_ref const &l, obj::integer_ref const &r) + bool lt(obj::integer_ref const l, obj::integer_ref const r) { return l->data < r->data; } - bool lt(obj::real_ref const &l, obj::real_ref const &r) + bool lt(obj::real_ref const l, obj::real_ref const r) { return l->data < r->data; } - bool lt(obj::real_ref const &l, object_ref const &r) + bool lt(obj::real_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> bool { return typed_l < typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> bool { return typed_l < typed_r->data; }, r, l->data); } - bool lt(object_ref const &l, obj::real_ref const &r) + bool lt(object_ref const l, obj::real_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> bool { return typed_l->data < typed_r; }, + [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data < typed_r; }, l, r->data); } - bool lt(obj::real_ref const &l, obj::integer_ref const &r) + bool lt(obj::real_ref const l, obj::integer_ref const r) { return l->data < static_cast(r->data); } - bool lt(obj::integer_ref const &l, obj::real_ref const &r) + bool lt(obj::integer_ref const l, obj::real_ref const r) { return static_cast(l->data) < r->data; } - bool lt(object_ref const &l, f64 const r) + bool lt(object_ref const l, f64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> bool { return typed_l->data < typed_r; }, + [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data < typed_r; }, l, r); } - bool lt(f64 const l, object_ref const &r) + bool lt(f64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> bool { return typed_l < typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> bool { return typed_l < typed_r->data; }, r, l); } @@ -1009,18 +1007,18 @@ namespace jank::runtime return l < static_cast(r); } - bool lt(object_ref const &l, i64 const r) + bool lt(object_ref const l, i64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> bool { return typed_l->data < typed_r; }, + [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data < typed_r; }, l, r); } - bool lt(i64 const l, object_ref const &r) + bool lt(i64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> bool { return typed_l < typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> bool { return typed_l < typed_r->data; }, r, l); } @@ -1030,12 +1028,12 @@ namespace jank::runtime return l < r; } - bool lte(object_ref const &l, object_ref const &r) + bool lte(object_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &r) -> bool { + [](auto const typed_l, auto const r) -> bool { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> bool { return typed_l <= typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> bool { return typed_l <= typed_r->data; }, r, typed_l->data); }, @@ -1043,70 +1041,70 @@ namespace jank::runtime r); } - bool lte(obj::integer_ref const &l, object_ref const &r) + bool lte(obj::integer_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> bool { return typed_l <= typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> bool { return typed_l <= typed_r->data; }, r, l->data); } - bool lte(object_ref const &l, obj::integer_ref const &r) + bool lte(object_ref const l, obj::integer_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> bool { return typed_l->data <= typed_r; }, + [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data <= typed_r; }, l, r->data); } - bool lte(obj::integer_ref const &l, obj::integer_ref const &r) + bool lte(obj::integer_ref const l, obj::integer_ref const r) { return l->data <= r->data; } - bool lte(obj::real_ref const &l, obj::real_ref const &r) + bool lte(obj::real_ref const l, obj::real_ref const r) { return l->data <= r->data; } - bool lte(obj::real_ref const &l, object_ref const &r) + bool lte(obj::real_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> bool { return typed_l <= typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> bool { return typed_l <= typed_r->data; }, r, l->data); } - bool lte(object_ref const &l, obj::real_ref const &r) + bool lte(object_ref const l, obj::real_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> bool { return typed_l->data <= typed_r; }, + [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data <= typed_r; }, l, r->data); } - bool lte(obj::real_ref const &l, obj::integer_ref const &r) + bool lte(obj::real_ref const l, obj::integer_ref const r) { return l->data <= static_cast(r->data); } - bool lte(obj::integer_ref const &l, obj::real_ref const &r) + bool lte(obj::integer_ref const l, obj::real_ref const r) { return static_cast(l->data) <= r->data; } - bool lte(object_ref const &l, f64 const r) + bool lte(object_ref const l, f64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> bool { return typed_l->data <= typed_r; }, + [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data <= typed_r; }, l, r); } - bool lte(f64 const l, object_ref const &r) + bool lte(f64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> bool { return typed_l <= typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> bool { return typed_l <= typed_r->data; }, r, l); } @@ -1126,18 +1124,18 @@ namespace jank::runtime return l <= static_cast(r); } - bool lte(object_ref const &l, i64 const r) + bool lte(object_ref const l, i64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> bool { return typed_l->data <= typed_r; }, + [](auto const typed_l, auto const typed_r) -> bool { return typed_l->data <= typed_r; }, l, r); } - bool lte(i64 const l, object_ref const &r) + bool lte(i64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> bool { return typed_l <= typed_r->data; }, + [](auto const typed_r, auto const typed_l) -> bool { return typed_l <= typed_r->data; }, r, l); } @@ -1147,12 +1145,12 @@ namespace jank::runtime return l <= r; } - object_ref min(object_ref const &l, object_ref const &r) + object_ref min(object_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &r) -> object_ref { + [](auto const typed_l, auto const r) -> object_ref { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return typed_l < typed_r->data ? make_box(typed_l).erase() : make_box(typed_r->data).erase(); }, @@ -1163,10 +1161,10 @@ namespace jank::runtime r); } - object_ref min(obj::integer_ref const &l, object_ref const &r) + object_ref min(obj::integer_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return typed_l < typed_r->data ? make_box(typed_l).erase() : make_box(typed_r->data).erase(); }, @@ -1174,10 +1172,10 @@ namespace jank::runtime l->data); } - object_ref min(object_ref const &l, obj::integer_ref const &r) + object_ref min(object_ref const l, obj::integer_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return typed_l->data < typed_r ? make_box(typed_l->data).erase() : make_box(typed_r).erase(); }, @@ -1185,20 +1183,20 @@ namespace jank::runtime r->data); } - i64 min(obj::integer_ref const &l, obj::integer_ref const &r) + i64 min(obj::integer_ref const l, obj::integer_ref const r) { return std::min(l->data, r->data); } - f64 min(obj::real_ref const &l, obj::real_ref const &r) + f64 min(obj::real_ref const l, obj::real_ref const r) { return std::min(l->data, r->data); } - f64 min(obj::real_ref const &l, object_ref const &r) + f64 min(obj::real_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> f64 { + [](auto const typed_r, auto const typed_l) -> f64 { auto const typed_r_data{ to_real(typed_r->data) }; using C = std::common_type_t, jtl::decay_t>; @@ -1208,10 +1206,10 @@ namespace jank::runtime l->data); } - f64 min(object_ref const &l, obj::real_ref const &r) + f64 min(object_ref const l, obj::real_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> f64 { + [](auto const typed_l, auto const typed_r) -> f64 { auto const typed_l_data{ to_real(typed_l->data) }; using C = std::common_type_t, jtl::decay_t>; @@ -1221,20 +1219,20 @@ namespace jank::runtime r->data); } - f64 min(obj::real_ref const &l, obj::integer_ref const &r) + f64 min(obj::real_ref const l, obj::integer_ref const r) { return std::min(l->data, static_cast(r->data)); } - f64 min(obj::integer_ref const &l, obj::real_ref const &r) + f64 min(obj::integer_ref const l, obj::real_ref const r) { return std::min(static_cast(l->data), r->data); } - f64 min(object_ref const &l, f64 const r) + f64 min(object_ref const l, f64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> f64 { + [](auto const typed_l, auto const typed_r) -> f64 { auto const typed_l_data{ to_real(typed_l->data) }; using C = std::common_type_t>; return std::min(static_cast(typed_l_data), static_cast(typed_r)); @@ -1243,11 +1241,11 @@ namespace jank::runtime r); } - f64 min(f64 const l, object_ref const &r) + f64 min(f64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> f64 { - auto const &typed_r_data{ to_real(typed_r->data) }; + [](auto const typed_r, auto const typed_l) -> f64 { + auto const typed_r_data{ to_real(typed_r->data) }; using C = std::common_type_t>; return std::min(static_cast(typed_r_data), static_cast(typed_l)); }, @@ -1270,20 +1268,20 @@ namespace jank::runtime return std::min(l, static_cast(r)); } - object_ref min(object_ref const &l, i64 const r) + object_ref min(object_ref const l, i64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return typed_l->data < typed_r ? make_box(typed_l).erase() : make_box(typed_r).erase(); }, l, r); } - object_ref min(i64 const l, object_ref const &r) + object_ref min(i64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return typed_l < typed_r->data ? make_box(typed_l).erase() : make_box(typed_r).erase(); }, r, @@ -1295,12 +1293,12 @@ namespace jank::runtime return std::min(l, r); } - object_ref max(object_ref const &l, object_ref const &r) + object_ref max(object_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &r) -> object_ref { + [](auto const typed_l, auto const r) -> object_ref { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return typed_r->data > typed_l ? make_box(typed_r).erase() : make_box(typed_l).erase(); }, r, @@ -1310,40 +1308,40 @@ namespace jank::runtime r); } - object_ref max(obj::integer_ref const &l, object_ref const &r) + object_ref max(obj::integer_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return typed_l > typed_r->data ? make_box(typed_l).erase() : make_box(typed_r).erase(); }, r, l->data); } - object_ref max(object_ref const &l, obj::integer_ref const &r) + object_ref max(object_ref const l, obj::integer_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return typed_l->data > typed_r ? make_box(typed_l).erase() : make_box(typed_r).erase(); }, l, r->data); } - i64 max(obj::integer_ref const &l, obj::integer_ref const &r) + i64 max(obj::integer_ref const l, obj::integer_ref const r) { return std::max(l->data, r->data); } - f64 max(obj::real_ref const &l, obj::real_ref const &r) + f64 max(obj::real_ref const l, obj::real_ref const r) { return std::max(l->data, r->data); } - f64 max(obj::real_ref const &l, object_ref const &r) + f64 max(obj::real_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> f64 { + [](auto const typed_r, auto const typed_l) -> f64 { auto const typed_r_data{ to_real(typed_r->data) }; using C = std::common_type_t, decltype(typed_r_data)>; return std::max(static_cast(typed_l), static_cast(typed_r_data)); @@ -1352,10 +1350,10 @@ namespace jank::runtime l->data); } - f64 max(object_ref const &l, obj::real_ref const &r) + f64 max(object_ref const l, obj::real_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> f64 { + [](auto const typed_l, auto const typed_r) -> f64 { auto const typed_l_data{ to_real(typed_l->data) }; using C = std::common_type_t>; return std::max(static_cast(typed_r), static_cast(typed_l_data)); @@ -1364,20 +1362,20 @@ namespace jank::runtime r->data); } - f64 max(obj::real_ref const &l, obj::integer_ref const &r) + f64 max(obj::real_ref const l, obj::integer_ref const r) { return std::max(l->data, static_cast(r->data)); } - f64 max(obj::integer_ref const &l, obj::real_ref const &r) + f64 max(obj::integer_ref const l, obj::real_ref const r) { return std::max(static_cast(l->data), r->data); } - object_ref max(object_ref const &l, f64 const r) + object_ref max(object_ref const l, f64 const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { auto const typed_l_data{ to_real(typed_l->data) }; using C = std::common_type_t>; return make_box(std::max(static_cast(typed_r), static_cast(typed_l_data))); @@ -1386,10 +1384,10 @@ namespace jank::runtime r); } - object_ref max(f64 const l, object_ref const &r) + object_ref max(f64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { auto const typed_r_data{ to_real(typed_r->data) }; using C = std::common_type_t, decltype(typed_r_data)>; return make_box(std::max(static_cast(typed_l), static_cast(typed_r_data))); @@ -1413,20 +1411,20 @@ namespace jank::runtime return std::max(l, static_cast(r)); } - object_ref max(object_ref const &l, i64 const r) + object_ref max(object_ref const l, i64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { return typed_l->data > typed_r ? make_box(typed_l).erase() : make_box(typed_r).erase(); }, l, r); } - object_ref max(i64 const l, object_ref const &r) + object_ref max(i64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { return typed_l > typed_r->data ? make_box(typed_l).erase() : make_box(typed_r).erase(); }, r, @@ -1438,22 +1436,22 @@ namespace jank::runtime return std::max(l, r); } - object_ref abs(object_ref const &l) + object_ref abs(object_ref const l) { return visit_number_like( - [](auto const &typed_l) -> object_ref { + [](auto const typed_l) -> object_ref { return typed_l->data < 0ll ? make_box(-1ll * typed_l->data).erase() : make_box(typed_l->data).erase(); }, l); } - i64 abs(obj::integer_ref const &l) + i64 abs(obj::integer_ref const l) { return std::abs(l->data); } - f64 abs(obj::real_ref const &l) + f64 abs(obj::real_ref const l) { return std::fabs(l->data); } @@ -1468,25 +1466,24 @@ namespace jank::runtime return std::fabs(l); } - f64 tan(object_ref const &l) + f64 tan(object_ref const l) { - return visit_number_like([](auto const &typed_l) -> f64 { return tanf(typed_l->to_real()); }, - l); + return visit_number_like([](auto const typed_l) -> f64 { return tanf(typed_l->to_real()); }, l); } - f64 sqrt(object_ref const &l) + f64 sqrt(object_ref const l) { return visit_number_like( - [](auto const &typed_l) -> f64 { return std::sqrt(typed_l->to_real()); }, + [](auto const typed_l) -> f64 { return std::sqrt(typed_l->to_real()); }, l); } - f64 sqrt(obj::integer_ref const &l) + f64 sqrt(obj::integer_ref const l) { return std::sqrt(l->data); } - f64 sqrt(obj::real_ref const &l) + f64 sqrt(obj::real_ref const l) { return std::sqrt(l->data); } @@ -1501,12 +1498,12 @@ namespace jank::runtime return std::sqrt(l); } - f64 pow(object_ref const &l, object_ref const &r) + f64 pow(object_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &r) -> f64 { + [](auto const typed_l, auto const r) -> f64 { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> f64 { + [](auto const typed_r, auto const typed_l) -> f64 { auto const typed_r_data{ to_real(typed_r->data) }; auto const typed_l_data{ to_real(typed_l) }; using C = std::common_type_t; @@ -1519,10 +1516,10 @@ namespace jank::runtime r); } - f64 pow(obj::integer_ref const &l, object_ref const &r) + f64 pow(obj::integer_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> f64 { + [](auto const typed_r, auto const typed_l) -> f64 { auto const typed_r_data{ to_real(typed_r->data) }; auto const typed_l_data{ to_real(typed_l) }; using C = std::common_type_t; @@ -1532,10 +1529,10 @@ namespace jank::runtime l->data); } - f64 pow(object_ref const &l, obj::integer_ref const &r) + f64 pow(object_ref const l, obj::integer_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> f64 { + [](auto const typed_l, auto const typed_r) -> f64 { auto const typed_l_data{ to_real(typed_l->data) }; using C = std::common_type_t>; return std::pow(static_cast(typed_l_data), static_cast(typed_r)); @@ -1544,20 +1541,20 @@ namespace jank::runtime r->data); } - f64 pow(obj::integer_ref const &l, obj::integer_ref const &r) + f64 pow(obj::integer_ref const l, obj::integer_ref const r) { return std::pow(l->data, r->data); } - f64 pow(obj::real_ref const &l, obj::real_ref const &r) + f64 pow(obj::real_ref const l, obj::real_ref const r) { return std::pow(l->data, r->data); } - f64 pow(obj::real_ref const &l, object_ref const &r) + f64 pow(obj::real_ref const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const &typed_l) -> f64 { + [](auto const typed_r, auto const typed_l) -> f64 { auto const typed_r_data{ to_real(typed_r->data) }; using C = std::common_type_t, decltype(typed_r_data)>; return std::pow(static_cast(typed_l), static_cast(typed_r_data)); @@ -1566,10 +1563,10 @@ namespace jank::runtime l->data); } - f64 pow(object_ref const &l, obj::real_ref const &r) + f64 pow(object_ref const l, obj::real_ref const r) { return visit_number_like( - [](auto const &typed_l, auto const &typed_r) -> f64 { + [](auto const typed_l, auto const typed_r) -> f64 { auto const typed_l_data{ to_real(typed_l->data) }; using C = std::common_type_t>; return std::pow(static_cast(typed_l_data), static_cast(typed_r)); @@ -1578,20 +1575,20 @@ namespace jank::runtime r->data); } - f64 pow(obj::real_ref const &l, obj::integer_ref const &r) + f64 pow(obj::real_ref const l, obj::integer_ref const r) { return std::pow(l->data, static_cast(r->data)); } - f64 pow(obj::integer_ref const &l, obj::real_ref const &r) + f64 pow(obj::integer_ref const l, obj::real_ref const r) { return std::pow(static_cast(l->data), r->data); } - object_ref pow(object_ref const &l, f64 const r) + object_ref pow(object_ref const l, f64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> object_ref { + [](auto const typed_l, auto const typed_r) -> object_ref { auto const typed_l_data{ to_real(typed_l->data) }; using C = std::common_type_t>; return make_box(std::pow(static_cast(typed_l_data), static_cast(typed_r))); @@ -1600,10 +1597,10 @@ namespace jank::runtime r); } - object_ref pow(f64 const l, object_ref const &r) + object_ref pow(f64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const typed_l) -> object_ref { auto const typed_r_data{ to_real(typed_r->data) }; using C = std::common_type_t, decltype(typed_r_data)>; return make_box(std::pow(static_cast(typed_l), static_cast(typed_r_data))); @@ -1627,10 +1624,10 @@ namespace jank::runtime return std::pow(l, static_cast(r)); } - f64 pow(object_ref const &l, i64 const r) + f64 pow(object_ref const l, i64 const r) { return visit_number_like( - [](auto const &typed_l, auto const typed_r) -> f64 { + [](auto const typed_l, auto const typed_r) -> f64 { auto const typed_l_data{ to_real(typed_l->data) }; using C = std::common_type_t>; return std::pow(static_cast(typed_l_data), static_cast(typed_r)); @@ -1639,11 +1636,11 @@ namespace jank::runtime r); } - f64 pow(i64 const l, object_ref const &r) + f64 pow(i64 const l, object_ref const r) { return visit_number_like( - [](auto const &typed_r, auto const typed_l) -> f64 { - auto const &typed_r_data{ to_real(typed_r->data) }; + [](auto const typed_r, auto const typed_l) -> f64 { + auto const typed_r_data{ to_real(typed_r->data) }; using C = std::common_type_t, decltype(typed_r_data)>; return std::pow(static_cast(typed_l), static_cast(typed_r_data)); }, @@ -1656,27 +1653,27 @@ namespace jank::runtime return std::pow(l, r); } - native_big_integer numerator(object_ref const &o) + native_big_integer numerator(object_ref const o) { return try_object(o)->data.numerator; } - native_big_integer denominator(object_ref const &o) + native_big_integer denominator(object_ref const o) { return try_object(o)->data.denominator; } - i64 to_int(object_ref const &l) + i64 to_int(object_ref const l) { - return visit_number_like([](auto const &typed_l) -> i64 { return typed_l->to_integer(); }, l); + return visit_number_like([](auto const typed_l) -> i64 { return typed_l->to_integer(); }, l); } - i64 to_int(obj::integer_ref const &l) + i64 to_int(obj::integer_ref const l) { return l->data; } - i64 to_int(obj::real_ref const &l) + i64 to_int(obj::real_ref const l) { return static_cast(l->data); } @@ -1691,45 +1688,45 @@ namespace jank::runtime return static_cast(l); } - f64 to_real(object_ref const &o) + f64 to_real(object_ref const o) { return visit_number_like( - [](auto const &typed_o) -> f64 { return typed_o->to_real(); }, + [](auto const typed_o) -> f64 { return typed_o->to_real(); }, [=]() -> f64 { throw std::runtime_error{ util::format("not a number: {}", to_string(o)) }; }, o); } - bool is_number(object_ref const &o) + bool is_number(object_ref const o) { - return visit_number_like([=](auto const &) -> bool { return true; }, + return visit_number_like([=](auto const) -> bool { return true; }, [=]() -> bool { return false; }, o); } - bool is_integer(object_ref const &o) + bool is_integer(object_ref const o) { return o->type == object_type::integer; } - bool is_real(object_ref const &o) + bool is_real(object_ref const o) { return o->type == object_type::real; } - bool is_ratio(object_ref const &o) + bool is_ratio(object_ref const o) { return o->type == object_type::ratio; } - bool is_boolean(object_ref const &o) + bool is_boolean(object_ref const o) { return o->type == object_type::boolean; } - bool is_nan(object_ref const &o) + bool is_nan(object_ref const o) { return visit_number_like( - [=](auto const &typed_o) -> bool { + [=](auto const typed_o) -> bool { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -1744,10 +1741,10 @@ namespace jank::runtime o); } - bool is_infinite(object_ref const &o) + bool is_infinite(object_ref const o) { return visit_number_like( - [=](auto const &typed_o) -> bool { + [=](auto const typed_o) -> bool { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -1763,7 +1760,7 @@ namespace jank::runtime } /* TODO: Rename these to match the type name. */ - i64 parse_long(object_ref const &o) + i64 parse_long(object_ref const o) { auto const typed_o{ dyn_cast(o) }; if(typed_o.is_some()) @@ -1776,7 +1773,7 @@ namespace jank::runtime } } - f64 parse_double(object_ref const &o) + f64 parse_double(object_ref const o) { auto const typed_o{ dyn_cast(o) }; if(typed_o.is_some()) @@ -1789,15 +1786,15 @@ namespace jank::runtime } } - bool is_big_decimal(object_ref const &o) + bool is_big_decimal(object_ref const o) { return o->type == object_type::big_decimal; } - obj::big_decimal_ref to_big_decimal(object_ref const &o) + obj::big_decimal_ref to_big_decimal(object_ref const o) { return visit_number_like( - [&](auto const &typed_o) -> obj::big_decimal_ref { + [&](auto const typed_o) -> obj::big_decimal_ref { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) diff --git a/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp b/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp index dff17c2f5..b7035ebe6 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/meta.cpp @@ -10,7 +10,7 @@ namespace jank::runtime { - object_ref meta(object_ref const &m) + object_ref meta(object_ref const m) { if(m.is_nil()) { @@ -18,7 +18,7 @@ namespace jank::runtime } return visit_object( - [](auto const &typed_m) -> object_ref { + [](auto const typed_m) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::metadatable) @@ -33,10 +33,10 @@ namespace jank::runtime m); } - object_ref with_meta(object_ref const &o, object_ref const &m) + object_ref with_meta(object_ref const o, object_ref const m) { return visit_object( - [&o](auto const &typed_o, object_ref const &m) -> object_ref { + [&o](auto const typed_o, object_ref const m) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::metadatable) @@ -59,10 +59,10 @@ namespace jank::runtime /* This is the same as with_meta, but it gracefully handles the target * not supporting metadata. In that case, the target is returned and nothing * is done with the meta. */ - object_ref with_meta_graceful(object_ref const &o, object_ref const &m) + object_ref with_meta_graceful(object_ref const o, object_ref const m) { return visit_object( - [](auto const &typed_o, object_ref const &m) -> object_ref { + [](auto const typed_o, object_ref const m) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::metadatable) @@ -78,10 +78,10 @@ namespace jank::runtime m); } - object_ref reset_meta(object_ref const &o, object_ref const &m) + object_ref reset_meta(object_ref const o, object_ref const m) { return visit_object( - [](auto const &typed_o, object_ref const &m) -> object_ref { + [](auto const typed_o, object_ref const m) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::metadatable) @@ -147,7 +147,7 @@ namespace jank::runtime }; } - read::source object_source(object_ref const &o) + read::source object_source(object_ref const o) { auto const meta(runtime::meta(o)); if(meta == jank_nil()) @@ -212,7 +212,7 @@ namespace jank::runtime return source_to_meta(source); } - object_ref strip_source_from_meta(object_ref const &meta) + object_ref strip_source_from_meta(object_ref const meta) { auto const kw{ __rt_ctx->intern_keyword("jank/source").expect_ok() }; return dissoc(meta, kw); diff --git a/compiler+runtime/src/cpp/jank/runtime/core/munge.cpp b/compiler+runtime/src/cpp/jank/runtime/core/munge.cpp index c2b27d3cb..449eaffa4 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/munge.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/munge.cpp @@ -299,7 +299,7 @@ namespace jank::runtime } /* TODO: Support symbols and other data; Clojure takes in anything and passes it through str. */ - object_ref munge(object_ref const &o) + object_ref munge(object_ref const o) { auto const s{ dyn_cast(o) }; if(s.is_some()) diff --git a/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp b/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp index a4e8358b1..4cf44c42f 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/seq.cpp @@ -24,10 +24,10 @@ namespace jank::runtime { - bool is_empty(object_ref const &o) + bool is_empty(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> bool { + [=](auto const typed_o) -> bool { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -51,10 +51,10 @@ namespace jank::runtime o); } - bool is_seq(object_ref const &o) + bool is_seq(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> bool { + [=](auto const typed_o) -> bool { using T = typename jtl::decay_t::value_type; return behavior::sequenceable; @@ -62,17 +62,17 @@ namespace jank::runtime o); } - bool is_seqable(object_ref const &o) + bool is_seqable(object_ref const o) { return visit_seqable([=](auto const &) -> bool { return true; }, [=]() -> bool { return false; }, o); } - bool is_sequential(object_ref const &o) + bool is_sequential(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> bool { + [=](auto const typed_o) -> bool { using T = typename jtl::decay_t::value_type; return behavior::sequential; @@ -80,10 +80,10 @@ namespace jank::runtime o); } - bool is_collection(object_ref const &o) + bool is_collection(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> bool { + [=](auto const typed_o) -> bool { using T = typename jtl::decay_t::value_type; return behavior::collection_like; @@ -91,29 +91,29 @@ namespace jank::runtime o); } - bool is_list(object_ref const &o) + bool is_list(object_ref const o) { /* TODO: Visit and use a behavior for this check instead. * It should apply to conses and others. */ return o->type == object_type::persistent_list; } - bool is_vector(object_ref const &o) + bool is_vector(object_ref const o) { return o->type == object_type::persistent_vector; } - bool is_map(object_ref const &o) + bool is_map(object_ref const o) { return (o->type == object_type::persistent_hash_map || o->type == object_type::persistent_array_map || o->type == object_type::persistent_sorted_map); } - bool is_associative(object_ref const &o) + bool is_associative(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> bool { + [=](auto const typed_o) -> bool { using T = typename jtl::decay_t::value_type; return (behavior::associatively_readable && behavior::associatively_writable); @@ -121,16 +121,16 @@ namespace jank::runtime o); } - bool is_set(object_ref const &o) + bool is_set(object_ref const o) { return (o->type == object_type::persistent_hash_set || o->type == object_type::persistent_sorted_set); } - bool is_counted(object_ref const &o) + bool is_counted(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> bool { + [=](auto const typed_o) -> bool { using T = typename jtl::decay_t::value_type; return behavior::countable; @@ -138,10 +138,10 @@ namespace jank::runtime o); } - bool is_transientable(object_ref const &o) + bool is_transientable(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> bool { + [=](auto const typed_o) -> bool { using T = typename jtl::decay_t::value_type; return behavior::transientable; @@ -149,16 +149,16 @@ namespace jank::runtime o); } - bool is_sorted(object_ref const &o) + bool is_sorted(object_ref const o) { return o->type == object_type::persistent_sorted_map || o->type == object_type::persistent_sorted_set; } - object_ref transient(object_ref const &o) + object_ref transient(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> object_ref { + [=](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::transientable) @@ -174,10 +174,10 @@ namespace jank::runtime o); } - object_ref persistent(object_ref const &o) + object_ref persistent(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> object_ref { + [=](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::persistentable) @@ -193,10 +193,10 @@ namespace jank::runtime o); } - object_ref conj_in_place(object_ref const &coll, object_ref const &o) + object_ref conj_in_place(object_ref const coll, object_ref const o) { return visit_object( - [](auto const &typed_coll, auto const &o) -> object_ref { + [](auto const typed_coll, auto const &o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::conjable_in_place) @@ -213,7 +213,7 @@ namespace jank::runtime o); } - object_ref disj_in_place(object_ref const &coll, object_ref const &o) + object_ref disj_in_place(object_ref const coll, object_ref const o) { /* TODO: disjoinable_in_place */ if(coll->type == object_type::transient_hash_set) @@ -233,10 +233,10 @@ namespace jank::runtime runtime::to_code_string(coll)) }; } - object_ref assoc_in_place(object_ref const &coll, object_ref const &k, object_ref const &v) + object_ref assoc_in_place(object_ref const coll, object_ref const k, object_ref const v) { return visit_object( - [](auto const &typed_coll, auto const &k, auto const &v) -> object_ref { + [](auto const typed_coll, auto const &k, auto const &v) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_writable_in_place) @@ -254,10 +254,10 @@ namespace jank::runtime v); } - object_ref dissoc_in_place(object_ref const &coll, object_ref const &k) + object_ref dissoc_in_place(object_ref const coll, object_ref const k) { return visit_object( - [](auto const &typed_coll, auto const &k) -> object_ref { + [](auto const typed_coll, auto const &k) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_writable_in_place) @@ -274,16 +274,16 @@ namespace jank::runtime k); } - object_ref pop_in_place(object_ref const &coll) + object_ref pop_in_place(object_ref const coll) { auto const trans(try_object(coll)); return trans->pop_in_place(); } - object_ref seq(object_ref const &s) + object_ref seq(object_ref const s) { return visit_object( - [](auto const &typed_s) -> object_ref { + [](auto const typed_s) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -308,10 +308,10 @@ namespace jank::runtime s); } - object_ref fresh_seq(object_ref const &s) + object_ref fresh_seq(object_ref const s) { return visit_object( - [](auto const &typed_s) -> object_ref { + [](auto const typed_s) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -336,10 +336,10 @@ namespace jank::runtime s); } - object_ref first(object_ref const &s) + object_ref first(object_ref const s) { return visit_object( - [](auto const &typed_s) -> object_ref { + [](auto const typed_s) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -368,15 +368,15 @@ namespace jank::runtime s); } - object_ref second(object_ref const &s) + object_ref second(object_ref const s) { return first(next(s)); } - object_ref next(object_ref const &s) + object_ref next(object_ref const s) { return visit_object( - [](auto const &typed_s) -> object_ref { + [](auto const typed_s) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -405,10 +405,10 @@ namespace jank::runtime s); } - object_ref next_in_place(object_ref const &s) + object_ref next_in_place(object_ref const s) { return visit_object( - [](auto const &typed_s) -> object_ref { + [](auto const typed_s) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -441,14 +441,14 @@ namespace jank::runtime s); } - object_ref rest(object_ref const &s) + object_ref rest(object_ref const s) { if(s.is_nil()) { return obj::persistent_list::empty(); } return visit_seqable( - [=](auto const &typed_s) -> object_ref { + [=](auto const typed_s) -> object_ref { auto const seq(typed_s->seq()); if(seq.is_nil()) { @@ -464,10 +464,10 @@ namespace jank::runtime s); } - object_ref cons(object_ref const &head, object_ref const &tail) + object_ref cons(object_ref const head, object_ref const tail) { return visit_seqable( - [=](auto const &typed_tail) -> object_ref { + [=](auto const typed_tail) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(jtl::is_same) @@ -489,10 +489,10 @@ namespace jank::runtime tail); } - object_ref conj(object_ref const &s, object_ref const &o) + object_ref conj(object_ref const s, object_ref const o) { return visit_object( - [&](auto const &typed_s) -> object_ref { + [&](auto const typed_s) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -511,7 +511,7 @@ namespace jank::runtime s); } - object_ref disj(object_ref const &s, object_ref const &o) + object_ref disj(object_ref const s, object_ref const o) { if(s->type == object_type::nil) { @@ -528,10 +528,10 @@ namespace jank::runtime } } - object_ref assoc(object_ref const &m, object_ref const &k, object_ref const &v) + object_ref assoc(object_ref const m, object_ref const k, object_ref const v) { return visit_object( - [&](auto const &typed_m) -> object_ref { + [&](auto const typed_m) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_writable) @@ -547,10 +547,10 @@ namespace jank::runtime m); } - object_ref dissoc(object_ref const &m, object_ref const &k) + object_ref dissoc(object_ref const m, object_ref const k) { return visit_object( - [&](auto const &typed_m) -> object_ref { + [&](auto const typed_m) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_writable) @@ -566,10 +566,10 @@ namespace jank::runtime m); } - object_ref get(object_ref const &m, object_ref const &key) + object_ref get(object_ref const m, object_ref const key) { return visit_object( - [&](auto const &typed_m) -> object_ref { + [&](auto const typed_m) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_readable) @@ -584,10 +584,10 @@ namespace jank::runtime m); } - object_ref get(object_ref const &m, object_ref const &key, object_ref const &fallback) + object_ref get(object_ref const m, object_ref const key, object_ref const fallback) { return visit_object( - [&](auto const &typed_m) -> object_ref { + [&](auto const typed_m) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_readable) @@ -602,16 +602,16 @@ namespace jank::runtime m); } - object_ref get_in(object_ref const &m, object_ref const &keys) + object_ref get_in(object_ref const m, object_ref const keys) { return visit_object( - [&](auto const &typed_m) -> object_ref { + [&](auto const typed_m) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_readable) { return visit_seqable( - [&](auto const &typed_keys) -> object_ref { + [&](auto const typed_keys) -> object_ref { object_ref ret{ typed_m }; for(auto const &e : make_sequence_range(typed_keys)) { @@ -629,16 +629,16 @@ namespace jank::runtime m); } - object_ref get_in(object_ref const &m, object_ref const &keys, object_ref const &fallback) + object_ref get_in(object_ref const m, object_ref const keys, object_ref const fallback) { return visit_object( - [&](auto const &typed_m) -> object_ref { + [&](auto const typed_m) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_readable) { return visit_seqable( - [&](auto const &typed_keys) -> object_ref { + [&](auto const typed_keys) -> object_ref { object_ref ret{ typed_m }; for(auto const &e : make_sequence_range(typed_keys)) { @@ -661,7 +661,7 @@ namespace jank::runtime m); } - object_ref find(object_ref const &s, object_ref const &key) + object_ref find(object_ref const s, object_ref const key) { if(s.is_nil()) { @@ -669,7 +669,7 @@ namespace jank::runtime } return visit_object( - [](auto const &typed_s, object_ref const &key) -> object_ref { + [](auto const typed_s, object_ref const key) -> object_ref { using S = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_readable) @@ -685,7 +685,7 @@ namespace jank::runtime key); } - bool contains(object_ref const &s, object_ref const &key) + bool contains(object_ref const s, object_ref const key) { if(s.is_nil()) { @@ -693,7 +693,7 @@ namespace jank::runtime } return visit_object( - [&](auto const &typed_s) -> bool { + [&](auto const typed_s) -> bool { using S = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_readable || behavior::set_like) @@ -708,10 +708,10 @@ namespace jank::runtime s); } - object_ref merge(object_ref const &m, object_ref const &other) + object_ref merge(object_ref const m, object_ref const other) { return visit_object( - [](auto const &typed_m, object_ref const &other) -> object_ref { + [](auto const typed_m, object_ref const other) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(jtl::is_same) @@ -723,7 +723,7 @@ namespace jank::runtime using R = decltype(assoc(typed_m, jank_nil(), jank_nil())); return visit_map_like( - [](auto const &typed_other, auto const &typed_m) -> object_ref { + [](auto const typed_other, auto const typed_m) -> object_ref { R ret{ typed_m }; for(auto seq{ typed_other->fresh_seq() }; seq.is_some(); seq = seq->next_in_place()) { @@ -745,21 +745,21 @@ namespace jank::runtime other); } - object_ref merge_in_place(object_ref const &m, object_ref const &other) + object_ref merge_in_place(object_ref const m, object_ref const other) { if(other.is_nil()) { return m; } return visit_object( - [](auto const &typed_m, auto const &other) -> object_ref { + [](auto const typed_m, auto const &other) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::associatively_writable_in_place) { using R = decltype(assoc_in_place(typed_m, jank_nil(), jank_nil())); return visit_map_like( - [](auto const &typed_other, auto const &typed_m) -> object_ref { + [](auto const typed_other, auto const typed_m) -> object_ref { R ret{ typed_m }; for(auto seq{ typed_other->fresh_seq() }; seq.is_some(); seq = seq->next_in_place()) { @@ -781,7 +781,7 @@ namespace jank::runtime other); } - object_ref subvec(object_ref const &o, i64 const start, i64 const end) + object_ref subvec(object_ref const o, i64 const start, i64 const end) { if(o->type != object_type::persistent_vector) { @@ -802,7 +802,7 @@ namespace jank::runtime detail::native_persistent_vector{ v->data.begin() + start, v->data.begin() + end }); } - object_ref nth(object_ref const &o, object_ref const &idx) + object_ref nth(object_ref const o, object_ref const idx) { auto const index(to_int(idx)); if(index < 0) @@ -815,7 +815,7 @@ namespace jank::runtime } return visit_object( - [&](auto const &typed_o) -> object_ref { + [&](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::indexable) @@ -843,7 +843,7 @@ namespace jank::runtime o); } - object_ref nth(object_ref const &o, object_ref const &idx, object_ref const &fallback) + object_ref nth(object_ref const o, object_ref const idx, object_ref const fallback) { auto const index(to_int(idx)); if(index < 0 || o == jank_nil()) @@ -852,7 +852,7 @@ namespace jank::runtime } return visit_object( - [&](auto const &typed_o) -> object_ref { + [&](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::indexable) @@ -880,7 +880,7 @@ namespace jank::runtime o); } - object_ref peek(object_ref const &o) + object_ref peek(object_ref const o) { if(o == jank_nil()) { @@ -888,7 +888,7 @@ namespace jank::runtime } return visit_object( - [&](auto const &typed_o) -> object_ref { + [&](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::stackable) @@ -903,7 +903,7 @@ namespace jank::runtime o); } - object_ref pop(object_ref const &o) + object_ref pop(object_ref const o) { if(o == jank_nil()) { @@ -911,7 +911,7 @@ namespace jank::runtime } return visit_object( - [&](auto const &typed_o) -> object_ref { + [&](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::stackable) @@ -926,10 +926,10 @@ namespace jank::runtime o); } - object_ref empty(object_ref const &o) + object_ref empty(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> object_ref { + [=](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::collection_like) @@ -945,12 +945,12 @@ namespace jank::runtime o); } - jtl::immutable_string str(object_ref const &o) + jtl::immutable_string str(object_ref const o) { return runtime::to_string(o); } - jtl::immutable_string str(object_ref const &o, object_ref const &args) + jtl::immutable_string str(object_ref const o, object_ref const args) { jtl::string_builder buff; buff.reserve(16); @@ -959,7 +959,7 @@ namespace jank::runtime runtime::to_string(o, buff); } return visit_seqable( - [](auto const &typed_args, jtl::string_builder &buff) -> jtl::immutable_string { + [](auto const typed_args, jtl::string_builder &buff) -> jtl::immutable_string { for(auto const &e : make_sequence_range(typed_args)) { if(is_nil(e)) @@ -974,30 +974,30 @@ namespace jank::runtime buff); } - obj::persistent_list_ref list(object_ref const &s) + obj::persistent_list_ref list(object_ref const s) { return visit_seqable( - [](auto const &typed_s) -> obj::persistent_list_ref { + [](auto const typed_s) -> obj::persistent_list_ref { return obj::persistent_list::create(typed_s); }, s); } - obj::persistent_vector_ref vec(object_ref const &s) + obj::persistent_vector_ref vec(object_ref const s) { return visit_seqable( - [](auto const &typed_s) -> obj::persistent_vector_ref { + [](auto const typed_s) -> obj::persistent_vector_ref { return obj::persistent_vector::create(typed_s); }, s); } - usize sequence_length(object_ref const &s) + usize sequence_length(object_ref const s) { return sequence_length(s, std::numeric_limits::max()); } - usize sequence_length(object_ref const &s, usize const max) + usize sequence_length(object_ref const s, usize const max) { if(s.is_nil()) { @@ -1005,7 +1005,7 @@ namespace jank::runtime } return visit_object( - [&](auto const &typed_s) -> usize { + [&](auto const typed_s) -> usize { using T = typename jtl::decay_t::value_type; if constexpr(std::same_as) @@ -1034,7 +1034,7 @@ namespace jank::runtime s); } - bool sequence_equal(object_ref const &l, object_ref const &r) + bool sequence_equal(object_ref const l, object_ref const r) { if(l == r) { @@ -1043,9 +1043,9 @@ namespace jank::runtime /* TODO: visit_sequence. */ return visit_seqable( - [](auto const &typed_l, object_ref const &r) -> bool { + [](auto const typed_l, object_ref const r) -> bool { return visit_seqable( - [](auto const &typed_r, auto const &typed_l) -> bool { + [](auto const typed_r, auto const typed_l) -> bool { auto const &l_range{ make_sequence_range(typed_l) }; auto const &r_range{ make_sequence_range(typed_r) }; auto r_it(r_range.begin()); @@ -1067,10 +1067,10 @@ namespace jank::runtime r); } - object_ref reduce(object_ref const &f, object_ref const &init, object_ref const &s) + object_ref reduce(object_ref const f, object_ref const init, object_ref const s) { return visit_seqable( - [](auto const &typed_coll, object_ref const &f, object_ref const &init) -> object_ref { + [](auto const typed_coll, object_ref const f, object_ref const init) -> object_ref { object_ref res{ init }; for(auto const &e : make_sequence_range(typed_coll)) { @@ -1088,38 +1088,38 @@ namespace jank::runtime init); } - object_ref reduced(object_ref const &o) + object_ref reduced(object_ref const o) { return make_box(o); } - bool is_reduced(object_ref const &o) + bool is_reduced(object_ref const o) { return o->type == object_type::reduced; } - object_ref chunk_buffer(object_ref const &capacity) + object_ref chunk_buffer(object_ref const capacity) { return make_box(capacity); } - object_ref chunk_append(object_ref const &buff, object_ref const &val) + object_ref chunk_append(object_ref const buff, object_ref const val) { auto const &buffer(try_object(buff)); buffer->append(val); return jank_nil(); } - object_ref chunk(object_ref const &buff) + object_ref chunk(object_ref const buff) { auto const &buffer(try_object(buff)); return buffer->chunk(); } - object_ref chunk_first(object_ref const &o) + object_ref chunk_first(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> object_ref { + [=](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::chunkable) @@ -1133,10 +1133,10 @@ namespace jank::runtime o); } - object_ref chunk_next(object_ref const &o) + object_ref chunk_next(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> object_ref { + [=](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::chunkable) @@ -1150,10 +1150,10 @@ namespace jank::runtime o); } - object_ref chunk_rest(object_ref const &o) + object_ref chunk_rest(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> object_ref { + [=](auto const typed_o) -> object_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::chunkable) @@ -1172,15 +1172,15 @@ namespace jank::runtime o); } - object_ref chunk_cons(object_ref const &chunk, object_ref const &rest) + object_ref chunk_cons(object_ref const chunk, object_ref const rest) { return make_box(chunk, seq(rest)); } - bool is_chunked_seq(object_ref const &o) + bool is_chunked_seq(object_ref const o) { return visit_object( - [=](auto const &typed_o) -> bool { + [=](auto const typed_o) -> bool { using T = typename jtl::decay_t::value_type; return behavior::chunkable; @@ -1188,32 +1188,32 @@ namespace jank::runtime o); } - object_ref iterate(object_ref const &fn, object_ref const &o) + object_ref iterate(object_ref const fn, object_ref const o) { return make_box(fn, o); } - object_ref repeat(object_ref const &val) + object_ref repeat(object_ref const val) { return obj::repeat::create(val); } - object_ref repeat(object_ref const &n, object_ref const &val) + object_ref repeat(object_ref const n, object_ref const val) { return obj::repeat::create(n, val); } - object_ref sort(object_ref const &coll) + object_ref sort(object_ref const coll) { return visit_seqable( - [](auto const &typed_coll) -> object_ref { + [](auto const typed_coll) -> object_ref { native_vector vec; for(auto const &e : make_sequence_range(typed_coll)) { vec.push_back(e); } - std::stable_sort(vec.begin(), vec.end(), [](object_ref const &a, object_ref const &b) { + std::stable_sort(vec.begin(), vec.end(), [](object_ref const a, object_ref const b) { return runtime::compare(a, b) < 0; }); @@ -1231,10 +1231,10 @@ namespace jank::runtime coll); } - object_ref shuffle(object_ref const &coll) + object_ref shuffle(object_ref const coll) { return visit_seqable( - [](auto const &typed_coll) -> object_ref { + [](auto const typed_coll) -> object_ref { native_vector vec; for(auto const &e : make_sequence_range(typed_coll)) { diff --git a/compiler+runtime/src/cpp/jank/runtime/core/to_string.cpp b/compiler+runtime/src/cpp/jank/runtime/core/to_string.cpp index 6818495c9..a240d2bc3 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/to_string.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/to_string.cpp @@ -3,7 +3,7 @@ namespace jank::runtime { - jtl::immutable_string to_string(weak_object_ref const o) + jtl::immutable_string to_string(object_ref const o) { return visit_object([](auto const typed_o) { return typed_o->to_string(); }, o); } @@ -13,14 +13,14 @@ namespace jank::runtime obj::character{ ch }.to_string(buff); } - void to_string(object_ref const &o, jtl::string_builder &buff) + void to_string(object_ref const o, jtl::string_builder &buff) { - visit_object([&](auto const &typed_o) { typed_o->to_string(buff); }, o); + visit_object([&](auto const typed_o) { typed_o->to_string(buff); }, o); } - jtl::immutable_string to_code_string(object_ref const &o) + jtl::immutable_string to_code_string(object_ref const o) { - return visit_object([](auto const &typed_o) { return typed_o->to_code_string(); }, o); + return visit_object([](auto const typed_o) { return typed_o->to_code_string(); }, o); } void to_code_string(char const ch, jtl::string_builder &buff) @@ -28,9 +28,9 @@ namespace jank::runtime buff(obj::character{ ch }.to_code_string()); } - void to_code_string(object_ref const &o, jtl::string_builder &buff) + void to_code_string(object_ref const o, jtl::string_builder &buff) { - auto const value{ visit_object([](auto const &typed_o) { return typed_o->to_code_string(); }, + auto const value{ visit_object([](auto const typed_o) { return typed_o->to_code_string(); }, o) }; buff(value); } diff --git a/compiler+runtime/src/cpp/jank/runtime/core/truthy.cpp b/compiler+runtime/src/cpp/jank/runtime/core/truthy.cpp index 6bc42d47e..d5aa183e4 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/truthy.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/truthy.cpp @@ -24,17 +24,17 @@ namespace jank::runtime return true; } - bool truthy(object_ref const &o) + bool truthy(object_ref const o) { return truthy(o.data); } - bool truthy(obj::nil_ref const &) + bool truthy(obj::nil_ref const ) { return false; } - bool truthy(obj::boolean_ref const &o) + bool truthy(obj::boolean_ref const o) { return o.is_some() && o->data; } diff --git a/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp b/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp index 2c9c15742..1998c155d 100644 --- a/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp @@ -9,8 +9,8 @@ namespace jank::runtime::detail static object_ref *make_next_array(object_ref * const prev, u8 const cap, u8 const length, - object_ref const &key, - object_ref const &value) + object_ref const key, + object_ref const value) { if((length + 2) <= cap) { @@ -125,7 +125,7 @@ namespace jank::runtime::detail //delete[] data; } - void native_array_map::insert_unique(object_ref const &key, object_ref const &val) + void native_array_map::insert_unique(object_ref const key, object_ref const val) { data = make_next_array(data, cap, length, key, val); length += 2; @@ -133,7 +133,7 @@ namespace jank::runtime::detail hash = 0; } - void native_array_map::insert_or_assign(object_ref const &key, object_ref const &val) + void native_array_map::insert_or_assign(object_ref const key, object_ref const val) { if(key->type == runtime::object_type::keyword) { @@ -162,7 +162,7 @@ namespace jank::runtime::detail insert_unique(key, val); } - jtl::option native_array_map::find(object_ref const &key) const + jtl::option native_array_map::find(object_ref const key) const { if(key->type == runtime::object_type::keyword) { @@ -187,7 +187,7 @@ namespace jank::runtime::detail return {}; } - void native_array_map::erase(object_ref const &key) + void native_array_map::erase(object_ref const key) { if(key->type == runtime::object_type::keyword) { diff --git a/compiler+runtime/src/cpp/jank/runtime/detail/type.cpp b/compiler+runtime/src/cpp/jank/runtime/detail/type.cpp index 8ea3d9fa6..b8c4abafd 100644 --- a/compiler+runtime/src/cpp/jank/runtime/detail/type.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/detail/type.cpp @@ -3,7 +3,7 @@ namespace jank::runtime::detail { - bool object_ref_compare::operator()(object_ref const &l, object_ref const &r) const + bool object_ref_compare::operator()(object_ref const l, object_ref const r) const { return runtime::compare(l, r) < 0; } diff --git a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp index cc6e4fedf..fba062e00 100644 --- a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp @@ -828,13 +828,13 @@ namespace jank::runtime::module auto const loaded_libs_atom{ runtime::try_object( __rt_ctx->loaded_libs_var->deref()) }; - auto const swap_fn{ [&](object_ref const &curr_val) { + auto const swap_fn{ [&](object_ref const curr_val) { return runtime::try_object(curr_val)->conj( make_box(module)); } }; auto const swap_fn_wrapper{ make_box( - std::function{ swap_fn }) }; + std::function{ swap_fn }) }; loaded_libs_atom->swap(swap_fn_wrapper); } diff --git a/compiler+runtime/src/cpp/jank/runtime/ns.cpp b/compiler+runtime/src/cpp/jank/runtime/ns.cpp index a42966e8b..2306fe325 100644 --- a/compiler+runtime/src/cpp/jank/runtime/ns.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/ns.cpp @@ -8,7 +8,7 @@ namespace jank::runtime { - ns::ns(obj::symbol_ref const &name) + ns::ns(obj::symbol_ref const name) : name{ name } , vars{ obj::persistent_hash_map::empty() } , aliases{ obj::persistent_hash_map::empty() } @@ -20,7 +20,7 @@ namespace jank::runtime return intern_var(make_box(name)); } - var_ref ns::intern_var(obj::symbol_ref const &sym) + var_ref ns::intern_var(obj::symbol_ref const sym) { obj::symbol_ref unqualified_sym{ sym }; if(!unqualified_sym->ns.empty()) @@ -59,7 +59,7 @@ namespace jank::runtime * WARNING 'println' already referred to #'clojure.core/println in namespace 'foo' but has been replaced by #'foo/println * ``` */ - var_ref ns::intern_owned_var(obj::symbol_ref const &sym) + var_ref ns::intern_owned_var(obj::symbol_ref const sym) { obj::symbol_ref unqualified_sym{ sym }; if(!unqualified_sym->ns.empty()) @@ -98,7 +98,7 @@ namespace jank::runtime return new_var; } - jtl::result ns::unmap(obj::symbol_ref const &sym) + jtl::result ns::unmap(obj::symbol_ref const sym) { if(!sym->ns.empty()) { @@ -110,7 +110,7 @@ namespace jank::runtime return ok(); } - var_ref ns::find_var(obj::symbol_ref const &sym) + var_ref ns::find_var(obj::symbol_ref const sym) { if(!sym->ns.empty()) { @@ -128,7 +128,7 @@ namespace jank::runtime } jtl::result - ns::add_alias(obj::symbol_ref const &sym, ns_ref const &nsp) + ns::add_alias(obj::symbol_ref const sym, ns_ref const nsp) { auto locked_aliases(aliases.wlock()); auto const found((*locked_aliases)->data.find(sym)); @@ -149,13 +149,13 @@ namespace jank::runtime return ok(); } - void ns::remove_alias(obj::symbol_ref const &sym) + void ns::remove_alias(obj::symbol_ref const sym) { auto locked_aliases(aliases.wlock()); *locked_aliases = make_box((*locked_aliases)->data.erase(sym)); } - ns_ref ns::find_alias(obj::symbol_ref const &sym) const + ns_ref ns::find_alias(obj::symbol_ref const sym) const { auto locked_aliases(aliases.rlock()); auto const found((*locked_aliases)->data.find(sym)); @@ -166,7 +166,7 @@ namespace jank::runtime return {}; } - jtl::result ns::refer(obj::symbol_ref const &sym, var_ref const &var) + jtl::result ns::refer(obj::symbol_ref const sym, var_ref const var) { auto locked_vars(vars.wlock()); if(auto const found = (*locked_vars)->data.find(sym)) diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/array_chunk.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/array_chunk.cpp index 755968dbf..9b14b3442 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/array_chunk.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/array_chunk.cpp @@ -75,7 +75,7 @@ namespace jank::runtime::obj return buffer.size() - offset; } - object_ref array_chunk::nth(object_ref const &index) const + object_ref array_chunk::nth(object_ref const index) const { if(index->type == object_type::integer) { @@ -97,7 +97,7 @@ namespace jank::runtime::obj } } - object_ref array_chunk::nth(object_ref const &index, object_ref const &fallback) const + object_ref array_chunk::nth(object_ref const index, object_ref const fallback) const { if(index->type == object_type::integer) { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp index 09e5a312c..5136480f9 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp @@ -7,16 +7,10 @@ namespace jank::runtime::obj { - atom::atom(object_ref const &o) + atom::atom(object_ref const o) : val{ o.data } , watches{ persistent_hash_map::empty() } { - o->retain(); - } - - atom::~atom() - { - val.load()->release(); } bool atom::equal(object const &o) const @@ -51,7 +45,8 @@ namespace jank::runtime::obj return val.load(); } - static void notify_watches(atom_ref const &a, object_ref const &old_val, object_ref const &new_val) + static void + notify_watches(atom_ref const a, object_ref const old_val, object_ref const new_val) { auto const locked_watches(a->watches.rlock()); for(auto const &entry : (*locked_watches)->data) @@ -64,18 +59,16 @@ namespace jank::runtime::obj } } - object_ref atom::reset(object_ref const &o) + object_ref atom::reset(object_ref const o) { jank_debug_assert(o.is_some()); auto const v(val.load()); val = o.data; notify_watches(this, v, o); - o->retain(); - v->release(); return o; } - persistent_vector_ref atom::reset_vals(object_ref const &o) + persistent_vector_ref atom::reset_vals(object_ref const o) { while(true) { @@ -84,15 +77,13 @@ namespace jank::runtime::obj { notify_watches(this, v, o); auto ret{ make_box(std::in_place, v, o) }; - o->retain(); - v->release(); return ret; } } } /* NOLINTNEXTLINE(cppcoreguidelines-noexcept-swap,bugprone-exception-escape) */ - object_ref atom::swap(object_ref const &fn) + object_ref atom::swap(object_ref const fn) { while(true) { @@ -101,15 +92,13 @@ namespace jank::runtime::obj if(val.compare_exchange_weak(v, next.data)) { notify_watches(this, v, next); - next->retain(); - v->release(); return next; } } } /* NOLINTNEXTLINE(cppcoreguidelines-noexcept-swap,bugprone-exception-escape) */ - object_ref atom::swap(object_ref const &fn, object_ref const &a1) + object_ref atom::swap(object_ref const fn, object_ref const a1) { while(true) { @@ -118,15 +107,13 @@ namespace jank::runtime::obj if(val.compare_exchange_weak(v, next.data)) { notify_watches(this, v, next); - next->retain(); - v->release(); return next; } } } /* NOLINTNEXTLINE(cppcoreguidelines-noexcept-swap,bugprone-exception-escape) */ - object_ref atom::swap(object_ref const &fn, object_ref const &a1, object_ref const &a2) + object_ref atom::swap(object_ref const fn, object_ref const a1, object_ref const a2) { while(true) { @@ -135,8 +122,6 @@ namespace jank::runtime::obj if(val.compare_exchange_weak(v, next.data)) { notify_watches(this, v, next); - next->retain(); - v->release(); return next; } } @@ -144,7 +129,10 @@ namespace jank::runtime::obj object_ref /* NOLINTNEXTLINE(cppcoreguidelines-noexcept-swap,bugprone-exception-escape) */ - atom::swap(object_ref const &fn, object_ref const &a1, object_ref const &a2, object_ref const &rest) + atom::swap(object_ref const fn, + object_ref const a1, + object_ref const a2, + object_ref const rest) { while(true) { @@ -154,14 +142,12 @@ namespace jank::runtime::obj if(val.compare_exchange_weak(v, next.data)) { notify_watches(this, v, next); - next->retain(); - v->release(); return next; } } } - persistent_vector_ref atom::swap_vals(object_ref const &fn) + persistent_vector_ref atom::swap_vals(object_ref const fn) { while(true) { @@ -171,14 +157,12 @@ namespace jank::runtime::obj { notify_watches(this, v, next); auto ret{ make_box(std::in_place, v, next) }; - next->retain(); - v->release(); return ret; } } } - persistent_vector_ref atom::swap_vals(object_ref const &fn, object_ref const &a1) + persistent_vector_ref atom::swap_vals(object_ref const fn, object_ref const a1) { while(true) { @@ -188,15 +172,13 @@ namespace jank::runtime::obj { notify_watches(this, v, next); auto ret{ make_box(std::in_place, v, next) }; - next->retain(); - v->release(); return ret; } } } persistent_vector_ref - atom::swap_vals(object_ref const &fn, object_ref const &a1, object_ref const &a2) + atom::swap_vals(object_ref const fn, object_ref const a1, object_ref const a2) { while(true) { @@ -206,17 +188,15 @@ namespace jank::runtime::obj { notify_watches(this, v, next); auto ret{ make_box(std::in_place, v, next) }; - next->retain(); - v->release(); return ret; } } } - persistent_vector_ref atom::swap_vals(object_ref const &fn, - object_ref const &a1, - object_ref const &a2, - object_ref const &rest) + persistent_vector_ref atom::swap_vals(object_ref const fn, + object_ref const a1, + object_ref const a2, + object_ref const rest) { while(true) { @@ -227,14 +207,12 @@ namespace jank::runtime::obj { notify_watches(this, v, next); auto ret{ make_box(std::in_place, v, next) }; - next->retain(); - v->release(); return ret; } } } - object_ref atom::compare_and_set(object_ref const &old_val, object_ref const &new_val) + object_ref atom::compare_and_set(object_ref const old_val, object_ref const new_val) { /* NOLINTNEXTLINE(misc-const-correctness): Can't actually be const. */ object *old{ old_val.data }; @@ -242,19 +220,17 @@ namespace jank::runtime::obj if(ret) { notify_watches(this, old_val, new_val); - new_val->retain(); - old_val->release(); } return make_box(ret); } - void atom::add_watch(object_ref const &key, object_ref const &fn) + void atom::add_watch(object_ref const key, object_ref const fn) { auto locked_watches(this->watches.wlock()); *locked_watches = (*locked_watches)->assoc(key, fn); } - void atom::remove_watch(object_ref const &key) + void atom::remove_watch(object_ref const key) { auto locked_watches(this->watches.wlock()); *locked_watches = (*locked_watches)->dissoc(key); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/big_decimal.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/big_decimal.cpp index d534fc1f2..0317d6ec7 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/big_decimal.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/big_decimal.cpp @@ -136,7 +136,7 @@ namespace jank::runtime::obj bool big_decimal::equal(object const &o) const { return visit_number_like( - [this](auto const &typed_o) -> bool { + [this](auto const typed_o) -> bool { return abs(data - typed_o->data) < std::numeric_limits::epsilon(); }, [&]() -> bool { return false; }, @@ -166,7 +166,7 @@ namespace jank::runtime::obj i64 big_decimal::compare(object const &o) const { return visit_number_like( - [this](auto const &typed_o) -> i64 { + [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, [&]() -> i64 { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/big_integer.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/big_integer.cpp index db23160ff..66cff7d22 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/big_integer.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/big_integer.cpp @@ -279,7 +279,7 @@ namespace jank::runtime::obj i64 big_integer::compare(object const &o) const { return visit_number_like( - [this](auto const &typed_o) -> i64 { + [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, [&]() -> i64 { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/chunk_buffer.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/chunk_buffer.cpp index 367c1bc33..dcdd84cdd 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/chunk_buffer.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/chunk_buffer.cpp @@ -11,7 +11,7 @@ namespace jank::runtime::obj buffer.reserve(capacity); } - chunk_buffer::chunk_buffer(object_ref const &capacity) + chunk_buffer::chunk_buffer(object_ref const capacity) { auto const c(to_int(capacity)); if(c < 0) @@ -54,7 +54,7 @@ namespace jank::runtime::obj return buffer.size(); } - void chunk_buffer::append(object_ref const &o) + void chunk_buffer::append(object_ref const o) { if(buffer.size() == capacity) { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/chunked_cons.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/chunked_cons.cpp index 3911034ee..0c74b2f02 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/chunked_cons.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/chunked_cons.cpp @@ -7,14 +7,14 @@ namespace jank::runtime::obj { - chunked_cons::chunked_cons(object_ref const &head, object_ref const &tail) + chunked_cons::chunked_cons(object_ref const head, object_ref const tail) : head{ head } , tail{ tail } { jank_debug_assert(head.is_some()); } - chunked_cons::chunked_cons(object_ref const &meta, object_ref const &head, object_ref const &tail) + chunked_cons::chunked_cons(object_ref const meta, object_ref const head, object_ref const tail) : head{ head } , tail{ tail } , meta{ meta } @@ -75,7 +75,7 @@ namespace jank::runtime::obj head); } - static chunked_cons_ref next_in_place_non_chunked(chunked_cons_ref const &o) + static chunked_cons_ref next_in_place_non_chunked(chunked_cons_ref const o) { if(o->tail.is_nil()) { @@ -83,7 +83,7 @@ namespace jank::runtime::obj } return visit_object( - [&](auto const &typed_tail) -> chunked_cons_ref { + [&](auto const typed_tail) -> chunked_cons_ref { using T = typename jtl::decay_t::value_type; if constexpr(behavior::sequenceable) @@ -177,12 +177,12 @@ namespace jank::runtime::obj return hash::ordered(&base); } - cons_ref chunked_cons::conj(object_ref const &head) const + cons_ref chunked_cons::conj(object_ref const head) const { return make_box(head, this); } - chunked_cons_ref chunked_cons::with_meta(object_ref const &m) const + chunked_cons_ref chunked_cons::with_meta(object_ref const m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(fresh_seq()); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/cons.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/cons.cpp index 0c15c82d9..1baff1f0b 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/cons.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/cons.cpp @@ -5,7 +5,7 @@ namespace jank::runtime::obj { - cons::cons(object_ref const &head, object_ref const &tail) + cons::cons(object_ref const head, object_ref const tail) : head{ head } , tail{ tail } { @@ -66,12 +66,12 @@ namespace jank::runtime::obj return hash = hash::ordered(&base); } - cons_ref cons::conj(object_ref const &head) const + cons_ref cons::conj(object_ref const head) const { return make_box(head, this); } - cons_ref cons::with_meta(object_ref const &m) const + cons_ref cons::with_meta(object_ref const m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(fresh_seq()); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/delay.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/delay.cpp index edf6dc6ac..41c425990 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/delay.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/delay.cpp @@ -5,7 +5,7 @@ namespace jank::runtime::obj { - delay::delay(object_ref const &fn) + delay::delay(object_ref const fn) : fn{ fn } { } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map.cpp index ab0617717..a3cfc7859 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map.cpp @@ -23,7 +23,7 @@ namespace jank::runtime::obj::detail } return visit_map_like( - [&](auto const &typed_o) -> bool { + [&](auto const typed_o) -> bool { if(typed_o->count() != count()) { return false; @@ -158,7 +158,7 @@ namespace jank::runtime::obj::detail } template - object_ref base_persistent_map::conj(object_ref const &head) const + object_ref base_persistent_map::conj(object_ref const head) const { auto const ret(static_cast(this)); if(head.is_nil()) @@ -188,7 +188,7 @@ namespace jank::runtime::obj::detail } template - oref base_persistent_map::with_meta(object_ref const &m) const + oref base_persistent_map::with_meta(object_ref const m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(make_box(static_cast(this)->data)); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.cpp index 9066ec1fd..b42ddcd61 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/detail/base_persistent_map_sequence.cpp @@ -5,7 +5,7 @@ namespace jank::runtime::obj::detail { template - base_persistent_map_sequence::base_persistent_map_sequence(object_ref const &c, + base_persistent_map_sequence::base_persistent_map_sequence(object_ref const c, IT const &b, IT const &e) : coll{ c } @@ -138,7 +138,7 @@ namespace jank::runtime::obj::detail } template - obj::cons_ref base_persistent_map_sequence::conj(object_ref const &head) + obj::cons_ref base_persistent_map_sequence::conj(object_ref const head) { return make_box(head, static_cast(this)); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/detail/iterator_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/detail/iterator_sequence.cpp index f5d11eef5..6d23dcb48 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/detail/iterator_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/detail/iterator_sequence.cpp @@ -5,13 +5,13 @@ namespace jank::runtime { - bool equal(object_ref const &lhs, object_ref const &rhs); + bool equal(object_ref const lhs, object_ref const rhs); } namespace jank::runtime::obj::detail { template - iterator_sequence::iterator_sequence(object_ref const &c, + iterator_sequence::iterator_sequence(object_ref const c, It const &b, It const &e, usize const s) @@ -112,7 +112,7 @@ namespace jank::runtime::obj::detail } template - obj::cons_ref iterator_sequence::conj(object_ref const &head) + obj::cons_ref iterator_sequence::conj(object_ref const head) { return make_box(head, static_cast(this)); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/integer_range.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/integer_range.cpp index f2406aeb0..de5917f0a 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/integer_range.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/integer_range.cpp @@ -7,17 +7,17 @@ namespace jank::runtime::obj { - static bool positive_step_bounds_check(integer_ref const &val, integer_ref const &end) + static bool positive_step_bounds_check(integer_ref const val, integer_ref const end) { return lte(end, val); } - static bool negative_step_bounds_check(integer_ref const &val, integer_ref const &end) + static bool negative_step_bounds_check(integer_ref const val, integer_ref const end) { return lte(val, end); } - integer_range::integer_range(integer_ref const &end) + integer_range::integer_range(integer_ref const end) : start{ make_box(0) } , end{ end } , step{ make_box(1) } @@ -25,7 +25,7 @@ namespace jank::runtime::obj { } - integer_range::integer_range(integer_ref const &start, integer_ref const &end) + integer_range::integer_range(integer_ref const start, integer_ref const end) : start{ start } , end{ end } , step{ make_box(1) } @@ -33,9 +33,9 @@ namespace jank::runtime::obj { } - integer_range::integer_range(integer_ref const &start, - integer_ref const &end, - integer_ref const &step) + integer_range::integer_range(integer_ref const start, + integer_ref const end, + integer_ref const step) : start{ start } , end{ end } , step{ step } @@ -45,9 +45,9 @@ namespace jank::runtime::obj { } - integer_range::integer_range(integer_ref const &start, - integer_ref const &end, - integer_ref const &step, + integer_range::integer_range(integer_ref const start, + integer_ref const end, + integer_ref const step, integer_range::bounds_check_t const bounds_check) : start{ start } , end{ end } @@ -56,7 +56,7 @@ namespace jank::runtime::obj { } - object_ref integer_range::create(integer_ref const &end) + object_ref integer_range::create(integer_ref const end) { if(is_pos(end)) { @@ -68,13 +68,13 @@ namespace jank::runtime::obj return persistent_list::empty(); } - object_ref integer_range::create(integer_ref const &start, integer_ref const &end) + object_ref integer_range::create(integer_ref const start, integer_ref const end) { return create(start, end, make_box(1)); } object_ref - integer_range::create(integer_ref const &start, integer_ref const &end, integer_ref const &step) + integer_range::create(integer_ref const start, integer_ref const end, integer_ref const step) { if((is_pos(step) && lt(end, start)) || (is_neg(step) && lt(start, end)) || is_equiv(start, end)) { @@ -126,7 +126,7 @@ namespace jank::runtime::obj return this; } - cons_ref integer_range::conj(object_ref const &head) const + cons_ref integer_range::conj(object_ref const head) const { return make_box(head, this); } @@ -156,7 +156,7 @@ namespace jank::runtime::obj return hash::ordered(&base); } - integer_range_ref integer_range::with_meta(object_ref const &m) const + integer_range_ref integer_range::with_meta(object_ref const m) const { auto const meta(behavior::detail::validate_meta(m)); auto const ret(fresh_seq()); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/iterator.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/iterator.cpp index a7bcbeb08..ccc3b3fcb 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/iterator.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/iterator.cpp @@ -5,7 +5,7 @@ namespace jank::runtime::obj { - iterator::iterator(object_ref const &fn, object_ref const &start) + iterator::iterator(object_ref const fn, object_ref const start) : fn{ fn } , current{ start } { @@ -81,7 +81,7 @@ namespace jank::runtime::obj return hash::ordered(&base); } - cons_ref iterator::conj(object_ref const &head) const + cons_ref iterator::conj(object_ref const head) const { return make_box(head, this); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/jit_closure.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/jit_closure.cpp index 1799927a4..5e37e08c8 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/jit_closure.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/jit_closure.cpp @@ -17,7 +17,7 @@ namespace jank::runtime::obj { } - jit_closure::jit_closure(object_ref const &meta) + jit_closure::jit_closure(object_ref const meta) : meta{ meta } { } @@ -55,7 +55,7 @@ namespace jank::runtime::obj return static_cast(reinterpret_cast(this)); } - jit_closure_ref jit_closure::with_meta(object_ref const &m) + jit_closure_ref jit_closure::with_meta(object_ref const m) { auto const new_meta(behavior::detail::validate_meta(m)); meta = new_meta; @@ -71,7 +71,7 @@ namespace jank::runtime::obj return arity_0(&base); } - object_ref jit_closure::call(object_ref const &a1) + object_ref jit_closure::call(object_ref const a1) { if(!arity_1) { @@ -80,7 +80,7 @@ namespace jank::runtime::obj return arity_1(&base, a1.data); } - object_ref jit_closure::call(object_ref const &a1, object_ref const &a2) + object_ref jit_closure::call(object_ref const a1, object_ref const a2) { if(!arity_2) { @@ -89,7 +89,7 @@ namespace jank::runtime::obj return arity_2(&base, a1.data, a2.data); } - object_ref jit_closure::call(object_ref const &a1, object_ref const &a2, object_ref const &a3) + object_ref jit_closure::call(object_ref const a1, object_ref const a2, object_ref const a3) { if(!arity_3) { @@ -98,10 +98,10 @@ namespace jank::runtime::obj return arity_3(&base, a1.data, a2.data, a3.data); } - object_ref jit_closure::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4) + object_ref jit_closure::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4) { if(!arity_4) { @@ -110,11 +110,11 @@ namespace jank::runtime::obj return arity_4(&base, a1.data, a2.data, a3.data, a4.data); } - object_ref jit_closure::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5) + object_ref jit_closure::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5) { if(!arity_5) { @@ -123,12 +123,12 @@ namespace jank::runtime::obj return arity_5(&base, a1.data, a2.data, a3.data, a4.data, a5.data); } - object_ref jit_closure::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6) + object_ref jit_closure::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6) { if(!arity_6) { @@ -137,13 +137,13 @@ namespace jank::runtime::obj return arity_6(&base, a1.data, a2.data, a3.data, a4.data, a5.data, a6.data); } - object_ref jit_closure::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7) + object_ref jit_closure::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7) { if(!arity_7) { @@ -152,14 +152,14 @@ namespace jank::runtime::obj return arity_7(&base, a1.data, a2.data, a3.data, a4.data, a5.data, a6.data, a7.data); } - object_ref jit_closure::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7, - object_ref const &a8) + object_ref jit_closure::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7, + object_ref const a8) { if(!arity_8) { @@ -168,15 +168,15 @@ namespace jank::runtime::obj return arity_8(&base, a1.data, a2.data, a3.data, a4.data, a5.data, a6.data, a7.data, a8.data); } - object_ref jit_closure::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7, - object_ref const &a8, - object_ref const &a9) + object_ref jit_closure::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7, + object_ref const a8, + object_ref const a9) { if(!arity_9) { @@ -194,16 +194,16 @@ namespace jank::runtime::obj a9.data); } - object_ref jit_closure::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7, - object_ref const &a8, - object_ref const &a9, - object_ref const &a10) + object_ref jit_closure::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7, + object_ref const a8, + object_ref const a9, + object_ref const a10) { if(!arity_10) { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/jit_function.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/jit_function.cpp index fab9ac162..1ecf859db 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/jit_function.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/jit_function.cpp @@ -16,7 +16,7 @@ namespace jank::runtime::obj { } - jit_function::jit_function(object_ref const &meta) + jit_function::jit_function(object_ref const meta) : meta{ meta } { } @@ -54,7 +54,7 @@ namespace jank::runtime::obj return static_cast(reinterpret_cast(this)); } - jit_function_ref jit_function::with_meta(object_ref const &m) + jit_function_ref jit_function::with_meta(object_ref const m) { auto const new_meta(behavior::detail::validate_meta(m)); meta = new_meta; @@ -70,7 +70,7 @@ namespace jank::runtime::obj return arity_0(&base); } - object_ref jit_function::call(object_ref const &a1) + object_ref jit_function::call(object_ref const a1) { if(!arity_1) { @@ -79,7 +79,7 @@ namespace jank::runtime::obj return arity_1(&base, a1.data); } - object_ref jit_function::call(object_ref const &a1, object_ref const &a2) + object_ref jit_function::call(object_ref const a1, object_ref const a2) { if(!arity_2) { @@ -88,7 +88,7 @@ namespace jank::runtime::obj return arity_2(&base, a1.data, a2.data); } - object_ref jit_function::call(object_ref const &a1, object_ref const &a2, object_ref const &a3) + object_ref jit_function::call(object_ref const a1, object_ref const a2, object_ref const a3) { if(!arity_3) { @@ -97,10 +97,10 @@ namespace jank::runtime::obj return arity_3(&base, a1.data, a2.data, a3.data); } - object_ref jit_function::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4) + object_ref jit_function::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4) { if(!arity_4) { @@ -109,11 +109,11 @@ namespace jank::runtime::obj return arity_4(&base, a1.data, a2.data, a3.data, a4.data); } - object_ref jit_function::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5) + object_ref jit_function::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5) { if(!arity_5) { @@ -122,12 +122,12 @@ namespace jank::runtime::obj return arity_5(&base, a1.data, a2.data, a3.data, a4.data, a5.data); } - object_ref jit_function::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6) + object_ref jit_function::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6) { if(!arity_6) { @@ -136,13 +136,13 @@ namespace jank::runtime::obj return arity_6(&base, a1.data, a2.data, a3.data, a4.data, a5.data, a6.data); } - object_ref jit_function::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7) + object_ref jit_function::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7) { if(!arity_7) { @@ -151,14 +151,14 @@ namespace jank::runtime::obj return arity_7(&base, a1.data, a2.data, a3.data, a4.data, a5.data, a6.data, a7.data); } - object_ref jit_function::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7, - object_ref const &a8) + object_ref jit_function::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7, + object_ref const a8) { if(!arity_8) { @@ -167,15 +167,15 @@ namespace jank::runtime::obj return arity_8(&base, a1.data, a2.data, a3.data, a4.data, a5.data, a6.data, a7.data, a8.data); } - object_ref jit_function::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7, - object_ref const &a8, - object_ref const &a9) + object_ref jit_function::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7, + object_ref const a8, + object_ref const a9) { if(!arity_9) { @@ -193,16 +193,16 @@ namespace jank::runtime::obj a9.data); } - object_ref jit_function::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7, - object_ref const &a8, - object_ref const &a9, - object_ref const &a10) + object_ref jit_function::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7, + object_ref const a8, + object_ref const a9, + object_ref const a10) { if(!arity_10) { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/keyword.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/keyword.cpp index 79eca4dcf..5feacd4c5 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/keyword.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/keyword.cpp @@ -71,12 +71,12 @@ namespace jank::runtime::obj return sym->ns; } - object_ref keyword::call(object_ref const &m) + object_ref keyword::call(object_ref const m) { return runtime::get(m, this); } - object_ref keyword::call(object_ref const &m, object_ref const &fallback) + object_ref keyword::call(object_ref const m, object_ref const fallback) { return runtime::get(m, this, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp index 3f95d473a..931a74bcf 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/lazy_sequence.cpp @@ -11,13 +11,13 @@ namespace jank::runtime::obj { - lazy_sequence::lazy_sequence(object_ref const &fn) + lazy_sequence::lazy_sequence(object_ref const fn) : fn{ fn } { jank_debug_assert(fn.is_some()); } - lazy_sequence::lazy_sequence(object_ref const &fn, object_ref const &sequence) + lazy_sequence::lazy_sequence(object_ref const fn, object_ref const sequence) : fn{ fn } , s{ sequence } { @@ -92,7 +92,7 @@ namespace jank::runtime::obj return hash::ordered(s.erase().data); } - cons_ref lazy_sequence::conj(object_ref const &head) const + cons_ref lazy_sequence::conj(object_ref const head) const { return make_box(head, seq()); } @@ -150,7 +150,7 @@ namespace jank::runtime::obj return ls; } - lazy_sequence_ref lazy_sequence::with_meta(object_ref const &m) const + lazy_sequence_ref lazy_sequence::with_meta(object_ref const m) const { auto const ret(make_box(jank_nil(), seq())); auto const meta(behavior::detail::validate_meta(m)); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/multi_function.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/multi_function.cpp index 0ba7c2451..bf5c92018 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/multi_function.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/multi_function.cpp @@ -9,10 +9,10 @@ namespace jank::runtime::obj { - multi_function::multi_function(object_ref const &name, - object_ref const &dispatch, - object_ref const &default_, - object_ref const &hierarchy) + multi_function::multi_function(object_ref const name, + object_ref const dispatch, + object_ref const default_, + object_ref const hierarchy) : dispatch{ dispatch } , default_dispatch_value{ default_ } , hierarchy{ hierarchy } @@ -59,44 +59,44 @@ namespace jank::runtime::obj return dynamic_call(get_fn(dynamic_call(dispatch))); } - object_ref multi_function::call(object_ref const &a1) + object_ref multi_function::call(object_ref const a1) { return dynamic_call(get_fn(dynamic_call(dispatch, a1)), a1); } - object_ref multi_function::call(object_ref const &a1, object_ref const &a2) + object_ref multi_function::call(object_ref const a1, object_ref const a2) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2)), a1, a2); } - object_ref multi_function::call(object_ref const &a1, object_ref const &a2, object_ref const &a3) + object_ref multi_function::call(object_ref const a1, object_ref const a2, object_ref const a3) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3)), a1, a2, a3); } - object_ref multi_function::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4) + object_ref multi_function::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3, a4)), a1, a2, a3, a4); } - object_ref multi_function::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5) + object_ref multi_function::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3, a4, a5)), a1, a2, a3, a4, a5); } - object_ref multi_function::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6) + object_ref multi_function::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3, a4, a5, a6)), a1, @@ -107,13 +107,13 @@ namespace jank::runtime::obj a6); } - object_ref multi_function::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7) + object_ref multi_function::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3, a4, a5, a6, a7)), a1, @@ -125,14 +125,14 @@ namespace jank::runtime::obj a7); } - object_ref multi_function::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7, - object_ref const &a8) + object_ref multi_function::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7, + object_ref const a8) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3, a4, a5, a6, a7, a8)), a1, @@ -145,15 +145,15 @@ namespace jank::runtime::obj a8); } - object_ref multi_function::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7, - object_ref const &a8, - object_ref const &a9) + object_ref multi_function::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7, + object_ref const a8, + object_ref const a9) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3, a4, a5, a6, a7, a8, a9)), a1, @@ -167,16 +167,16 @@ namespace jank::runtime::obj a9); } - object_ref multi_function::call(object_ref const &a1, - object_ref const &a2, - object_ref const &a3, - object_ref const &a4, - object_ref const &a5, - object_ref const &a6, - object_ref const &a7, - object_ref const &a8, - object_ref const &a9, - object_ref const &a10) + object_ref multi_function::call(object_ref const a1, + object_ref const a2, + object_ref const a3, + object_ref const a4, + object_ref const a5, + object_ref const a6, + object_ref const a7, + object_ref const a8, + object_ref const a9, + object_ref const a10) { return dynamic_call(get_fn(dynamic_call(dispatch, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)), a1, @@ -213,7 +213,7 @@ namespace jank::runtime::obj } multi_function_ref - multi_function::add_method(object_ref const &dispatch_val, object_ref const &method) + multi_function::add_method(object_ref const dispatch_val, object_ref const method) { std::lock_guard const locked{ data_lock }; @@ -222,7 +222,7 @@ namespace jank::runtime::obj return this; } - multi_function_ref multi_function::remove_method(object_ref const &dispatch_val) + multi_function_ref multi_function::remove_method(object_ref const dispatch_val) { std::lock_guard const locked{ data_lock }; method_table = method_table->dissoc(dispatch_val); @@ -230,7 +230,7 @@ namespace jank::runtime::obj return this; } - multi_function_ref multi_function::prefer_method(object_ref const &x, object_ref const &y) + multi_function_ref multi_function::prefer_method(object_ref const x, object_ref const y) { std::lock_guard const locked{ data_lock }; @@ -250,9 +250,9 @@ namespace jank::runtime::obj return this; } - bool multi_function::is_preferred(object_ref const &hierarchy, - object_ref const &x, - object_ref const &y) const + bool multi_function::is_preferred(object_ref const hierarchy, + object_ref const x, + object_ref const y) const { auto const x_prefs(prefer_table->get(x)); if(x_prefs != jank_nil() && expect_object(x_prefs)->contains(y)) @@ -285,7 +285,7 @@ namespace jank::runtime::obj return false; } - bool multi_function::is_a(object_ref const &hierarchy, object_ref const &x, object_ref const &y) + bool multi_function::is_a(object_ref const hierarchy, object_ref const x, object_ref const y) { static object_ref const isa{ __rt_ctx->intern_var("clojure.core", "isa?").expect_ok()->deref() @@ -293,14 +293,14 @@ namespace jank::runtime::obj return truthy(dynamic_call(isa, deref(hierarchy), x, y)); } - bool multi_function::is_dominant(object_ref const &hierarchy, - object_ref const &x, - object_ref const &y) const + bool multi_function::is_dominant(object_ref const hierarchy, + object_ref const x, + object_ref const y) const { return is_preferred(hierarchy, x, y) || is_a(hierarchy, x, y); } - object_ref multi_function::get_fn(object_ref const &dispatch_val) + object_ref multi_function::get_fn(object_ref const dispatch_val) { auto const target(get_method(dispatch_val)); if(target == jank_nil()) @@ -312,7 +312,7 @@ namespace jank::runtime::obj return target; } - object_ref multi_function::get_method(object_ref const &dispatch_val) + object_ref multi_function::get_method(object_ref const dispatch_val) { if(cached_hierarchy != deref(hierarchy)) { @@ -328,7 +328,7 @@ namespace jank::runtime::obj return find_and_cache_best_method(dispatch_val); } - object_ref multi_function::find_and_cache_best_method(object_ref const &dispatch_val) + object_ref multi_function::find_and_cache_best_method(object_ref const dispatch_val) { /* TODO: Clojure uses a RW lock here for better parallelism. */ std::lock_guard const locked{ data_lock }; diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/native_array_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/native_array_sequence.cpp index fceeb936a..1bcc265c6 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/native_array_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/native_array_sequence.cpp @@ -102,7 +102,7 @@ namespace jank::runtime::obj return this; } - cons_ref native_array_sequence::conj(object_ref const &head) + cons_ref native_array_sequence::conj(object_ref const head) { return make_box(head, this); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp index cc2a0e262..981254049 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp @@ -55,7 +55,7 @@ namespace jank::runtime::obj template struct build_arity { - using type = typename build_arity::type; + using type = typename build_arity::type; }; template @@ -95,101 +95,101 @@ namespace jank::runtime::obj return apply_function(*this); } - object_ref native_function_wrapper::call(object_ref const &arg1) + object_ref native_function_wrapper::call(object_ref const arg1) { return apply_function(*this, arg1); } - object_ref native_function_wrapper::call(object_ref const &arg1, object_ref const &arg2) + object_ref native_function_wrapper::call(object_ref const arg1, object_ref const arg2) { return apply_function(*this, arg1, arg2); } - object_ref native_function_wrapper::call(object_ref const &arg1, - object_ref const &arg2, - object_ref const &arg3) + object_ref native_function_wrapper::call(object_ref const arg1, + object_ref const arg2, + object_ref const arg3) { return apply_function(*this, arg1, arg2, arg3); } - object_ref native_function_wrapper::call(object_ref const &arg1, - object_ref const &arg2, - object_ref const &arg3, - object_ref const &arg4) + object_ref native_function_wrapper::call(object_ref const arg1, + object_ref const arg2, + object_ref const arg3, + object_ref const arg4) { return apply_function(*this, arg1, arg2, arg3, arg4); } - object_ref native_function_wrapper::call(object_ref const &arg1, - object_ref const &arg2, - object_ref const &arg3, - object_ref const &arg4, - object_ref const &arg5) + object_ref native_function_wrapper::call(object_ref const arg1, + object_ref const arg2, + object_ref const arg3, + object_ref const arg4, + object_ref const arg5) { return apply_function(*this, arg1, arg2, arg3, arg4, arg5); } - object_ref native_function_wrapper::call(object_ref const &arg1, - object_ref const &arg2, - object_ref const &arg3, - object_ref const &arg4, - object_ref const &arg5, - object_ref const &arg6) + object_ref native_function_wrapper::call(object_ref const arg1, + object_ref const arg2, + object_ref const arg3, + object_ref const arg4, + object_ref const arg5, + object_ref const arg6) { return apply_function(*this, arg1, arg2, arg3, arg4, arg5, arg6); } - object_ref native_function_wrapper::call(object_ref const &arg1, - object_ref const &arg2, - object_ref const &arg3, - object_ref const &arg4, - object_ref const &arg5, - object_ref const &arg6, - object_ref const &arg7) + object_ref native_function_wrapper::call(object_ref const arg1, + object_ref const arg2, + object_ref const arg3, + object_ref const arg4, + object_ref const arg5, + object_ref const arg6, + object_ref const arg7) { return apply_function(*this, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } - object_ref native_function_wrapper::call(object_ref const &arg1, - object_ref const &arg2, - object_ref const &arg3, - object_ref const &arg4, - object_ref const &arg5, - object_ref const &arg6, - object_ref const &arg7, - object_ref const &arg8) + object_ref native_function_wrapper::call(object_ref const arg1, + object_ref const arg2, + object_ref const arg3, + object_ref const arg4, + object_ref const arg5, + object_ref const arg6, + object_ref const arg7, + object_ref const arg8) { return apply_function(*this, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } - object_ref native_function_wrapper::call(object_ref const &arg1, - object_ref const &arg2, - object_ref const &arg3, - object_ref const &arg4, - object_ref const &arg5, - object_ref const &arg6, - object_ref const &arg7, - object_ref const &arg8, - object_ref const &arg9) + object_ref native_function_wrapper::call(object_ref const arg1, + object_ref const arg2, + object_ref const arg3, + object_ref const arg4, + object_ref const arg5, + object_ref const arg6, + object_ref const arg7, + object_ref const arg8, + object_ref const arg9) { return apply_function(*this, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); } - object_ref native_function_wrapper::call(object_ref const &arg1, - object_ref const &arg2, - object_ref const &arg3, - object_ref const &arg4, - object_ref const &arg5, - object_ref const &arg6, - object_ref const &arg7, - object_ref const &arg8, - object_ref const &arg9, - object_ref const &arg10) + object_ref native_function_wrapper::call(object_ref const arg1, + object_ref const arg2, + object_ref const arg3, + object_ref const arg4, + object_ref const arg5, + object_ref const arg6, + object_ref const arg7, + object_ref const arg8, + object_ref const arg9, + object_ref const arg10) { return apply_function(*this, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); } - native_function_wrapper_ref native_function_wrapper::with_meta(object_ref const &m) const + native_function_wrapper_ref native_function_wrapper::with_meta(object_ref const m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(make_box(data)); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/native_vector_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/native_vector_sequence.cpp index b48f748a5..cea169687 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/native_vector_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/native_vector_sequence.cpp @@ -111,12 +111,12 @@ namespace jank::runtime::obj return this; } - cons_ref native_vector_sequence::conj(object_ref const &head) + cons_ref native_vector_sequence::conj(object_ref const head) { return make_box(head, data.empty() ? nullptr : this); } - native_vector_sequence_ref native_vector_sequence::with_meta(object_ref const &m) const + native_vector_sequence_ref native_vector_sequence::with_meta(object_ref const m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(fresh_seq()); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp index 5001c62aa..226ec4e78 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/nil.cpp @@ -40,32 +40,32 @@ namespace jank::runtime::obj return 0; } - object_ref nil::get(object_ref const &) + object_ref nil::get(object_ref const) { return &base; } - object_ref nil::get(object_ref const &, object_ref const &fallback) + object_ref nil::get(object_ref const, object_ref const fallback) { return fallback; } - object_ref nil::get_entry(object_ref const &) + object_ref nil::get_entry(object_ref const) { return &base; } - bool nil::contains(object_ref const &) const + bool nil::contains(object_ref const) const { return false; } - persistent_array_map_ref nil::assoc(object_ref const &key, object_ref const &val) const + persistent_array_map_ref nil::assoc(object_ref const key, object_ref const val) const { return persistent_array_map::create_unique(key, val); } - nil_ref nil::dissoc(object_ref const &) const + nil_ref nil::dissoc(object_ref const) const { return this; } @@ -108,13 +108,9 @@ namespace jank::runtime return lhs->type != object_type::nil; } - obj::weak_nil_ref jank_nil() + obj::nil_ref jank_nil() { - static auto n{ []() { - obj::nil n; - n.base.retain(); - return n; - }() }; + static obj::nil n{}; return &n; } } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp index c2ad18714..25b61e57b 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp @@ -48,7 +48,7 @@ namespace jank::runtime::obj i64 boolean::compare(object const &o) const { return visit_number_like( - [this](auto const &typed_o) -> i64 { + [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, [&]() -> i64 { @@ -103,7 +103,7 @@ namespace jank::runtime::obj i64 integer::compare(object const &o) const { return visit_number_like( - [this](auto const &typed_o) -> i64 { + [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, [&]() -> i64 { @@ -188,7 +188,7 @@ namespace jank::runtime::obj i64 real::compare(object const &o) const { return visit_number_like( - [this](auto const &typed_o) -> i64 { + [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, [&]() -> i64 { @@ -218,14 +218,12 @@ namespace jank::runtime static obj::boolean_ref true_const() { static obj::boolean r{ true }; - r.base.retain(); return &r; } static obj::boolean_ref false_const() { static obj::boolean r{ false }; - r.base.retain(); return &r; } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/opaque_box.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/opaque_box.cpp index b0b6a22e4..f3133cacd 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/opaque_box.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/opaque_box.cpp @@ -44,7 +44,7 @@ namespace jank::runtime::obj return static_cast(reinterpret_cast(data.data)); } - opaque_box_ref opaque_box::with_meta(object_ref const &m) + opaque_box_ref opaque_box::with_meta(object_ref const m) { meta = behavior::detail::validate_meta(m); return this; diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_array_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_array_map.cpp index 7a6013e5e..6bee67e1a 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_array_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_array_map.cpp @@ -27,17 +27,17 @@ namespace jank::runtime::obj { } - object_ref persistent_array_map::get(object_ref const &key) const + object_ref persistent_array_map::get(object_ref const key) const { return data.find(key).unwrap_or(jank_nil()); } - object_ref persistent_array_map::get(object_ref const &key, object_ref const &fallback) const + object_ref persistent_array_map::get(object_ref const key, object_ref const fallback) const { return data.find(key).unwrap_or(fallback); } - object_ref persistent_array_map::get_entry(object_ref const &key) const + object_ref persistent_array_map::get_entry(object_ref const key) const { auto const res(data.find(key)); if(res.is_some()) @@ -47,12 +47,12 @@ namespace jank::runtime::obj return jank_nil(); } - bool persistent_array_map::contains(object_ref const &key) const + bool persistent_array_map::contains(object_ref const key) const { return data.find(key).is_some(); } - object_ref persistent_array_map::assoc(object_ref const &key, object_ref const &val) const + object_ref persistent_array_map::assoc(object_ref const key, object_ref const val) const { /* If we've hit the max array map size, it's time to promote to a hash map. * @@ -73,19 +73,19 @@ namespace jank::runtime::obj } } - persistent_array_map_ref persistent_array_map::dissoc(object_ref const &key) const + persistent_array_map_ref persistent_array_map::dissoc(object_ref const key) const { auto copy(data.clone()); copy.erase(key); return make_box(meta, std::move(copy)); } - object_ref persistent_array_map::call(object_ref const &o) const + object_ref persistent_array_map::call(object_ref const o) const { return get(o); } - object_ref persistent_array_map::call(object_ref const &o, object_ref const &fallback) const + object_ref persistent_array_map::call(object_ref const o, object_ref const fallback) const { return get(o, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp index 9cd43500b..c3f0e5d8b 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_map.cpp @@ -11,8 +11,8 @@ namespace jank::runtime::obj { persistent_hash_map::persistent_hash_map(jtl::option const &meta, runtime::detail::native_array_map const &m, - object_ref const &key, - object_ref const &val) + object_ref const key, + object_ref const val) : parent_type{ meta } { runtime::detail::native_transient_hash_map transient; @@ -46,10 +46,10 @@ namespace jank::runtime::obj return ret; } - persistent_hash_map_ref persistent_hash_map::create_from_seq(object_ref const &seq) + persistent_hash_map_ref persistent_hash_map::create_from_seq(object_ref const seq) { return make_box(visit_seqable( - [](auto const &typed_seq) -> persistent_hash_map::value_type { + [](auto const typed_seq) -> persistent_hash_map::value_type { runtime::detail::native_transient_hash_map transient; auto const r{ make_sequence_range(typed_seq) }; for(auto it(r.begin()); it != r.end(); ++it) @@ -72,7 +72,7 @@ namespace jank::runtime::obj seq)); } - object_ref persistent_hash_map::get(object_ref const &key) const + object_ref persistent_hash_map::get(object_ref const key) const { auto const res(data.find(key)); if(res) @@ -82,7 +82,7 @@ namespace jank::runtime::obj return jank_nil(); } - object_ref persistent_hash_map::get(object_ref const &key, object_ref const &fallback) const + object_ref persistent_hash_map::get(object_ref const key, object_ref const fallback) const { auto const res(data.find(key)); if(res) @@ -92,7 +92,7 @@ namespace jank::runtime::obj return fallback; } - object_ref persistent_hash_map::get_entry(object_ref const &key) const + object_ref persistent_hash_map::get_entry(object_ref const key) const { auto const res(data.find(key)); if(res) @@ -102,30 +102,30 @@ namespace jank::runtime::obj return jank_nil(); } - bool persistent_hash_map::contains(object_ref const &key) const + bool persistent_hash_map::contains(object_ref const key) const { return data.find(key); } persistent_hash_map_ref - persistent_hash_map::assoc(object_ref const &key, object_ref const &val) const + persistent_hash_map::assoc(object_ref const key, object_ref const val) const { auto copy(data.set(key, val)); return make_box(meta, std::move(copy)); } - persistent_hash_map_ref persistent_hash_map::dissoc(object_ref const &key) const + persistent_hash_map_ref persistent_hash_map::dissoc(object_ref const key) const { auto copy(data.erase(key)); return make_box(meta, std::move(copy)); } - object_ref persistent_hash_map::call(object_ref const &o) const + object_ref persistent_hash_map::call(object_ref const o) const { return get(o); } - object_ref persistent_hash_map::call(object_ref const &o, object_ref const &fallback) const + object_ref persistent_hash_map::call(object_ref const o, object_ref const fallback) const { return get(o, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp index 2a8e79435..4225904c3 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_hash_set.cpp @@ -27,10 +27,10 @@ namespace jank::runtime::obj return ret; } - persistent_hash_set_ref persistent_hash_set::create_from_seq(object_ref const &seq) + persistent_hash_set_ref persistent_hash_set::create_from_seq(object_ref const seq) { return make_box(visit_seqable( - [](auto const &typed_seq) -> persistent_hash_set::value_type { + [](auto const typed_seq) -> persistent_hash_set::value_type { runtime::detail::native_transient_hash_set transient; for(auto const e : make_sequence_range(typed_seq)) { @@ -49,7 +49,7 @@ namespace jank::runtime::obj } return visit_set_like( - [&](auto const &typed_o) -> bool { + [&](auto const typed_o) -> bool { if(typed_o->count() != count()) { return false; @@ -113,7 +113,7 @@ namespace jank::runtime::obj return data.size(); } - persistent_hash_set_ref persistent_hash_set::with_meta(object_ref const &m) const + persistent_hash_set_ref persistent_hash_set::with_meta(object_ref const m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(make_box(data)); @@ -121,14 +121,14 @@ namespace jank::runtime::obj return ret; } - persistent_hash_set_ref persistent_hash_set::conj(object_ref const &head) const + persistent_hash_set_ref persistent_hash_set::conj(object_ref const head) const { auto set(data.insert(head)); auto ret(make_box(meta, std::move(set))); return ret; } - object_ref persistent_hash_set::call(object_ref const &o) const + object_ref persistent_hash_set::call(object_ref const o) const { auto const found(data.find(o)); if(!found) @@ -143,12 +143,12 @@ namespace jank::runtime::obj return make_box(data); } - bool persistent_hash_set::contains(object_ref const &o) const + bool persistent_hash_set::contains(object_ref const o) const { return data.find(o); } - persistent_hash_set_ref persistent_hash_set::disj(object_ref const &o) const + persistent_hash_set_ref persistent_hash_set::disj(object_ref const o) const { auto set(data.erase(o)); auto ret(make_box(meta, std::move(set))); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp index 0c90bcc83..30cefa244 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp @@ -18,7 +18,7 @@ namespace jank::runtime::obj { } - persistent_list_ref persistent_list::create(object_ref const &meta, object_ref const &s) + persistent_list_ref persistent_list::create(object_ref const meta, object_ref const s) { auto const ret{ create(s) }; auto const m{ behavior::detail::validate_meta(meta) }; @@ -26,7 +26,7 @@ namespace jank::runtime::obj return ret; } - persistent_list_ref persistent_list::create(object_ref const &s) + persistent_list_ref persistent_list::create(object_ref const s) { if(s.is_nil()) { @@ -55,12 +55,12 @@ namespace jank::runtime::obj s); } - persistent_list_ref persistent_list::create(persistent_list_ref const &s) + persistent_list_ref persistent_list::create(persistent_list_ref const s) { return s; } - persistent_list_ref persistent_list::create(nil_ref const &) + persistent_list_ref persistent_list::create(nil_ref const ) { return empty(); } @@ -114,7 +114,7 @@ namespace jank::runtime::obj return data.size(); } - persistent_list_ref persistent_list::conj(object_ref const &head) const + persistent_list_ref persistent_list::conj(object_ref const head) const { auto l(data.conj(head)); auto ret(make_box(meta, std::move(l))); @@ -151,7 +151,7 @@ namespace jank::runtime::obj return this; } - persistent_list_ref persistent_list::with_meta(object_ref const &m) const + persistent_list_ref persistent_list::with_meta(object_ref const m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(make_box(data)); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp index 39815e091..7e0f980a9 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_map.cpp @@ -18,7 +18,7 @@ namespace jank::runtime::obj { } - persistent_sorted_map::persistent_sorted_map(object_ref const &meta, value_type &&d) + persistent_sorted_map::persistent_sorted_map(object_ref const meta, value_type &&d) : data{ std::move(d) } { this->meta = meta; @@ -36,10 +36,10 @@ namespace jank::runtime::obj return ret; } - persistent_sorted_map_ref persistent_sorted_map::create_from_seq(object_ref const &seq) + persistent_sorted_map_ref persistent_sorted_map::create_from_seq(object_ref const seq) { return make_box(visit_object( - [](auto const &typed_seq) -> persistent_sorted_map::value_type { + [](auto const typed_seq) -> persistent_sorted_map::value_type { using T = typename jtl::decay_t::value_type; if constexpr(behavior::seqable) @@ -68,7 +68,7 @@ namespace jank::runtime::obj seq)); } - object_ref persistent_sorted_map::get(object_ref const &key) const + object_ref persistent_sorted_map::get(object_ref const key) const { auto const res(data.find(key)); if(res != data.end()) @@ -78,7 +78,7 @@ namespace jank::runtime::obj return jank_nil(); } - object_ref persistent_sorted_map::get(object_ref const &key, object_ref const &fallback) const + object_ref persistent_sorted_map::get(object_ref const key, object_ref const fallback) const { auto const res(data.find(key)); if(res != data.end()) @@ -88,7 +88,7 @@ namespace jank::runtime::obj return fallback; } - object_ref persistent_sorted_map::get_entry(object_ref const &key) const + object_ref persistent_sorted_map::get_entry(object_ref const key) const { auto const res(data.find(key)); if(res != data.end()) @@ -98,32 +98,32 @@ namespace jank::runtime::obj return jank_nil(); } - bool persistent_sorted_map::contains(object_ref const &key) const + bool persistent_sorted_map::contains(object_ref const key) const { return data.contains(key); } persistent_sorted_map_ref - persistent_sorted_map::assoc(object_ref const &key, object_ref const &val) const + persistent_sorted_map::assoc(object_ref const key, object_ref const val) const { auto copy(data); copy[key] = val; return make_box(meta, std::move(copy)); } - persistent_sorted_map_ref persistent_sorted_map::dissoc(object_ref const &key) const + persistent_sorted_map_ref persistent_sorted_map::dissoc(object_ref const key) const { auto copy(data); copy.erase(key); return make_box(meta, std::move(copy)); } - object_ref persistent_sorted_map::call(object_ref const &o) const + object_ref persistent_sorted_map::call(object_ref const o) const { return get(o); } - object_ref persistent_sorted_map::call(object_ref const &o, object_ref const &fallback) const + object_ref persistent_sorted_map::call(object_ref const o, object_ref const fallback) const { return get(o, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp index 80ab478b6..1f53e2bbf 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_sorted_set.cpp @@ -16,7 +16,7 @@ namespace jank::runtime::obj { } - persistent_sorted_set::persistent_sorted_set(object_ref const &meta, value_type &&d) + persistent_sorted_set::persistent_sorted_set(object_ref const meta, value_type &&d) : data{ std::move(d) } , meta{ meta } { @@ -34,10 +34,10 @@ namespace jank::runtime::obj return ret; } - persistent_sorted_set_ref persistent_sorted_set::create_from_seq(object_ref const &seq) + persistent_sorted_set_ref persistent_sorted_set::create_from_seq(object_ref const seq) { return make_box(visit_seqable( - [](auto const &typed_seq) -> persistent_sorted_set::value_type { + [](auto const typed_seq) -> persistent_sorted_set::value_type { runtime::detail::native_transient_sorted_set transient; for(auto const e : make_sequence_range(typed_seq)) { @@ -56,7 +56,7 @@ namespace jank::runtime::obj } return visit_set_like( - [&](auto const &typed_o) -> bool { + [&](auto const typed_o) -> bool { if(typed_o->count() != count()) { return false; @@ -120,7 +120,7 @@ namespace jank::runtime::obj return data.size(); } - persistent_sorted_set_ref persistent_sorted_set::with_meta(object_ref const &m) const + persistent_sorted_set_ref persistent_sorted_set::with_meta(object_ref const m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(make_box(data)); @@ -128,7 +128,7 @@ namespace jank::runtime::obj return ret; } - persistent_sorted_set_ref persistent_sorted_set::conj(object_ref const &head) const + persistent_sorted_set_ref persistent_sorted_set::conj(object_ref const head) const { auto copy(data); copy.insert(head); @@ -136,7 +136,7 @@ namespace jank::runtime::obj return ret; } - object_ref persistent_sorted_set::call(object_ref const &o) + object_ref persistent_sorted_set::call(object_ref const o) { auto const found(data.find(o)); if(found != data.end()) @@ -151,12 +151,12 @@ namespace jank::runtime::obj return make_box(data); } - bool persistent_sorted_set::contains(object_ref const &o) const + bool persistent_sorted_set::contains(object_ref const o) const { return data.contains(o); } - persistent_sorted_set_ref persistent_sorted_set::disj(object_ref const &o) const + persistent_sorted_set_ref persistent_sorted_set::disj(object_ref const o) const { auto copy(data); copy.erase(o); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp index e16a3bb93..c768a11fc 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp @@ -60,12 +60,12 @@ namespace jank::runtime::obj return data.compare(s.data); } - object_ref persistent_string::get(object_ref const &key) const + object_ref persistent_string::get(object_ref const key) const { return get(key, jank_nil()); } - object_ref persistent_string::get(object_ref const &key, object_ref const &fallback) const + object_ref persistent_string::get(object_ref const key, object_ref const fallback) const { if(key->type == object_type::integer) { @@ -82,7 +82,7 @@ namespace jank::runtime::obj } } - bool persistent_string::contains(object_ref const &key) const + bool persistent_string::contains(object_ref const key) const { if(key->type == object_type::integer) { @@ -92,12 +92,12 @@ namespace jank::runtime::obj return false; } - object_ref persistent_string::get_entry(object_ref const &) const + object_ref persistent_string::get_entry(object_ref const ) const { throw std::runtime_error{ util::format("get_entry not supported on string") }; } - object_ref persistent_string::nth(object_ref const &index) const + object_ref persistent_string::nth(object_ref const index) const { if(index->type == object_type::integer) { @@ -117,7 +117,7 @@ namespace jank::runtime::obj } } - object_ref persistent_string::nth(object_ref const &index, object_ref const &fallback) const + object_ref persistent_string::nth(object_ref const index, object_ref const fallback) const { return get(index, fallback); } @@ -146,7 +146,7 @@ namespace jank::runtime::obj return ok(make_box(data.substr(start, end - start))); } - i64 persistent_string::first_index_of(object_ref const &m) const + i64 persistent_string::first_index_of(object_ref const m) const { auto const s(runtime::to_string(m)); auto const found(data.find(s)); @@ -157,7 +157,7 @@ namespace jank::runtime::obj return static_cast(found); } - i64 persistent_string::last_index_of(object_ref const &m) const + i64 persistent_string::last_index_of(object_ref const m) const { auto const s(runtime::to_string(m)); auto const found(data.rfind(s)); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string_sequence.cpp index 56a4659a9..1ffe3d19a 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string_sequence.cpp @@ -5,13 +5,13 @@ namespace jank::runtime::obj { - persistent_string_sequence::persistent_string_sequence(persistent_string_ref const &s) + persistent_string_sequence::persistent_string_sequence(persistent_string_ref const s) : str{ s } { jank_debug_assert(!s->data.empty()); } - persistent_string_sequence::persistent_string_sequence(persistent_string_ref const &s, + persistent_string_sequence::persistent_string_sequence(persistent_string_ref const s, usize const i) : str{ s } , index{ i } @@ -97,7 +97,7 @@ namespace jank::runtime::obj return this; } - cons_ref persistent_string_sequence::conj(object_ref const &head) + cons_ref persistent_string_sequence::conj(object_ref const head) { return make_box(head, this); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp index 07f3a5969..7d52bc144 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp @@ -25,7 +25,7 @@ namespace jank::runtime::obj { } - persistent_vector_ref persistent_vector::create(object_ref const &s) + persistent_vector_ref persistent_vector::create(object_ref const s) { if(s.is_nil()) { @@ -120,7 +120,7 @@ namespace jank::runtime::obj i64 persistent_vector::compare(object const &o) const { - return visit_type([this](auto const &typed_o) { return compare(*typed_o); }, + return visit_type([this](auto const typed_o) { return compare(*typed_o); }, &o); } @@ -169,14 +169,14 @@ namespace jank::runtime::obj return data.size(); } - persistent_vector_ref persistent_vector::conj(object_ref const &head) const + persistent_vector_ref persistent_vector::conj(object_ref const head) const { auto vec(data.push_back(head)); auto ret(make_box(meta, std::move(vec))); return ret; } - object_ref persistent_vector::call(object_ref const &o) const + object_ref persistent_vector::call(object_ref const o) const { return get(o); } @@ -186,7 +186,7 @@ namespace jank::runtime::obj return make_box(data); } - persistent_vector_ref persistent_vector::with_meta(object_ref const &m) const + persistent_vector_ref persistent_vector::with_meta(object_ref const m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(make_box(data)); @@ -194,12 +194,12 @@ namespace jank::runtime::obj return ret; } - object_ref persistent_vector::get(object_ref const &key) const + object_ref persistent_vector::get(object_ref const key) const { return get(key, jank_nil()); } - object_ref persistent_vector::get(object_ref const &key, object_ref const &fallback) const + object_ref persistent_vector::get(object_ref const key, object_ref const fallback) const { if(key->type == object_type::integer) { @@ -216,7 +216,7 @@ namespace jank::runtime::obj } } - object_ref persistent_vector::get_entry(object_ref const &key) const + object_ref persistent_vector::get_entry(object_ref const key) const { if(key->type == object_type::integer) { @@ -234,7 +234,7 @@ namespace jank::runtime::obj } } - bool persistent_vector::contains(object_ref const &key) const + bool persistent_vector::contains(object_ref const key) const { if(key->type == object_type::integer) { @@ -247,7 +247,7 @@ namespace jank::runtime::obj } } - persistent_vector_ref persistent_vector::assoc(object_ref const &key, object_ref const &val) const + persistent_vector_ref persistent_vector::assoc(object_ref const key, object_ref const val) const { if(key->type != object_type::integer) { @@ -272,7 +272,7 @@ namespace jank::runtime::obj return make_box(meta, std::move(vec)); } - persistent_vector_ref persistent_vector::dissoc(object_ref const & /*key*/) const + persistent_vector_ref persistent_vector::dissoc(object_ref const /*key*/) const { throw std::runtime_error{ "Type 'persistent_vector' does not support 'dissoc'." }; } @@ -297,7 +297,7 @@ namespace jank::runtime::obj return make_box(meta, data.take(data.size() - 1)); } - object_ref persistent_vector::nth(object_ref const &index) const + object_ref persistent_vector::nth(object_ref const index) const { if(index->type == object_type::integer) { @@ -317,7 +317,7 @@ namespace jank::runtime::obj } } - object_ref persistent_vector::nth(object_ref const &index, object_ref const &fallback) const + object_ref persistent_vector::nth(object_ref const index, object_ref const fallback) const { return get(index, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector_sequence.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector_sequence.cpp index 139b77917..73897a8ea 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector_sequence.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector_sequence.cpp @@ -5,13 +5,13 @@ namespace jank::runtime::obj { - persistent_vector_sequence::persistent_vector_sequence(persistent_vector_ref const &v) + persistent_vector_sequence::persistent_vector_sequence(persistent_vector_ref const v) : vec{ v } { jank_debug_assert(!v->data.empty()); } - persistent_vector_sequence::persistent_vector_sequence(persistent_vector_ref const &v, + persistent_vector_sequence::persistent_vector_sequence(persistent_vector_ref const v, usize const i) : vec{ v } , index{ i } @@ -118,7 +118,7 @@ namespace jank::runtime::obj return this; } - cons_ref persistent_vector_sequence::conj(object_ref const &head) + cons_ref persistent_vector_sequence::conj(object_ref const head) { return make_box(head, this); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/range.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/range.cpp index 5de0713e5..70fa102c9 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/range.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/range.cpp @@ -8,17 +8,17 @@ namespace jank::runtime::obj { - static bool positive_step_bounds_check(object_ref const &val, object_ref const &end) + static bool positive_step_bounds_check(object_ref const val, object_ref const end) { return lte(end, val); } - static bool negative_step_bounds_check(object_ref const &val, object_ref const &end) + static bool negative_step_bounds_check(object_ref const val, object_ref const end) { return lte(val, end); } - range::range(object_ref const &end) + range::range(object_ref const end) : start{ make_box(0) } , end{ end } , step{ make_box(1) } @@ -26,7 +26,7 @@ namespace jank::runtime::obj { } - range::range(object_ref const &start, object_ref const &end) + range::range(object_ref const start, object_ref const end) : start{ start } , end{ end } , step{ make_box(1) } @@ -34,7 +34,7 @@ namespace jank::runtime::obj { } - range::range(object_ref const &start, object_ref const &end, object_ref const &step) + range::range(object_ref const start, object_ref const end, object_ref const step) : start{ start } , end{ end } , step{ step } @@ -43,9 +43,9 @@ namespace jank::runtime::obj { } - range::range(object_ref const &start, - object_ref const &end, - object_ref const &step, + range::range(object_ref const start, + object_ref const end, + object_ref const step, range::bounds_check_t const bounds_check) : start{ start } , end{ end } @@ -54,12 +54,12 @@ namespace jank::runtime::obj { } - range::range(object_ref const &start, - object_ref const &end, - object_ref const &step, + range::range(object_ref const start, + object_ref const end, + object_ref const step, range::bounds_check_t const bounds_check, - array_chunk_ref const &chunk, - range_ref const &chunk_next) + array_chunk_ref const chunk, + range_ref const chunk_next) : start{ start } , end{ end } , step{ step } @@ -69,7 +69,7 @@ namespace jank::runtime::obj { } - object_ref range::create(object_ref const &end) + object_ref range::create(object_ref const end) { if(is_pos(end)) { @@ -81,12 +81,12 @@ namespace jank::runtime::obj return persistent_list::empty(); } - object_ref range::create(object_ref const &start, object_ref const &end) + object_ref range::create(object_ref const start, object_ref const end) { return create(start, end, make_box(1)); } - object_ref range::create(object_ref const &start, object_ref const &end, object_ref const &step) + object_ref range::create(object_ref const start, object_ref const end, object_ref const step) { if((is_pos(step) && lt(end, start)) || (is_neg(step) && lt(start, end)) || is_equiv(start, end)) { @@ -200,7 +200,7 @@ namespace jank::runtime::obj return chunk_next; } - cons_ref range::conj(object_ref const &head) const + cons_ref range::conj(object_ref const head) const { return make_box(head, this); } @@ -230,7 +230,7 @@ namespace jank::runtime::obj return hash::ordered(&base); } - range_ref range::with_meta(object_ref const &m) const + range_ref range::with_meta(object_ref const m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(fresh_seq()); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp index 6bd25e49f..932dcf03c 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp @@ -22,7 +22,7 @@ namespace jank::runtime::obj return to_native_big_decimal(r.data); } - static native_big_integer extract_big_integer(object_ref const &d) + static native_big_integer extract_big_integer(object_ref const d) { native_big_integer result{}; if(d->type == object_type::big_integer) @@ -71,7 +71,7 @@ namespace jank::runtime::obj { } - ratio_data::ratio_data(object_ref const &numerator, object_ref const &denominator) + ratio_data::ratio_data(object_ref const numerator, object_ref const denominator) : ratio_data(extract_big_integer(numerator), extract_big_integer(denominator)) { } @@ -168,7 +168,7 @@ namespace jank::runtime::obj i64 ratio::compare(object const &o) const { return visit_number_like( - [this](auto const &typed_o) -> i64 { + [this](auto const typed_o) -> i64 { using T = std::decay_t; if constexpr(std::is_same_v) { @@ -194,22 +194,22 @@ namespace jank::runtime::obj return ratio::create(num, denom); } - ratio_ref operator+(integer_ref const &l, ratio_data const &r) + ratio_ref operator+(integer_ref const l, ratio_data const &r) { return l->data + r; } - ratio_ref operator+(ratio_data const &l, integer_ref const &r) + ratio_ref operator+(ratio_data const &l, integer_ref const r) { return r + l; } - f64 operator+(real_ref const &l, ratio_data const &r) + f64 operator+(real_ref const l, ratio_data const &r) { return l->data + r.to_real(); } - f64 operator+(ratio_data const &l, real_ref const &r) + f64 operator+(ratio_data const &l, real_ref const r) { return l.to_real() + r->data; } @@ -241,22 +241,22 @@ namespace jank::runtime::obj return ratio::create(num, denom); } - ratio_ref operator-(integer_ref const &l, ratio_data const &r) + ratio_ref operator-(integer_ref const l, ratio_data const &r) { return l->data - r; } - ratio_ref operator-(ratio_data const &l, integer_ref const &r) + ratio_ref operator-(ratio_data const &l, integer_ref const r) { return l - r->data; } - f64 operator-(real_ref const &l, ratio_data const &r) + f64 operator-(real_ref const l, ratio_data const &r) { return l->data - r.to_real(); } - f64 operator-(ratio_data const &l, real_ref const &r) + f64 operator-(ratio_data const &l, real_ref const r) { return l.to_real() - r->data; } @@ -286,22 +286,22 @@ namespace jank::runtime::obj return ratio::create(l.numerator * r.numerator, l.denominator * r.denominator); } - object_ref operator*(integer_ref const &l, ratio_data const &r) + object_ref operator*(integer_ref const l, ratio_data const &r) { return ratio_data(l->data, 1ll) * r; } - object_ref operator*(ratio_data const &l, integer_ref const &r) + object_ref operator*(ratio_data const &l, integer_ref const r) { return l * ratio_data(r->data, 1ll); } - f64 operator*(real_ref const &l, ratio_data const &r) + f64 operator*(real_ref const l, ratio_data const &r) { return l->data * r.to_real(); } - f64 operator*(ratio_data const &l, real_ref const &r) + f64 operator*(ratio_data const &l, real_ref const r) { return l.to_real() * r->data; } @@ -331,22 +331,22 @@ namespace jank::runtime::obj return ratio::create(l.numerator * r.denominator, l.denominator * r.numerator); } - object_ref operator/(integer_ref const &l, ratio_data const &r) + object_ref operator/(integer_ref const l, ratio_data const &r) { return ratio_data(l->data, 1ll) / r; } - ratio_ref operator/(ratio_data const &l, integer_ref const &r) + ratio_ref operator/(ratio_data const &l, integer_ref const r) { return l / r->data; } - f64 operator/(real_ref const &l, ratio_data const &r) + f64 operator/(real_ref const l, ratio_data const &r) { return l->data / r.to_real(); } - f64 operator/(ratio_data const &l, real_ref const &r) + f64 operator/(ratio_data const &l, real_ref const r) { return l.to_real() / r->data; } @@ -376,22 +376,22 @@ namespace jank::runtime::obj return l.numerator == r.numerator && l.denominator == r.denominator; } - bool operator==(integer_ref const &l, ratio_data const &r) + bool operator==(integer_ref const l, ratio_data const &r) { return l->data * r.denominator == r.numerator; } - bool operator==(ratio_data const &l, integer_ref const &r) + bool operator==(ratio_data const &l, integer_ref const r) { return l.numerator == r->data * l.denominator; } - bool operator==(real_ref const &l, ratio_data const &r) + bool operator==(real_ref const l, ratio_data const &r) { return std::fabs(l->data - r) < epsilon; } - bool operator==(ratio_data const &l, real_ref const &r) + bool operator==(ratio_data const &l, real_ref const r) { return r == l; } @@ -426,42 +426,42 @@ namespace jank::runtime::obj return l.numerator * r.denominator <= r.numerator * l.denominator; } - bool operator<(integer_ref const &l, ratio_data const &r) + bool operator<(integer_ref const l, ratio_data const &r) { return l->data * r.denominator < r.numerator; } - bool operator<(ratio_data const &l, integer_ref const &r) + bool operator<(ratio_data const &l, integer_ref const r) { return l.numerator < r->data * l.denominator; } - bool operator<=(integer_ref const &l, ratio_data const &r) + bool operator<=(integer_ref const l, ratio_data const &r) { return l->data * r.denominator <= r.numerator; } - bool operator<=(ratio_data const &l, integer_ref const &r) + bool operator<=(ratio_data const &l, integer_ref const r) { return l.numerator <= r->data * l.denominator; } - bool operator<(real_ref const &l, ratio_data const &r) + bool operator<(real_ref const l, ratio_data const &r) { return l->data < r.to_real(); } - bool operator<(ratio_data const &l, real_ref const &r) + bool operator<(ratio_data const &l, real_ref const r) { return l.to_real() < r->data; } - bool operator<=(real_ref const &l, ratio_data const &r) + bool operator<=(real_ref const l, ratio_data const &r) { return l->data <= r.to_real(); } - bool operator<=(ratio_data const &l, real_ref const &r) + bool operator<=(ratio_data const &l, real_ref const r) { return l.to_real() <= r->data; } @@ -511,22 +511,22 @@ namespace jank::runtime::obj return l.numerator * r.denominator > r.numerator * l.denominator; } - bool operator>(integer_ref const &l, ratio_data const &r) + bool operator>(integer_ref const l, ratio_data const &r) { return l->data * r.denominator > r.numerator; } - bool operator>(ratio_data const &l, integer_ref const &r) + bool operator>(ratio_data const &l, integer_ref const r) { return l.numerator > r->data * l.denominator; } - bool operator>(real_ref const &l, ratio_data const &r) + bool operator>(real_ref const l, ratio_data const &r) { return l->data > r.to_real(); } - bool operator>(ratio_data const &l, real_ref const &r) + bool operator>(ratio_data const &l, real_ref const r) { return l.to_real() > r->data; } @@ -556,22 +556,22 @@ namespace jank::runtime::obj return l.numerator * r.denominator >= r.numerator * l.denominator; } - bool operator>=(integer_ref const &l, ratio_data const &r) + bool operator>=(integer_ref const l, ratio_data const &r) { return l->data * r.denominator >= r.numerator; } - bool operator>=(ratio_data const &l, integer_ref const &r) + bool operator>=(ratio_data const &l, integer_ref const r) { return l.numerator >= r->data * l.denominator; } - bool operator>=(real_ref const &l, ratio_data const &r) + bool operator>=(real_ref const l, ratio_data const &r) { return l->data >= r.to_real(); } - bool operator>=(ratio_data const &l, real_ref const &r) + bool operator>=(ratio_data const &l, real_ref const r) { return l.to_real() >= r->data; } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/re_matcher.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/re_matcher.cpp index ede3f080a..57673a760 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/re_matcher.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/re_matcher.cpp @@ -4,7 +4,7 @@ namespace jank::runtime::obj { - re_matcher::re_matcher(re_pattern_ref const &re, jtl::immutable_string const &s) + re_matcher::re_matcher(re_pattern_ref const re, jtl::immutable_string const &s) : re{ re } , match_input{ s.c_str() } { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/reduced.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/reduced.cpp index 15a802c14..1e9fce965 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/reduced.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/reduced.cpp @@ -3,7 +3,7 @@ namespace jank::runtime::obj { - reduced::reduced(object_ref const &o) + reduced::reduced(object_ref const o) : val{ o } { jank_debug_assert(val.is_some()); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/repeat.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/repeat.cpp index cd31d93de..fdd84f7d4 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/repeat.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/repeat.cpp @@ -6,13 +6,13 @@ namespace jank::runtime::obj { - repeat::repeat(object_ref const &value) + repeat::repeat(object_ref const value) : value{ value } , count{ make_box(infinite) } { } - repeat::repeat(object_ref const &count, object_ref const &value) + repeat::repeat(object_ref const count, object_ref const value) : value{ value } , count{ count } { @@ -23,12 +23,12 @@ namespace jank::runtime::obj } } - object_ref repeat::create(object_ref const &value) + object_ref repeat::create(object_ref const value) { return make_box(value); } - object_ref repeat::create(object_ref const &count, object_ref const &value) + object_ref repeat::create(object_ref const count, object_ref const value) { if(lte(count, make_box(0))) { @@ -83,7 +83,7 @@ namespace jank::runtime::obj return this; } - cons_ref repeat::conj(object_ref const &head) const + cons_ref repeat::conj(object_ref const head) const { return make_box(head, this); } @@ -113,7 +113,7 @@ namespace jank::runtime::obj return hash::ordered(&base); } - repeat_ref repeat::with_meta(object_ref const &m) const + repeat_ref repeat::with_meta(object_ref const m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(fresh_seq()); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/symbol.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/symbol.cpp index 0ad038c17..b219741f9 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/symbol.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/symbol.cpp @@ -41,7 +41,7 @@ namespace jank::runtime::obj { } - symbol::symbol(object_ref const &meta, + symbol::symbol(object_ref const meta, jtl::immutable_string const &ns, jtl::immutable_string const &n) : ns{ ns } @@ -50,7 +50,7 @@ namespace jank::runtime::obj { } - symbol::symbol(object_ref const &ns, object_ref const &n) + symbol::symbol(object_ref const ns, object_ref const n) : ns{ runtime::to_string(ns) } , name{ runtime::to_string(n) } { @@ -74,7 +74,7 @@ namespace jank::runtime::obj i64 symbol::compare(object const &o) const { - return visit_type([this](auto const &typed_o) { return compare(*typed_o); }, &o); + return visit_type([this](auto const typed_o) { return compare(*typed_o); }, &o); } i64 symbol::compare(symbol const &s) const @@ -144,7 +144,7 @@ namespace jank::runtime::obj return hash = hash::combine(hash::string(name), hash::string(ns)); } - symbol_ref symbol::with_meta(object_ref const &m) const + symbol_ref symbol::with_meta(object_ref const m) const { auto const meta(behavior::detail::validate_meta(m)); auto ret(make_box(ns, name)); @@ -194,14 +194,14 @@ namespace std } size_t hash::operator()( - jank::runtime::obj::symbol_ref const &o) const noexcept + jank::runtime::obj::symbol_ref const o) const noexcept { return o->to_hash(); } bool equal_to::operator()( - jank::runtime::obj::symbol_ref const &lhs, - jank::runtime::obj::symbol_ref const &rhs) const noexcept + jank::runtime::obj::symbol_ref const lhs, + jank::runtime::obj::symbol_ref const rhs) const noexcept { if(lhs.is_nil()) { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp index 07301144a..afe71e3ab 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp @@ -9,7 +9,7 @@ namespace jank::runtime::obj { - tagged_literal::tagged_literal(object_ref const &tag, object_ref const &form) + tagged_literal::tagged_literal(object_ref const tag, object_ref const form) : tag{ tag } , form{ form } { @@ -27,7 +27,7 @@ namespace jank::runtime::obj } static void - to_string_impl(object_ref const &tag, object_ref const &form, jtl::string_builder &buff) + to_string_impl(object_ref const tag, object_ref const form, jtl::string_builder &buff) { buff('#'); runtime::to_string(tag, buff); @@ -62,7 +62,7 @@ namespace jank::runtime::obj return hash = hash::combine(hash::visit(tag.get()), hash::visit(form.get())); } - object_ref tagged_literal::get(object_ref const &key, object_ref const &fallback) const + object_ref tagged_literal::get(object_ref const key, object_ref const fallback) const { auto const tag_kw{ __rt_ctx->intern_keyword("tag").expect_ok() }; auto const form_kw{ __rt_ctx->intern_keyword("form").expect_ok() }; @@ -80,12 +80,12 @@ namespace jank::runtime::obj return fallback; } - object_ref tagged_literal::get(object_ref const &key) const + object_ref tagged_literal::get(object_ref const key) const { return get(key, jank_nil()); } - object_ref tagged_literal::get_entry(object_ref const &key) const + object_ref tagged_literal::get_entry(object_ref const key) const { auto const tag_kw{ __rt_ctx->intern_keyword("tag").expect_ok() }; auto const form_kw{ __rt_ctx->intern_keyword("form").expect_ok() }; @@ -103,7 +103,7 @@ namespace jank::runtime::obj return jank_nil(); } - bool tagged_literal::contains(object_ref const &key) const + bool tagged_literal::contains(object_ref const key) const { auto const tag_kw{ __rt_ctx->intern_keyword("tag").expect_ok() }; auto const form_kw{ __rt_ctx->intern_keyword("form").expect_ok() }; diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_array_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_array_map.cpp index 9e96e1b4f..f6a4c9917 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_array_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_array_map.cpp @@ -61,18 +61,18 @@ namespace jank::runtime::obj return data.size(); } - object_ref transient_array_map::get(object_ref const &key) const + object_ref transient_array_map::get(object_ref const key) const { assert_active(); return data.find(key).unwrap_or(jank_nil()); } - object_ref transient_array_map::get(object_ref const &key, object_ref const &fallback) const + object_ref transient_array_map::get(object_ref const key, object_ref const fallback) const { return data.find(key).unwrap_or(fallback); } - object_ref transient_array_map::get_entry(object_ref const &key) const + object_ref transient_array_map::get_entry(object_ref const key) const { auto const res(data.find(key)); if(res.is_some()) @@ -82,12 +82,12 @@ namespace jank::runtime::obj return jank_nil(); } - bool transient_array_map::contains(object_ref const &key) const + bool transient_array_map::contains(object_ref const key) const { return data.find(key).is_some(); } - object_ref transient_array_map::assoc_in_place(object_ref const &key, object_ref const &value) + object_ref transient_array_map::assoc_in_place(object_ref const key, object_ref const value) { assert_active(); /* If we've hit the max array map size, it's time to promote to a hash map. @@ -111,14 +111,14 @@ namespace jank::runtime::obj } } - transient_array_map_ref transient_array_map::dissoc_in_place(object_ref const &key) + transient_array_map_ref transient_array_map::dissoc_in_place(object_ref const key) { assert_active(); data.erase(key); return this; } - object_ref transient_array_map::conj_in_place(object_ref const &head) + object_ref transient_array_map::conj_in_place(object_ref const head) { assert_active(); @@ -155,12 +155,12 @@ namespace jank::runtime::obj return make_box(std::move(data)); } - object_ref transient_array_map::call(object_ref const &o) const + object_ref transient_array_map::call(object_ref const o) const { return get(o); } - object_ref transient_array_map::call(object_ref const &o, object_ref const &fallback) const + object_ref transient_array_map::call(object_ref const o, object_ref const fallback) const { return get(o, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_map.cpp index 2793f8793..9001a44a4 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_map.cpp @@ -73,7 +73,7 @@ namespace jank::runtime::obj return data.size(); } - object_ref transient_hash_map::get(object_ref const &key) const + object_ref transient_hash_map::get(object_ref const key) const { assert_active(); auto const res(data.find(key)); @@ -84,7 +84,7 @@ namespace jank::runtime::obj return jank_nil(); } - object_ref transient_hash_map::get(object_ref const &key, object_ref const &fallback) const + object_ref transient_hash_map::get(object_ref const key, object_ref const fallback) const { assert_active(); auto const res(data.find(key)); @@ -95,7 +95,7 @@ namespace jank::runtime::obj return fallback; } - object_ref transient_hash_map::get_entry(object_ref const &key) const + object_ref transient_hash_map::get_entry(object_ref const key) const { assert_active(); auto const res(data.find(key)); @@ -106,28 +106,28 @@ namespace jank::runtime::obj return jank_nil(); } - bool transient_hash_map::contains(object_ref const &key) const + bool transient_hash_map::contains(object_ref const key) const { assert_active(); return data.find(key); } transient_hash_map_ref - transient_hash_map::assoc_in_place(object_ref const &key, object_ref const &val) + transient_hash_map::assoc_in_place(object_ref const key, object_ref const val) { assert_active(); data.set(key, val); return this; } - transient_hash_map_ref transient_hash_map::dissoc_in_place(object_ref const &key) + transient_hash_map_ref transient_hash_map::dissoc_in_place(object_ref const key) { assert_active(); data.erase(key); return this; } - transient_hash_map_ref transient_hash_map::conj_in_place(object_ref const &head) + transient_hash_map_ref transient_hash_map::conj_in_place(object_ref const head) { assert_active(); @@ -163,12 +163,12 @@ namespace jank::runtime::obj return make_box(std::move(data).persistent()); } - object_ref transient_hash_map::call(object_ref const &o) const + object_ref transient_hash_map::call(object_ref const o) const { return get(o); } - object_ref transient_hash_map::call(object_ref const &o, object_ref const &fallback) const + object_ref transient_hash_map::call(object_ref const o, object_ref const fallback) const { return get(o, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_set.cpp index a03b68fde..9d6e927ba 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_hash_set.cpp @@ -61,7 +61,7 @@ namespace jank::runtime::obj return data.size(); } - transient_hash_set_ref transient_hash_set::conj_in_place(object_ref const &elem) + transient_hash_set_ref transient_hash_set::conj_in_place(object_ref const elem) { assert_active(); data.insert(elem); @@ -75,7 +75,7 @@ namespace jank::runtime::obj return make_box(data.persistent()); } - object_ref transient_hash_set::call(object_ref const &elem) const + object_ref transient_hash_set::call(object_ref const elem) const { assert_active(); auto const found(data.find(elem)); @@ -86,7 +86,7 @@ namespace jank::runtime::obj return *found; } - object_ref transient_hash_set::call(object_ref const &elem, object_ref const &fallback) const + object_ref transient_hash_set::call(object_ref const elem, object_ref const fallback) const { assert_active(); auto const found(data.find(elem)); @@ -97,17 +97,17 @@ namespace jank::runtime::obj return *found; } - object_ref transient_hash_set::get(object_ref const &elem) const + object_ref transient_hash_set::get(object_ref const elem) const { return call(elem); } - object_ref transient_hash_set::get(object_ref const &elem, object_ref const &fallback) const + object_ref transient_hash_set::get(object_ref const elem, object_ref const fallback) const { return call(elem, fallback); } - object_ref transient_hash_set::get_entry(object_ref const &elem) const + object_ref transient_hash_set::get_entry(object_ref const elem) const { auto const found = call(elem); auto const nil(jank_nil()); @@ -119,13 +119,13 @@ namespace jank::runtime::obj return make_box(std::in_place, found, found); } - bool transient_hash_set::contains(object_ref const &elem) const + bool transient_hash_set::contains(object_ref const elem) const { assert_active(); return data.find(elem); } - transient_hash_set_ref transient_hash_set::disjoin_in_place(object_ref const &elem) + transient_hash_set_ref transient_hash_set::disjoin_in_place(object_ref const elem) { assert_active(); data.erase(elem); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp index 25b1caf97..9a7c9f994 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_map.cpp @@ -59,7 +59,7 @@ namespace jank::runtime::obj return data.size(); } - object_ref transient_sorted_map::get(object_ref const &key) const + object_ref transient_sorted_map::get(object_ref const key) const { assert_active(); auto const res(data.find(key)); @@ -70,7 +70,7 @@ namespace jank::runtime::obj return jank_nil(); } - object_ref transient_sorted_map::get(object_ref const &key, object_ref const &fallback) const + object_ref transient_sorted_map::get(object_ref const key, object_ref const fallback) const { assert_active(); auto const res(data.find(key)); @@ -81,7 +81,7 @@ namespace jank::runtime::obj return fallback; } - object_ref transient_sorted_map::get_entry(object_ref const &key) const + object_ref transient_sorted_map::get_entry(object_ref const key) const { assert_active(); auto const res(data.find(key)); @@ -92,28 +92,28 @@ namespace jank::runtime::obj return jank_nil(); } - bool transient_sorted_map::contains(object_ref const &key) const + bool transient_sorted_map::contains(object_ref const key) const { assert_active(); return data.contains(key); } transient_sorted_map_ref - transient_sorted_map::assoc_in_place(object_ref const &key, object_ref const &val) + transient_sorted_map::assoc_in_place(object_ref const key, object_ref const val) { assert_active(); data[key] = val; return this; } - transient_sorted_map_ref transient_sorted_map::dissoc_in_place(object_ref const &key) + transient_sorted_map_ref transient_sorted_map::dissoc_in_place(object_ref const key) { assert_active(); data.erase(key); return this; } - transient_sorted_map_ref transient_sorted_map::conj_in_place(object_ref const &head) + transient_sorted_map_ref transient_sorted_map::conj_in_place(object_ref const head) { assert_active(); @@ -149,12 +149,12 @@ namespace jank::runtime::obj return make_box(std::move(data)); } - object_ref transient_sorted_map::call(object_ref const &o) const + object_ref transient_sorted_map::call(object_ref const o) const { return get(o); } - object_ref transient_sorted_map::call(object_ref const &o, object_ref const &fallback) const + object_ref transient_sorted_map::call(object_ref const o, object_ref const fallback) const { return get(o, fallback); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp index f43d7a0e6..e727dbc3f 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_sorted_set.cpp @@ -56,7 +56,7 @@ namespace jank::runtime::obj return data.size(); } - transient_sorted_set_ref transient_sorted_set::conj_in_place(object_ref const &elem) + transient_sorted_set_ref transient_sorted_set::conj_in_place(object_ref const elem) { assert_active(); data.insert(elem); @@ -70,7 +70,7 @@ namespace jank::runtime::obj return make_box(data); } - object_ref transient_sorted_set::call(object_ref const &elem) + object_ref transient_sorted_set::call(object_ref const elem) { assert_active(); auto const found(data.find(elem)); @@ -81,7 +81,7 @@ namespace jank::runtime::obj return jank_nil(); } - object_ref transient_sorted_set::call(object_ref const &elem, object_ref const &fallback) + object_ref transient_sorted_set::call(object_ref const elem, object_ref const fallback) { assert_active(); auto const found(data.find(elem)); @@ -92,17 +92,17 @@ namespace jank::runtime::obj return fallback; } - object_ref transient_sorted_set::get(object_ref const &elem) + object_ref transient_sorted_set::get(object_ref const elem) { return call(elem); } - object_ref transient_sorted_set::get(object_ref const &elem, object_ref const &fallback) + object_ref transient_sorted_set::get(object_ref const elem, object_ref const fallback) { return call(elem, fallback); } - object_ref transient_sorted_set::get_entry(object_ref const &elem) + object_ref transient_sorted_set::get_entry(object_ref const elem) { auto found{ call(elem) }; if(found == jank_nil()) @@ -113,13 +113,13 @@ namespace jank::runtime::obj return make_box(std::in_place, found, found); } - bool transient_sorted_set::contains(object_ref const &elem) const + bool transient_sorted_set::contains(object_ref const elem) const { assert_active(); return data.contains(elem); } - transient_sorted_set_ref transient_sorted_set::disjoin_in_place(object_ref const &elem) + transient_sorted_set_ref transient_sorted_set::disjoin_in_place(object_ref const elem) { assert_active(); data.erase(elem); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/transient_vector.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/transient_vector.cpp index 18ac426d4..c90ea73d8 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/transient_vector.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/transient_vector.cpp @@ -63,7 +63,7 @@ namespace jank::runtime::obj return data.size(); } - transient_vector_ref transient_vector::conj_in_place(object_ref const &head) + transient_vector_ref transient_vector::conj_in_place(object_ref const head) { assert_active(); data.push_back(head); @@ -77,7 +77,7 @@ namespace jank::runtime::obj return make_box(data.persistent()); } - object_ref transient_vector::call(object_ref const &idx) const + object_ref transient_vector::call(object_ref const idx) const { assert_active(); if(idx->type == object_type::integer) @@ -99,7 +99,7 @@ namespace jank::runtime::obj } } - object_ref transient_vector::get(object_ref const &idx) const + object_ref transient_vector::get(object_ref const idx) const { assert_active(); if(idx->type == object_type::integer) @@ -119,7 +119,7 @@ namespace jank::runtime::obj } } - object_ref transient_vector::get(object_ref const &idx, object_ref const &fallback) const + object_ref transient_vector::get(object_ref const idx, object_ref const fallback) const { assert_active(); if(idx->type == object_type::integer) @@ -139,7 +139,7 @@ namespace jank::runtime::obj } } - object_ref transient_vector::get_entry(object_ref const &idx) const + object_ref transient_vector::get_entry(object_ref const idx) const { if(idx->type == object_type::integer) { @@ -158,7 +158,7 @@ namespace jank::runtime::obj } } - bool transient_vector::contains(object_ref const &elem) const + bool transient_vector::contains(object_ref const elem) const { if(elem->type == object_type::integer) { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/volatile.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/volatile.cpp index 1018b8dc9..ad26b9787 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/volatile.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/volatile.cpp @@ -3,7 +3,7 @@ namespace jank::runtime::obj { - volatile_::volatile_(object_ref const &o) + volatile_::volatile_(object_ref const o) : val{ o } { jank_debug_assert(val.is_some()); @@ -41,7 +41,7 @@ namespace jank::runtime::obj return val; } - object_ref volatile_::reset(object_ref const &o) + object_ref volatile_::reset(object_ref const o) { val = o; jank_debug_assert(val.is_some()); diff --git a/compiler+runtime/src/cpp/jank/runtime/object.cpp b/compiler+runtime/src/cpp/jank/runtime/object.cpp index 445869564..699fcdbc6 100644 --- a/compiler+runtime/src/cpp/jank/runtime/object.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/object.cpp @@ -21,29 +21,6 @@ namespace jank::runtime { } - void object::retain() - { - ++ref_count; - jank_debug_assert(ref_count > 0); - //util::println("retain {} type {} count {}", this, object_type_str(type), ref_count); - } - - void object::release() - { - jank_debug_assert(ref_count > 0); - //util::println("release {} type {} count {}", this, object_type_str(type), ref_count); - if(--ref_count == 0) - { - visit_object( - [](auto const typed_this) { - using T = typename decltype(typed_this)::value_type; - //util::println("\tfreeing {}", typed_this.data); - delete static_cast(typed_this.data); - }, - this); - } - } - object &object::operator=(object const &rhs) noexcept { if(this == &rhs) @@ -64,7 +41,7 @@ namespace jank::runtime return *this; } - bool very_equal_to::operator()(object_ref const &lhs, object_ref const &rhs) const noexcept + bool very_equal_to::operator()(object_ref const lhs, object_ref const rhs) const noexcept { if(lhs->type != rhs->type) { @@ -73,12 +50,12 @@ namespace jank::runtime return equal(lhs, rhs); } - bool operator==(object const * const lhs, object_ref const &rhs) + bool operator==(object const * const lhs, object_ref const rhs) { return lhs == rhs.data; } - bool operator!=(object const * const lhs, object_ref const &rhs) + bool operator!=(object const * const lhs, object_ref const rhs) { return lhs != rhs.data; } @@ -89,7 +66,7 @@ namespace std using namespace jank; using namespace jank::runtime; - size_t hash::operator()(object_ref const &o) const noexcept + size_t hash::operator()(object_ref const o) const noexcept { return jank::hash::visit(o.data); } @@ -101,7 +78,7 @@ namespace std bool // NOLINTNEXTLINE(bugprone-exception-escape): TODO: Sort this out. - equal_to::operator()(object_ref const &lhs, object_ref const &rhs) const noexcept + equal_to::operator()(object_ref const lhs, object_ref const rhs) const noexcept { return equal(lhs, rhs); } diff --git a/compiler+runtime/src/cpp/jank/runtime/perf.cpp b/compiler+runtime/src/cpp/jank/runtime/perf.cpp index 67214b6de..08d8be739 100644 --- a/compiler+runtime/src/cpp/jank/runtime/perf.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/perf.cpp @@ -8,12 +8,12 @@ namespace jank::runtime::perf { - object_ref benchmark(object_ref const &opts, object_ref const &f) + object_ref benchmark(object_ref const opts, object_ref const f) { auto const label(get(opts, __rt_ctx->intern_keyword("label").expect_ok())); auto const label_str(to_string(label)); visit_object( - [](auto const &typed_f, jtl::immutable_string const &label) { + [](auto const typed_f, jtl::immutable_string const &label) { using T = typename jtl::decay_t::value_type; if constexpr(std::is_base_of_v) diff --git a/compiler+runtime/src/cpp/jank/runtime/var.cpp b/compiler+runtime/src/cpp/jank/runtime/var.cpp index fc7ffa72a..aca244db6 100644 --- a/compiler+runtime/src/cpp/jank/runtime/var.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/var.cpp @@ -13,23 +13,23 @@ namespace jank::runtime { - var::var(weak_ns_ref const &n, obj::symbol_ref const &name) + var::var(ns_ref const n, obj::symbol_ref const name) : n{ n } , name{ name } , root{ make_box(this) } { } - var::var(weak_ns_ref const &n, obj::symbol_ref const &name, object_ref const &root) + var::var(ns_ref const n, obj::symbol_ref const name, object_ref const root) : n{ n } , name{ name } , root{ root } { } - var::var(weak_ns_ref const &n, - obj::symbol_ref const &name, - object_ref const &root, + var::var(ns_ref const n, + obj::symbol_ref const name, + object_ref const root, bool const dynamic, bool const thread_bound) : n{ n } @@ -55,8 +55,7 @@ namespace jank::runtime return n == v.n && name == v.name; } - static void - to_string_impl(weak_ns_ref const n, obj::symbol_ref const &name, jtl::string_builder &buff) + static void to_string_impl(ns_ref const n, obj::symbol_ref const name, jtl::string_builder &buff) { buff("#'")(n->name->name)('/')(name->name); } @@ -88,7 +87,7 @@ namespace jank::runtime return hash = hash::combine(n->to_hash(), name->to_hash()); } - var_ref var::with_meta(object_ref const &m) + var_ref var::with_meta(object_ref const m) { meta = behavior::detail::validate_meta(m); return this; @@ -105,21 +104,21 @@ namespace jank::runtime return *root.rlock(); } - var_ref var::bind_root(object_ref const &r) + var_ref var::bind_root(object_ref const r) { profile::timer const timer{ "var bind_root" }; *root.wlock() = r; return this; } - object_ref var::alter_root(object_ref const &f, object_ref const &args) + object_ref var::alter_root(object_ref const f, object_ref const args) { auto locked_root(root.wlock()); *locked_root = apply_to(f, cons(*locked_root, args)); return *locked_root; } - jtl::string_result var::set(object_ref const &r) const + jtl::string_result var::set(object_ref const r) const { profile::timer const timer{ "var set" }; @@ -187,7 +186,7 @@ namespace jank::runtime return make_box(n, name, get_root(), dynamic.load(), thread_bound.load()); } - var_thread_binding::var_thread_binding(object_ref const &value, std::thread::id const id) + var_thread_binding::var_thread_binding(object_ref const value, std::thread::id const id) : value{ value } , thread_id{ id } { @@ -218,7 +217,7 @@ namespace jank::runtime return hash::visit(value.get()); } - var_unbound_root::var_unbound_root(var_ref const &var) + var_unbound_root::var_unbound_root(var_ref const var) : var{ var } { } @@ -259,15 +258,14 @@ namespace std return hasher(*o.name); } - size_t hash::operator()(jank::runtime::var_ref const &o) const noexcept + size_t hash::operator()(jank::runtime::var_ref const o) const noexcept { static auto hasher(std::hash{}); return hasher(*o->name); } - bool - equal_to::operator()(jank::runtime::var_ref const &lhs, - jank::runtime::var_ref const &rhs) const noexcept + bool equal_to::operator()(jank::runtime::var_ref const lhs, + jank::runtime::var_ref const rhs) const noexcept { return lhs->equal(*rhs); } diff --git a/compiler+runtime/src/cpp/jank/util/try.cpp b/compiler+runtime/src/cpp/jank/util/try.cpp index 0c5bc73f6..c50e77d98 100644 --- a/compiler+runtime/src/cpp/jank/util/try.cpp +++ b/compiler+runtime/src/cpp/jank/util/try.cpp @@ -88,7 +88,7 @@ namespace jank::util print_exception_stack_trace(); } - void print_exception(runtime::object_ref const &e) + void print_exception(runtime::object_ref const e) { if(e->type == runtime::object_type::persistent_string) { From 44253c459a654d68fea18445e29cb2e43af2bec6 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sun, 21 Dec 2025 13:38:58 -0800 Subject: [PATCH 085/122] Add bdwgc back --- .gitmodules | 3 + compiler+runtime/CMakeLists.txt | 13 +- compiler+runtime/cmake/dependency/bdwgc.cmake | 41 ++++++ .../include/cpp/jank/runtime/oref.hpp | 10 +- compiler+runtime/include/cpp/jank/type.hpp | 13 +- compiler+runtime/include/cpp/jtl/ref.hpp | 2 +- compiler+runtime/src/cpp/jank/c_api.cpp | 6 +- .../src/cpp/jank/codegen/processor.cpp | 40 ++++-- .../src/cpp/jank/runtime/context.cpp | 2 +- .../jank/runtime/detail/native_array_map.cpp | 118 +++++++++--------- compiler+runtime/src/cpp/main.cpp | 4 +- compiler+runtime/third-party/bdwgc | 1 + 12 files changed, 166 insertions(+), 87 deletions(-) create mode 100644 compiler+runtime/cmake/dependency/bdwgc.cmake create mode 160000 compiler+runtime/third-party/bdwgc diff --git a/.gitmodules b/.gitmodules index f723a3232..4bc396c22 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,6 +25,9 @@ [submodule "compiler+runtime/third-party/boost-multiprecision"] path = compiler+runtime/third-party/boost-multiprecision url = https://github.com/jank-lang/boost-multiprecision.git +[submodule "compiler+runtime/third-party/bdwgc"] + path = compiler+runtime/third-party/bdwgc + url = https://github.com/jank-lang/bdwgc.git [submodule "compiler+runtime/third-party/stduuid"] path = compiler+runtime/third-party/stduuid url = https://github.com/jank-lang/stduuid.git diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index 457a3dd6c..db9f87027 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -28,6 +28,13 @@ project( LANGUAGES C CXX ) +# BDWGC redefines BUILD_SHARED_LIBS as an option. The old policy behavior here +# is to reset the value to the new default defined, which is ON. However, we +# want it to keep the value we've already specified, to force BDWGC to build +# as a static lib, so we choose the new behavior. +set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) +cmake_policy(SET CMP0077 NEW) + # All options are available here. option(jank_local_clang "Whether or not to use a local Clang/LLVM source build" OFF) option(jank_install_local_clang "Whether or not to install the local Clang/LLVM alongside jank" ON) @@ -94,7 +101,7 @@ set( -std=gnu++20 # https://groups.google.com/g/llvm-dev/c/W-OweiAjDcU?pli=1 -femulated-tls - -DIMMER_TAGGED_NODE=0 -DHAVE_CXX14=1 + -DIMMER_HAS_LIBGC=1 -DIMMER_TAGGED_NODE=0 -DHAVE_CXX14=1 -DCPPINTEROP_USE_REPL -DFOLLY_HAVE_JEMALLOC=0 -DFOLLY_HAVE_TCMALLOC=0 -DFOLLY_ASSUME_NO_JEMALLOC=1 -DFOLLY_ASSUME_NO_TCMALLOC=1 #-DLIBASSERT_STATIC_DEFINE=1 @@ -324,6 +331,7 @@ set(jank_lib_standalone_deps Boost::multiprecision nanobench_lib jankzip_lib + bdwgc::gc bdwgc::gctba folly_lib clangCppInterOp ) @@ -359,6 +367,7 @@ add_custom_target( set(BUILD_SHARED_LIBS OFF) include(FetchContent) +include(cmake/dependency/bdwgc.cmake) include(cmake/dependency/ftxui.cmake) include(cmake/dependency/cpptrace.cmake) include(cmake/dependency/cppinterop.cmake) @@ -546,6 +555,7 @@ target_include_directories( PUBLIC "$" "$" + "$" "$" "$" "$" @@ -566,6 +576,7 @@ target_link_libraries( ftxui::screen ftxui::dom Boost::multiprecision nanobench_lib + bdwgc::gc bdwgc::gctba ) if(APPLE) diff --git a/compiler+runtime/cmake/dependency/bdwgc.cmake b/compiler+runtime/cmake/dependency/bdwgc.cmake new file mode 100644 index 000000000..0176e2692 --- /dev/null +++ b/compiler+runtime/cmake/dependency/bdwgc.cmake @@ -0,0 +1,41 @@ +set(CMAKE_C_FLAGS_OLD "${CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS_OLD "${CMAKE_CXX_FLAGS}") +set(BUILD_SHARED_LIBS_OLD ${BUILD_SHARED_LIBS}) +set(CMAKE_CXX_CLANG_TIDY_OLD ${CMAKE_CXX_CLANG_TIDY}) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w") + + if(NOT APPLE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DREDIRECT_MALLOC=GC_malloc_uncollectable -DREDIR_MALLOC_AND_LINUX_THREADS") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DREDIRECT_MALLOC=GC_malloc_uncollectable -DREDIR_MALLOC_AND_LINUX_THREADS") + endif() + + set(BUILD_SHARED_LIBS OFF) + set(CMAKE_CXX_CLANG_TIDY "") + set(enable_cplusplus ON CACHE BOOL "Enable C++") + set(build_cord OFF CACHE BOOL "Build cord") + set(enable_docs OFF CACHE BOOL "Enable docs") + set(enable_threads ON CACHE BOOL "Enable multi-threading support") + set(enable_large_config ON CACHE BOOL "Optimize for large heap or root set") + set(enable_throw_bad_alloc_library ON CACHE BOOL "Enable C++ gctba library build") + set(enable_gc_debug OFF CACHE BOOL "Support for pointer back-tracing") + + if(jank_debug_gc) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGC_ASSERTIONS") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGC_ASSERTIONS") + set(enable_gc_debug ON CACHE BOOL "Support for pointer back-tracing") + endif() + + add_subdirectory(third-party/bdwgc EXCLUDE_FROM_ALL) + + unset(enable_cplusplus) + unset(build_cord) + unset(enable_docs) + unset(enable_threads) + unset(enable_large_config) + unset(enable_throw_bad_alloc_library) + unset(enable_gc_debug) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_OLD}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_OLD}") +set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_OLD}) +set(CMAKE_CXX_CLANG_TIDY ${CMAKE_CXX_CLANG_TIDY_OLD}) diff --git a/compiler+runtime/include/cpp/jank/runtime/oref.hpp b/compiler+runtime/include/cpp/jank/runtime/oref.hpp index ef40aecae..377f13338 100644 --- a/compiler+runtime/include/cpp/jank/runtime/oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/oref.hpp @@ -490,7 +490,7 @@ namespace jank::runtime { static_assert(sizeof(jtl::ref) == sizeof(T *)); /* TODO: Figure out cleanup for this. */ - T *ret{ new T{ std::forward(args)... } }; + T *ret{ new(GC) T{ std::forward(args)... } }; if(!ret) { throw std::runtime_error{ "unable to allocate box" }; @@ -510,7 +510,7 @@ namespace jank::runtime oref make_box(Args &&...args) { static_assert(sizeof(oref) == sizeof(T *)); - oref ret{ new T{ std::forward(args)... } }; + oref ret{ new(GC) T{ std::forward(args)... } }; return ret; } @@ -518,7 +518,7 @@ namespace jank::runtime jtl::ref make_array_box() { /* TODO: Figure out cleanup for this. */ - auto const ret(new T[N]{}); + auto const ret(new(GC) T[N]{}); if(!ret) { throw std::runtime_error{ "unable to allocate array box" }; @@ -530,7 +530,7 @@ namespace jank::runtime jtl::ref make_array_box(usize const length) { /* TODO: Figure out cleanup for this. */ - auto const ret(new T[length]{}); + auto const ret(new(GC) T[length]{}); if(!ret) { throw std::runtime_error{ "Unable to allocate array box" }; @@ -542,7 +542,7 @@ namespace jank::runtime jtl::ref make_array_box(Args &&...args) { /* TODO: Figure out cleanup for this. */ - auto const ret(new T[sizeof...(Args)]{ std::forward(args)... }); + auto const ret(new(GC) T[sizeof...(Args)]{ std::forward(args)... }); if(!ret) { throw std::runtime_error{ "Unable to allocate array box" }; diff --git a/compiler+runtime/include/cpp/jank/type.hpp b/compiler+runtime/include/cpp/jank/type.hpp index 31be4f94e..0fb35c802 100644 --- a/compiler+runtime/include/cpp/jank/type.hpp +++ b/compiler+runtime/include/cpp/jank/type.hpp @@ -7,6 +7,11 @@ #include #include +#include +#include + +#include +#include #include #include #include @@ -17,8 +22,12 @@ namespace jank { template - using native_allocator = std::allocator; - using memory_policy = immer::default_memory_policy; + using native_allocator = gc_allocator; + using memory_policy = immer::memory_policy, + immer::no_refcount_policy, + immer::default_lock_policy, + immer::gc_transience_policy, + false>; using native_persistent_string_view = std::string_view; using native_big_integer diff --git a/compiler+runtime/include/cpp/jtl/ref.hpp b/compiler+runtime/include/cpp/jtl/ref.hpp index bffbeeb3c..7fca2646c 100644 --- a/compiler+runtime/include/cpp/jtl/ref.hpp +++ b/compiler+runtime/include/cpp/jtl/ref.hpp @@ -100,7 +100,7 @@ namespace jtl { static_assert(sizeof(ref) == sizeof(T *)); /* TODO: Figure out cleanup for this. */ - T *ret{ new T{ jtl::forward(args)... } }; + T *ret{ new(GC) T{ jtl::forward(args)... } }; jank_debug_assert(ret); return ret; } diff --git a/compiler+runtime/src/cpp/jank/c_api.cpp b/compiler+runtime/src/cpp/jank/c_api.cpp index c9b2c4190..15c1af730 100644 --- a/compiler+runtime/src/cpp/jank/c_api.cpp +++ b/compiler+runtime/src/cpp/jank/c_api.cpp @@ -1042,8 +1042,8 @@ extern "C" /* The GC needs to enabled even before arg parsing, since our native types, * like strings, use the GC for allocations. It can still be configured later. */ - //GC_set_all_interior_pointers(1); - //GC_init(); + GC_set_all_interior_pointers(1); + GC_init(); llvm::llvm_shutdown_obj const Y{}; @@ -1057,7 +1057,7 @@ extern "C" } if(init_default_ctx) { - runtime::__rt_ctx = new runtime::context{}; + runtime::__rt_ctx = new(GC) runtime::context{}; } return fn(argc, argv); diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 36b76ba77..a84452200 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -2347,12 +2347,26 @@ namespace jank::codegen auto finalizer_tmp{ runtime::munge(__rt_ctx->unique_string("finalizer")) }; auto value_tmp{ gen(expr->value_expr, arity) }; auto const type_name{ cpp_util::get_qualified_type_name(expr->type) }; + auto const needs_finalizer{ !Cpp::IsTriviallyDestructible(expr->type) }; + + if(needs_finalizer) + { + util::format_to(body_buffer, + "using T = {};\n" + "static auto const {}{ " + "[](void * const obj, void *){" + "reinterpret_cast(obj)->~T();" + "} };", + type_name, + finalizer_tmp); + } util::format_to(body_buffer, "auto {}{ " - "new {}{ {} }" + "new (GC{}) {}{ {} }" " };", ret_tmp, + (needs_finalizer ? ", " + finalizer_tmp : ""), type_name, value_tmp.unwrap().str(false)); @@ -2371,20 +2385,20 @@ namespace jank::codegen auto value_tmp{ gen(expr->value_expr, arity).unwrap() }; auto const value_type{ Cpp::GetPointeeType(cpp_util::expression_type(expr->value_expr)) }; auto const type_name{ cpp_util::get_qualified_type_name(value_type) }; - //auto const needs_finalizer{ !Cpp::IsTriviallyDestructible(value_type) }; + auto const needs_finalizer{ !Cpp::IsTriviallyDestructible(value_type) }; /* Calling GC_free won't trigger the finalizer. Not sure why, but it's explicitly * documented in bdwgc. So, we'll invoke it manually if needed, prior to GC_free. */ - //if(needs_finalizer) - //{ - // util::format_to(body_buffer, - // "using T = {};\n" - // "{}->~T();", - // type_name, - // value_tmp.str(false)); - //} + if(needs_finalizer) + { + util::format_to(body_buffer, + "using T = {};\n" + "{}->~T();", + type_name, + value_tmp.str(false)); + } - util::format_to(body_buffer, "delete {};", value_tmp.str(false)); + util::format_to(body_buffer, "GC_free({});", value_tmp.str(false)); if(expr->position == expression_position::tail) { @@ -2743,7 +2757,7 @@ namespace jank::codegen { util::format_to( footer_buffer, - R"(new (&{}::{}) jank::runtime::var_ref(jank::runtime::__rt_ctx->intern_owned_var("{}").expect_ok());)", + R"(new (&{}::{}) jank::runtime::var_ref(jank::runtime::__rt_ctx->intern_owned_var("{}").expect_ok());)", ns, v.second.native_name, v.first); @@ -2752,7 +2766,7 @@ namespace jank::codegen { util::format_to( footer_buffer, - R"(new (&{}::{}) jank::runtime::var_ref(jank::runtime::__rt_ctx->intern_var("{}").expect_ok());)", + R"(new (&{}::{}) jank::runtime::var_ref(jank::runtime::__rt_ctx->intern_var("{}").expect_ok());)", ns, v.second.native_name, v.first); diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 52c77e28e..6713e98da 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -133,7 +133,7 @@ namespace jank::runtime return find_var(make_box(ns, name)); } - jtl::option context::find_local(obj::symbol_ref const ) + jtl::option context::find_local(obj::symbol_ref const) { return none; } diff --git a/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp b/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp index 1998c155d..cb98f1f0c 100644 --- a/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/detail/native_array_map.cpp @@ -23,91 +23,91 @@ namespace jank::runtime::detail { case 0: { - auto const ret(new object_ref[2]{ key, value }); + auto const ret(new(GC) object_ref[2]{ key, value }); return ret; } case 2: { - auto const ret(new object_ref[4]{ prev[0], prev[1], key, value }); + auto const ret(new(GC) object_ref[4]{ prev[0], prev[1], key, value }); return ret; } case 4: { - auto const ret(new object_ref[6]{ prev[0], prev[1], prev[2], prev[3], key, value }); + auto const ret(new(GC) object_ref[6]{ prev[0], prev[1], prev[2], prev[3], key, value }); return ret; } case 6: { - auto const ret( - new object_ref[8]{ prev[0], prev[1], prev[2], prev[3], prev[4], prev[5], key, value }); + auto const ret(new( + GC) object_ref[8]{ prev[0], prev[1], prev[2], prev[3], prev[4], prev[5], key, value }); return ret; } case 8: { - auto const ret(new object_ref[10]{ prev[0], - prev[1], - prev[2], - prev[3], - prev[4], - prev[5], - prev[6], - prev[7], - key, - value }); + auto const ret(new(GC) object_ref[10]{ prev[0], + prev[1], + prev[2], + prev[3], + prev[4], + prev[5], + prev[6], + prev[7], + key, + value }); return ret; } case 10: { - auto const ret(new object_ref[12]{ prev[0], - prev[1], - prev[2], - prev[3], - prev[4], - prev[5], - prev[6], - prev[7], - prev[8], - prev[9], - key, - value }); + auto const ret(new(GC) object_ref[12]{ prev[0], + prev[1], + prev[2], + prev[3], + prev[4], + prev[5], + prev[6], + prev[7], + prev[8], + prev[9], + key, + value }); return ret; } case 12: { - auto const ret(new object_ref[14]{ prev[0], - prev[1], - prev[2], - prev[3], - prev[4], - prev[5], - prev[6], - prev[7], - prev[8], - prev[9], - prev[10], - prev[11], - key, - value }); + auto const ret(new(GC) object_ref[14]{ prev[0], + prev[1], + prev[2], + prev[3], + prev[4], + prev[5], + prev[6], + prev[7], + prev[8], + prev[9], + prev[10], + prev[11], + key, + value }); return ret; } case 14: { - auto const ret(new object_ref[16]{ prev[0], - prev[1], - prev[2], - prev[3], - prev[4], - prev[5], - prev[6], - prev[7], - prev[8], - prev[9], - prev[10], - prev[11], - prev[12], - prev[13], - key, - value }); + auto const ret(new(GC) object_ref[16]{ prev[0], + prev[1], + prev[2], + prev[3], + prev[4], + prev[5], + prev[6], + prev[7], + prev[8], + prev[9], + prev[10], + prev[11], + prev[12], + prev[13], + key, + value }); return ret; } default: @@ -305,7 +305,7 @@ namespace jank::runtime::detail return; } - auto const new_data{ new object_ref[new_capacity]{} }; + auto const new_data{ new(GC) object_ref[new_capacity]{} }; for(u8 i{}; i < length; i += 2) { @@ -337,7 +337,7 @@ namespace jank::runtime::detail native_array_map native_array_map::clone() const { native_array_map ret{ *this }; - ret.data = new object_ref[cap]; + ret.data = new(GC) object_ref[cap]; for(u8 i{}; i < length; ++i) { ret.data[i] = data[i]; diff --git a/compiler+runtime/src/cpp/main.cpp b/compiler+runtime/src/cpp/main.cpp index 922a389c8..96d3339b5 100644 --- a/compiler+runtime/src/cpp/main.cpp +++ b/compiler+runtime/src/cpp/main.cpp @@ -288,7 +288,7 @@ int main(int const argc, char const **argv) if(jank::util::cli::opts.gc_incremental) { - //GC_enable_incremental(); + GC_enable_incremental(); } profile::configure(); @@ -299,7 +299,7 @@ int main(int const argc, char const **argv) return jank::environment::check_health() ? 0 : 1; } - __rt_ctx = new runtime::context{}; + __rt_ctx = new(GC) runtime::context{}; jank_load_clojure_core_native(); jank_load_jank_compiler_native(); diff --git a/compiler+runtime/third-party/bdwgc b/compiler+runtime/third-party/bdwgc new file mode 160000 index 000000000..19a7f495c --- /dev/null +++ b/compiler+runtime/third-party/bdwgc @@ -0,0 +1 @@ +Subproject commit 19a7f495cd7c48cdf6f56c593c6dd57187afa079 From bde619a9edc2316c9bc745a48d830d728bd2cad6 Mon Sep 17 00:00:00 2001 From: jeaye Date: Mon, 22 Dec 2025 00:22:15 -0800 Subject: [PATCH 086/122] Upgrade bdwgc --- compiler+runtime/cmake/dependency/bdwgc.cmake | 11 +++++------ compiler+runtime/third-party/bdwgc | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/compiler+runtime/cmake/dependency/bdwgc.cmake b/compiler+runtime/cmake/dependency/bdwgc.cmake index 0176e2692..250793fe2 100644 --- a/compiler+runtime/cmake/dependency/bdwgc.cmake +++ b/compiler+runtime/cmake/dependency/bdwgc.cmake @@ -5,13 +5,10 @@ set(CMAKE_CXX_CLANG_TIDY_OLD ${CMAKE_CXX_CLANG_TIDY}) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w") - if(NOT APPLE) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DREDIRECT_MALLOC=GC_malloc_uncollectable -DREDIR_MALLOC_AND_LINUX_THREADS") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DREDIRECT_MALLOC=GC_malloc_uncollectable -DREDIR_MALLOC_AND_LINUX_THREADS") - endif() - - set(BUILD_SHARED_LIBS OFF) set(CMAKE_CXX_CLANG_TIDY "") + set(GC_BUILD_SHARED_LIBS OFF) + set(enable_redirect_malloc ON CACHE BOOL "Redirect malloc and friends to collector routines") + set(enable_uncollectable_redirection ON CACHE BOOL "Redirect to uncollectible malloc instead of garbage-collected one") set(enable_cplusplus ON CACHE BOOL "Enable C++") set(build_cord OFF CACHE BOOL "Build cord") set(enable_docs OFF CACHE BOOL "Enable docs") @@ -28,6 +25,8 @@ set(CMAKE_CXX_CLANG_TIDY_OLD ${CMAKE_CXX_CLANG_TIDY}) add_subdirectory(third-party/bdwgc EXCLUDE_FROM_ALL) + unset(enable_redirect_malloc) + unset(enable_uncollectable_redirection) unset(enable_cplusplus) unset(build_cord) unset(enable_docs) diff --git a/compiler+runtime/third-party/bdwgc b/compiler+runtime/third-party/bdwgc index 19a7f495c..32b748111 160000 --- a/compiler+runtime/third-party/bdwgc +++ b/compiler+runtime/third-party/bdwgc @@ -1 +1 @@ -Subproject commit 19a7f495cd7c48cdf6f56c593c6dd57187afa079 +Subproject commit 32b74811147649efab0944b2762fc3300074d25e From 72745537ee2f275b9ecc29f36c9a8aa94bb89a15 Mon Sep 17 00:00:00 2001 From: jeaye Date: Mon, 22 Dec 2025 13:15:39 -0800 Subject: [PATCH 087/122] Disable collection on macOS --- compiler+runtime/cmake/dependency/bdwgc.cmake | 12 ++++++++++-- compiler+runtime/src/cpp/jank/c_api.cpp | 16 +++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/compiler+runtime/cmake/dependency/bdwgc.cmake b/compiler+runtime/cmake/dependency/bdwgc.cmake index 250793fe2..f4f50066b 100644 --- a/compiler+runtime/cmake/dependency/bdwgc.cmake +++ b/compiler+runtime/cmake/dependency/bdwgc.cmake @@ -7,8 +7,16 @@ set(CMAKE_CXX_CLANG_TIDY_OLD ${CMAKE_CXX_CLANG_TIDY}) set(CMAKE_CXX_CLANG_TIDY "") set(GC_BUILD_SHARED_LIBS OFF) - set(enable_redirect_malloc ON CACHE BOOL "Redirect malloc and friends to collector routines") - set(enable_uncollectable_redirection ON CACHE BOOL "Redirect to uncollectible malloc instead of garbage-collected one") + + # Malloc redirection is causing crashes on macOS. However, without it, we get + # premature collections. Because of this, collection is disabled on macOS entirely. + # + # https://github.com/bdwgc/bdwgc/issues/829 + if(NOT APPLE) + set(enable_redirect_malloc ON CACHE BOOL "Redirect malloc and friends to collector routines") + set(enable_uncollectable_redirection ON CACHE BOOL "Redirect to uncollectible malloc instead of garbage-collected one") + endif() + set(enable_cplusplus ON CACHE BOOL "Enable C++") set(build_cord OFF CACHE BOOL "Build cord") set(enable_docs OFF CACHE BOOL "Enable docs") diff --git a/compiler+runtime/src/cpp/jank/c_api.cpp b/compiler+runtime/src/cpp/jank/c_api.cpp index 15c1af730..38c595f5e 100644 --- a/compiler+runtime/src/cpp/jank/c_api.cpp +++ b/compiler+runtime/src/cpp/jank/c_api.cpp @@ -1040,9 +1040,23 @@ extern "C" * Notably, this might make text encoding become more platform dependent. */ std::locale::global(std::locale("")); - /* The GC needs to enabled even before arg parsing, since our native types, + /* The GC needs to initialized even before arg parsing, since our native types, * like strings, use the GC for allocations. It can still be configured later. */ GC_set_all_interior_pointers(1); + + /* Collection is disabled on macOS, due to a combination of two issues. Firstly, + * bdwgc will prematurely collect if we don't use malloc redirection. My research + * indicates that this is due to (at least) bdwgc not knowing about globals within + * JIT compiled C++. Secondly, we can't use malloc redirection on macOS due to an + * issue which leads to a crash in LLVM code. + * + * https://github.com/bdwgc/bdwgc/issues/829 */ + if constexpr(jtl::current_platform == jtl::platform::macos_like) + { + /* Although this is called enable, by calling it right here, we actually disable the GC. */ + GC_enable(); + } + GC_init(); llvm::llvm_shutdown_obj const Y{}; From 281c278554661bcc610876e85da76ebc069ce0ae Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 23 Dec 2025 13:14:29 -0800 Subject: [PATCH 088/122] Compile AOT modules using separate clang --- .../include/cpp/jank/aot/processor.hpp | 4 +- .../src/cpp/jank/aot/processor.cpp | 215 ++++++++++++------ .../src/cpp/jank/codegen/processor.cpp | 6 + .../src/cpp/jank/environment/check_health.cpp | 2 +- .../src/cpp/jank/runtime/context.cpp | 26 ++- .../src/cpp/jank/util/environment.cpp | 8 +- compiler+runtime/src/cpp/main.cpp | 2 +- .../test/cpp/jank/jit/processor.cpp | 2 +- compiler+runtime/test/cpp/jank/read/parse.cpp | 2 +- 9 files changed, 188 insertions(+), 79 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/aot/processor.hpp b/compiler+runtime/include/cpp/jank/aot/processor.hpp index 637e18a68..178b1d3c7 100644 --- a/compiler+runtime/include/cpp/jank/aot/processor.hpp +++ b/compiler+runtime/include/cpp/jank/aot/processor.hpp @@ -8,6 +8,8 @@ namespace jank::aot { struct processor { - jtl::result compile(jtl::immutable_string const &module) const; + jtl::result build_executable(jtl::immutable_string const &module) const; + jtl::result compile_object(jtl::immutable_string const &module_name, + jtl::immutable_string const &cpp_source) const; }; } diff --git a/compiler+runtime/src/cpp/jank/aot/processor.cpp b/compiler+runtime/src/cpp/jank/aot/processor.cpp index cfeadd2ec..f3017e36b 100644 --- a/compiler+runtime/src/cpp/jank/aot/processor.cpp +++ b/compiler+runtime/src/cpp/jank/aot/processor.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include namespace jank::aot @@ -118,58 +119,10 @@ int main(int argc, const char** argv) return main_file_path; } - jtl::result processor::compile(jtl::immutable_string const &module) const + static jtl::result, error_ref> build_compiler_args() { - auto const main_var(__rt_ctx->find_var(module, "-main")); - if(main_var.is_nil()) - { - return error::aot_unresolved_main(util::format( - "The entrypoint of the program is expected to be #'{}/-main, but this var was not found.", - module)); - } - std::vector compiler_args{}; - auto const modules_rlocked{ __rt_ctx->loaded_modules_in_order.rlock() }; - for(auto const &it : *modules_rlocked) - { - /* Core modules will be linked as part of libjank-standalone.a. */ - if(runtime::module::is_core_module(it)) - { - continue; - } - - auto const &module_path{ util::format("{}.o", - relative_to_cache_dir(module::module_to_path(it))) }; - - if(std::filesystem::exists(module_path.c_str())) - { - compiler_args.push_back(strdup(module_path.c_str())); - } - else - { - auto const find_res{ __rt_ctx->module_loader.find(it, module::origin::latest) }; - if(find_res.is_ok() && find_res.expect_ok().sources.o.is_some()) - { - compiler_args.push_back(strdup(find_res.expect_ok().sources.o.unwrap().path.c_str())); - } - else - { - return error::internal_aot_failure(util::format("Compiled module '{}' not found.", it)); - } - } - } - - auto const entrypoint_path{ gen_entrypoint(module) }; - compiler_args.push_back(strdup("-x")); - compiler_args.push_back(strdup("c++")); - compiler_args.push_back(strdup(entrypoint_path.c_str())); - - for(auto const &include_dir : util::cli::opts.include_dirs) - { - compiler_args.push_back(strdup(util::format("-I{}", include_dir).c_str())); - } - auto const clang_path_str{ util::find_clang() }; if(clang_path_str.is_none()) { @@ -192,6 +145,13 @@ int main(int argc, const char** argv) compiler_args.emplace_back(strdup("-L")); compiler_args.emplace_back(strdup(util::format("{}/lib", jank_resource_dir).c_str())); + std::stringstream flags{ JANK_JIT_FLAGS }; + std::string flag; + while(std::getline(flags, flag, ' ')) + { + compiler_args.emplace_back(strdup(flag.c_str())); + } + { std::string_view const flags{ JANK_AOT_FLAGS }; size_t start{}; @@ -213,6 +173,16 @@ int main(int argc, const char** argv) } } + if(auto const extra{ getenv("JANK_EXTRA_FLAGS") }; extra) + { + std::stringstream flags{ extra }; + std::string flag; + while(std::getline(flags, flag, ' ')) + { + compiler_args.emplace_back(strdup(flag.c_str())); + } + } + if constexpr(jtl::current_platform == jtl::platform::macos_like) { compiler_args.push_back(strdup("-L/opt/homebrew/lib")); @@ -223,6 +193,82 @@ int main(int argc, const char** argv) compiler_args.push_back(strdup(util::format("-L{}", library_dir).c_str())); } + for(auto const &include_dir : util::cli::opts.include_dirs) + { + compiler_args.push_back(strdup(util::format("-I{}", include_dir).c_str())); + } + + for(auto const &define : util::cli::opts.define_macros) + { + compiler_args.push_back(strdup(util::format("-D{}", define).c_str())); + } + + compiler_args.push_back(strdup("-std=c++20")); + compiler_args.push_back(strdup("-Wno-c23-extensions")); + if constexpr(jtl::current_platform == jtl::platform::linux_like) + { + compiler_args.push_back(strdup("-Wl,--export-dynamic")); + } + compiler_args.push_back(strdup("-rdynamic")); + /* TODO: Change this based on the CLI optimization level. */ + compiler_args.push_back(strdup("-O2")); + + return compiler_args; + } + + jtl::result + processor::build_executable(jtl::immutable_string const &module) const + { + auto const main_var(__rt_ctx->find_var(module, "-main")); + if(main_var.is_nil()) + { + return error::aot_unresolved_main(util::format( + "The entrypoint of the program is expected to be #'{}/-main, but this var was not found.", + module)); + } + + auto const compiler_args_res{ build_compiler_args() }; + if(compiler_args_res.is_err()) + { + return compiler_args_res.expect_err(); + } + std::vector compiler_args{ jtl::move(compiler_args_res.expect_ok()) }; + + auto const modules_rlocked{ __rt_ctx->loaded_modules_in_order.rlock() }; + for(auto const &it : *modules_rlocked) + { + /* Core modules will be linked as part of libjank-standalone.a. */ + if(runtime::module::is_core_module(it)) + { + continue; + } + + auto const &module_path{ util::format("{}.o", + relative_to_cache_dir(module::module_to_path(it))) }; + + if(std::filesystem::exists(module_path.c_str())) + { + compiler_args.push_back(strdup(module_path.c_str())); + } + else + { + auto const find_res{ __rt_ctx->module_loader.find(it, module::origin::latest) }; + if(find_res.is_ok() && find_res.expect_ok().sources.o.is_some()) + { + compiler_args.push_back(strdup(find_res.expect_ok().sources.o.unwrap().path.c_str())); + } + else + { + return error::internal_aot_failure(util::format("Compiled module '{}' not found.", it)); + } + } + } + + auto const entrypoint_path{ gen_entrypoint(module) }; + compiler_args.push_back(strdup("-x")); + compiler_args.push_back(strdup("c++")); + compiler_args.push_back(strdup(entrypoint_path.c_str())); + for(auto const &lib : { "-ljank-standalone", /* Default libraries that jank depends on. */ "-lm", @@ -242,20 +288,6 @@ int main(int argc, const char** argv) compiler_args.push_back(strdup("-lstdc++")); } - for(auto const &define : util::cli::opts.define_macros) - { - compiler_args.push_back(strdup(util::format("-D{}", define).c_str())); - } - - compiler_args.push_back(strdup("-std=c++20")); - compiler_args.push_back(strdup("-Wno-c23-extensions")); - if constexpr(jtl::current_platform == jtl::platform::linux_like) - { - compiler_args.push_back(strdup("-Wl,--export-dynamic")); - } - compiler_args.push_back(strdup("-rdynamic")); - compiler_args.push_back(strdup("-O2")); - /* Required because of `strdup` usage and need to manually free the memory. * Clang expects C strings that we own. */ /* TODO: I doubt this is really needed. These strings aren't captured by Clang. */ @@ -270,7 +302,62 @@ int main(int argc, const char** argv) compiler_args.push_back(strdup("-o")); compiler_args.push_back(strdup(util::cli::opts.output_filename.c_str())); - //util::println("compilation command: {} ", compiler_args); + util::println("compilation command: {} ", compiler_args); + + auto const res{ util::invoke_clang(compiler_args) }; + if(res.is_err()) + { + return res.expect_err(); + } + + return ok(); + } + + jtl::result + processor::compile_object(jtl::immutable_string const &module_name, + jtl::immutable_string const &cpp_source) const + { + auto const compiler_args_res{ build_compiler_args() }; + if(compiler_args_res.is_err()) + { + return compiler_args_res.expect_err(); + } + std::vector compiler_args{ jtl::move(compiler_args_res.expect_ok()) }; + + std::filesystem::path const module_path{ + util::cli::opts.output_object_filename.empty() + ? util::format("{}/{}.o", __rt_ctx->binary_cache_dir, module::module_to_path(module_name)) + : jtl::immutable_string{ util::cli::opts.output_object_filename } + }; + std::filesystem::create_directories(module_path.parent_path()); + + auto const tmp{ std::filesystem::temp_directory_path() }; + std::string path_tmp{ tmp / "jank-compile-XXXXXX" }; + mkstemp(path_tmp.data()); + + { + std::ofstream ofs{ path_tmp }; + ofs << cpp_source; + //ofs << util::format_cpp_source(cpp_source).expect_ok(); + } + + std::filesystem::path const jank_resource_dir{ util::resource_dir().c_str() }; + compiler_args.push_back("-include"); + auto const prelude_path{ jank_resource_dir / "include/cpp/jank/prelude.hpp" }; + compiler_args.push_back(prelude_path.c_str()); + + compiler_args.push_back("-c"); + compiler_args.push_back("-o"); + compiler_args.push_back(module_path.c_str()); + + compiler_args.push_back("-x"); + compiler_args.push_back("c++"); + compiler_args.push_back(path_tmp.c_str()); + + compiler_args.push_back("-w"); + compiler_args.push_back("-Wno-c++11-narrowing"); + + util::println("compilation command: {} ", compiler_args); auto const res{ util::invoke_clang(compiler_args) }; if(res.is_err()) diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index a84452200..8e14248f8 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -1943,6 +1943,12 @@ namespace jank::codegen jtl::option processor::gen(analyze::expr::cpp_call_ref const expr, analyze::expr::function_arity const &arity) { + if((target == compilation_target::module || target == compilation_target::function) + && !expr->function_code.empty()) + { + util::format_to(cpp_raw_buffer, "\n{}\n", expr->function_code); + } + if(expr->source_expr->kind == expression_kind::cpp_value) { auto const source{ static_cast(expr->source_expr.data) }; diff --git a/compiler+runtime/src/cpp/jank/environment/check_health.cpp b/compiler+runtime/src/cpp/jank/environment/check_health.cpp index e04689e4f..68254fd14 100644 --- a/compiler+runtime/src/cpp/jank/environment/check_health.cpp +++ b/compiler+runtime/src/cpp/jank/environment/check_health.cpp @@ -402,7 +402,7 @@ namespace jank::environment runtime::__rt_ctx->compile_module(util::cli::opts.target_module).expect_ok(); jank::aot::processor const aot_prc{}; - aot_prc.compile(util::cli::opts.target_module).expect_ok(); + aot_prc.build_executable(util::cli::opts.target_module).expect_ok(); auto const stdout_file{ std::filesystem::path{ path_tmp } / "stdout" }; auto const proc_code{ llvm::sys::ExecuteAndWait( diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 84900274c..72268b9a7 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -223,17 +224,24 @@ namespace jank::runtime codegen::processor cg_prc{ fn, module, codegen::compilation_target::module }; //util::println("{}\n", util::format_cpp_source(cg_prc.declaration_str()).expect_ok()); auto const code{ cg_prc.declaration_str() }; - auto parse_res{ jit_prc.interpreter->Parse({ code.data(), code.size() }) }; - if(!parse_res) + auto module_name{ runtime::to_string(current_module_var->deref()) }; + aot::processor aot_prc; + auto const res{ aot_prc.compile_object(module_name, code) }; + if(res.is_err()) { - /* TODO: Helper to turn an llvm::Error into a string. */ - jtl::immutable_string const res{ "Unable to compile generated C++ source." }; - llvm::logAllUnhandledErrors(parse_res.takeError(), llvm::errs(), "error: "); - throw error::internal_codegen_failure(res); + throw res.expect_err(); } - auto &partial_tu{ parse_res.get() }; - auto module_name{ runtime::to_string(current_module_var->deref()) }; - write_module(module_name, partial_tu.TheModule.get()).expect_ok(); + //auto parse_res{ jit_prc.interpreter->Parse({ code.data(), code.size() }) }; + //if(!parse_res) + //{ + // /* TODO: Helper to turn an llvm::Error into a string. */ + // jtl::immutable_string const res{ "Unable to compile generated C++ source." }; + // llvm::logAllUnhandledErrors(parse_res.takeError(), llvm::errs(), "error: "); + // throw error::internal_codegen_failure(res); + //} + //auto &partial_tu{ parse_res.get() }; + ////auto module_name{ runtime::to_string(current_module_var->deref()) }; + //write_module(module_name, partial_tu.TheModule.get()).expect_ok(); } } diff --git a/compiler+runtime/src/cpp/jank/util/environment.cpp b/compiler+runtime/src/cpp/jank/util/environment.cpp index f21fcc197..fff692f50 100644 --- a/compiler+runtime/src/cpp/jank/util/environment.cpp +++ b/compiler+runtime/src/cpp/jank/util/environment.cpp @@ -173,8 +173,14 @@ namespace jank::util auto const dev_build{ jank_path.filename() == "build" && jank_path.parent_path().filename() == "compiler+runtime" }; + if(dev_build) + { + auto const compiler_runtime{ jank_path / ".." }; + return compiler_runtime.c_str(); + } + auto const configured_path{ (jank_path / dir) }; - if(std::filesystem::exists(configured_path) || dev_build) + if(std::filesystem::exists(configured_path)) { return configured_path.c_str(); } diff --git a/compiler+runtime/src/cpp/main.cpp b/compiler+runtime/src/cpp/main.cpp index df24dbbeb..9689022d0 100644 --- a/compiler+runtime/src/cpp/main.cpp +++ b/compiler+runtime/src/cpp/main.cpp @@ -286,7 +286,7 @@ namespace jank __rt_ctx->compile_module(opts.target_module).expect_ok(); jank::aot::processor const aot_prc{}; - aot_prc.compile(opts.target_module).expect_ok(); + aot_prc.build_executable(opts.target_module).expect_ok(); } } diff --git a/compiler+runtime/test/cpp/jank/jit/processor.cpp b/compiler+runtime/test/cpp/jank/jit/processor.cpp index 3170094aa..8ed8ce340 100644 --- a/compiler+runtime/test/cpp/jank/jit/processor.cpp +++ b/compiler+runtime/test/cpp/jank/jit/processor.cpp @@ -108,7 +108,7 @@ namespace jank::jit } }; auto const result( - __rt_ctx->eval_file(dir_entry.path().string()).unwrap_or(runtime::jank_nil)); + __rt_ctx->eval_file(dir_entry.path().string()).unwrap_or(runtime::jank_nil())); if(!expect_success) { failures.push_back({ dir_entry.path(), diff --git a/compiler+runtime/test/cpp/jank/read/parse.cpp b/compiler+runtime/test/cpp/jank/read/parse.cpp index 072d0bd30..8523225bc 100644 --- a/compiler+runtime/test/cpp/jank/read/parse.cpp +++ b/compiler+runtime/test/cpp/jank/read/parse.cpp @@ -992,7 +992,7 @@ namespace jank::read::parse auto const r(p.next()); CHECK(equal(r.expect_ok().unwrap().ptr, obj::persistent_array_map::empty())); auto const m{ meta(r.expect_ok().unwrap().ptr) }; - CHECK(equal(get(m, __rt_ctx->intern_keyword("foo").expect_ok()), jank_nil)); + CHECK(equal(get(m, __rt_ctx->intern_keyword("foo").expect_ok()), jank_nil())); } SUBCASE("Symbol meta for a non-metadatable target") From f98fa2ae6e197b0fa92b6956bdd1f10a0eb8d2b7 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 23 Dec 2025 13:24:14 -0800 Subject: [PATCH 089/122] Add CMake option for GC profiling --- compiler+runtime/CMakeLists.txt | 2 ++ compiler+runtime/cmake/dependency/bdwgc.cmake | 6 ++++++ compiler+runtime/cmake/summary.cmake | 2 ++ 3 files changed, 10 insertions(+) diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index f28aa1c92..a08596e55 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -42,6 +42,8 @@ option(jank_coverage "Enable code coverage measurement" OFF) option(jank_analyze "Enable static analysis" OFF) option(jank_test "Enable jank's test suite" OFF) option(jank_unity_build "Optimize translation unit compilation for the number of cores" OFF) +option(jank_debug_gc "Enable GC debug assertions" OFF) +option(jank_profile_gc "Enable GC profiling (via massif or heaptrack)" OFF) set(jank_sanitize "none" CACHE STRING "The type of Clang sanitization to use (or none)") set(jank_resource_dir "../lib/jank/${CMAKE_PROJECT_VERSION}" diff --git a/compiler+runtime/cmake/dependency/bdwgc.cmake b/compiler+runtime/cmake/dependency/bdwgc.cmake index f4f50066b..c814c07e7 100644 --- a/compiler+runtime/cmake/dependency/bdwgc.cmake +++ b/compiler+runtime/cmake/dependency/bdwgc.cmake @@ -25,6 +25,10 @@ set(CMAKE_CXX_CLANG_TIDY_OLD ${CMAKE_CXX_CLANG_TIDY}) set(enable_throw_bad_alloc_library ON CACHE BOOL "Enable C++ gctba library build") set(enable_gc_debug OFF CACHE BOOL "Support for pointer back-tracing") + if(jank_profile_gc) + set(enable_valgrind_tracking ON CACHE BOOL "Support tracking GC_malloc and friends for heap profiling tools") + endif() + if(jank_debug_gc) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DGC_ASSERTIONS") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGC_ASSERTIONS") @@ -33,6 +37,7 @@ set(CMAKE_CXX_CLANG_TIDY_OLD ${CMAKE_CXX_CLANG_TIDY}) add_subdirectory(third-party/bdwgc EXCLUDE_FROM_ALL) + unset(GC_BUILD_SHARED_LIBS) unset(enable_redirect_malloc) unset(enable_uncollectable_redirection) unset(enable_cplusplus) @@ -41,6 +46,7 @@ set(CMAKE_CXX_CLANG_TIDY_OLD ${CMAKE_CXX_CLANG_TIDY}) unset(enable_threads) unset(enable_large_config) unset(enable_throw_bad_alloc_library) + unset(enable_valgrind_tracking) unset(enable_gc_debug) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS_OLD}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_OLD}") diff --git a/compiler+runtime/cmake/summary.cmake b/compiler+runtime/cmake/summary.cmake index d5000b845..ec6dbe11a 100644 --- a/compiler+runtime/cmake/summary.cmake +++ b/compiler+runtime/cmake/summary.cmake @@ -11,6 +11,8 @@ jank_message("│ jank analyze : ${jank_analyze}") jank_message("│ jank sanitize : ${jank_sanitize}") jank_message("│ jank unity build : ${jank_unity_build}") jank_message("│ jank resource dir : ${jank_resource_dir}") +jank_message("│ jank debug gc : ${jank_debug_gc}") +jank_message("│ jank profile gc : ${jank_profile_gc}") jank_message("│ clang version : ${LLVM_PACKAGE_VERSION}") jank_message("│ clang prefix : ${CLANG_INSTALL_PREFIX}") jank_message("│ clang resource dir : ${clang_resource_dir}") From 013b37d2aafd7040e13c64349e4208503f713411 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 23 Dec 2025 13:26:45 -0800 Subject: [PATCH 090/122] Add explicit libedit and libxml2 deps to flake.nix This MIGHT be needed, based on some issues I saw locally. We can revert if not. --- flake.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/flake.nix b/flake.nix index a9aca9a34..395a72732 100644 --- a/flake.nix +++ b/flake.nix @@ -42,6 +42,8 @@ "-L${lib.getLib pkgs.openssl}/lib" "-L${lib.getLib pkgs.zlib}/lib" "-L${lib.getLib pkgs.zstd}/lib" + "-L${lib.getLib pkgs.libedit}/lib" + "-L${lib.getLib pkgs.libxml2}/lib" ]; in { legacyPackages = pkgs; @@ -81,6 +83,8 @@ bzip2 openssl zstd + libedit + libxml2 ]); checkInputs = with pkgs; [ @@ -171,6 +175,7 @@ shellHook = '' export CC=${llvm.clang}/bin/clang export CXX=${llvm.clang}/bin/clang++ + export CMAKE_CXX_FLAGS=${lib.escapeShellArg cmakeCxxFlags} export ASAN_OPTIONS=detect_leaks=0 ''; From 07a921af1b43f1fb6ee02bfa95883a2f9ff5b679 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 23 Dec 2025 13:52:36 -0800 Subject: [PATCH 091/122] Fix clang-tidy issues --- .../include/cpp/clojure/core_native.hpp | 5 +- .../include/cpp/jank/analyze/processor.hpp | 72 +++--- .../cpp/jank/runtime/behavior/callable.hpp | 228 +++++++++--------- .../include/cpp/jank/runtime/context.hpp | 16 +- .../cpp/jank/runtime/convert/function.hpp | 4 +- .../include/cpp/jank/runtime/core.hpp | 15 +- .../include/cpp/jank/runtime/core/equal.hpp | 2 +- .../include/cpp/jank/runtime/core/truthy.hpp | 2 +- .../include/cpp/jank/runtime/ns.hpp | 9 +- .../include/cpp/jank/runtime/obj/atom.hpp | 7 +- .../cpp/jank/runtime/obj/integer_range.hpp | 6 +- .../cpp/jank/runtime/obj/jit_closure.hpp | 99 ++++---- .../cpp/jank/runtime/obj/jit_function.hpp | 98 ++++---- .../include/cpp/jank/runtime/obj/keyword.hpp | 4 +- .../cpp/jank/runtime/obj/multi_function.hpp | 98 ++++---- .../runtime/obj/native_function_wrapper.hpp | 99 ++++---- .../jank/runtime/obj/persistent_array_map.hpp | 4 +- .../jank/runtime/obj/persistent_hash_set.hpp | 2 +- .../runtime/obj/persistent_sorted_map.hpp | 7 +- .../runtime/obj/persistent_sorted_set.hpp | 2 +- .../jank/runtime/obj/persistent_vector.hpp | 2 +- .../include/cpp/jank/runtime/obj/range.hpp | 5 +- .../include/cpp/jank/runtime/obj/ratio.hpp | 2 +- .../jank/runtime/obj/transient_array_map.hpp | 4 +- .../jank/runtime/obj/transient_hash_map.hpp | 4 +- .../jank/runtime/obj/transient_hash_set.hpp | 4 +- .../jank/runtime/obj/transient_sorted_map.hpp | 4 +- .../jank/runtime/obj/transient_sorted_set.hpp | 4 +- .../cpp/jank/runtime/obj/transient_vector.hpp | 2 +- .../include/cpp/jank/runtime/oref.hpp | 31 +-- .../include/cpp/jank/util/try.hpp | 2 +- .../src/cpp/jank/analyze/local_frame.cpp | 5 +- .../src/cpp/jank/codegen/llvm_processor.cpp | 2 +- .../cpp/jank/runtime/behavior/callable.cpp | 98 ++++---- .../src/cpp/jank/runtime/context.cpp | 2 +- .../src/cpp/jank/runtime/core.cpp | 15 +- .../src/cpp/jank/runtime/core/math.cpp | 22 +- .../src/cpp/jank/runtime/core/truthy.cpp | 2 +- .../src/cpp/jank/runtime/module/loader.cpp | 2 +- .../src/cpp/jank/runtime/obj/atom.cpp | 8 +- .../src/cpp/jank/runtime/obj/big_decimal.cpp | 4 +- .../src/cpp/jank/runtime/obj/big_integer.cpp | 4 +- .../runtime/obj/native_function_wrapper.cpp | 7 +- .../src/cpp/jank/runtime/obj/number.cpp | 12 +- .../cpp/jank/runtime/obj/persistent_list.cpp | 2 +- .../jank/runtime/obj/persistent_string.cpp | 2 +- .../jank/runtime/obj/persistent_vector.cpp | 2 +- .../cpp/jank/runtime/obj/tagged_literal.cpp | 3 +- 48 files changed, 491 insertions(+), 544 deletions(-) diff --git a/compiler+runtime/include/cpp/clojure/core_native.hpp b/compiler+runtime/include/cpp/clojure/core_native.hpp index 5f9c903f9..ecebd5399 100644 --- a/compiler+runtime/include/cpp/clojure/core_native.hpp +++ b/compiler+runtime/include/cpp/clojure/core_native.hpp @@ -30,8 +30,7 @@ namespace clojure::core_native object_ref ns_map(object_ref const ns); object_ref var_ns(object_ref const v); object_ref ns_resolve(object_ref const ns, object_ref const sym); - object_ref - alias(object_ref const current_ns, object_ref const remote_ns, object_ref const alias); + object_ref alias(object_ref const current_ns, object_ref const remote_ns, object_ref const alias); object_ref refer(object_ref const current_ns, object_ref const sym, object_ref const var); object_ref load_module(object_ref const path); object_ref compile(object_ref const path); @@ -59,7 +58,7 @@ namespace clojure::core_native object_ref current_time(); object_ref eval(object_ref const expr); - object_ref read_string(object_ref const /* opts */, object_ref const str); + object_ref read_string(object_ref const /* opts */, object_ref const str); object_ref lazy_seq(object_ref const o); diff --git a/compiler+runtime/include/cpp/jank/analyze/processor.hpp b/compiler+runtime/include/cpp/jank/analyze/processor.hpp index 71ee1b02b..44049dcba 100644 --- a/compiler+runtime/include/cpp/jank/analyze/processor.hpp +++ b/compiler+runtime/include/cpp/jank/analyze/processor.hpp @@ -49,175 +49,175 @@ namespace jank::analyze expression_result analyze(read::parse::processor::iterator, read::parse::processor::iterator const &); - expression_result analyze(runtime::object_ref const , expression_position); - expression_result analyze(runtime::object_ref const , + expression_result analyze(runtime::object_ref const, expression_position); + expression_result analyze(runtime::object_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_call(runtime::obj::persistent_list_ref const , + expression_result analyze_call(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_def(runtime::obj::persistent_list_ref const , + expression_result analyze_def(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_symbol(runtime::obj::symbol_ref const , + expression_result analyze_symbol(runtime::obj::symbol_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_fn(runtime::obj::persistent_list_ref const , + expression_result analyze_fn(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_recur(runtime::obj::persistent_list_ref const , + expression_result analyze_recur(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_do(runtime::obj::persistent_list_ref const , + expression_result analyze_do(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); jtl::result - analyze_fn_arity(runtime::obj::persistent_list_ref const , + analyze_fn_arity(runtime::obj::persistent_list_ref const, jtl::immutable_string const &name, local_frame_ptr); - expression_result analyze_let(runtime::obj::persistent_list_ref const , + expression_result analyze_let(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_letfn(runtime::obj::persistent_list_ref const , + expression_result analyze_letfn(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_loop(runtime::obj::persistent_list_ref const , + expression_result analyze_loop(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_if(runtime::obj::persistent_list_ref const , + expression_result analyze_if(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_quote(runtime::obj::persistent_list_ref const , + expression_result analyze_quote(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_var_call(runtime::obj::persistent_list_ref const , + expression_result analyze_var_call(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_var_val(runtime::var_ref const , + expression_result analyze_var_val(runtime::var_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_throw(runtime::obj::persistent_list_ref const , + expression_result analyze_throw(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_try(runtime::obj::persistent_list_ref const , + expression_result analyze_try(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_primitive_literal(runtime::object_ref const , + expression_result analyze_primitive_literal(runtime::object_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_vector(runtime::obj::persistent_vector_ref const , + expression_result analyze_vector(runtime::obj::persistent_vector_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_map(runtime::object_ref const , + expression_result analyze_map(runtime::object_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_set(runtime::object_ref const , + expression_result analyze_set(runtime::object_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_case(runtime::obj::persistent_list_ref const , + expression_result analyze_case(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_symbol(runtime::obj::symbol_ref const , + expression_result analyze_cpp_symbol(runtime::obj::symbol_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_call(runtime::obj::persistent_list_ref const , + expression_result analyze_cpp_call(runtime::obj::persistent_list_ref const, expression_ref, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_raw(runtime::obj::persistent_list_ref const , + expression_result analyze_cpp_raw(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_literal(runtime::obj::persistent_list_ref const , + expression_result analyze_cpp_literal(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box, literal_kind kind); - expression_result analyze_cpp_type(runtime::obj::persistent_list_ref const , + expression_result analyze_cpp_type(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_value(runtime::obj::persistent_list_ref const , + expression_result analyze_cpp_value(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_cast(runtime::obj::persistent_list_ref const , + expression_result analyze_cpp_cast(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_box(runtime::obj::persistent_list_ref const , + expression_result analyze_cpp_box(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_unbox(runtime::obj::persistent_list_ref const , + expression_result analyze_cpp_unbox(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_new(runtime::obj::persistent_list_ref const , + expression_result analyze_cpp_new(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_delete(runtime::obj::persistent_list_ref const , + expression_result analyze_cpp_delete(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, bool needs_box); - expression_result analyze_cpp_member_access(runtime::obj::persistent_list_ref const , + expression_result analyze_cpp_member_access(runtime::obj::persistent_list_ref const, expr::cpp_value_ref, local_frame_ptr, expression_position, @@ -228,7 +228,7 @@ namespace jank::analyze bool is_special(runtime::object_ref const form); using special_function_type - = expression_result (processor::*)(runtime::obj::persistent_list_ref const , + = expression_result (processor::*)(runtime::obj::persistent_list_ref const, local_frame_ptr, expression_position, jtl::option const &, diff --git a/compiler+runtime/include/cpp/jank/runtime/behavior/callable.hpp b/compiler+runtime/include/cpp/jank/runtime/behavior/callable.hpp index e6dcc6607..59bc2dbac 100644 --- a/compiler+runtime/include/cpp/jank/runtime/behavior/callable.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/behavior/callable.hpp @@ -22,80 +22,78 @@ namespace jank::runtime * dynamic code. We may not every know if the source is callable at all, so * codegen will use this suite of fns instead. */ object_ref dynamic_call(object_ref const source); - object_ref dynamic_call(object_ref const source, object_ref const ); - object_ref dynamic_call(object_ref const source, object_ref const , object_ref const ); + object_ref dynamic_call(object_ref const source, object_ref const); + object_ref dynamic_call(object_ref const source, object_ref const, object_ref const); + object_ref + dynamic_call(object_ref const source, object_ref const, object_ref const, object_ref const); object_ref dynamic_call(object_ref const source, - object_ref const , - object_ref const , - object_ref const ); + object_ref const, + object_ref const, + object_ref const, + object_ref const); object_ref dynamic_call(object_ref const source, - object_ref const , - object_ref const , - object_ref const , - object_ref const ); + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const); object_ref dynamic_call(object_ref const source, - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ); + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const); object_ref dynamic_call(object_ref const source, - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ); + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const); object_ref dynamic_call(object_ref const source, - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ); + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const); object_ref dynamic_call(object_ref const source, - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ); + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const); object_ref dynamic_call(object_ref const source, - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ); + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const); object_ref dynamic_call(object_ref const source, - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ); - object_ref dynamic_call(object_ref const source, - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - obj::persistent_list_ref const ); + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + obj::persistent_list_ref const); object_ref apply_to(object_ref const source, object_ref const args); @@ -109,56 +107,56 @@ namespace jank::runtime virtual ~callable() = default; virtual object_ref call(); - virtual object_ref call(object_ref const ); - virtual object_ref call(object_ref const , object_ref const ); - virtual object_ref call(object_ref const , object_ref const , object_ref const ); + virtual object_ref call(object_ref const); + virtual object_ref call(object_ref const, object_ref const); + virtual object_ref call(object_ref const, object_ref const, object_ref const); virtual object_ref - call(object_ref const , object_ref const , object_ref const , object_ref const ); - virtual object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ); - virtual object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ); - virtual object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ); - virtual object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ); - virtual object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ); - virtual object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ); + call(object_ref const, object_ref const, object_ref const, object_ref const); + virtual object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const); + virtual object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const); + virtual object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const); + virtual object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const); + virtual object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const); + virtual object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const); /* Callables need a way to get back to the root object so we can do helpful * error reporting on failed calls. */ diff --git a/compiler+runtime/include/cpp/jank/runtime/context.hpp b/compiler+runtime/include/cpp/jank/runtime/context.hpp index 8132ee01a..3e021e4c1 100644 --- a/compiler+runtime/include/cpp/jank/runtime/context.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/context.hpp @@ -45,29 +45,29 @@ namespace jank::runtime context(context &&) noexcept = delete; ns_ref intern_ns(jtl::immutable_string const &); - ns_ref intern_ns(obj::symbol_ref const ); - ns_ref remove_ns(obj::symbol_ref const ); + ns_ref intern_ns(obj::symbol_ref const); + ns_ref remove_ns(obj::symbol_ref const); /* Looks up a ns by its symbol. Does not resolve aliases. Does not intern. */ - ns_ref find_ns(obj::symbol_ref const ); + ns_ref find_ns(obj::symbol_ref const); /* Resolves a symbol which could be an alias to its ns, based on the aliases * in the current ns. Does not intern. */ - ns_ref resolve_ns(obj::symbol_ref const ); + ns_ref resolve_ns(obj::symbol_ref const); ns_ref current_ns() const; /* Adds the current ns to unqualified symbols and resolves the ns of qualified symbols. * Does not intern. */ - obj::symbol_ref qualify_symbol(obj::symbol_ref const ) const; - jtl::option find_local(obj::symbol_ref const ); + obj::symbol_ref qualify_symbol(obj::symbol_ref const) const; + jtl::option find_local(obj::symbol_ref const); jtl::result intern_var(obj::symbol_ref const qualified_name); jtl::result intern_var(jtl::immutable_string const &); jtl::result intern_var(jtl::immutable_string const &ns, jtl::immutable_string const &name); - jtl::result intern_owned_var(obj::symbol_ref const ); + jtl::result intern_owned_var(obj::symbol_ref const); jtl::result intern_owned_var(jtl::immutable_string const &); jtl::result intern_owned_var(jtl::immutable_string const &ns, jtl::immutable_string const &name); - var_ref find_var(obj::symbol_ref const ); + var_ref find_var(obj::symbol_ref const); var_ref find_var(jtl::immutable_string const &ns, jtl::immutable_string const &name); jtl::result diff --git a/compiler+runtime/include/cpp/jank/runtime/convert/function.hpp b/compiler+runtime/include/cpp/jank/runtime/convert/function.hpp index adceb7f3e..948964063 100644 --- a/compiler+runtime/include/cpp/jank/runtime/convert/function.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/convert/function.hpp @@ -7,14 +7,14 @@ namespace jank::runtime template struct always_object_ref { - using type = object_ref const ; + using type = object_ref const; }; template auto convert_function(R (* const fn)(Args...)) { if constexpr(std::conjunction_v, - std::is_same...>) + std::is_same...>) { return fn; } diff --git a/compiler+runtime/include/cpp/jank/runtime/core.hpp b/compiler+runtime/include/cpp/jank/runtime/core.hpp index d8f588494..f161dc872 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core.hpp @@ -33,8 +33,7 @@ namespace jank::runtime object_ref prn(object_ref const args); obj::persistent_string_ref subs(object_ref const s, object_ref const start); - obj::persistent_string_ref - subs(object_ref const s, object_ref const start, object_ref const end); + obj::persistent_string_ref subs(object_ref const s, object_ref const start, object_ref const end); i64 first_index_of(object_ref const s, object_ref const m); i64 last_index_of(object_ref const s, object_ref const m); @@ -60,10 +59,8 @@ namespace jank::runtime object_ref deref(object_ref const o); object_ref swap_atom(object_ref const atom, object_ref const fn); object_ref swap_atom(object_ref const atom, object_ref const fn, object_ref const a1); - object_ref swap_atom(object_ref const atom, - object_ref const fn, - object_ref const a1, - object_ref const a2); + object_ref + swap_atom(object_ref const atom, object_ref const fn, object_ref const a1, object_ref const a2); object_ref swap_atom(object_ref const atom, object_ref const fn, object_ref const a1, @@ -71,10 +68,8 @@ namespace jank::runtime object_ref const rest); object_ref swap_vals(object_ref const atom, object_ref const fn); object_ref swap_vals(object_ref const atom, object_ref const fn, object_ref const a1); - object_ref swap_vals(object_ref const atom, - object_ref const fn, - object_ref const a1, - object_ref const a2); + object_ref + swap_vals(object_ref const atom, object_ref const fn, object_ref const a1, object_ref const a2); object_ref swap_vals(object_ref const atom, object_ref const fn, object_ref const a1, diff --git a/compiler+runtime/include/cpp/jank/runtime/core/equal.hpp b/compiler+runtime/include/cpp/jank/runtime/core/equal.hpp index 82167351d..f72ebce16 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/equal.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/equal.hpp @@ -6,6 +6,6 @@ namespace jank::runtime { bool equal(char lhs, object_ref const rhs); bool equal(object_ref const lhs, object_ref const rhs); - i64 compare(object_ref const , object_ref const ); + i64 compare(object_ref const, object_ref const); bool is_identical(object_ref const lhs, object_ref const rhs); } diff --git a/compiler+runtime/include/cpp/jank/runtime/core/truthy.hpp b/compiler+runtime/include/cpp/jank/runtime/core/truthy.hpp index f954502ae..e90340380 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/truthy.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/truthy.hpp @@ -7,7 +7,7 @@ namespace jank::runtime { bool truthy(object const *o); bool truthy(object_ref const o); - bool truthy(obj::nil_ref const ); + bool truthy(obj::nil_ref const); bool truthy(obj::boolean_ref const o); bool truthy(bool const o); diff --git a/compiler+runtime/include/cpp/jank/runtime/ns.hpp b/compiler+runtime/include/cpp/jank/runtime/ns.hpp index 57fd1a5b9..90c0f8ad8 100644 --- a/compiler+runtime/include/cpp/jank/runtime/ns.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/ns.hpp @@ -24,14 +24,13 @@ namespace jank::runtime ns(obj::symbol_ref const name); var_ref intern_var(jtl::immutable_string_view const &); - var_ref intern_var(obj::symbol_ref const ); + var_ref intern_var(obj::symbol_ref const); var_ref intern_owned_var(jtl::immutable_string_view const &); - var_ref intern_owned_var(obj::symbol_ref const ); - var_ref find_var(obj::symbol_ref const ); + var_ref intern_owned_var(obj::symbol_ref const); + var_ref find_var(obj::symbol_ref const); jtl::result unmap(obj::symbol_ref const sym); - jtl::result - add_alias(obj::symbol_ref const sym, ns_ref const ns); + jtl::result add_alias(obj::symbol_ref const sym, ns_ref const ns); void remove_alias(obj::symbol_ref const sym); ns_ref find_alias(obj::symbol_ref const sym) const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp index f084c7d7b..435163ecc 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/atom.hpp @@ -43,12 +43,9 @@ namespace jank::runtime::obj /* Same as swap, but returns a vector of the old value and the new value. */ persistent_vector_ref swap_vals(object_ref const fn); persistent_vector_ref swap_vals(object_ref const fn, object_ref const a1); + persistent_vector_ref swap_vals(object_ref const fn, object_ref const a1, object_ref const a2); persistent_vector_ref - swap_vals(object_ref const fn, object_ref const a1, object_ref const a2); - persistent_vector_ref swap_vals(object_ref const fn, - object_ref const a1, - object_ref const a2, - object_ref const rest); + swap_vals(object_ref const fn, object_ref const a1, object_ref const a2, object_ref const rest); object_ref compare_and_set(object_ref const old_val, object_ref const new_val); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/integer_range.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/integer_range.hpp index 13124e0cd..73edde554 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/integer_range.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/integer_range.hpp @@ -18,7 +18,7 @@ namespace jank::runtime::obj static constexpr bool pointer_free{ false }; static constexpr bool is_sequential{ true }; - using bounds_check_t = bool (*)(integer_ref const , integer_ref const ); + using bounds_check_t = bool (*)(integer_ref const, integer_ref const); /* Constructors are only to be used within integer_range.cpp. Prefer integer_range::create. */ integer_range() = default; @@ -26,9 +26,7 @@ namespace jank::runtime::obj integer_range(integer_range const &) = default; integer_range(integer_ref const end); integer_range(integer_ref const start, obj::integer_ref const end); - integer_range(integer_ref const start, - obj::integer_ref const end, - obj::integer_ref const step); + integer_range(integer_ref const start, obj::integer_ref const end, obj::integer_ref const step); integer_range(integer_ref const start, integer_ref const end, integer_ref const step, diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp index e07b8e479..c9fdd944a 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/jit_closure.hpp @@ -30,56 +30,55 @@ namespace jank::runtime::obj /* behavior::callable */ object_ref call() final; - object_ref call(object_ref const ) final; - object_ref call(object_ref const , object_ref const ) final; - object_ref call(object_ref const , object_ref const , object_ref const ) final; - object_ref - call(object_ref const , object_ref const , object_ref const , object_ref const ) final; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) final; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) final; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) final; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) final; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) final; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) final; + object_ref call(object_ref const) final; + object_ref call(object_ref const, object_ref const) final; + object_ref call(object_ref const, object_ref const, object_ref const) final; + object_ref call(object_ref const, object_ref const, object_ref const, object_ref const) final; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) final; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) final; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) final; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) final; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) final; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) final; arity_flag_t get_arity_flags() const final; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp index 1e5399dbc..84960c689 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/jit_function.hpp @@ -30,56 +30,56 @@ namespace jank::runtime::obj /* behavior::callable */ object_ref call() override; - object_ref call(object_ref const ) override; - object_ref call(object_ref const , object_ref const ) override; - object_ref call(object_ref const , object_ref const , object_ref const ) override; + object_ref call(object_ref const) override; + object_ref call(object_ref const, object_ref const) override; + object_ref call(object_ref const, object_ref const, object_ref const) override; object_ref - call(object_ref const , object_ref const , object_ref const , object_ref const ) override; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) override; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) override; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) override; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) override; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) override; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) override; + call(object_ref const, object_ref const, object_ref const, object_ref const) override; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) override; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) override; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) override; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) override; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) override; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) override; arity_flag_t get_arity_flags() const override; object_ref this_object_ref() override; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp index 57be5a60f..855347934 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp @@ -40,8 +40,8 @@ namespace jank::runtime::obj jtl::immutable_string const &get_namespace() const; /* behavior::callable */ - object_ref call(object_ref const ); - object_ref call(object_ref const , object_ref const ); + object_ref call(object_ref const); + object_ref call(object_ref const, object_ref const); bool operator==(keyword const &rhs) const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp index d603427e0..48d6c5359 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/multi_function.hpp @@ -31,56 +31,56 @@ namespace jank::runtime::obj /* behavior::callable */ object_ref call() override; - object_ref call(object_ref const ) override; - object_ref call(object_ref const , object_ref const ) override; - object_ref call(object_ref const , object_ref const , object_ref const ) override; + object_ref call(object_ref const) override; + object_ref call(object_ref const, object_ref const) override; + object_ref call(object_ref const, object_ref const, object_ref const) override; object_ref - call(object_ref const , object_ref const , object_ref const , object_ref const ) override; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) override; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) override; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) override; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) override; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) override; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) override; + call(object_ref const, object_ref const, object_ref const, object_ref const) override; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) override; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) override; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) override; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) override; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) override; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) override; object_ref this_object_ref() final; multi_function_ref reset(); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp index 25afe1da8..41d2b6db2 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/native_function_wrapper.hpp @@ -84,56 +84,55 @@ namespace jank::runtime /* behavior::callable */ object_ref call() final; - object_ref call(object_ref const ) final; - object_ref call(object_ref const , object_ref const ) final; - object_ref call(object_ref const , object_ref const , object_ref const ) final; - object_ref - call(object_ref const , object_ref const , object_ref const , object_ref const ) final; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) final; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) final; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) final; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) final; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) final; - object_ref call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) final; + object_ref call(object_ref const) final; + object_ref call(object_ref const, object_ref const) final; + object_ref call(object_ref const, object_ref const, object_ref const) final; + object_ref call(object_ref const, object_ref const, object_ref const, object_ref const) final; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) final; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) final; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) final; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) final; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) final; + object_ref call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) final; object_ref this_object_ref() final; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_array_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_array_map.hpp index 05acb123b..0bf8f6388 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_array_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_array_map.hpp @@ -78,8 +78,8 @@ namespace jank::runtime::obj persistent_array_map_ref dissoc(object_ref const key) const; /* behavior::callable */ - object_ref call(object_ref const ) const; - object_ref call(object_ref const , object_ref const ) const; + object_ref call(object_ref const) const; + object_ref call(object_ref const, object_ref const) const; /* behavior::transientable */ transient_array_map_ref to_transient() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp index 2c9fbaec5..083b5af7a 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_hash_set.hpp @@ -62,7 +62,7 @@ namespace jank::runtime::obj persistent_hash_set_ref conj(object_ref const head) const; /* behavior::callable */ - object_ref call(object_ref const ) const; + object_ref call(object_ref const) const; /* behavior::transientable */ obj::transient_hash_set_ref to_transient() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_map.hpp index 5b20feb63..18338d998 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_map.hpp @@ -56,8 +56,7 @@ namespace jank::runtime::obj } template - static persistent_sorted_map_ref - create_unique_with_meta(object_ref const meta, Args &&...pairs) + static persistent_sorted_map_ref create_unique_with_meta(object_ref const meta, Args &&...pairs) { return make_box(meta, runtime::detail::in_place_unique{}, @@ -77,8 +76,8 @@ namespace jank::runtime::obj persistent_sorted_map_ref dissoc(object_ref const key) const; /* behavior::callable */ - object_ref call(object_ref const ) const; - object_ref call(object_ref const , object_ref const ) const; + object_ref call(object_ref const) const; + object_ref call(object_ref const, object_ref const) const; /* behavior::transientable */ obj::transient_sorted_map_ref to_transient() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp index f44ff943d..1e3d43cb7 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_sorted_set.hpp @@ -62,7 +62,7 @@ namespace jank::runtime::obj persistent_sorted_set_ref conj(object_ref const head) const; /* behavior::callable */ - object_ref call(object_ref const ); + object_ref call(object_ref const); /* behavior::transientable */ obj::transient_sorted_set_ref to_transient() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp index 5a35f3992..1613c6df8 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/persistent_vector.hpp @@ -87,7 +87,7 @@ namespace jank::runtime::obj object_ref nth(object_ref const index, object_ref const fallback) const; /* behavior::callable */ - object_ref call(object_ref const ) const; + object_ref call(object_ref const) const; /* behavior::transientable */ obj::transient_vector_ref to_transient() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp index d81beb91c..8a9a9d7e8 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/range.hpp @@ -20,7 +20,7 @@ namespace jank::runtime::obj static constexpr bool is_sequential{ true }; static constexpr i64 chunk_size{ 32 }; - using bounds_check_t = bool (*)(object_ref const , object_ref const ); + using bounds_check_t = bool (*)(object_ref const, object_ref const); /* Constructors are only to be used within range.cpp. Prefer range::create. */ range() = default; @@ -42,8 +42,7 @@ namespace jank::runtime::obj static object_ref create(object_ref const end); static object_ref create(object_ref const start, object_ref const end); - static object_ref - create(object_ref const start, object_ref const end, object_ref const step); + static object_ref create(object_ref const start, object_ref const end, object_ref const step); /* behavior::object_like */ bool equal(object const &) const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp index 56027543f..ede52f9db 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp @@ -10,7 +10,7 @@ namespace jank::runtime::obj ratio_data(i64 const, i64 const); ratio_data(native_big_integer const &, native_big_integer const &); ratio_data(big_integer const &, big_integer const &); - ratio_data(object_ref const , object_ref const ); + ratio_data(object_ref const, object_ref const); ratio_data(ratio_data const &) = default; f64 to_real() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp index 7a388acad..f69f05373 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_array_map.hpp @@ -51,8 +51,8 @@ namespace jank::runtime::obj persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const ) const; - object_ref call(object_ref const , object_ref const ) const; + object_ref call(object_ref const) const; + object_ref call(object_ref const, object_ref const) const; void assert_active() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp index a9aeebd5b..dbaa65bc2 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_map.hpp @@ -57,8 +57,8 @@ namespace jank::runtime::obj persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const ) const; - object_ref call(object_ref const , object_ref const ) const; + object_ref call(object_ref const) const; + object_ref call(object_ref const, object_ref const) const; void assert_active() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp index b657140f3..280aef166 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_hash_set.hpp @@ -41,8 +41,8 @@ namespace jank::runtime::obj persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const ) const; - object_ref call(object_ref const , object_ref const fallback) const; + object_ref call(object_ref const) const; + object_ref call(object_ref const, object_ref const fallback) const; /* behavior::associatively_readable */ object_ref get(object_ref const elem) const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp index cb367f550..8ea7ec99f 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_map.hpp @@ -50,8 +50,8 @@ namespace jank::runtime::obj persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const ) const; - object_ref call(object_ref const , object_ref const ) const; + object_ref call(object_ref const) const; + object_ref call(object_ref const, object_ref const) const; void assert_active() const; diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp index a47d5a214..bbd60a91a 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_sorted_set.hpp @@ -40,8 +40,8 @@ namespace jank::runtime::obj persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const ); - object_ref call(object_ref const , object_ref const fallback); + object_ref call(object_ref const); + object_ref call(object_ref const, object_ref const fallback); /* behavior::associatively_readable */ object_ref get(object_ref const elem); diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp index d515ebc59..d211cb9ca 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/transient_vector.hpp @@ -41,7 +41,7 @@ namespace jank::runtime::obj persistent_type_ref to_persistent(); /* behavior::callable */ - object_ref call(object_ref const ) const; + object_ref call(object_ref const) const; /* behavior::associatively_readable */ object_ref get(object_ref const idx) const; diff --git a/compiler+runtime/include/cpp/jank/runtime/oref.hpp b/compiler+runtime/include/cpp/jank/runtime/oref.hpp index 377f13338..e7e0c2d4a 100644 --- a/compiler+runtime/include/cpp/jank/runtime/oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/oref.hpp @@ -37,18 +37,8 @@ namespace jank::runtime using value_type = object; oref() = default; - - oref(oref const &rhs) - : data{ rhs.data } - { - jank_assert_throw(data); - } - - oref(oref &&rhs) noexcept - : data{ jtl::move(rhs.data) } - { - jank_assert_throw(data); - } + oref(oref const &rhs) = default; + oref(oref &&rhs) noexcept = default; oref(nullptr_t) noexcept = delete; @@ -194,16 +184,8 @@ namespace jank::runtime using value_type = T; oref() = default; - - oref(oref const &rhs) noexcept - : data{ rhs.data } - { - } - - oref(oref &&rhs) noexcept - : data{ rhs.data } - { - } + oref(oref const &rhs) noexcept = default; + oref(oref &&rhs) noexcept = default; oref(nullptr_t) = delete; @@ -376,6 +358,8 @@ namespace jank::runtime using value_type = obj::nil; oref() = default; + oref(oref const &) = default; + oref(oref &&) noexcept = default; oref(nullptr_t) = delete; @@ -443,6 +427,9 @@ namespace jank::runtime return rhs.is_some(); } + oref &operator=(oref const &rhs) noexcept = default; + oref &operator=(oref &&rhs) noexcept = default; + oref &operator=(jtl::nullptr_t) noexcept = delete; bool operator==(jtl::nullptr_t) noexcept = delete; bool operator!=(jtl::nullptr_t) noexcept = delete; diff --git a/compiler+runtime/include/cpp/jank/util/try.hpp b/compiler+runtime/include/cpp/jank/util/try.hpp index c2a7c2352..718c4e36a 100644 --- a/compiler+runtime/include/cpp/jank/util/try.hpp +++ b/compiler+runtime/include/cpp/jank/util/try.hpp @@ -69,7 +69,7 @@ namespace jank::util fun(e); \ then; \ } \ - catch(jank::error_ref const e) \ + catch(jank::error_ref const e) \ { \ fun(e); \ then; \ diff --git a/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp b/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp index f4d0a0ea4..be49eaa6c 100644 --- a/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/local_frame.cpp @@ -37,9 +37,8 @@ namespace jank::analyze { } - static jtl::option find_local_impl(local_frame_ptr const start, - obj::symbol_ref const sym, - bool const allow_captures) + static jtl::option + find_local_impl(local_frame_ptr const start, obj::symbol_ref const sym, bool const allow_captures) { decltype(local_frame::binding_find_result::crossed_fns) crossed_fns; diff --git a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp index fde156db5..5e2015ef1 100644 --- a/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/llvm_processor.cpp @@ -135,7 +135,7 @@ namespace jank::codegen void create_global_ctor() const; llvm::GlobalVariable *create_global_var(jtl::immutable_string const &name) const; - llvm::Value *gen_global(runtime::obj::nil_ref const ) const; + llvm::Value *gen_global(runtime::obj::nil_ref const) const; llvm::Value *gen_global(runtime::obj::boolean_ref const b) const; llvm::Value *gen_global(runtime::obj::integer_ref const i) const; llvm::Value *gen_global(runtime::obj::big_integer_ref const i) const; diff --git a/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp b/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp index bc5a5c261..3c5cc78a8 100644 --- a/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/behavior/callable.cpp @@ -975,92 +975,92 @@ namespace jank::runtime throw invalid_arity<0>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const ) + object_ref callable::call(object_ref const) { throw invalid_arity<1>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const , object_ref const ) + object_ref callable::call(object_ref const, object_ref const) { throw invalid_arity<2>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const , object_ref const , object_ref const ) + object_ref callable::call(object_ref const, object_ref const, object_ref const) { throw invalid_arity<3>{ runtime::to_code_string(this_object_ref()) }; } object_ref - callable::call(object_ref const , object_ref const , object_ref const , object_ref const ) + callable::call(object_ref const, object_ref const, object_ref const, object_ref const) { throw invalid_arity<4>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) + object_ref callable::call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) { throw invalid_arity<5>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) + object_ref callable::call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) { throw invalid_arity<6>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) + object_ref callable::call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) { throw invalid_arity<7>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) + object_ref callable::call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) { throw invalid_arity<8>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) + object_ref callable::call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) { throw invalid_arity<9>{ runtime::to_code_string(this_object_ref()) }; } - object_ref callable::call(object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const , - object_ref const ) + object_ref callable::call(object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const, + object_ref const) { throw invalid_arity<10>{ runtime::to_code_string(this_object_ref()) }; } diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 72268b9a7..b9d4f4054 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -225,7 +225,7 @@ namespace jank::runtime //util::println("{}\n", util::format_cpp_source(cg_prc.declaration_str()).expect_ok()); auto const code{ cg_prc.declaration_str() }; auto module_name{ runtime::to_string(current_module_var->deref()) }; - aot::processor aot_prc; + aot::processor const aot_prc; auto const res{ aot_prc.compile_object(module_name, code) }; if(res.is_err()) { diff --git a/compiler+runtime/src/cpp/jank/runtime/core.cpp b/compiler+runtime/src/cpp/jank/runtime/core.cpp index 0bafd044d..49ccb6652 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core.cpp @@ -223,8 +223,7 @@ namespace jank::runtime to_int(start)); } - obj::persistent_string_ref - subs(object_ref const s, object_ref const start, object_ref const end) + obj::persistent_string_ref subs(object_ref const s, object_ref const start, object_ref const end) { return visit_type( [](auto const typed_s, i64 const start, i64 const end) -> obj::persistent_string_ref { @@ -391,10 +390,8 @@ namespace jank::runtime return try_object(atom)->swap(fn, a1); } - object_ref swap_atom(object_ref const atom, - object_ref const fn, - object_ref const a1, - object_ref const a2) + object_ref + swap_atom(object_ref const atom, object_ref const fn, object_ref const a1, object_ref const a2) { return try_object(atom)->swap(fn, a1, a2); } @@ -418,10 +415,8 @@ namespace jank::runtime return try_object(atom)->swap_vals(fn, a1); } - object_ref swap_vals(object_ref const atom, - object_ref const fn, - object_ref const a1, - object_ref const a2) + object_ref + swap_vals(object_ref const atom, object_ref const fn, object_ref const a1, object_ref const a2) { return try_object(atom)->swap_vals(fn, a1, a2); } diff --git a/compiler+runtime/src/cpp/jank/runtime/core/math.cpp b/compiler+runtime/src/cpp/jank/runtime/core/math.cpp index 54825ca1f..ef019d663 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/math.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/math.cpp @@ -41,7 +41,7 @@ namespace jank::runtime return visit_number_like( [](auto const typed_l, auto const r) -> object_ref { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l + typed_r->data).erase(); }, r, @@ -210,7 +210,7 @@ namespace jank::runtime return visit_number_like( [](auto const typed_l, auto const r) -> object_ref { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l - typed_r->data).erase(); }, r, @@ -379,7 +379,7 @@ namespace jank::runtime return visit_number_like( [](auto const typed_l, auto const r) -> object_ref { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l / typed_r->data).erase(); }, r, @@ -514,7 +514,7 @@ namespace jank::runtime return visit_number_like( [](auto const typed_l, auto const r) -> object_ref { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const &typed_l) -> object_ref { return make_box(typed_l * typed_r->data).erase(); }, r, @@ -728,7 +728,7 @@ namespace jank::runtime return visit_number_like( [](auto const typed_l, auto const r) -> object_ref { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const &typed_l) -> object_ref { auto const typed_l_data{ to_real(typed_l) }; auto const typed_r_data{ to_real(typed_r->data) }; #pragma clang diagnostic push @@ -899,7 +899,7 @@ namespace jank::runtime return visit_number_like( [](auto const typed_l, object_ref const r) -> bool { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> bool { + [](auto const typed_r, auto const &typed_l) -> bool { auto const data_l{ to_real(typed_l) }; auto const data_r{ to_real(typed_r->data) }; @@ -1088,7 +1088,7 @@ namespace jank::runtime return visit_number_like( [](auto const typed_l, auto const r) -> bool { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> bool { return typed_l < typed_r->data; }, + [](auto const typed_r, auto const &typed_l) -> bool { return typed_l < typed_r->data; }, r, typed_l->data); }, @@ -1205,7 +1205,7 @@ namespace jank::runtime return visit_number_like( [](auto const typed_l, auto const r) -> bool { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> bool { return typed_l <= typed_r->data; }, + [](auto const typed_r, auto const &typed_l) -> bool { return typed_l <= typed_r->data; }, r, typed_l->data); }, @@ -1322,7 +1322,7 @@ namespace jank::runtime return visit_number_like( [](auto const typed_l, auto const r) -> object_ref { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const &typed_l) -> object_ref { return typed_l < typed_r->data ? make_box(typed_l).erase() : make_box(typed_r->data).erase(); }, @@ -1470,7 +1470,7 @@ namespace jank::runtime return visit_number_like( [](auto const typed_l, auto const r) -> object_ref { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> object_ref { + [](auto const typed_r, auto const &typed_l) -> object_ref { return typed_r->data > typed_l ? make_box(typed_r).erase() : make_box(typed_l).erase(); }, r, @@ -1675,7 +1675,7 @@ namespace jank::runtime return visit_number_like( [](auto const typed_l, auto const r) -> f64 { return visit_number_like( - [](auto const typed_r, auto const typed_l) -> f64 { + [](auto const typed_r, auto const &typed_l) -> f64 { auto const typed_r_data{ to_real(typed_r->data) }; auto const typed_l_data{ to_real(typed_l) }; using C = std::common_type_t; diff --git a/compiler+runtime/src/cpp/jank/runtime/core/truthy.cpp b/compiler+runtime/src/cpp/jank/runtime/core/truthy.cpp index d5aa183e4..ac7fe3074 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/truthy.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/truthy.cpp @@ -29,7 +29,7 @@ namespace jank::runtime return truthy(o.data); } - bool truthy(obj::nil_ref const ) + bool truthy(obj::nil_ref const) { return false; } diff --git a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp index fba062e00..af68aeefa 100644 --- a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp @@ -834,7 +834,7 @@ namespace jank::runtime::module } }; auto const swap_fn_wrapper{ make_box( - std::function{ swap_fn }) }; + std::function{ swap_fn }) }; loaded_libs_atom->swap(swap_fn_wrapper); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp index 5136480f9..16c181421 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/atom.cpp @@ -45,8 +45,7 @@ namespace jank::runtime::obj return val.load(); } - static void - notify_watches(atom_ref const a, object_ref const old_val, object_ref const new_val) + static void notify_watches(atom_ref const a, object_ref const old_val, object_ref const new_val) { auto const locked_watches(a->watches.rlock()); for(auto const &entry : (*locked_watches)->data) @@ -129,10 +128,7 @@ namespace jank::runtime::obj object_ref /* NOLINTNEXTLINE(cppcoreguidelines-noexcept-swap,bugprone-exception-escape) */ - atom::swap(object_ref const fn, - object_ref const a1, - object_ref const a2, - object_ref const rest) + atom::swap(object_ref const fn, object_ref const a1, object_ref const a2, object_ref const rest) { while(true) { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/big_decimal.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/big_decimal.cpp index 0317d6ec7..5debf7607 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/big_decimal.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/big_decimal.cpp @@ -166,9 +166,7 @@ namespace jank::runtime::obj i64 big_decimal::compare(object const &o) const { return visit_number_like( - [this](auto const typed_o) -> i64 { - return (data > typed_o->data) - (data < typed_o->data); - }, + [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, [&]() -> i64 { throw std::runtime_error{ util::format("not comparable: {}", runtime::to_string(&o)) }; }, diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/big_integer.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/big_integer.cpp index 66cff7d22..0e49badb4 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/big_integer.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/big_integer.cpp @@ -279,9 +279,7 @@ namespace jank::runtime::obj i64 big_integer::compare(object const &o) const { return visit_number_like( - [this](auto const typed_o) -> i64 { - return (data > typed_o->data) - (data < typed_o->data); - }, + [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, [&]() -> i64 { throw std::runtime_error{ util::format("not comparable: {}", runtime::to_string(&o)) }; }, diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp index 981254049..ae6dc6cdd 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/native_function_wrapper.cpp @@ -55,7 +55,7 @@ namespace jank::runtime::obj template struct build_arity { - using type = typename build_arity::type; + using type = typename build_arity::type; }; template @@ -105,9 +105,8 @@ namespace jank::runtime::obj return apply_function(*this, arg1, arg2); } - object_ref native_function_wrapper::call(object_ref const arg1, - object_ref const arg2, - object_ref const arg3) + object_ref + native_function_wrapper::call(object_ref const arg1, object_ref const arg2, object_ref const arg3) { return apply_function(*this, arg1, arg2, arg3); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp index bbe292b16..85dbecca5 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp @@ -48,9 +48,7 @@ namespace jank::runtime::obj i64 boolean::compare(object const &o) const { return visit_number_like( - [this](auto const typed_o) -> i64 { - return (data > typed_o->data) - (data < typed_o->data); - }, + [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, [&]() -> i64 { throw std::runtime_error{ util::format("not comparable: {}", runtime::to_string(&o)) }; }, @@ -109,9 +107,7 @@ namespace jank::runtime::obj i64 integer::compare(object const &o) const { return visit_number_like( - [this](auto const typed_o) -> i64 { - return (data > typed_o->data) - (data < typed_o->data); - }, + [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, [&]() -> i64 { throw std::runtime_error{ util::format("not comparable: {}", runtime::to_string(&o)) }; }, @@ -194,9 +190,7 @@ namespace jank::runtime::obj i64 real::compare(object const &o) const { return visit_number_like( - [this](auto const typed_o) -> i64 { - return (data > typed_o->data) - (data < typed_o->data); - }, + [this](auto const typed_o) -> i64 { return (data > typed_o->data) - (data < typed_o->data); }, [&]() -> i64 { throw std::runtime_error{ util::format("not comparable: {}", runtime::to_string(&o)) }; }, diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp index 30cefa244..a17275b5d 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_list.cpp @@ -60,7 +60,7 @@ namespace jank::runtime::obj return s; } - persistent_list_ref persistent_list::create(nil_ref const ) + persistent_list_ref persistent_list::create(nil_ref const) { return empty(); } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp index c768a11fc..e06d9c195 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_string.cpp @@ -92,7 +92,7 @@ namespace jank::runtime::obj return false; } - object_ref persistent_string::get_entry(object_ref const ) const + object_ref persistent_string::get_entry(object_ref const) const { throw std::runtime_error{ util::format("get_entry not supported on string") }; } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp index 7d52bc144..d5d67a667 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/persistent_vector.cpp @@ -272,7 +272,7 @@ namespace jank::runtime::obj return make_box(meta, std::move(vec)); } - persistent_vector_ref persistent_vector::dissoc(object_ref const /*key*/) const + persistent_vector_ref persistent_vector::dissoc(object_ref const /*key*/) const { throw std::runtime_error{ "Type 'persistent_vector' does not support 'dissoc'." }; } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp index afe71e3ab..aa184c0b1 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/tagged_literal.cpp @@ -26,8 +26,7 @@ namespace jank::runtime::obj return runtime::equal(tag, s->tag) && runtime::equal(form, s->form); } - static void - to_string_impl(object_ref const tag, object_ref const form, jtl::string_builder &buff) + static void to_string_impl(object_ref const tag, object_ref const form, jtl::string_builder &buff) { buff('#'); runtime::to_string(tag, buff); From b98a0528553deee69ece7b099ce86049172fa0ec Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 23 Dec 2025 13:54:54 -0800 Subject: [PATCH 092/122] Disable Linux ASan in CI again --- .github/workflows/build.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e87c092ac..06e4f89dd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -97,10 +97,11 @@ jobs: analyze: on ## Debug + sanitization - - name: Ubuntu - address sanitizer - os: ubuntu-24.04 - build_type: Debug - sanitize: address + # TODO: Fix this. GC issue: https://github.com/bdwgc/bdwgc/issues/772 + #- name: Ubuntu - address sanitizer + # os: ubuntu-24.04 + # build_type: Debug + # sanitize: address - name: Ubuntu - undefined behavior sanitizer os: ubuntu-24.04 From a0f22d9db3d2c64663ce0d353e7efb26bef29d32 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 23 Dec 2025 14:03:23 -0800 Subject: [PATCH 093/122] Ignore more noisy clang-tidy bits --- .clang-tidy | 1 + 1 file changed, 1 insertion(+) diff --git a/.clang-tidy b/.clang-tidy index 4838578fd..70f2c3d89 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -47,6 +47,7 @@ misc-definitions-in-headers,\ -bugprone-macro-parentheses,\ -bugprone-throwing-static-initialization,\ -readability-redundant-member-init,\ +-readability-redundant-typename,\ -readability-implicit-bool-conversion,\ -readability-magic-numbers,\ -readability-identifier-length,\ From a3aefa75f3bbf07634f663f25778f52f8227743b Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 23 Dec 2025 14:07:25 -0800 Subject: [PATCH 094/122] Disable a debug log --- compiler+runtime/src/cpp/jank/aot/processor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/aot/processor.cpp b/compiler+runtime/src/cpp/jank/aot/processor.cpp index f3017e36b..7a0043d06 100644 --- a/compiler+runtime/src/cpp/jank/aot/processor.cpp +++ b/compiler+runtime/src/cpp/jank/aot/processor.cpp @@ -302,7 +302,7 @@ int main(int argc, const char** argv) compiler_args.push_back(strdup("-o")); compiler_args.push_back(strdup(util::cli::opts.output_filename.c_str())); - util::println("compilation command: {} ", compiler_args); + //util::println("compilation command: {} ", compiler_args); auto const res{ util::invoke_clang(compiler_args) }; if(res.is_err()) @@ -357,7 +357,7 @@ int main(int argc, const char** argv) compiler_args.push_back("-w"); compiler_args.push_back("-Wno-c++11-narrowing"); - util::println("compilation command: {} ", compiler_args); + //util::println("compilation command: {} ", compiler_args); auto const res{ util::invoke_clang(compiler_args) }; if(res.is_err()) From 7640d3eca4e8e21bb4647ca2982ceca47a7eb7ff Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 25 Dec 2025 11:31:21 -0800 Subject: [PATCH 095/122] Document a bug --- compiler+runtime/src/cpp/jank/aot/processor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler+runtime/src/cpp/jank/aot/processor.cpp b/compiler+runtime/src/cpp/jank/aot/processor.cpp index 7a0043d06..a6596efb2 100644 --- a/compiler+runtime/src/cpp/jank/aot/processor.cpp +++ b/compiler+runtime/src/cpp/jank/aot/processor.cpp @@ -357,6 +357,9 @@ int main(int argc, const char** argv) compiler_args.push_back("-w"); compiler_args.push_back("-Wno-c++11-narrowing"); + /* TODO: This has an unwind issue which prevents exceptions thrown from these compiled + * objects from being caught in jank itself. */ + //util::println("compilation command: {} ", compiler_args); auto const res{ util::invoke_clang(compiler_args) }; From 42fa268403e605f62b74983b30cfd65127ec04a5 Mon Sep 17 00:00:00 2001 From: jeaye Date: Thu, 25 Dec 2025 16:40:07 -0800 Subject: [PATCH 096/122] Allow for custom output targets; infer as needed This will set the stage for us to compile `clojure.core` to a C++ file, which we'll then compile right into jank for phase 2. This shouldn't be needed, but it gets us around some memory usage issues in CI with all of the C++ compilation we're doing. --- .../include/cpp/jank/runtime/context.hpp | 2 + .../include/cpp/jank/util/cli.hpp | 32 ++- .../src/cpp/jank/aot/processor.cpp | 4 +- .../src/cpp/jank/runtime/context.cpp | 183 ++++++++++++------ compiler+runtime/src/cpp/jank/util/cli.cpp | 11 +- compiler+runtime/src/cpp/main.cpp | 58 ++++++ 6 files changed, 229 insertions(+), 61 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/runtime/context.hpp b/compiler+runtime/include/cpp/jank/runtime/context.hpp index 3e021e4c1..14f472316 100644 --- a/compiler+runtime/include/cpp/jank/runtime/context.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/context.hpp @@ -106,7 +106,9 @@ namespace jank::runtime object_ref eval(object_ref const o); + jtl::immutable_string get_output_module_name(jtl::immutable_string const &module_name) const; jtl::string_result write_module(jtl::immutable_string const &module_name, + jtl::immutable_string const &cpp_code, jtl::ref const &module) const; /* Generates a unique name for use with anything from codgen structs, diff --git a/compiler+runtime/include/cpp/jank/util/cli.hpp b/compiler+runtime/include/cpp/jank/util/cli.hpp index 56b44ba88..a0d1557a5 100644 --- a/compiler+runtime/include/cpp/jank/util/cli.hpp +++ b/compiler+runtime/include/cpp/jank/util/cli.hpp @@ -34,6 +34,33 @@ namespace jank::util::cli } } + enum class compilation_target : u8 + { + /* The target will be determined based on the extension of the output. + * If that's not possible, we'll error out. */ + unspecified, + llvm_ir, + cpp, + object + }; + + constexpr char const *compilation_target_str(compilation_target const target) + { + switch(target) + { + case compilation_target::unspecified: + return "unspecified"; + case compilation_target::llvm_ir: + return "llvm-ir"; + case compilation_target::cpp: + return "cpp"; + case compilation_target::object: + return "object"; + default: + return "unknown"; + } + } + struct options { /* Runtime. */ @@ -62,7 +89,10 @@ namespace jank::util::cli std::string target_module; std::string target_runtime{ "dynamic" }; std::string output_filename{ "a.out" }; - std::string output_object_filename; + + /* Compile-module command. */ + std::string output_module_filename; + compilation_target output_target; /* REPL command. */ bool repl_server{}; diff --git a/compiler+runtime/src/cpp/jank/aot/processor.cpp b/compiler+runtime/src/cpp/jank/aot/processor.cpp index a6596efb2..f3b4c2166 100644 --- a/compiler+runtime/src/cpp/jank/aot/processor.cpp +++ b/compiler+runtime/src/cpp/jank/aot/processor.cpp @@ -325,9 +325,9 @@ int main(int argc, const char** argv) std::vector compiler_args{ jtl::move(compiler_args_res.expect_ok()) }; std::filesystem::path const module_path{ - util::cli::opts.output_object_filename.empty() + util::cli::opts.output_module_filename.empty() ? util::format("{}/{}.o", __rt_ctx->binary_cache_dir, module::module_to_path(module_name)) - : jtl::immutable_string{ util::cli::opts.output_object_filename } + : jtl::immutable_string{ util::cli::opts.output_module_filename } }; std::filesystem::create_directories(module_path.parent_path()); diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index b9d4f4054..03fcf9d2f 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -216,7 +218,8 @@ namespace jank::runtime codegen::llvm_processor const cg_prc{ fn, module, codegen::compilation_target::module }; cg_prc.gen().expect_ok(); cg_prc.optimize(); - write_module(cg_prc.get_module_name(), cg_prc.get_module().getModuleUnlocked()).expect_ok(); + write_module(cg_prc.get_module_name(), "", cg_prc.get_module().getModuleUnlocked()) + .expect_ok(); } else { @@ -225,23 +228,23 @@ namespace jank::runtime //util::println("{}\n", util::format_cpp_source(cg_prc.declaration_str()).expect_ok()); auto const code{ cg_prc.declaration_str() }; auto module_name{ runtime::to_string(current_module_var->deref()) }; - aot::processor const aot_prc; - auto const res{ aot_prc.compile_object(module_name, code) }; - if(res.is_err()) - { - throw res.expect_err(); - } - //auto parse_res{ jit_prc.interpreter->Parse({ code.data(), code.size() }) }; - //if(!parse_res) + //aot::processor const aot_prc; + //auto const res{ aot_prc.compile_object(module_name, code) }; + //if(res.is_err()) //{ - // /* TODO: Helper to turn an llvm::Error into a string. */ - // jtl::immutable_string const res{ "Unable to compile generated C++ source." }; - // llvm::logAllUnhandledErrors(parse_res.takeError(), llvm::errs(), "error: "); - // throw error::internal_codegen_failure(res); + // throw res.expect_err(); //} - //auto &partial_tu{ parse_res.get() }; - ////auto module_name{ runtime::to_string(current_module_var->deref()) }; - //write_module(module_name, partial_tu.TheModule.get()).expect_ok(); + auto parse_res{ jit_prc.interpreter->Parse({ code.data(), code.size() }) }; + if(!parse_res) + { + /* TODO: Helper to turn an llvm::Error into a string. */ + jtl::immutable_string const res{ "Unable to compile generated C++ source." }; + llvm::logAllUnhandledErrors(parse_res.takeError(), llvm::errs(), "error: "); + throw error::internal_codegen_failure(res); + } + auto &partial_tu{ parse_res.get() }; + //auto module_name{ runtime::to_string(current_module_var->deref()) }; + write_module(module_name, code, partial_tu.TheModule.get()).expect_ok(); } } @@ -266,7 +269,7 @@ namespace jank::runtime if(truthy(compile_files_var->deref())) { auto module_name{ runtime::to_string(current_module_var->deref()) }; - write_module(module_name, partial_tu.TheModule.get()).expect_ok(); + write_module(module_name, code, partial_tu.TheModule.get()).expect_ok(); } auto exec_res(jit_prc.interpreter->Execute(partial_tu)); @@ -388,57 +391,123 @@ namespace jank::runtime return evaluate::eval(expr); } + jtl::immutable_string + context::get_output_module_name(jtl::immutable_string const &module_name) const + { + char const *ext{}; + switch(util::cli::opts.output_target) + { + case util::cli::compilation_target::llvm_ir: + ext = "ll"; + break; + case util::cli::compilation_target::cpp: + ext = "cpp"; + break; + case util::cli::compilation_target::object: + ext = "o"; + break; + case util::cli::compilation_target::unspecified: + default: + throw error::internal_runtime_failure( + util::format("Unable to determine output module name, given output target '{}'.", + util::cli::compilation_target_str(util::cli::opts.output_target))); + } + + return util::cli::opts.output_module_filename.empty() + ? util::format("{}/{}.{}", binary_cache_dir, module::module_to_path(module_name), ext) + : jtl::immutable_string{ util::cli::opts.output_module_filename }; + } + jtl::string_result context::write_module(jtl::immutable_string const &module_name, + jtl::immutable_string const &cpp_code, jtl::ref const &module) const { profile::timer const timer{ util::format("write_module {}", module_name) }; - std::filesystem::path const module_path{ - util::cli::opts.output_object_filename.empty() - ? util::format("{}/{}.o", binary_cache_dir, module::module_to_path(module_name)) - : jtl::immutable_string{ util::cli::opts.output_object_filename } - }; - std::filesystem::create_directories(module_path.parent_path()); - - /* TODO: Is there a better place for this block of code? */ - std::error_code file_error{}; - llvm::raw_fd_ostream os(module_path.c_str(), file_error, llvm::sys::fs::OpenFlags::OF_None); - if(file_error) + std::filesystem::path const module_path{ get_output_module_name(module_name) }; + auto const &module_dir{ module_path.parent_path() }; + if(!module_dir.empty()) { - return err(util::format("failed to open module file {} with error {}", - module_path.c_str(), - file_error.message())); + std::filesystem::create_directories(module_dir); } - //module->print(llvm::outs(), nullptr); - auto const target_triple{ util::default_target_triple() }; - std::string target_error; - auto const target{ llvm::TargetRegistry::lookupTarget(target_triple.c_str(), target_error) }; - if(!target) - { - return err(target_error); - } - llvm::TargetOptions const opt; - auto const target_machine{ target->createTargetMachine(llvm::Triple{ target_triple.c_str() }, - "generic", - "", - opt, - llvm::Reloc::PIC_, - llvm::CodeModel::Large, - llvm::CodeGenOptLevel::Default) }; - if(!target_machine) + switch(util::cli::opts.output_target) { - return err(util::format("failed to create target machine for {}", target_triple)); - } - llvm::legacy::PassManager pass; + case util::cli::compilation_target::cpp: + { + std::ofstream ofs{ module_path.c_str() }; + ofs << cpp_code; + return ok(); + } + case util::cli::compilation_target::llvm_ir: + { + std::error_code file_error{}; + llvm::raw_fd_ostream os(module_path.c_str(), + file_error, + llvm::sys::fs::OpenFlags::OF_None); + if(file_error) + { + return err(util::format("Failed to open module file '{}' with error '{}'.", + module_path.c_str(), + file_error.message())); + } + module->print(os, nullptr); + return ok(); + } + case util::cli::compilation_target::object: + { + /* TODO: Is there a better place for this block of code? */ + std::error_code file_error{}; + llvm::raw_fd_ostream os(module_path.c_str(), + file_error, + llvm::sys::fs::OpenFlags::OF_None); + if(file_error) + { + return err(util::format("Failed to open module file '{}' with error '{}'.", + module_path.c_str(), + file_error.message())); + } + //module->print(llvm::outs(), nullptr); - if(target_machine->addPassesToEmitFile(pass, os, nullptr, llvm::CodeGenFileType::ObjectFile)) - { - return err(util::format("failed to write module to object file for {}", target_triple)); - } + auto const target_triple{ util::default_target_triple() }; + std::string target_error; + auto const target{ llvm::TargetRegistry::lookupTarget(target_triple.c_str(), + target_error) }; + if(!target) + { + return err(target_error); + } + llvm::TargetOptions const opt; + auto const target_machine{ target->createTargetMachine( + llvm::Triple{ target_triple.c_str() }, + "generic", + "", + opt, + llvm::Reloc::PIC_, + llvm::CodeModel::Large, + llvm::CodeGenOptLevel::Default) }; + if(!target_machine) + { + return err(util::format("Failed to create target machine for '{}'.", target_triple)); + } + llvm::legacy::PassManager pass; - pass.run(*module); + if(target_machine->addPassesToEmitFile(pass, + os, + nullptr, + llvm::CodeGenFileType::ObjectFile)) + { + return err( + util::format("Failed to write module to object file for '{}'.", target_triple)); + } - return ok(); + pass.run(*module); + return ok(); + } + case util::cli::compilation_target::unspecified: + default: + return err(util::format("Unable to write module, given output target '{}'.", + util::cli::compilation_target_str(util::cli::opts.output_target))); + } } jtl::immutable_string context::unique_namespaced_string() const diff --git a/compiler+runtime/src/cpp/jank/util/cli.cpp b/compiler+runtime/src/cpp/jank/util/cli.cpp index ab4e6dfc0..bad7aa9cd 100644 --- a/compiler+runtime/src/cpp/jank/util/cli.cpp +++ b/compiler+runtime/src/cpp/jank/util/cli.cpp @@ -91,7 +91,16 @@ namespace jank::util::cli cli_compile_module .add_option("module", opts.target_module, "Module to compile (must be on the module path).") ->required(); - cli_compile_module.add_option("-o", opts.output_object_filename, "Output object file name."); + cli_compile_module.add_option("-o,--output", opts.output_module_filename, "Output file name."); + + std::map const output_targets{ + { "llvm-ir", compilation_target::llvm_ir }, + { "cpp", compilation_target::cpp }, + { "object", compilation_target::object } + }; + cli_compile_module + .add_option("--output-target", opts.output_target, "The type of file to generate.") + ->transform(CLI::CheckedTransformer(output_targets).description("{llvm-ir,cpp,object}")); /* REPL subcommand. */ auto &cli_repl(*cli.add_subcommand("repl", "Start up a terminal REPL and optional server.")); diff --git a/compiler+runtime/src/cpp/main.cpp b/compiler+runtime/src/cpp/main.cpp index 9689022d0..0ee43e8d0 100644 --- a/compiler+runtime/src/cpp/main.cpp +++ b/compiler+runtime/src/cpp/main.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -111,6 +112,63 @@ namespace jank using namespace jank; using namespace jank::runtime; + if(opts.output_target == util::cli::compilation_target::unspecified) + { + if(opts.output_module_filename.empty()) + { + opts.output_target = util::cli::compilation_target::object; + } + else + { + auto const ext{ std::filesystem::path{ opts.output_module_filename }.extension() }; + if(ext == ".ll") + { + opts.output_target = util::cli::compilation_target::llvm_ir; + } + else if(ext == ".cpp") + { + opts.output_target = util::cli::compilation_target::cpp; + } + else if(ext == ".o") + { + opts.output_target = util::cli::compilation_target::object; + } + else + { + /* TODO: Dedicated error. */ + throw error::internal_failure( + util::format("Unable to determine the output target type, given output file name '{}'. " + "If you provide a '.ll', '.cpp', or '.o' extension, this can be inferred. " + "Otherwise, please provide the --output-type flag to specify.", + opts.output_module_filename)); + } + } + } + else if(!opts.output_module_filename.empty()) + { + auto const ext{ std::filesystem::path{ opts.output_module_filename }.extension() }; + if((ext == ".ll" && opts.output_target != util::cli::compilation_target::llvm_ir) + || (ext == ".cpp" && opts.output_target != util::cli::compilation_target::cpp) + || (ext == ".o" && opts.output_target != util::cli::compilation_target::object)) + { + error::warn(util::format("The output file name '{}' has the extension '{}', but the output " + "target is '{}'. These appear to be mismatched.", + opts.output_module_filename, + ext, + util::cli::compilation_target_str(opts.output_target))); + } + } + + if(opts.output_target == util::cli::compilation_target::cpp + && opts.codegen != util::cli::codegen_type::cpp) + { + /* TODO: Dedicated error. */ + throw error::internal_failure( + util::format("Unable to output C++ when the codegen flag is set to '{}'. Please either " + "output a different target or change the codegen to C++.", + util::cli::codegen_type_str(opts.codegen))); + } + if(opts.target_module != "clojure.core") { __rt_ctx->load_module("/clojure.core", module::origin::latest).expect_ok(); From 15afe5d5b1dbb586a74563f34bb2e60c67b61ef3 Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 26 Dec 2025 13:14:44 -0800 Subject: [PATCH 097/122] Address clang-tidy issues --- .clang-tidy | 1 + compiler+runtime/include/cpp/jank/util/cli.hpp | 2 +- .../include/cpp/jtl/immutable_string.hpp | 2 +- compiler+runtime/src/cpp/clojure/core_native.cpp | 4 ++-- .../src/cpp/jank/runtime/core/math.cpp | 3 ++- compiler+runtime/src/cpp/jank/runtime/object.cpp | 16 ++++++++-------- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 70f2c3d89..0da0af222 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -48,6 +48,7 @@ misc-definitions-in-headers,\ -bugprone-throwing-static-initialization,\ -readability-redundant-member-init,\ -readability-redundant-typename,\ +-readability-redundant-casting,\ -readability-implicit-bool-conversion,\ -readability-magic-numbers,\ -readability-identifier-length,\ diff --git a/compiler+runtime/include/cpp/jank/util/cli.hpp b/compiler+runtime/include/cpp/jank/util/cli.hpp index a0d1557a5..6e9150a72 100644 --- a/compiler+runtime/include/cpp/jank/util/cli.hpp +++ b/compiler+runtime/include/cpp/jank/util/cli.hpp @@ -92,7 +92,7 @@ namespace jank::util::cli /* Compile-module command. */ std::string output_module_filename; - compilation_target output_target; + compilation_target output_target{ compilation_target::unspecified }; /* REPL command. */ bool repl_server{}; diff --git a/compiler+runtime/include/cpp/jtl/immutable_string.hpp b/compiler+runtime/include/cpp/jtl/immutable_string.hpp index c23d420a0..ba05ea857 100644 --- a/compiler+runtime/include/cpp/jtl/immutable_string.hpp +++ b/compiler+runtime/include/cpp/jtl/immutable_string.hpp @@ -746,7 +746,7 @@ namespace jtl jank_debug_assert(s <= max_small_size); /* NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index) */ store.small[s] = 0; - store.small[max_small_size] = value_type((max_small_size - s) << small_shift); + store.small[max_small_size] = static_cast((max_small_size - s) << small_shift); jank_debug_assert(get_category() == category::small && size() == s); } diff --git a/compiler+runtime/src/cpp/clojure/core_native.cpp b/compiler+runtime/src/cpp/clojure/core_native.cpp index 39b03cea7..3c8a14955 100644 --- a/compiler+runtime/src/cpp/clojure/core_native.cpp +++ b/compiler+runtime/src/cpp/clojure/core_native.cpp @@ -417,8 +417,8 @@ void jank_load_clojure_core_native() intern_fn("pos?", &is_pos); intern_fn("neg?", &is_neg); intern_fn("zero?", &is_zero); - intern_fn("rem", static_cast(&rem)); - intern_fn("quot", static_cast(")); + intern_fn("rem", &rem); + intern_fn("quot", "); intern_fn("integer?", &is_integer); intern_fn("real?", &is_real); intern_fn("ratio?", &is_ratio); diff --git a/compiler+runtime/src/cpp/jank/runtime/core/math.cpp b/compiler+runtime/src/cpp/jank/runtime/core/math.cpp index ef019d663..071db4f09 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/math.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/math.cpp @@ -1078,7 +1078,8 @@ namespace jank::runtime f64 rand() { - static std::mt19937 gen; + static std::random_device dev; + static std::mt19937 gen{ dev() }; static std::uniform_real_distribution dis(0.0, 1.0); return dis(gen); } diff --git a/compiler+runtime/src/cpp/jank/runtime/object.cpp b/compiler+runtime/src/cpp/jank/runtime/object.cpp index 699fcdbc6..af12fae2e 100644 --- a/compiler+runtime/src/cpp/jank/runtime/object.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/object.cpp @@ -63,23 +63,23 @@ namespace jank::runtime namespace std { - using namespace jank; - using namespace jank::runtime; - - size_t hash::operator()(object_ref const o) const noexcept + size_t + hash::operator()(jank::runtime::object_ref const o) const noexcept { return jank::hash::visit(o.data); } - size_t hash::operator()(object const &o) const noexcept + size_t hash::operator()(jank::runtime::object const &o) const noexcept { - return jank::hash::visit(const_cast(&o)); + return jank::hash::visit(const_cast(&o)); } bool // NOLINTNEXTLINE(bugprone-exception-escape): TODO: Sort this out. - equal_to::operator()(object_ref const lhs, object_ref const rhs) const noexcept + equal_to::operator()( + jank::runtime::object_ref const lhs, + jank::runtime::object_ref const rhs) const noexcept { - return equal(lhs, rhs); + return jank::runtime::equal(lhs, rhs); } } From f00b3c706ee8853320ef7447a9d902d67016b1d9 Mon Sep 17 00:00:00 2001 From: jeaye Date: Fri, 26 Dec 2025 16:29:11 -0800 Subject: [PATCH 098/122] Build phase 2 from cpp source; add option for CI This will allow CI to cook `clojure.core` into jank directly from the C++ source, which will lower memory usage during compilation. It should also lead to better optimizations, so no complaining here. --- compiler+runtime/CMakeLists.txt | 26 +++++++++++++----- compiler+runtime/bin/ar-merge | 2 +- compiler+runtime/cmake/summary.cmake | 27 ++++++++++--------- .../src/cpp/jank/codegen/processor.cpp | 2 +- .../src/cpp/jank/environment/check_health.cpp | 2 +- .../src/cpp/jank/runtime/context.cpp | 1 + .../src/cpp/jank/runtime/module/loader.cpp | 15 ++--------- compiler+runtime/src/cpp/main.cpp | 2 +- compiler+runtime/test/cpp/main.cpp | 12 +++++++-- 9 files changed, 50 insertions(+), 39 deletions(-) diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index a08596e55..a3f638838 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -44,12 +44,12 @@ option(jank_test "Enable jank's test suite" OFF) option(jank_unity_build "Optimize translation unit compilation for the number of cores" OFF) option(jank_debug_gc "Enable GC debug assertions" OFF) option(jank_profile_gc "Enable GC profiling (via massif or heaptrack)" OFF) +option(jank_force_phase_2 "Force the linking of core libs into the jank binary" OFF) set(jank_sanitize "none" CACHE STRING "The type of Clang sanitization to use (or none)") set(jank_resource_dir "../lib/jank/${CMAKE_PROJECT_VERSION}" CACHE STRING "Where jank's runtime files are installed. Relative paths are based on the runtime jank binary path") -set(jank_clojure_core_o "${CMAKE_BINARY_DIR}/core-libs/clojure/core.o") find_package(Git REQUIRED) execute_process( @@ -136,10 +136,16 @@ elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") list(APPEND jank_common_compiler_flags -Og -g -DNDEBUG) endif() -if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") +if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug" OR jank_force_phase_2) set(jank_enable_phase_2 ON) endif() +if(jank_enable_phase_2) + set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.cpp") +else() + set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.o") +endif() + if(jank_test) list(APPEND jank_common_compiler_flags -DJANK_TEST) endif() @@ -756,11 +762,13 @@ if(jank_enable_phase_2) add_executable( jank_exe_phase_2 "$" + ${jank_clojure_core_output} ) add_executable(jank::exe ALIAS jank_exe_phase_2) - set_property(TARGET jank_exe_phase_2 PROPERTY OUTPUT_NAME jank) + set_source_files_properties(${jank_clojure_core_output} PROPERTIES COMPILE_FLAGS "-w -Wno-c++11-narrowing") + # Symbol exporting for JIT. set_target_properties(jank_exe_phase_2 PROPERTIES ENABLE_EXPORTS 1) @@ -773,7 +781,6 @@ if(jank_enable_phase_2) target_link_libraries( jank_exe_phase_2 PUBLIC "$" - ${jank_clojure_core_o} ) jank_hook_llvm(jank_exe_phase_2) @@ -783,7 +790,7 @@ if(jank_enable_phase_2) #set_target_properties(jank_exe_phase_2 PROPERTIES LINK_FLAGS_RELEASE "-s") else() add_custom_command( - DEPENDS ${CMAKE_BINARY_DIR}/jank-phase-1 ${jank_clojure_core_o} ${jank_incremental_pch_flag} + DEPENDS ${CMAKE_BINARY_DIR}/jank-phase-1 ${jank_clojure_core_output} ${jank_incremental_pch_flag} WORKING_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT ${CMAKE_BINARY_DIR}/jank COMMAND ln -sf jank-phase-1 jank @@ -828,6 +835,11 @@ if(jank_test) add_executable(jank::test_exe ALIAS jank_test_exe) add_dependencies(jank_test_exe jank_exe_phase_1 jank_core_libraries) + if(jank_enable_phase_2) + target_sources(jank_test_exe PUBLIC ${jank_clojure_core_output}) + target_compile_options(jank_test_exe PUBLIC -DJANK_PHASE_2) + endif() + set_property(TARGET jank_test_exe PROPERTY OUTPUT_NAME jank-test) target_compile_features(jank_test_exe PRIVATE ${jank_cxx_standard}) @@ -907,8 +919,8 @@ set(jank_core_libraries_flag "${CMAKE_BINARY_DIR}/classes/core-libraries") add_custom_command( DEPENDS ${CMAKE_BINARY_DIR}/jank-phase-1 ${CMAKE_SOURCE_DIR}/src/jank/clojure/core.jank ${jank_incremental_pch_flag} OUTPUT ${jank_core_libraries_flag} - BYPRODUCTS ${jank_clojure_core_o} - COMMAND ${CMAKE_BINARY_DIR}/jank-phase-1 compile-module -O3 -o ${jank_clojure_core_o} clojure.core + BYPRODUCTS ${jank_clojure_core_output} + COMMAND ${CMAKE_BINARY_DIR}/jank-phase-1 -O3 compile-module -o ${jank_clojure_core_output} clojure.core COMMAND touch ${jank_core_libraries_flag} ) add_custom_target( diff --git a/compiler+runtime/bin/ar-merge b/compiler+runtime/bin/ar-merge index c25a434f1..659804204 100755 --- a/compiler+runtime/bin/ar-merge +++ b/compiler+runtime/bin/ar-merge @@ -32,7 +32,7 @@ case "${command}" in # This follows merge, but also bundles in the Clojure core library object files, following # jank's phase 2 building. merge-phase-2) - object_files="$(cat "${cache_dir}"/*) ${cmake_binary_dir}/core-libs/clojure/core.o" + object_files="$(cat "${cache_dir}"/*)" merge_output="${cmake_binary_dir}/libjank-standalone.a" rm -f "${merge_output}" # shellcheck disable=SC2086 diff --git a/compiler+runtime/cmake/summary.cmake b/compiler+runtime/cmake/summary.cmake index ec6dbe11a..c18638433 100644 --- a/compiler+runtime/cmake/summary.cmake +++ b/compiler+runtime/cmake/summary.cmake @@ -3,17 +3,18 @@ function(jank_message msg) endfunction() jank_message("┌─ jank options ─────────────────────") -jank_message("│ jank build type : ${CMAKE_BUILD_TYPE}") -jank_message("│ jank version : ${jank_version}") -jank_message("│ jank tests : ${jank_test}") -jank_message("│ jank coverage : ${jank_coverage}") -jank_message("│ jank analyze : ${jank_analyze}") -jank_message("│ jank sanitize : ${jank_sanitize}") -jank_message("│ jank unity build : ${jank_unity_build}") -jank_message("│ jank resource dir : ${jank_resource_dir}") -jank_message("│ jank debug gc : ${jank_debug_gc}") -jank_message("│ jank profile gc : ${jank_profile_gc}") -jank_message("│ clang version : ${LLVM_PACKAGE_VERSION}") -jank_message("│ clang prefix : ${CLANG_INSTALL_PREFIX}") -jank_message("│ clang resource dir : ${clang_resource_dir}") +jank_message("│ jank build type : ${CMAKE_BUILD_TYPE}") +jank_message("│ jank version : ${jank_version}") +jank_message("│ jank enable phase 2 : ${jank_enable_phase_2}") +jank_message("│ jank tests : ${jank_test}") +jank_message("│ jank coverage : ${jank_coverage}") +jank_message("│ jank analyze : ${jank_analyze}") +jank_message("│ jank sanitize : ${jank_sanitize}") +jank_message("│ jank unity build : ${jank_unity_build}") +jank_message("│ jank resource dir : ${jank_resource_dir}") +jank_message("│ jank debug gc : ${jank_debug_gc}") +jank_message("│ jank profile gc : ${jank_profile_gc}") +jank_message("│ clang version : ${LLVM_PACKAGE_VERSION}") +jank_message("│ clang prefix : ${CLANG_INSTALL_PREFIX}") +jank_message("│ clang resource dir : ${clang_resource_dir}") jank_message("└─────────────────────────────────────") diff --git a/compiler+runtime/src/cpp/jank/codegen/processor.cpp b/compiler+runtime/src/cpp/jank/codegen/processor.cpp index 8e14248f8..88710df18 100644 --- a/compiler+runtime/src/cpp/jank/codegen/processor.cpp +++ b/compiler+runtime/src/cpp/jank/codegen/processor.cpp @@ -2728,7 +2728,7 @@ namespace jank::codegen if(target == compilation_target::module) { util::format_to(footer_buffer, - "void {}(){", + "extern \"C\" void {}(){", runtime::module::module_to_load_function(module)); auto const ns{ runtime::module::module_to_native_ns(module) }; diff --git a/compiler+runtime/src/cpp/jank/environment/check_health.cpp b/compiler+runtime/src/cpp/jank/environment/check_health.cpp index 68254fd14..6f27b0a89 100644 --- a/compiler+runtime/src/cpp/jank/environment/check_health.cpp +++ b/compiler+runtime/src/cpp/jank/environment/check_health.cpp @@ -25,7 +25,7 @@ #include #ifdef JANK_PHASE_2 -void jank_load_clojure_core(); +extern "C" void jank_load_clojure_core(); #endif namespace jank::environment diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 03fcf9d2f..80cd2c94f 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -435,6 +435,7 @@ namespace jank::runtime case util::cli::compilation_target::cpp: { std::ofstream ofs{ module_path.c_str() }; + ofs << "#include \n"; ofs << cpp_code; return ok(); } diff --git a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp index af68aeefa..c494ece2c 100644 --- a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp @@ -993,19 +993,8 @@ namespace jank::runtime::module __rt_ctx->jit_prc.load_object(entry.path); } - /* For C++ codegen, we don't use extern "C" for the load fn, since it's UB - * to throw exceptions across C boundaries. Instead, we just declare the function - * and then try to call it. */ - auto const load_fn_res{ __rt_ctx->jit_prc.find_symbol(load_function_name) }; - if(load_fn_res.is_ok()) - { - reinterpret_cast(load_fn_res.expect_ok())(); - } - else - { - __rt_ctx->jit_prc.eval_string( - util::format("void {}(); {}();", load_function_name, load_function_name)); - } + auto const load_fn_res{ __rt_ctx->jit_prc.find_symbol(load_function_name).expect_ok() }; + reinterpret_cast(load_fn_res)(); return ok(); } diff --git a/compiler+runtime/src/cpp/main.cpp b/compiler+runtime/src/cpp/main.cpp index 0ee43e8d0..1ac6103cc 100644 --- a/compiler+runtime/src/cpp/main.cpp +++ b/compiler+runtime/src/cpp/main.cpp @@ -34,7 +34,7 @@ #include #ifdef JANK_PHASE_2 -void jank_load_clojure_core(); +extern "C" void jank_load_clojure_core(); #endif namespace jank diff --git a/compiler+runtime/test/cpp/main.cpp b/compiler+runtime/test/cpp/main.cpp index 38b52523b..05f156eb3 100644 --- a/compiler+runtime/test/cpp/main.cpp +++ b/compiler+runtime/test/cpp/main.cpp @@ -16,6 +16,10 @@ #include #include +#ifdef JANK_PHASE_2 +extern "C" void jank_load_clojure_core(); +#endif + /* NOLINTNEXTLINE(bugprone-exception-escape): println can throw. */ int main(int const argc, char const **argv) try @@ -26,10 +30,14 @@ try context.setOption("no-breaks", true); jank_load_clojure_core_native(); - /* We're loading from source always due to a bug in how we generate symbols which is - * leading to duplicate symbols being generated. */ + +#ifdef JANK_PHASE_2 + jank_load_clojure_core(); + jank::runtime::__rt_ctx->module_loader.set_is_loaded("/clojure.core"); +#else jank::runtime::__rt_ctx->load_module("/clojure.core", jank::runtime::module::origin::latest) .expect_ok(); +#endif auto const res(context.run()); if(context.shouldExit()) From db01cc339dd94a8272bba84508dfaa3ec4353a34 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 27 Dec 2025 11:17:23 -0800 Subject: [PATCH 099/122] Switch back to C symbols for jank_load fns It's technically UB to throw an exception across that boundary, but it's also a pain in the ass to deal with mangling. --- compiler+runtime/include/cpp/clojure/core_native.hpp | 2 +- compiler+runtime/include/cpp/jank/compiler_native.hpp | 2 +- compiler+runtime/include/cpp/jank/perf_native.hpp | 2 +- compiler+runtime/src/cpp/clojure/core_native.cpp | 2 +- compiler+runtime/src/cpp/jank/aot/processor.cpp | 8 ++++---- compiler+runtime/src/cpp/jank/compiler_native.cpp | 2 +- .../src/cpp/jank/environment/check_health.cpp | 1 + compiler+runtime/src/cpp/jank/perf_native.cpp | 2 +- compiler+runtime/src/cpp/jank/runtime/context.cpp | 2 +- 9 files changed, 12 insertions(+), 11 deletions(-) diff --git a/compiler+runtime/include/cpp/clojure/core_native.hpp b/compiler+runtime/include/cpp/clojure/core_native.hpp index ecebd5399..bd9b23a46 100644 --- a/compiler+runtime/include/cpp/clojure/core_native.hpp +++ b/compiler+runtime/include/cpp/clojure/core_native.hpp @@ -3,7 +3,7 @@ #include #include -void jank_load_clojure_core_native(); +extern "C" void jank_load_clojure_core_native(); namespace clojure::core_native { diff --git a/compiler+runtime/include/cpp/jank/compiler_native.hpp b/compiler+runtime/include/cpp/jank/compiler_native.hpp index 929f26468..5703e4ddc 100644 --- a/compiler+runtime/include/cpp/jank/compiler_native.hpp +++ b/compiler+runtime/include/cpp/jank/compiler_native.hpp @@ -1,3 +1,3 @@ #pragma once -void jank_load_jank_compiler_native(); +extern "C" void jank_load_jank_compiler_native(); diff --git a/compiler+runtime/include/cpp/jank/perf_native.hpp b/compiler+runtime/include/cpp/jank/perf_native.hpp index d76892c86..44d962eac 100644 --- a/compiler+runtime/include/cpp/jank/perf_native.hpp +++ b/compiler+runtime/include/cpp/jank/perf_native.hpp @@ -2,4 +2,4 @@ #include -void jank_load_jank_perf_native(); +extern "C" void jank_load_jank_perf_native(); diff --git a/compiler+runtime/src/cpp/clojure/core_native.cpp b/compiler+runtime/src/cpp/clojure/core_native.cpp index 3c8a14955..de1bdf027 100644 --- a/compiler+runtime/src/cpp/clojure/core_native.cpp +++ b/compiler+runtime/src/cpp/clojure/core_native.cpp @@ -298,7 +298,7 @@ namespace clojure::core_native } } -void jank_load_clojure_core_native() +extern "C" void jank_load_clojure_core_native() { using namespace jank; using namespace jank::runtime; diff --git a/compiler+runtime/src/cpp/jank/aot/processor.cpp b/compiler+runtime/src/cpp/jank/aot/processor.cpp index f3b4c2166..45e9f5d04 100644 --- a/compiler+runtime/src/cpp/jank/aot/processor.cpp +++ b/compiler+runtime/src/cpp/jank/aot/processor.cpp @@ -43,9 +43,9 @@ extern "C" int jank_init_with_pch(int const argc, char const * const pch_data, jank_usize pch_size, int (*fn)(int const, char const ** const)); -void jank_load_clojure_core_native(); -void jank_load_clojure_core(); -void jank_load_jank_compiler_native(); +extern "C" void jank_load_clojure_core_native(); +extern "C" void jank_load_clojure_core(); +extern "C" void jank_load_jank_compiler_native(); extern "C" jank_object_ref jank_var_intern_c(char const *, char const *); extern "C" jank_object_ref jank_deref(jank_object_ref); extern "C" jank_object_ref jank_call2(jank_object_ref, jank_object_ref, jank_object_ref); @@ -56,7 +56,7 @@ extern "C" jank_object_ref jank_parse_command_line_args(int, char const **); auto const modules_rlocked{ __rt_ctx->loaded_modules_in_order.rlock() }; for(auto const &it : *modules_rlocked) { - util::format_to(sb, R"(void {}();)", module::module_to_load_function(it)); + util::format_to(sb, R"(extern "C" void {}();)", module::module_to_load_function(it)); sb("\n"); } diff --git a/compiler+runtime/src/cpp/jank/compiler_native.cpp b/compiler+runtime/src/cpp/jank/compiler_native.cpp index a18aad6e1..c0ee4680d 100644 --- a/compiler+runtime/src/cpp/jank/compiler_native.cpp +++ b/compiler+runtime/src/cpp/jank/compiler_native.cpp @@ -50,7 +50,7 @@ namespace jank::compiler_native } } -void jank_load_jank_compiler_native() +extern "C" void jank_load_jank_compiler_native() { using namespace jank; using namespace jank::runtime; diff --git a/compiler+runtime/src/cpp/jank/environment/check_health.cpp b/compiler+runtime/src/cpp/jank/environment/check_health.cpp index 6f27b0a89..1bd126e8e 100644 --- a/compiler+runtime/src/cpp/jank/environment/check_health.cpp +++ b/compiler+runtime/src/cpp/jank/environment/check_health.cpp @@ -386,6 +386,7 @@ namespace jank::environment auto const saved_opts{ util::cli::opts }; util::cli::opts.target_module = "health"; + util::cli::opts.output_target = util::cli::compilation_target::object; util::cli::opts.output_filename = exe_output; util::cli::opts.module_path = path_tmp; util::scope_exit const finally{ /* NOLINTNEXTLINE(bugprone-exception-escape) */ diff --git a/compiler+runtime/src/cpp/jank/perf_native.cpp b/compiler+runtime/src/cpp/jank/perf_native.cpp index 2a2819c3d..e7772652e 100644 --- a/compiler+runtime/src/cpp/jank/perf_native.cpp +++ b/compiler+runtime/src/cpp/jank/perf_native.cpp @@ -8,7 +8,7 @@ #include #include -void jank_load_jank_perf_native() +extern "C" void jank_load_jank_perf_native() { using namespace jank; using namespace jank::runtime; diff --git a/compiler+runtime/src/cpp/jank/runtime/context.cpp b/compiler+runtime/src/cpp/jank/runtime/context.cpp index 80cd2c94f..bd36ab730 100644 --- a/compiler+runtime/src/cpp/jank/runtime/context.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/context.cpp @@ -370,7 +370,7 @@ namespace jank::runtime } catch(error_ref const e) { - return error::runtime_unable_to_load_module(e); + return e; } } From 93ad88359f1bc9e26c8e4e5baf30a3263a16aa7b Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 27 Dec 2025 11:53:51 -0800 Subject: [PATCH 100/122] Get aot e2e tests passing again I've put back core.o into libjank-stanalone.a, since AOT is broken otherwise. We'll see if CI still dies from memory issues. --- compiler+runtime/CMakeLists.txt | 2 ++ compiler+runtime/bin/ar-merge | 2 +- compiler+runtime/src/cpp/jank/util/cli.cpp | 1 + .../bash/ahead-of-time/src/jank-and-cpp-modules/my_lib.cpp | 5 ++--- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index a3f638838..fd27fcbe5 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -138,6 +138,8 @@ endif() if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug" OR jank_force_phase_2) set(jank_enable_phase_2 ON) +else() + set(jank_enable_phase_2 OFF) endif() if(jank_enable_phase_2) diff --git a/compiler+runtime/bin/ar-merge b/compiler+runtime/bin/ar-merge index 659804204..c25a434f1 100755 --- a/compiler+runtime/bin/ar-merge +++ b/compiler+runtime/bin/ar-merge @@ -32,7 +32,7 @@ case "${command}" in # This follows merge, but also bundles in the Clojure core library object files, following # jank's phase 2 building. merge-phase-2) - object_files="$(cat "${cache_dir}"/*)" + object_files="$(cat "${cache_dir}"/*) ${cmake_binary_dir}/core-libs/clojure/core.o" merge_output="${cmake_binary_dir}/libjank-standalone.a" rm -f "${merge_output}" # shellcheck disable=SC2086 diff --git a/compiler+runtime/src/cpp/jank/util/cli.cpp b/compiler+runtime/src/cpp/jank/util/cli.cpp index bad7aa9cd..68335924b 100644 --- a/compiler+runtime/src/cpp/jank/util/cli.cpp +++ b/compiler+runtime/src/cpp/jank/util/cli.cpp @@ -179,6 +179,7 @@ namespace jank::util::cli else if(cli.got_subcommand(&cli_compile)) { opts.command = command::compile; + opts.output_target = compilation_target::object; } else if(cli.got_subcommand(&cli_check_health)) { diff --git a/compiler+runtime/test/bash/ahead-of-time/src/jank-and-cpp-modules/my_lib.cpp b/compiler+runtime/test/bash/ahead-of-time/src/jank-and-cpp-modules/my_lib.cpp index 727fb8952..ae7138497 100644 --- a/compiler+runtime/test/bash/ahead-of-time/src/jank-and-cpp-modules/my_lib.cpp +++ b/compiler+runtime/test/bash/ahead-of-time/src/jank-and-cpp-modules/my_lib.cpp @@ -20,10 +20,10 @@ static object_ref greet_str(object_ref name) { auto const s_obj(try_object(name)); auto const new_str{ "Hello from cpp module, " + s_obj->to_string() + "!" }; - return make_box(new_str).erase(); + return make_box(new_str).erase().data; } -extern "C" jank_object_ref jank_load_my_lib() +extern "C" void jank_load_my_lib() { auto const ns_name{ "my-lib" }; auto const ns(__rt_ctx->intern_ns(ns_name)); @@ -42,5 +42,4 @@ extern "C" jank_object_ref jank_load_my_lib() __rt_ctx->module_loader.set_is_loaded(ns_name); std::cout << "Loaded '" << ns_name << "\n"; - return jank_nil().erase(); } From 2d6447aec6ebfb9d8cfc9ac5f82848f1cd67b6d6 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 27 Dec 2025 12:20:01 -0800 Subject: [PATCH 101/122] Disable double? test for now Shantanu can look into why it's failing. --- .../src/jank_test/run_clojure_test_suite.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler+runtime/test/bash/clojure-test-suite/src/jank_test/run_clojure_test_suite.cljc b/compiler+runtime/test/bash/clojure-test-suite/src/jank_test/run_clojure_test_suite.cljc index a88e33bba..52fb5acb0 100644 --- a/compiler+runtime/test/bash/clojure-test-suite/src/jank_test/run_clojure_test_suite.cljc +++ b/compiler+runtime/test/bash/clojure-test-suite/src/jank_test/run_clojure_test_suite.cljc @@ -37,7 +37,7 @@ clojure.core-test.decimal-qmark ;clojure.core-test.denominator ; Failed a test. Expecting whitespace after the last token. due to M. ;clojure.core-test.double - clojure.core-test.double-qmark + ;clojure.core-test.double-qmark ;clojure.core-test.drop ; Uncaught exception: not a number: nil, https://github.com/jank-lang/jank/issues/243 , https://github.com/jank-lang/jank/issues/245 ;clojure.core-test.drop-last ; Uncaught exception: not a number: nil, https://github.com/jank-lang/jank/issues/244 ;clojure.core-test.drop-while ; Assertion failed! val.is_some(), In clojure.core-test.drop-while$fn_8-90, duplicate definition of symbol '_fn_55_1', https://github.com/jank-lang/jank/issues/243 , https://github.com/jank-lang/jank/issues/212 From fdf6698b276fdc324435d2d52e9a701901b27add Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 27 Dec 2025 12:22:02 -0800 Subject: [PATCH 102/122] Add a todo --- compiler+runtime/src/cpp/jank/aot/processor.cpp | 1 + compiler+runtime/src/cpp/jank/runtime/module/loader.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler+runtime/src/cpp/jank/aot/processor.cpp b/compiler+runtime/src/cpp/jank/aot/processor.cpp index 45e9f5d04..fa308eecd 100644 --- a/compiler+runtime/src/cpp/jank/aot/processor.cpp +++ b/compiler+runtime/src/cpp/jank/aot/processor.cpp @@ -324,6 +324,7 @@ int main(int argc, const char** argv) } std::vector compiler_args{ jtl::move(compiler_args_res.expect_ok()) }; + /* TODO: Use runtime::context::get_output_module_name. */ std::filesystem::path const module_path{ util::cli::opts.output_module_filename.empty() ? util::format("{}/{}.o", __rt_ctx->binary_cache_dir, module::module_to_path(module_name)) diff --git a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp index c494ece2c..eef941579 100644 --- a/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/module/loader.cpp @@ -63,6 +63,7 @@ namespace jank::runtime::module return util::format("jank_load_{}", ret); } + /* TODO: I don't think this is needed. */ jtl::immutable_string nest_module(jtl::immutable_string const &module, jtl::immutable_string const &sub) { From effbaba2c6951b2749e956407a4d5586990389d7 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 27 Dec 2025 12:48:42 -0800 Subject: [PATCH 103/122] Fix some clang-tidy issues --- compiler+runtime/CMakeLists.txt | 12 +-- .../include/cpp/jank/runtime/obj/keyword.hpp | 4 +- .../include/cpp/jank/runtime/oref.hpp | 76 +++++++++---------- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index fd27fcbe5..83fb58845 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -142,11 +142,13 @@ else() set(jank_enable_phase_2 OFF) endif() -if(jank_enable_phase_2) - set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.cpp") -else() - set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.o") -endif() +# TODO: This breaks AOT (and thus the health check), since we look for core object files. +#if(jank_enable_phase_2) +# set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.cpp") +#else() +# set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.o") +#endif() +set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.o") if(jank_test) list(APPEND jank_common_compiler_flags -DJANK_TEST) diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp index 855347934..bbe54dc41 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/keyword.hpp @@ -58,7 +58,7 @@ namespace std template <> struct hash { - size_t operator()(jank::runtime::obj::keyword_ref const o) const noexcept + size_t operator()(jank::runtime::obj::keyword_ref const o) const { return o->to_hash(); } @@ -67,7 +67,7 @@ namespace std template <> struct hash { - size_t operator()(jank::runtime::obj::keyword const &o) const noexcept + size_t operator()(jank::runtime::obj::keyword const &o) const { static auto hasher(std::hash{}); return hasher(const_cast(&o)); diff --git a/compiler+runtime/include/cpp/jank/runtime/oref.hpp b/compiler+runtime/include/cpp/jank/runtime/oref.hpp index e7e0c2d4a..7b8251db5 100644 --- a/compiler+runtime/include/cpp/jank/runtime/oref.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/oref.hpp @@ -42,32 +42,32 @@ namespace jank::runtime oref(nullptr_t) noexcept = delete; - oref(value_type * const data) + oref(value_type * const data) noexcept : data{ data } { - jank_assert_throw(data); + jank_assert(data); } - oref(value_type const * const data) + oref(value_type const * const data) noexcept : data{ const_cast(data) } { - jank_assert_throw(data); + jank_assert(data); } template requires behavior::object_like - oref(T * const typed_data) + oref(T * const typed_data) noexcept : data{ &typed_data->base } { - jank_assert_throw(this->data); + jank_assert(this->data); } template requires behavior::object_like - oref(T const * const typed_data) + oref(T const * const typed_data) noexcept : data{ const_cast(&typed_data->base) } { - jank_assert_throw(this->data); + jank_assert(this->data); } template @@ -79,30 +79,30 @@ namespace jank::runtime ~oref() = default; - void reset() + void reset() noexcept { data = std::bit_cast(jank_const_nil()); } - void reset(object * const o) + void reset(object * const o) noexcept { data = o; } - void reset(oref const &o) + void reset(oref const &o) noexcept { data = o.data; } - value_type *operator->() const + value_type *operator->() const noexcept { - jank_assert_throw(data); + jank_assert(data); return data; } - value_type &operator*() const + value_type &operator*() const noexcept { - jank_assert_throw(data); + jank_assert(data); return *data; } @@ -189,16 +189,16 @@ namespace jank::runtime oref(nullptr_t) = delete; - oref(jtl::remove_const_t * const data) + oref(jtl::remove_const_t * const data) noexcept : data{ data } { - jank_assert_throw(this->data); + jank_assert(this->data); } - oref(T const * const data) + oref(T const * const data) noexcept : data{ const_cast(data) } { - jank_assert_throw(this->data); + jank_assert(this->data); } template @@ -217,43 +217,43 @@ namespace jank::runtime ~oref() = default; - void reset() + void reset() noexcept { data = std::bit_cast(jank_const_nil()); } - void reset(object * const o) + void reset(object * const o) noexcept { data = o; } - void reset(oref const &o) + void reset(oref const &o) noexcept { data = o.data; } - void reset(T * const o) + void reset(T * const o) noexcept { data = o->base; } - void reset(oref const &o) + void reset(oref const &o) noexcept { data = o.data; } - T *operator->() const + T *operator->() const noexcept { /* TODO: Add type name. */ - //jank_assert_fmt_throw(*this, "Null reference on oref<{}>", jtl::type_name()); - jank_assert_throw(is_some()); + //jank_assert_fmt(*this, "Null reference on oref<{}>", jtl::type_name()); + jank_assert(is_some()); return reinterpret_cast(data); } - T &operator*() const + T &operator*() const noexcept { - //jank_assert_fmt_throw(*this, "Null reference on oref<{}>", jtl::type_name()); - jank_assert_throw(is_some()); + //jank_assert_fmt(*this, "Null reference on oref<{}>", jtl::type_name()); + jank_assert(is_some()); return *reinterpret_cast(data); } @@ -284,7 +284,7 @@ namespace jank::runtime oref &operator=(oref const &rhs) noexcept = default; oref &operator=(oref &&rhs) noexcept = default; - oref &operator=(std::remove_cv_t> * const rhs) + oref &operator=(std::remove_cv_t> * const rhs) noexcept { if(data == rhs) { @@ -292,11 +292,11 @@ namespace jank::runtime } data = rhs; - jank_assert_throw(data); + jank_assert(data); return *this; } - oref &operator=(std::remove_cv_t> const * const rhs) + oref &operator=(std::remove_cv_t> const * const rhs) noexcept { if(data == rhs) { @@ -304,7 +304,7 @@ namespace jank::runtime } data = const_cast(rhs); - jank_assert_throw(data); + jank_assert(data); return *this; } @@ -363,16 +363,16 @@ namespace jank::runtime oref(nullptr_t) = delete; - oref(value_type * const data) + oref(value_type * const data) noexcept : data{ data } { - jank_assert_throw(this->data); + jank_assert(this->data); } - oref(value_type const * const data) + oref(value_type const * const data) noexcept : data{ const_cast(data) } { - jank_assert_throw(this->data); + jank_assert(this->data); } template From e13558ed34512d7e85cf3dabe10f693f7fe74e11 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 27 Dec 2025 13:29:59 -0800 Subject: [PATCH 104/122] Force phase 2 source builds for Nix --- compiler+runtime/CMakeLists.txt | 3 +++ flake.nix | 2 ++ 2 files changed, 5 insertions(+) diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index 83fb58845..1f5acc87a 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -149,6 +149,9 @@ endif() # set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.o") #endif() set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.o") +if(jank_force_phase_2) + set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.cpp") +endif() if(jank_test) list(APPEND jank_common_compiler_flags -DJANK_TEST) diff --git a/flake.nix b/flake.nix index 395a72732..9173a8f9c 100644 --- a/flake.nix +++ b/flake.nix @@ -118,6 +118,8 @@ # jank options (lib.cmakeBool "jank_unity_build" true) (lib.cmakeBool "jank_test" finalAttrs.doCheck) + # We run out of memory in CI without this. + (lib.cmakeBool "jank_force_phase_2" true) ]; # Use a UTF-8 locale or else tests which use UTF-8 characters will From 542f60f7e7a52fd9544e6ef4cb6599c1ec732d16 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 27 Dec 2025 13:31:28 -0800 Subject: [PATCH 105/122] Revert "Force phase 2 source builds for Nix" This reverts commit e13558ed34512d7e85cf3dabe10f693f7fe74e11. --- compiler+runtime/CMakeLists.txt | 3 --- flake.nix | 2 -- 2 files changed, 5 deletions(-) diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index 1f5acc87a..83fb58845 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -149,9 +149,6 @@ endif() # set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.o") #endif() set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.o") -if(jank_force_phase_2) - set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.cpp") -endif() if(jank_test) list(APPEND jank_common_compiler_flags -DJANK_TEST) diff --git a/flake.nix b/flake.nix index 9173a8f9c..395a72732 100644 --- a/flake.nix +++ b/flake.nix @@ -118,8 +118,6 @@ # jank options (lib.cmakeBool "jank_unity_build" true) (lib.cmakeBool "jank_test" finalAttrs.doCheck) - # We run out of memory in CI without this. - (lib.cmakeBool "jank_force_phase_2" true) ]; # Use a UTF-8 locale or else tests which use UTF-8 characters will From 5af4cda1e445b25216be4d563b92f009351deb31 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 27 Dec 2025 15:13:57 -0800 Subject: [PATCH 106/122] Force phase 2 source building in CI --- compiler+runtime/CMakeLists.txt | 30 ++++++++++++------- compiler+runtime/bin/ar-merge | 2 +- .../bin/jank/compiler+runtime/build+test.clj | 5 +++- compiler+runtime/cmake/summary.cmake | 2 +- flake.nix | 2 ++ 5 files changed, 28 insertions(+), 13 deletions(-) diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index 83fb58845..0899bd168 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -142,13 +142,13 @@ else() set(jank_enable_phase_2 OFF) endif() -# TODO: This breaks AOT (and thus the health check), since we look for core object files. -#if(jank_enable_phase_2) -# set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.cpp") -#else() -# set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.o") -#endif() -set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.o") +if(jank_enable_phase_2) + set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.cpp") + set(jank_clojure_core_output_artifact "${CMAKE_BINARY_DIR}/CMakeFiles/jank_exe_phase_2.dir/core-libs/clojure/core.cpp.o") +else() + set(jank_clojure_core_output "${CMAKE_BINARY_DIR}/core-libs/clojure/core.o") + set(jank_clojure_core_output_artifact "${jank_clojure_core_output}") +endif() if(jank_test) list(APPEND jank_common_compiler_flags -DJANK_TEST) @@ -363,6 +363,17 @@ set(jank_lib_standalone_deps folly_lib clangCppInterOp ) + +# jank compiles in two phases. The first phase builds the compiler+runtime into a binary +# called jank-phase-1. We then we this compiler to build the core libs (like clojure.core) +# into cpp files. We then compile those and link them into a new binary which is just +# called jank. This bakes in the core libraries so they're very fast to load, but of +# course it means that updating a core library means updating the whole jank binary. +# +# For debug builds, we don't bother building the second phase and we just create a symlink +# called jank which points at jank-phase-1. This makes iteration a little faster, at the +# cost of jank's startup being a little slower, since it's loading the core libs via their +# object files, rather than having them baked in. add_custom_command( DEPENDS ${jank_lib_standalone_deps} OUTPUT ${CMAKE_BINARY_DIR}/libjank-standalone-phase-1.a @@ -377,8 +388,7 @@ add_custom_target( ) add_custom_command( - DEPENDS ${jank_lib_standalone_deps} - jank_core_libraries + DEPENDS ${jank_lib_standalone_deps} jank_exe_phase_2 OUTPUT ${CMAKE_BINARY_DIR}/libjank-standalone.a COMMAND_EXPAND_LISTS VERBATIM @@ -789,7 +799,7 @@ if(jank_enable_phase_2) jank_hook_llvm(jank_exe_phase_2) - add_dependencies(jank_exe_phase_2 jank_lib_standalone_phase_2 jank_core_libraries) + add_dependencies(jank_exe_phase_2 jank_core_libraries) #set_target_properties(jank_exe_phase_2 PROPERTIES LINK_FLAGS_RELEASE "-s") else() diff --git a/compiler+runtime/bin/ar-merge b/compiler+runtime/bin/ar-merge index c25a434f1..335e4180f 100755 --- a/compiler+runtime/bin/ar-merge +++ b/compiler+runtime/bin/ar-merge @@ -32,7 +32,7 @@ case "${command}" in # This follows merge, but also bundles in the Clojure core library object files, following # jank's phase 2 building. merge-phase-2) - object_files="$(cat "${cache_dir}"/*) ${cmake_binary_dir}/core-libs/clojure/core.o" + object_files="$(cat "${cache_dir}"/*) @jank_clojure_core_output_artifact@" merge_output="${cmake_binary_dir}/libjank-standalone.a" rm -f "${merge_output}" # shellcheck disable=SC2086 diff --git a/compiler+runtime/bin/jank/compiler+runtime/build+test.clj b/compiler+runtime/bin/jank/compiler+runtime/build+test.clj index 4c0de5131..8a886855a 100755 --- a/compiler+runtime/bin/jank/compiler+runtime/build+test.clj +++ b/compiler+runtime/bin/jank/compiler+runtime/build+test.clj @@ -31,7 +31,10 @@ (str "-DCMAKE_BUILD_TYPE=" build-type) (str "-Djank_analyze=" analyze) (str "-Djank_sanitize=" sanitize) - (str "-Djank_coverage=" coverage)] + (str "-Djank_coverage=" coverage) + ; We force phase 2 building to use less memory in CI by + ; compiling to cpp files instead of object files. + "-Djank_force_phase_2=on"] configure-flags (cond-> configure-flags (not= "on" analyze) (conj "-DCMAKE_C_COMPILER_LAUNCHER=ccache" diff --git a/compiler+runtime/cmake/summary.cmake b/compiler+runtime/cmake/summary.cmake index c18638433..d24e430d5 100644 --- a/compiler+runtime/cmake/summary.cmake +++ b/compiler+runtime/cmake/summary.cmake @@ -5,7 +5,7 @@ endfunction() jank_message("┌─ jank options ─────────────────────") jank_message("│ jank build type : ${CMAKE_BUILD_TYPE}") jank_message("│ jank version : ${jank_version}") -jank_message("│ jank enable phase 2 : ${jank_enable_phase_2}") +jank_message("│ jank phase 2 : ${jank_enable_phase_2}") jank_message("│ jank tests : ${jank_test}") jank_message("│ jank coverage : ${jank_coverage}") jank_message("│ jank analyze : ${jank_analyze}") diff --git a/flake.nix b/flake.nix index 395a72732..9173a8f9c 100644 --- a/flake.nix +++ b/flake.nix @@ -118,6 +118,8 @@ # jank options (lib.cmakeBool "jank_unity_build" true) (lib.cmakeBool "jank_test" finalAttrs.doCheck) + # We run out of memory in CI without this. + (lib.cmakeBool "jank_force_phase_2" true) ]; # Use a UTF-8 locale or else tests which use UTF-8 characters will From bcd5f6cce4f6e4be30f31dcddbf48b180e02e905 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 27 Dec 2025 15:33:37 -0800 Subject: [PATCH 107/122] Skip linting on generated core cpp files --- compiler+runtime/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index 0899bd168..d498e8e33 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -781,7 +781,10 @@ if(jank_enable_phase_2) add_executable(jank::exe ALIAS jank_exe_phase_2) set_property(TARGET jank_exe_phase_2 PROPERTY OUTPUT_NAME jank) + # Our generated code is not as precisely written as hand-written C++, so we ignore various + # warnings and skip linting. set_source_files_properties(${jank_clojure_core_output} PROPERTIES COMPILE_FLAGS "-w -Wno-c++11-narrowing") + set_source_files_properties(generatedBindings.cpp PROPERTIES SKIP_LINTING ON) # Symbol exporting for JIT. set_target_properties(jank_exe_phase_2 PROPERTIES ENABLE_EXPORTS 1) From 64842a69c7f163b869398bab84c0a1002691df0d Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 27 Dec 2025 15:49:06 -0800 Subject: [PATCH 108/122] Skip Nix builds in CI for now --- .github/workflows/build.yml | 53 +++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 06e4f89dd..ddda0b2ea 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -273,26 +273,33 @@ jobs: run: | scp -i ~/.ssh/jank_id_ed25519 -o StrictHostKeyChecking=no ~/*.tar.gz root@cache.jank-lang.org:/var/www/cache.jank-lang.org/html/ - build-nix: - name: "Nix - release" - runs-on: ubuntu-latest - steps: - - name: "Set up nix" - uses: cachix/install-nix-action@v31 - with: - nix_path: nixpkgs=channel:nixos-unstable - - name: "Set up cachix" - uses: cachix/cachix-action@v16 - with: - name: jank-lang - # If you chose API tokens for write access OR if you have a private cache - authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - # Only push to cache on main branch, not PRs - skipPush: "${{ github.ref != 'refs/heads/main' }}" - - uses: actions/checkout@v4 - with: - submodules: 'recursive' - - name: "Build jank" - run: nix build .?submodules=1 -L - - name: "Check health" - run: nix run .?submodules=1 check-health + # TODO: Fix Nix in CI! + # We're currently running out of memory in CI, due to Clang's memory usage for + # JIT compiled C++ code. Nix, unsurprisingly, uses more RAM than others, so it's + # blocked while others are merely hindered. We should be able to fix this by + # optimizing Clang's memory usage for JIT compiled code. See this gist for + # much more details: https://gist.github.com/jeaye/9adaaa56aee50d5912207907a48d1006 + # + #build-nix: + # name: "Nix - release" + # runs-on: ubuntu-latest + # steps: + # - name: "Set up nix" + # uses: cachix/install-nix-action@v31 + # with: + # nix_path: nixpkgs=channel:nixos-unstable + # - name: "Set up cachix" + # uses: cachix/cachix-action@v16 + # with: + # name: jank-lang + # # If you chose API tokens for write access OR if you have a private cache + # authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' + # # Only push to cache on main branch, not PRs + # skipPush: "${{ github.ref != 'refs/heads/main' }}" + # - uses: actions/checkout@v4 + # with: + # submodules: 'recursive' + # - name: "Build jank" + # run: nix build .?submodules=1 -L + # - name: "Check health" + # run: nix run .?submodules=1 check-health From d6163af5cf4a0f3d395cf09c886f2338c010969c Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 27 Dec 2025 15:55:17 -0800 Subject: [PATCH 109/122] Add an additional Nix note --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ddda0b2ea..a78936a7b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -280,6 +280,10 @@ jobs: # optimizing Clang's memory usage for JIT compiled code. See this gist for # much more details: https://gist.github.com/jeaye/9adaaa56aee50d5912207907a48d1006 # + # It's also possible that we can just use IR gen for Nix. That would require + # some additional CMake support, but is definitely doable. For the alpha, since + # we don't have a finished Nix package anyway, I'm not too concerned about this. + # #build-nix: # name: "Nix - release" # runs-on: ubuntu-latest From 718759fc0ea5ce523740b9d3250693ee27f3fd6e Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 27 Dec 2025 16:10:42 -0800 Subject: [PATCH 110/122] Oops, fix copy pasta --- compiler+runtime/CMakeLists.txt | 2 +- compiler+runtime/doc/install.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index d498e8e33..01145cb32 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -784,7 +784,7 @@ if(jank_enable_phase_2) # Our generated code is not as precisely written as hand-written C++, so we ignore various # warnings and skip linting. set_source_files_properties(${jank_clojure_core_output} PROPERTIES COMPILE_FLAGS "-w -Wno-c++11-narrowing") - set_source_files_properties(generatedBindings.cpp PROPERTIES SKIP_LINTING ON) + set_source_files_properties(${jank_clojure_core_output} PROPERTIES SKIP_LINTING ON) # Symbol exporting for JIT. set_target_properties(jank_exe_phase_2 PROPERTIES ENABLE_EXPORTS 1) diff --git a/compiler+runtime/doc/install.md b/compiler+runtime/doc/install.md index adbd5b46e..b26c3a439 100644 --- a/compiler+runtime/doc/install.md +++ b/compiler+runtime/doc/install.md @@ -1,6 +1,6 @@ # Installing jank If you're on any of the below systems, you can install jank using your system's -package manager. +package manager. If not, you can still [build jank yourself](https://github.com/jank-lang/jank/blob/main/compiler+runtime/doc/build.md). ## Homebrew (macOS or Linux) ### Install From 8fa7a4d31f4ca877f404339a6ef67846c18a7412 Mon Sep 17 00:00:00 2001 From: jeaye Date: Sat, 27 Dec 2025 17:22:16 -0800 Subject: [PATCH 111/122] Limit jobs for release in CI --- compiler+runtime/bin/jank/compiler+runtime/build+test.clj | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler+runtime/bin/jank/compiler+runtime/build+test.clj b/compiler+runtime/bin/jank/compiler+runtime/build+test.clj index 8a886855a..2808ecba6 100755 --- a/compiler+runtime/bin/jank/compiler+runtime/build+test.clj +++ b/compiler+runtime/bin/jank/compiler+runtime/build+test.clj @@ -58,7 +58,10 @@ (util/with-elapsed-time duration (util/quiet-shell {:dir compiler+runtime-dir :extra-env exports} - "./bin/compile -v") + (str "./bin/compile -v" + ; This uses more memory in CI, so we limit parallelism. + (when (= "Release" build-type) + " -j1"))) (util/log-info-with-time duration "Compiled")) (util/quiet-shell {:dir compiler+runtime-dir From 8af6e8f45c903ad31450cb24ac9705e93af5fccd Mon Sep 17 00:00:00 2001 From: jeaye Date: Mon, 29 Dec 2025 19:12:55 -0800 Subject: [PATCH 112/122] Work toward getting lein-jank going again --- .../src/cpp/jank/analyze/processor.cpp | 6 +-- compiler+runtime/src/cpp/jank/util/cli.cpp | 25 ++++++++--- compiler+runtime/src/jank/clojure/core.jank | 41 ++++++++++--------- lein-jank/src/leiningen/jank.clj | 20 ++++++++- 4 files changed, 61 insertions(+), 31 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/analyze/processor.cpp b/compiler+runtime/src/cpp/jank/analyze/processor.cpp index 3d75c2be1..229df9061 100644 --- a/compiler+runtime/src/cpp/jank/analyze/processor.cpp +++ b/compiler+runtime/src/cpp/jank/analyze/processor.cpp @@ -4055,7 +4055,7 @@ namespace jank::analyze auto const count(l->count()); if(count < 2) { - return error::analyze_invalid_cpp_cast( + return error::analyze_invalid_cpp_unbox( "This call to 'cpp/unbox' is missing a C++ type and a value as arguments.", object_source(l->first()), latest_expansion(macro_expansions)) @@ -4063,7 +4063,7 @@ namespace jank::analyze } else if(count < 3) { - return error::analyze_invalid_cpp_cast( + return error::analyze_invalid_cpp_unbox( "This call to 'cpp/unbox' is missing a value to unbox as an argument.", object_source(l->first()), latest_expansion(macro_expansions)) @@ -4071,7 +4071,7 @@ namespace jank::analyze } else if(3 < count) { - return error::analyze_invalid_cpp_cast( + return error::analyze_invalid_cpp_unbox( "A call to 'cpp/unbox' must only have a C++ type and a " "value as arguments and nothing else.", object_source(l->next()->next()->next()->first()), diff --git a/compiler+runtime/src/cpp/jank/util/cli.cpp b/compiler+runtime/src/cpp/jank/util/cli.cpp index 68335924b..93049cdb0 100644 --- a/compiler+runtime/src/cpp/jank/util/cli.cpp +++ b/compiler+runtime/src/cpp/jank/util/cli.cpp @@ -15,12 +15,8 @@ namespace jank::util::cli return "default: " + input; } - jtl::result parse(int const argc, char const **argv) + static void add_global_options(auto &cli) { - CLI::App cli{ "jank compiler" }; - - cli.set_help_flag("-h,--help", "Print this help message and exit."); - /* Runtime. */ cli.add_option( "--module-path", @@ -71,6 +67,15 @@ namespace jank::util::cli opts.libs, "Library identifiers, absolute or relative paths eg. -lfoo for libfoo.so or " "foo.dylib. Can be specified multiple times."); + } + + jtl::result parse(int const argc, char const **argv) + { + CLI::App cli{ "jank compiler" }; + + cli.set_help_flag("-h,--help", "Print this help message and exit."); + + add_global_options(cli); /* Run subcommand. */ auto &cli_run(*cli.add_subcommand("run", "Load and run a file.")); @@ -78,6 +83,7 @@ namespace jank::util::cli cli_run.add_option("file", opts.target_file, "The entrypoint file.") ->check(CLI::ExistingFile) ->required(); + add_global_options(cli_run); /* Compile module subcommand. */ auto &cli_compile_module( @@ -101,23 +107,28 @@ namespace jank::util::cli cli_compile_module .add_option("--output-target", opts.output_target, "The type of file to generate.") ->transform(CLI::CheckedTransformer(output_targets).description("{llvm-ir,cpp,object}")); + add_global_options(cli_compile_module); /* REPL subcommand. */ auto &cli_repl(*cli.add_subcommand("repl", "Start up a terminal REPL and optional server.")); cli_repl.fallthrough(); cli_repl.add_option("module", opts.target_module, "The entrypoint module."); cli_repl.add_flag("--server", opts.repl_server, "Start an nREPL server."); + add_global_options(cli_repl); /* C++ REPL subcommand. */ auto &cli_cpp_repl(*cli.add_subcommand("cpp-repl", "Start up a terminal C++ REPL.")); + cli_cpp_repl.fallthrough(); + add_global_options(cli_cpp_repl); /* Run-main subcommand. */ auto &cli_run_main(*cli.add_subcommand("run-main", "Load and execute -main.")); cli_run_main.fallthrough(); + add_global_options(cli_run_main); cli_run_main .add_option("module", opts.target_module, - "The entrypoint module (must be on the module path.") + "The entrypoint module (must be on the module path).") ->required(); /* Compile subcommand. */ @@ -132,11 +143,13 @@ namespace jank::util::cli cli_compile.add_option("-o", opts.output_filename, "Output executable name.") ->default_str(make_default(opts.output_filename)); cli_compile.add_option("module", opts.target_module, "The entrypoint module.")->required(); + add_global_options(cli_compile); /* Health check subcommand. */ auto &cli_check_health( *cli.add_subcommand("check-health", "Provide a status report on the jank installation.")); cli_check_health.fallthrough(); + add_global_options(cli_check_health); cli.require_subcommand(1); cli.failure_message(CLI::FailureMessage::help); diff --git a/compiler+runtime/src/jank/clojure/core.jank b/compiler+runtime/src/jank/clojure/core.jank index aad3e9d13..8dbacd855 100644 --- a/compiler+runtime/src/jank/clojure/core.jank +++ b/compiler+runtime/src/jank/clojure/core.jank @@ -38,6 +38,27 @@ (def ^:dynamic *print-readably* nil) (def ^:dynamic *read-eval* nil) +(def ^:dynamic + ^{:doc "bound in a repl thread to the most recent value printed"} + *1) + +(def ^:dynamic + ^{:doc "bound in a repl thread to the second most recent value printed"} + *2) + +(def ^:dynamic + ^{:doc "bound in a repl thread to the third most recent value printed"} + *3) + +(def ^:dynamic + ^{:doc "bound in a repl thread to the most recent exception caught by the repl"} + *e) + +(def ^:dynamic + ^{:doc "Bound to true in a repl thread"} + *repl* false) + + (cpp/raw "#include ") (cpp/raw "#include ") (cpp/raw "#include ") @@ -6608,26 +6629,6 @@ fails, attempts to require sym's namespace and retries." ;; (instance? clojure.lang.Indexed coll) (throw "TODO: port indexed?")) -(def ^:dynamic - ^{:doc "bound in a repl thread to the most recent value printed"} - *1) - -(def ^:dynamic - ^{:doc "bound in a repl thread to the second most recent value printed"} - *2) - -(def ^:dynamic - ^{:doc "bound in a repl thread to the third most recent value printed"} - *3) - -(def ^:dynamic - ^{:doc "bound in a repl thread to the most recent exception caught by the repl"} - *e) - -(def ^:dynamic - ^{:doc "Bound to true in a repl thread"} - *repl* false) - (defn trampoline "trampoline can be used to convert algorithms requiring mutual recursion without stack consumption. Calls f with supplied args, if diff --git a/lein-jank/src/leiningen/jank.clj b/lein-jank/src/leiningen/jank.clj index 52422e58a..e9170b141 100644 --- a/lein-jank/src/leiningen/jank.clj +++ b/lein-jank/src/leiningen/jank.clj @@ -9,6 +9,8 @@ [leiningen.core.main :as lmain]) (:import [java.io File])) +(defonce verbose? (atom false)) + (defn build-declarative-flag [flag value] (case flag :direct-call @@ -42,7 +44,6 @@ (build-declarative-flag flag value)) (:jank project)))) - (defn shell-out! [project classpath command compiler-args runtime-args] (let [jank (b.f/which "jank") env (System/getenv) @@ -53,6 +54,8 @@ runtime-args) ; TODO: Better error handling. _ (assert (some? jank)) + _ (when @verbose? + (println ">" (clojure.string/join " " args))) proc (apply ps/shell {:continue true :dir (:root project) @@ -126,12 +129,25 @@ :help (-> fn-ref meta :doc)}) subtask-kw->var))) +(defn process-args [args] + (loop [args args + ret []] + (if (empty? args) + ret + (let [arg (first args) + ret (case arg + "-v" (do + (reset! verbose? true) + ret) + (conj ret arg))] + (recur (rest args) ret))))) + (defn jank "Compile, run and repl into jank." [project subcmd & args] ;(clojure.pprint/pprint (:jank project)) (if-some [handler (subtask-kw->var (keyword subcmd))] - (apply handler project args) + (apply handler project (process-args args)) (do (lmain/warn "Invalid subcommand!") (print-help!) From 08d8a6d383948fa4974460a740420fd20eede37d Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 30 Dec 2025 11:57:53 -0800 Subject: [PATCH 113/122] Remove CLI11 It wouldn't allow me to do simple shit, so I wrote my own arg parser. --- .gitmodules | 3 - compiler+runtime/CMakeLists.txt | 1 - compiler+runtime/cmake/install.cmake | 5 - .../include/cpp/jank/util/cli.hpp | 27 +- compiler+runtime/src/cpp/jank/c_api.cpp | 2 +- compiler+runtime/src/cpp/jank/util/cli.cpp | 572 ++++++++++++------ compiler+runtime/src/cpp/main.cpp | 2 +- compiler+runtime/third-party/cli11 | 1 - 8 files changed, 402 insertions(+), 211 deletions(-) delete mode 160000 compiler+runtime/third-party/cli11 diff --git a/.gitmodules b/.gitmodules index 4bc396c22..087e2f87d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,9 +4,6 @@ [submodule "compiler+runtime/third-party/immer"] path = compiler+runtime/third-party/immer url = https://github.com/jank-lang/immer.git -[submodule "compiler+runtime/third-party/cli11"] - path = compiler+runtime/third-party/cli11 - url = https://github.com/jank-lang/CLI11.git [submodule "compiler+runtime/third-party/boost-preprocessor"] path = compiler+runtime/third-party/boost-preprocessor url = https://github.com/jank-lang/boost-preprocessor.git diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index 01145cb32..1f7959436 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -595,7 +595,6 @@ target_include_directories( "$" "$" "$" - "$" "$" "$" "$" diff --git a/compiler+runtime/cmake/install.cmake b/compiler+runtime/cmake/install.cmake index 70121d454..d13504262 100644 --- a/compiler+runtime/cmake/install.cmake +++ b/compiler+runtime/cmake/install.cmake @@ -67,11 +67,6 @@ jank_glob_install_without_prefix( PATTERN "${CMAKE_SOURCE_DIR}/third-party/immer/immer/*" ) -jank_glob_install_without_prefix( - INPUT_PREFIX "${CMAKE_SOURCE_DIR}/third-party/cli11/" - PATTERN "${CMAKE_SOURCE_DIR}/third-party/cli11/include/*" -) - jank_glob_install_without_prefix( INPUT_PREFIX "${CMAKE_SOURCE_DIR}/third-party/ftxui/" PATTERN "${CMAKE_SOURCE_DIR}/third-party/ftxui/include/*" diff --git a/compiler+runtime/include/cpp/jank/util/cli.hpp b/compiler+runtime/include/cpp/jank/util/cli.hpp index 6e9150a72..603a25dbb 100644 --- a/compiler+runtime/include/cpp/jank/util/cli.hpp +++ b/compiler+runtime/include/cpp/jank/util/cli.hpp @@ -64,8 +64,8 @@ namespace jank::util::cli struct options { /* Runtime. */ - std::string module_path; - std::string profiler_file{ "jank.profile" }; + jtl::immutable_string module_path; + jtl::immutable_string profiler_file{ "jank.profile" }; bool profiler_enabled{}; bool perf_profiling_enabled{}; bool gc_incremental{}; @@ -83,24 +83,22 @@ namespace jank::util::cli bool direct_call{}; /* Run command. */ - std::string target_file; + jtl::immutable_string target_file; /* Compile command. */ - std::string target_module; - std::string target_runtime{ "dynamic" }; - std::string output_filename{ "a.out" }; + jtl::immutable_string target_module; + jtl::immutable_string target_runtime{ "dynamic" }; + jtl::immutable_string output_filename{ "a.out" }; /* Compile-module command. */ - std::string output_module_filename; + jtl::immutable_string output_module_filename; compilation_target output_target{ compilation_target::unspecified }; /* REPL command. */ bool repl_server{}; - /* Extras. - * TODO: Use a native_persistent_vector instead. - * */ - std::vector extra_opts; + /* Extra flags, which will be passed to main. */ + native_vector extra_opts; command command{ command::repl }; }; @@ -108,6 +106,9 @@ namespace jank::util::cli /* NOLINTNEXTLINE */ extern options opts; - jtl::result parse(int const argc, char const **argv); - std::vector parse_empty(int const argc, char const **argv); + /* Affects the global opts. */ + jtl::result parse_opts(int const argc, char const **argv); + + /* Takes the CLI args and puts 'em in a vector. */ + native_vector parse_into_vector(int const argc, char const **argv); } diff --git a/compiler+runtime/src/cpp/jank/c_api.cpp b/compiler+runtime/src/cpp/jank/c_api.cpp index 2c3e0309d..1ab3877ae 100644 --- a/compiler+runtime/src/cpp/jank/c_api.cpp +++ b/compiler+runtime/src/cpp/jank/c_api.cpp @@ -1084,7 +1084,7 @@ extern "C" jank_object_ref jank_parse_command_line_args(int const argc, char const **argv) { obj::transient_vector trans; - auto const args{ util::cli::parse_empty(argc, argv) }; + auto const args{ util::cli::parse_into_vector(argc, argv) }; for(auto const &arg : args) { diff --git a/compiler+runtime/src/cpp/jank/util/cli.cpp b/compiler+runtime/src/cpp/jank/util/cli.cpp index 93049cdb0..e726b5cb9 100644 --- a/compiler+runtime/src/cpp/jank/util/cli.cpp +++ b/compiler+runtime/src/cpp/jank/util/cli.cpp @@ -1,7 +1,5 @@ -#include - #include -#include +#include #include #include @@ -10,210 +8,412 @@ namespace jank::util::cli /* NOLINTNEXTLINE */ options opts; - static std::string make_default(std::string const &input) + using flag_it = native_vector::const_iterator; + + static bool check_flag(flag_it &it, + flag_it const end, + jtl::immutable_string &out, + jtl::immutable_string const &short_flag, + jtl::immutable_string const &long_flag, + bool const needs_value) { - return "default: " + input; + if(*it == long_flag) + { + ++it; + if(needs_value) + { + if(it == end) + { + throw util::format("The '{}' flag requires an argument, but one was not provided.", + long_flag); + } + out = *it; + } + return true; + } + else if(!short_flag.empty() && (*it).starts_with(short_flag)) + { + if(needs_value) + { + out = (*it).substr(short_flag.size()); + if(out.empty()) + { + ++it; + if(it == end) + { + throw util::format("The '{}' flag requires an argument, but one was not provided.", + short_flag); + } + out = *it; + } + } + return true; + } + return false; } - static void add_global_options(auto &cli) + static bool check_flag(flag_it &it, + flag_it const end, + jtl::immutable_string &out, + jtl::immutable_string const &long_flag, + bool const needs_value) { - /* Runtime. */ - cli.add_option( - "--module-path", - opts.module_path, - util::format( - "A {} separated list of directories, JAR files, and ZIP files to search for modules.", - runtime::module::loader::module_separator_name)); - cli.add_flag("--profile", opts.profiler_enabled, "Enable compiler and runtime profiling."); - cli - .add_option("--profile-output", - opts.profiler_file, - "The file to write profile entries (will be overwritten).") - ->default_str(make_default(opts.profiler_file)); - cli.add_flag("--perf", opts.perf_profiling_enabled, "Enable Linux perf event sampling."); - cli.add_flag("--gc-incremental", opts.gc_incremental, "Enable incremental GC collection."); - cli.add_flag("--debug", opts.debug, "Enable debug symbol generation for generated code."); - cli.add_flag("--direct-call", - opts.direct_call, - "Elides the dereferencing of vars for improved performance."); - cli - .add_option("-O,--optimization", - opts.optimization_level, - "The optimization level to use for AOT compilation.") - /* TODO: This does not validate. */ - ->check(CLI::Range(0, 3)); - - std::map const codegen_types{ - { "llvm-ir", codegen_type::llvm_ir }, - { "cpp", codegen_type::cpp } - }; - cli.add_option("--codegen", opts.codegen, "The type of code generation to use.") - ->transform(CLI::CheckedTransformer(codegen_types).description("{llvm-ir,cpp}")) - ->default_str(make_default(codegen_type_str(opts.codegen))); - - /* Native dependencies. */ - cli.add_option("-I,--include-dir", - opts.include_dirs, - "Absolute or relative path to the directory for includes resolution. Can be " - "specified multiple times."); - cli.add_option("-L,--library-dir", - opts.library_dirs, - "Absolute or relative path to the directory to search dynamic libraries in. " - "Can be specified multiple times."); - cli.add_option("-D,--define-macro", - opts.define_macros, - "Defines macro value, sets to 1 if omitted. Can be specified multiple times."); - cli.add_option("-l", - opts.libs, - "Library identifiers, absolute or relative paths eg. -lfoo for libfoo.so or " - "foo.dylib. Can be specified multiple times."); + return check_flag(it, end, out, "", long_flag, needs_value); } - jtl::result parse(int const argc, char const **argv) + static jtl::immutable_string + get_positional_arg(jtl::immutable_string const &command, + jtl::immutable_string const &name, + native_deque &pending_positional_args) { - CLI::App cli{ "jank compiler" }; - - cli.set_help_flag("-h,--help", "Print this help message and exit."); - - add_global_options(cli); - - /* Run subcommand. */ - auto &cli_run(*cli.add_subcommand("run", "Load and run a file.")); - cli_run.fallthrough(); - cli_run.add_option("file", opts.target_file, "The entrypoint file.") - ->check(CLI::ExistingFile) - ->required(); - add_global_options(cli_run); - - /* Compile module subcommand. */ - auto &cli_compile_module( - *cli.add_subcommand("compile-module", - "Compile a module (given its namespace) and its dependencies.")); - cli_compile_module.fallthrough(); - cli_compile_module - .add_option("--runtime", opts.target_runtime, "The runtime of the compiled program.") - ->check(CLI::IsMember({ "dynamic", "static" })) - ->default_str(make_default("dynamic")); - cli_compile_module - .add_option("module", opts.target_module, "Module to compile (must be on the module path).") - ->required(); - cli_compile_module.add_option("-o,--output", opts.output_module_filename, "Output file name."); - - std::map const output_targets{ - { "llvm-ir", compilation_target::llvm_ir }, - { "cpp", compilation_target::cpp }, - { "object", compilation_target::object } - }; - cli_compile_module - .add_option("--output-target", opts.output_target, "The type of file to generate.") - ->transform(CLI::CheckedTransformer(output_targets).description("{llvm-ir,cpp,object}")); - add_global_options(cli_compile_module); - - /* REPL subcommand. */ - auto &cli_repl(*cli.add_subcommand("repl", "Start up a terminal REPL and optional server.")); - cli_repl.fallthrough(); - cli_repl.add_option("module", opts.target_module, "The entrypoint module."); - cli_repl.add_flag("--server", opts.repl_server, "Start an nREPL server."); - add_global_options(cli_repl); - - /* C++ REPL subcommand. */ - auto &cli_cpp_repl(*cli.add_subcommand("cpp-repl", "Start up a terminal C++ REPL.")); - cli_cpp_repl.fallthrough(); - add_global_options(cli_cpp_repl); - - /* Run-main subcommand. */ - auto &cli_run_main(*cli.add_subcommand("run-main", "Load and execute -main.")); - cli_run_main.fallthrough(); - add_global_options(cli_run_main); - cli_run_main - .add_option("module", - opts.target_module, - "The entrypoint module (must be on the module path).") - ->required(); - - /* Compile subcommand. */ - auto &cli_compile(*cli.add_subcommand( - "compile", - "Ahead of time compile project with entrypoint module containing -main.")); - cli_compile.fallthrough(); - cli_compile - .add_option("--runtime", opts.target_runtime, "The runtime of the compiled program.") - ->check(CLI::IsMember({ "dynamic", "static" })) - ->default_str(make_default(opts.target_runtime)); - cli_compile.add_option("-o", opts.output_filename, "Output executable name.") - ->default_str(make_default(opts.output_filename)); - cli_compile.add_option("module", opts.target_module, "The entrypoint module.")->required(); - add_global_options(cli_compile); - - /* Health check subcommand. */ - auto &cli_check_health( - *cli.add_subcommand("check-health", "Provide a status report on the jank installation.")); - cli_check_health.fallthrough(); - add_global_options(cli_check_health); - - cli.require_subcommand(1); - cli.failure_message(CLI::FailureMessage::help); - cli.allow_extras(); - - try + if(pending_positional_args.empty()) { - cli.parse(argc, argv); - } - catch(CLI::ParseError const &e) - { - return err(cli.exit(e)); + throw util::format("Please provide the {} command a {}.", command, name); } - if(cli.remaining_size() >= 0) - { - opts.extra_opts = cli.remaining(); - } + jtl::immutable_string ret{ pending_positional_args.front() }; + pending_positional_args.pop_front(); + return ret; + } - if(cli.got_subcommand(&cli_run)) - { - opts.command = command::run; - } - else if(cli.got_subcommand(&cli_compile_module)) - { - opts.command = command::compile_module; - } - else if(cli.got_subcommand(&cli_repl)) - { - opts.command = command::repl; - } - else if(cli.got_subcommand(&cli_cpp_repl)) - { - opts.command = command::cpp_repl; - } - else if(cli.got_subcommand(&cli_run_main)) - { - opts.command = command::run_main; - } - else if(cli.got_subcommand(&cli_compile)) + static bool check_pending_flag( + jtl::immutable_string const &long_flag, + jtl::immutable_string &out, + native_unordered_map &pending_flags) + { + auto const found{ pending_flags.find(long_flag) }; + if(found == pending_flags.end()) { - opts.command = command::compile; - opts.output_target = compilation_target::object; + return false; } - else if(cli.got_subcommand(&cli_check_health)) + out = found->second; + pending_flags.erase(found); + return true; + } + + static void show_help() + { + /* TODO: Support command help. */ + /* TODO: Provide examples. */ + /* TODO: Improve layout and required arg indicators. */ + /* TODO: Colorize output. */ + util::println(R"( +jank compiler {} + +The jank compiler is used to evaluate and compile jank, Clojure, and C++ sources. + +COMMANDS + run Load and run a file. + compile-module Compile a module (given its namespace) and its dependencies. + repl Start up a terminal REPL and optional server. + cpp-repl Start up a terminal C++ REPL. + run-main Load and execute -main. + compile Ahead of time compile project with entrypoint module containing + -main. + check-health Provide a status report on the jank installation. + +OPTIONS + -h, --help Print this help message and exit. + --module-path + A colon separated list of directories, JAR files, and ZIP files + to search for modules. + --profile Enable compiler and runtime profiling. + --profile-output [default: jank.profile] + The file to write profile entries (will be overwritten). + --perf Enable Linux perf event sampling. + --gc-incremental Enable incremental GC collection. + --debug Enable debug symbol generation for generated code. + --direct-call Elides the dereferencing of vars for improved performance. + -O, --optimization <0 - 3> + The optimization level to use for AOT compilation. + --codegen [default: cpp] + The type of code generation to use. + -I, --include-dir + Absolute or relative path to the directory for includes + resolution. Can be specified multiple times. + -D, --define-macro + Defines a macro. The value will be 1, if omitted. Can be specified + multiple times. + -L, --library-dir + Absolute or relative path to the directory to search dynamic + libraries in. Can be specified multiple times. + -l Library identifiers, absolute or relative paths eg. -lfoo for + libfoo.so or foo.dylib. Can be specified multiple times.)", + JANK_VERSION); + std::exit(1); + } + + jtl::result parse_opts(int const argc, char const **argv) + { + auto const flags{ parse_into_vector(argc, argv) }; + + static native_unordered_map valid_commands{ + { "run", command::run }, + { "run-main", command::run_main }, + { "repl", command::repl }, + { "cpp-repl", command::cpp_repl }, + { "compile-module", command::compile_module }, + { "compile", command::compile }, + { "check-health", command::check_health } + }; + + /* The flow of this is broken into the following steps. + * + * 1. Parse known flags into changes to the `opts` global + * 2. Determine the first positional arg to be the command + * 3. Store other positional args to be handled later (pending) + * 4. Store unhandled flags to be handled later (pending) + * 5. Once we've gone through everything, use the command we have + * to pick apart the pending flags and positional args + * 6. Complain about anything left over */ + try { - opts.command = command::check_health; - } + native_unordered_map pending_flags; + native_deque pending_positional_args; + auto const end{ flags.end() }; + jtl::immutable_string command; + jtl::immutable_string value; + + for(auto it{ flags.begin() }; it != end; ++it) + { + /**** These are all of the global flags which can apply to any command. ****/ + if(check_flag(it, end, value, "--", false)) + { + /* This implies that everything coming after is meant for the running program. */ + std::copy(it, end, std::back_inserter(opts.extra_opts)); + break; + } + else if(check_flag(it, end, value, "-h", "--help", false)) + { + show_help(); + } + else if(check_flag(it, end, value, "--module-path", true)) + { + opts.module_path = value; + } + else if(check_flag(it, end, value, "--profile", false)) + { + opts.profiler_enabled = true; + } + else if(check_flag(it, end, value, "--profile-output", true)) + { + opts.profiler_file = value; + } + else if(check_flag(it, end, value, "--perf", false)) + { + opts.perf_profiling_enabled = true; + } + else if(check_flag(it, end, value, "--direct-call", false)) + { + opts.direct_call = true; + } + else if(check_flag(it, end, value, "-O", "--optimization", true)) + { + if(value == "0") + { + opts.optimization_level = 0; + } + else if(value == "1") + { + opts.optimization_level = 1; + } + else if(value == "2") + { + opts.optimization_level = 2; + } + else if(value == "3") + { + opts.optimization_level = 3; + } + else + { + throw util::format("Invalid optimization level '{}'.", value); + } + } + else if(check_flag(it, end, value, "--codegen", true)) + { + if(value == "cpp") + { + opts.codegen = codegen_type::cpp; + } + else if(value == "llvm-ir") + { + opts.codegen = codegen_type::llvm_ir; + } + else + { + throw util::format("Invalid codegen type '{}'.", value); + } + } + else if(check_flag(it, end, value, "-I", "--include-dir", true)) + { + opts.include_dirs.emplace_back(value); + } + else if(check_flag(it, end, value, "-D", "--define-macro", true)) + { + opts.define_macros.emplace_back(value); + } + else if(check_flag(it, end, value, "-L", "--library-dir", true)) + { + opts.library_dirs.emplace_back(value); + } + else if(check_flag(it, end, value, "-l", "--link", true)) + { + opts.libs.emplace_back(value); + } + + /**** These are command-specific flags which we will store until we know the command. ****/ + else if(check_flag(it, end, value, "-o", "--output", true)) + { + pending_flags["--output"] = value; + } + else if(check_flag(it, end, value, "--output-target", true)) + { + pending_flags["--output-target"] = value; + } + else if(check_flag(it, end, value, "--runtime", true)) + { + pending_flags["--runtime"] = value; + } + else if(command.empty()) + { + command = *it; + auto const found_command{ valid_commands.find(command) }; + if(found_command == valid_commands.end()) + { + throw util::format("Invalid command '{}'.", command); + } + opts.command = found_command->second; + } + else + { + pending_positional_args.emplace_back(*it); + } + } + + if(command.empty()) + { + show_help(); + } - if(opts.codegen == codegen_type::llvm_ir) + /* CLI SHIT + * + * Commands + * run + * + * run-main + *
+ * repl + * cpp-repl + * compile-module + * -o,--output + * --output-target + * + * compile + * --runtime + * -o,--output + *
+ * check-health + * + * Options + * --module-path + * --profile + * --profile-output + * --perf + * --direct-call + * -O,--optimization + * --codegen + * -I + * -D + * -L + * -l + */ + + /* Now process all pending flags, depending on our command. */ + if(command == "run") + { + opts.target_file = get_positional_arg(command, "file", pending_positional_args); + /* TODO: Handle pending flags. */ + } + else if(command == "run-main") + { + opts.target_module = get_positional_arg(command, "module", pending_positional_args); + } + else if(command == "compile-module" || command == "compile") + { + opts.target_module = get_positional_arg(command, "module", pending_positional_args); + if(check_pending_flag("--output", value, pending_flags)) + { + opts.target_file = value; + } + if(check_pending_flag("--output-target", value, pending_flags)) + { + if(value == "llvm-ir") + { + opts.output_target = compilation_target::llvm_ir; + } + else if(value == "cpp") + { + opts.output_target = compilation_target::cpp; + } + else if(value == "object") + { + opts.output_target = compilation_target::object; + } + else + { + throw util::format("Invalid output type '{}'.", value); + } + } + if(check_pending_flag("--runtime", value, pending_flags)) + { + opts.target_file = value; + } + } + + /* If we have any more pending flags at this point, they don't belong. */ + if(!pending_flags.empty()) + { + jtl::string_builder sb; + util::format_to(sb, "These flags were not used:"); + for(auto const &flag : pending_flags) + { + util::format_to(sb, " {}", flag.first); + if(!flag.second.empty()) + { + util::format_to(sb, " {}", flag.second); + } + } + error::warn(sb.release()); + } + else if(!pending_positional_args.empty()) + { + jtl::string_builder sb; + util::format_to(sb, "Extra positional args:"); + for(auto const &arg : pending_positional_args) + { + util::format_to(sb, " {}", arg); + } + throw sb.release(); + } + } + catch(jtl::immutable_string const &msg) { - error::warn( - "LLVM IR code generation is currently unstable and incomplete. Use at your own risk."); + util::println(stderr, "error: {}", msg); + return err(1); } return ok(); } - std::vector parse_empty(int const argc, char const **argv) + native_vector parse_into_vector(int const argc, char const **argv) { - CLI::App cli{ "jank default cli" }; - cli.allow_extras(); - cli.parse(argc, argv); - - return cli.remaining(); + native_vector ret; + ret.reserve(argc - 1); + for(int i{ 1 }; i < argc; ++i) + { + ret.emplace_back(argv[i]); + } + return ret; } } diff --git a/compiler+runtime/src/cpp/main.cpp b/compiler+runtime/src/cpp/main.cpp index 1ac6103cc..9d89312b2 100644 --- a/compiler+runtime/src/cpp/main.cpp +++ b/compiler+runtime/src/cpp/main.cpp @@ -358,7 +358,7 @@ int main(int const argc, char const **argv) using namespace jank::runtime; return jank_init(argc, argv, /*init_default_ctx=*/false, [](int const argc, char const **argv) { - auto const parse_result(util::cli::parse(argc, argv)); + auto const parse_result(util::cli::parse_opts(argc, argv)); if(parse_result.is_err()) { return parse_result.expect_err(); diff --git a/compiler+runtime/third-party/cli11 b/compiler+runtime/third-party/cli11 deleted file mode 160000 index 5a03ee583..000000000 --- a/compiler+runtime/third-party/cli11 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5a03ee58384ce18b6b3de5a2256e18f5ef103633 From c1d0e79e18556788c972e715f1da522353ba45fa Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 30 Dec 2025 12:50:51 -0800 Subject: [PATCH 114/122] Add CI swap --- .github/workflows/build.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a78936a7b..6bbb48222 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -204,6 +204,20 @@ jobs: path: | ${{ github.workspace }}/compiler+runtime/.ctcache key: ctcache-${{ env.JANK_MATRIX_ID }}-${{ github.ref_name }} + - name: Setup swap + if: runner.os == 'Linux' + run: | + swap_size_gb=4 + swap_space_path=/mnt/swapfile + echo "Allocating ${swap_size_gb}G to $swap_space_path" + sudo fallocate -l ${swap_size_gb}G $swap_space_path + sudo chmod 600 $swap_space_path + echo + echo "Creating swap $swap_space_path" + sudo mkswap $swap_space_path + echo + echo "Enabling swap $swap_space_path" + sudo swapon $swap_space_path - name: Build and test jank id: jank-build-step run: | From 48b45382354e53343ed9362ef695d1deb5588529 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 30 Dec 2025 13:54:33 -0800 Subject: [PATCH 115/122] Carry over changes from #631 I didn't bring in the `-framework` usages, since those should not be hard-coded in jank. Instead, perhaps we need to provide an easier mechanism to forward flags to Clang. We do have `JANK_EXTRA_FLAGS`. --- compiler+runtime/src/cpp/jank/aot/processor.cpp | 5 +++++ compiler+runtime/src/cpp/jank/jit/processor.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler+runtime/src/cpp/jank/aot/processor.cpp b/compiler+runtime/src/cpp/jank/aot/processor.cpp index fa308eecd..8174c41d5 100644 --- a/compiler+runtime/src/cpp/jank/aot/processor.cpp +++ b/compiler+runtime/src/cpp/jank/aot/processor.cpp @@ -281,6 +281,11 @@ int main(int argc, const char** argv) compiler_args.push_back(strdup(lib)); } + for(auto const &lib : util::cli::opts.libs) + { + compiler_args.push_back(strdup(util::format("-l{}", lib).c_str())); + } + /* On non-macOS platforms, explicitly link libstdc++. * macOS uses libc++ implicitly via Clang. */ if constexpr(jtl::current_platform != jtl::platform::macos_like) diff --git a/compiler+runtime/src/cpp/jank/jit/processor.cpp b/compiler+runtime/src/cpp/jank/jit/processor.cpp index 5aac28c61..98468c6e3 100644 --- a/compiler+runtime/src/cpp/jank/jit/processor.cpp +++ b/compiler+runtime/src/cpp/jank/jit/processor.cpp @@ -32,7 +32,7 @@ namespace jank::jit static jtl::immutable_string default_shared_lib_name(jtl::immutable_string const &lib) #if defined(__APPLE__) { - return util::format("{}.dylib", lib); + return util::format("lib{}.dylib", lib); } #elif defined(__linux__) { From c4338efdddad42823fa94a92f5b86c0186de8251 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 30 Dec 2025 14:22:23 -0800 Subject: [PATCH 116/122] Use a swap helper --- .github/workflows/build.yml | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6bbb48222..9f98fc559 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -204,20 +204,12 @@ jobs: path: | ${{ github.workspace }}/compiler+runtime/.ctcache key: ctcache-${{ env.JANK_MATRIX_ID }}-${{ github.ref_name }} - - name: Setup swap + - uses: thejerrybao/setup-swap-space@466d59798fb9263b9c2331c83cf71f9b7bfd0c78 if: runner.os == 'Linux' - run: | - swap_size_gb=4 - swap_space_path=/mnt/swapfile - echo "Allocating ${swap_size_gb}G to $swap_space_path" - sudo fallocate -l ${swap_size_gb}G $swap_space_path - sudo chmod 600 $swap_space_path - echo - echo "Creating swap $swap_space_path" - sudo mkswap $swap_space_path - echo - echo "Enabling swap $swap_space_path" - sudo swapon $swap_space_path + with: + swap-space-path: /swapfile + swap-size-gb: 4 + remove-existing-swap-files: true - name: Build and test jank id: jank-build-step run: | From 085e900f98b36b7189f3fd3fbae9b526d379ae24 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 30 Dec 2025 14:42:35 -0800 Subject: [PATCH 117/122] Bump lein-jank version --- lein-jank-template/resources/leiningen/new/jank/project.clj | 2 +- lein-jank/project.clj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lein-jank-template/resources/leiningen/new/jank/project.clj b/lein-jank-template/resources/leiningen/new/jank/project.clj index 8bcbeae38..0de0e9635 100644 --- a/lein-jank-template/resources/leiningen/new/jank/project.clj +++ b/lein-jank-template/resources/leiningen/new/jank/project.clj @@ -2,7 +2,7 @@ :license {:name "MPL 2.0" :url "https://www.mozilla.org/en-US/MPL/2.0/"} :dependencies [] - :plugins [[org.jank-lang/lein-jank "0.2"]] + :plugins [[org.jank-lang/lein-jank "0.3"]] :middleware [leiningen.jank/middleware] :main {{namespace}} :profiles {:debug {:jank {:optimization-level 0}} diff --git a/lein-jank/project.clj b/lein-jank/project.clj index ea294dfa3..96bfcab0f 100644 --- a/lein-jank/project.clj +++ b/lein-jank/project.clj @@ -1,4 +1,4 @@ -(defproject org.jank-lang/lein-jank "0.2" +(defproject org.jank-lang/lein-jank "0.3" :description "Build your jank projects using leiningen." :url "https://jank-lang.org/" :license {:name "MPL 2.0" From c95cb6de16c6f97bd83fcdc15cf5bdadf63c9cb8 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 30 Dec 2025 14:46:44 -0800 Subject: [PATCH 118/122] Clean before building in CI --- compiler+runtime/bin/jank/compiler+runtime/build+test.clj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler+runtime/bin/jank/compiler+runtime/build+test.clj b/compiler+runtime/bin/jank/compiler+runtime/build+test.clj index 2808ecba6..6c4ced121 100755 --- a/compiler+runtime/bin/jank/compiler+runtime/build+test.clj +++ b/compiler+runtime/bin/jank/compiler+runtime/build+test.clj @@ -55,6 +55,12 @@ configure-cmd) (util/log-info-with-time duration "Configured")) + (util/with-elapsed-time duration + (util/quiet-shell {:dir compiler+runtime-dir + :extra-env exports} + "./bin/clean") + (util/log-info-with-time duration "Cleaned")) + (util/with-elapsed-time duration (util/quiet-shell {:dir compiler+runtime-dir :extra-env exports} From 1202356a9e78c673e886857a5c86f309923f4df4 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 30 Dec 2025 15:17:33 -0800 Subject: [PATCH 119/122] Fix cleaning to clear all old core libs --- compiler+runtime/bin/clean | 1 + compiler+runtime/src/cpp/jank/util/cli.cpp | 43 ++++------------------ 2 files changed, 9 insertions(+), 35 deletions(-) diff --git a/compiler+runtime/bin/clean b/compiler+runtime/bin/clean index d2d1022e0..1b1b0831b 100755 --- a/compiler+runtime/bin/clean +++ b/compiler+runtime/bin/clean @@ -13,4 +13,5 @@ pushd "${here}/../build" make clean fi rm -rf ar-cache + rm -rf core-libs popd diff --git a/compiler+runtime/src/cpp/jank/util/cli.cpp b/compiler+runtime/src/cpp/jank/util/cli.cpp index e726b5cb9..6bacf6ebf 100644 --- a/compiler+runtime/src/cpp/jank/util/cli.cpp +++ b/compiler+runtime/src/cpp/jank/util/cli.cpp @@ -296,44 +296,10 @@ OPTIONS show_help(); } - /* CLI SHIT - * - * Commands - * run - * - * run-main - *
- * repl - * cpp-repl - * compile-module - * -o,--output - * --output-target - * - * compile - * --runtime - * -o,--output - *
- * check-health - * - * Options - * --module-path - * --profile - * --profile-output - * --perf - * --direct-call - * -O,--optimization - * --codegen - * -I - * -D - * -L - * -l - */ - /* Now process all pending flags, depending on our command. */ if(command == "run") { opts.target_file = get_positional_arg(command, "file", pending_positional_args); - /* TODO: Handle pending flags. */ } else if(command == "run-main") { @@ -344,7 +310,14 @@ OPTIONS opts.target_module = get_positional_arg(command, "module", pending_positional_args); if(check_pending_flag("--output", value, pending_flags)) { - opts.target_file = value; + if(command == "compile-module") + { + opts.output_module_filename = value; + } + else + { + opts.output_filename = value; + } } if(check_pending_flag("--output-target", value, pending_flags)) { From bb139703c8d2c734c962de7f5e3d159928373895 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 30 Dec 2025 18:08:16 -0800 Subject: [PATCH 120/122] Fix some CLI flags --- compiler+runtime/src/cpp/jank/util/cli.cpp | 12 ++++++++++++ compiler+runtime/test/bash/ahead-of-time/pass-test | 2 +- .../bin/jank/test/error_reporting.clj | 2 +- .../bash/error-reporting/src/aot-with-reparse/setup | 2 +- .../test/bash/error-reporting/src/aot/setup | 2 +- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/compiler+runtime/src/cpp/jank/util/cli.cpp b/compiler+runtime/src/cpp/jank/util/cli.cpp index 6bacf6ebf..93d90b16b 100644 --- a/compiler+runtime/src/cpp/jank/util/cli.cpp +++ b/compiler+runtime/src/cpp/jank/util/cli.cpp @@ -305,6 +305,13 @@ OPTIONS { opts.target_module = get_positional_arg(command, "module", pending_positional_args); } + else if(command == "repl") + { + if(!pending_positional_args.empty()) + { + opts.target_module = get_positional_arg(command, "module", pending_positional_args); + } + } else if(command == "compile-module" || command == "compile") { opts.target_module = get_positional_arg(command, "module", pending_positional_args); @@ -342,6 +349,11 @@ OPTIONS { opts.target_file = value; } + + if(command == "compile" && opts.output_target == compilation_target::unspecified) + { + opts.output_target = compilation_target::object; + } } /* If we have any more pending flags at this point, they don't belong. */ diff --git a/compiler+runtime/test/bash/ahead-of-time/pass-test b/compiler+runtime/test/bash/ahead-of-time/pass-test index dde02123d..6e0229548 100755 --- a/compiler+runtime/test/bash/ahead-of-time/pass-test +++ b/compiler+runtime/test/bash/ahead-of-time/pass-test @@ -18,7 +18,7 @@ :or {optimization-flag "-O0" output-file default-output-file}}] (str "jank " optimization-flag - " --module-path=" module-path + " --module-path " module-path " compile " main-module " -o " output-file)) diff --git a/compiler+runtime/test/bash/error-reporting/bin/jank/test/error_reporting.clj b/compiler+runtime/test/bash/error-reporting/bin/jank/test/error_reporting.clj index f88971779..682edc5b7 100755 --- a/compiler+runtime/test/bash/error-reporting/bin/jank/test/error_reporting.clj +++ b/compiler+runtime/test/bash/error-reporting/bin/jank/test/error_reporting.clj @@ -48,7 +48,7 @@ (let [res @(b.p/process {:out :string :err :out :dir (:dir test)} - "jank --module-path=.:jar.jar run input.jank")] + "jank --module-path .:jar.jar run input.jank")] (assoc test :output (strip-ansi-codes (string/trim (:out res)))))) (defn generate! [tests] diff --git a/compiler+runtime/test/bash/error-reporting/src/aot-with-reparse/setup b/compiler+runtime/test/bash/error-reporting/src/aot-with-reparse/setup index fd7c38e62..883c45c8f 100755 --- a/compiler+runtime/test/bash/error-reporting/src/aot-with-reparse/setup +++ b/compiler+runtime/test/bash/error-reporting/src/aot-with-reparse/setup @@ -2,4 +2,4 @@ set -euo pipefail -jank --module-path=. compile-module aot +jank --module-path . compile-module aot diff --git a/compiler+runtime/test/bash/error-reporting/src/aot/setup b/compiler+runtime/test/bash/error-reporting/src/aot/setup index fd7c38e62..883c45c8f 100755 --- a/compiler+runtime/test/bash/error-reporting/src/aot/setup +++ b/compiler+runtime/test/bash/error-reporting/src/aot/setup @@ -2,4 +2,4 @@ set -euo pipefail -jank --module-path=. compile-module aot +jank --module-path . compile-module aot From 45a1a820e487ee994f49f1876039fb7375412dd3 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 30 Dec 2025 18:36:33 -0800 Subject: [PATCH 121/122] Fix a failing bash test We no longer use CLI11, so we just return 1 on failure. --- compiler+runtime/test/bash/main-exit/pass-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler+runtime/test/bash/main-exit/pass-test b/compiler+runtime/test/bash/main-exit/pass-test index 520defefc..06493c1c6 100755 --- a/compiler+runtime/test/bash/main-exit/pass-test +++ b/compiler+runtime/test/bash/main-exit/pass-test @@ -20,7 +20,7 @@ (is-shell-exit 0 "jank --module-path src run-main jank-test.successful-exit-code") (is-shell-exit 1 "jank --module-path src run-main jank-test.fail-throw-exit") (is-shell-exit 1 "jank --module-path src run-main jank-test.fail-uncatchable-exit") - (is-shell-exit 106 "jank") + (is-shell-exit 1 "jank") (is-shell-exit 1 "jank run src/jank_test/throwing_script.jank") (is-shell-exit 1 "jank run src/jank_test/uncatchable_script.jank") (is-shell-exit 0 "jank run src/jank_test/successful_script.jank")) From 7108bfeb53e57c37d6185c7a970d136b1d456e51 Mon Sep 17 00:00:00 2001 From: jeaye Date: Tue, 30 Dec 2025 18:37:58 -0800 Subject: [PATCH 122/122] Bump up CI swap space --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9f98fc559..d282052a6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -208,7 +208,7 @@ jobs: if: runner.os == 'Linux' with: swap-space-path: /swapfile - swap-size-gb: 4 + swap-size-gb: 8 remove-existing-swap-files: true - name: Build and test jank id: jank-build-step