Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

namespace jank::runtime::behavior
{
template <typename T>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should split metadatable into two separate concepts? Some objects in Clojure have metadata, but don't support with-meta, so it feels like we need a concept that says: this objects supports reading metadata, but says nothing about how that metadata is set.

Also, I know this should be in its own file, putting it here temporarily.

concept metable = requires(T * const t) {
{ t->meta } -> std::convertible_to<jtl::option<object_ref>>;
};

template <typename T>
concept metadatable = requires(T * const t) {
{ t->with_meta(object_ref{}) } -> std::convertible_to<object_ref>;
Expand Down
1 change: 1 addition & 0 deletions compiler+runtime/include/cpp/jank/runtime/ns.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ namespace jank::runtime

object base{ obj_type };
obj::symbol_ref name{};
jtl::option<object_ref> meta;
/* TODO: Benchmark the use of atomics here. That's what Clojure uses. */
folly::Synchronized<obj::persistent_hash_map_ref> vars;
folly::Synchronized<obj::persistent_hash_map_ref> aliases;
Expand Down
4 changes: 2 additions & 2 deletions compiler+runtime/src/cpp/jank/runtime/core/meta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace jank::runtime
[](auto const typed_m) -> object_ref {
using T = typename decltype(typed_m)::value_type;

if constexpr(behavior::metadatable<T>)
if constexpr(behavior::metable<T>)
{
return typed_m->meta.unwrap_or(jank_nil);
}
Expand Down Expand Up @@ -84,7 +84,7 @@ namespace jank::runtime
[](auto const typed_o, object_ref const m) -> object_ref {
using T = typename decltype(typed_o)::value_type;

if constexpr(behavior::metadatable<T>)
if constexpr(behavior::metable<T>)
{
auto const meta(behavior::detail::validate_meta(m));
typed_o->meta = meta;
Expand Down
88 changes: 61 additions & 27 deletions compiler+runtime/src/jank/clojure/core.jank
Original file line number Diff line number Diff line change
Expand Up @@ -4345,33 +4345,6 @@
[& 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>)"
[& filters]
Expand Down Expand Up @@ -5228,6 +5201,67 @@
(reduce merge-entry (or m1 {}) (seq m2)))]
(reduce merge2 maps))))

(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 ...) (:import ...) (:load ...) (:gen-class)
with the syntax of refer-clojure/require/use/import/load/gen-class
respectively, except the arguments are unevaluated and need not be
quoted. (:gen-class ...), when supplied, defaults to :name
corresponding to the ns name, :main true, :impl-ns same as ns, and
:init-impl-ns true. All options of gen-class are
supported. The :gen-class directive is ignored when not
compiling. If :gen-class is not supplied, when compiled only an
nsname__init.class will be generated. If :refer-clojure is not used, a
default (refer 'clojure.core) is used. Use of ns is preferred to
individual calls to in-ns/require/use/import:

(ns foo.bar
(:refer-clojure :exclude [ancestors printf])
(:require (clojure.contrib sql combinatorics))
(:use (my.lib this that))
(:import (java.util Date Timer Random)
(java.sql Connection Statement)))"
{:arglists '([name docstring? attr-map? references*])
:added "1.0"}
[name & references]
(let [process-reference
(fn [[kname & args]]
`(~(symbol "clojure.core" (clojure.core/name kname))
~@(map #(list 'quote %) args)))
docstring (when (string? (first references)) (first references))
references (if docstring (next references) references)
name (if docstring
(vary-meta name assoc :doc docstring)
name)
metadata (when (map? (first references)) (first references))
references (if metadata (next references) references)
name (if metadata
(vary-meta name merge metadata)
name)
;; gen-class-clause (first (filter #(= :gen-class (first %)) references))
;; gen-class-call
;; (when gen-class-clause
;; (list* `gen-class :name (.replace (str name) \- \_) :impl-ns name :main true (next gen-class-clause)))
references (remove #(= :gen-class (first %)) references)
;ns-effect (clojure.core/in-ns name)
name-metadata (meta name)
refer-full-clojure? (not-any? (fn [ref]
(= :refer-clojure (first ref)))
references)]
`(do
(clojure.core/in-ns '~name)
~@(when name-metadata
`((clojure.core/reset-meta! (clojure.core/find-ns '~name) ~name-metadata)))
; 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)))))

(defn line-seq
"Returns the lines of text from rdr as a lazy sequence of strings.
rdr must implement java.io.BufferedReader."
Expand Down
Loading