<commit_before>;; Copyright (c) <NAME>. All rights reserved.
;; The use and distribution terms for this software are covered by the
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
;; which can be found in the file LICENSE at the root of this distribution.
;; By using this software in any fashion, you are agreeing to be bound by
;; the terms of this license.
;; You must not remove this notice, or any other, from this software.

(ns conexp.contrib.java
  (:use conexp.base)
  (:use clojure.java.io)
  (:require conexp.main
            clojure.pprint))

;;;

(defn- to-valid-Java-name
  "Convert old-name to a valid Java variable name."
  [old-name]
  (let [new-name (-> (str old-name)
                     (.replaceAll "-" "_")
                     (.replaceAll " " "_")
                     (.replaceAll "!" "")
                     (.replaceAll "\\?" "")
                     (.replaceAll "<" "_lt_")
                     (.replaceAll ">" "_gt_")
                     (.replaceAll "=" "_eq_"))]
    (symbol new-name)))

(defvar- conexp-functions
  (let [public-map (ns-publics 'conexp.main)]
    (reduce! (fn [map [sym, ^clojure.lang.Var var]]
               (if-not (.isMacro var)
                 (conj! map [(to-valid-Java-name sym) var])
                 map))
             {}
             public-map))
  "All functions exported by conexp-clj, as a set of Vars.")

(defn- dissect-arglist
  [arglist]
  (let [[a b] (split-with #(not= '& %) arglist)]
    [a (rest b)]))

(defn- function-signatures
  "Returns sequence of function signatures, each being suitable for
  gen-class."
  [new-name, ^clojure.lang.Var var]
  (let [arglists (:arglists (meta var)),
        return   (or (:tag (meta var)) 'Object),
        tag      (fn [x]
                   (let [tag (:tag (meta x))]
                     (if-not tag
                       'Object
                       (case tag
                         Lattice conexp.fca.lattices.Lattice
                         Context conexp.fca.contexts.Context
                         Association-Rule conexp.fca.association_rules.Association-Rule
                         tag))))]
    (if-not arglists
      nil
      (for [arglist arglists]
        (let [arglist-split (dissect-arglist arglist)]
          [new-name
           (if (empty? (second arglist-split))
             (vec (map tag (first arglist-split)))
             (conj (vec (map tag (first arglist-split)))
                   "[Ljava.lang.Object;"))
           return])))))

(defn- generate-definition
  "Generates function definition with name new-name, calling orig-name
  with supplied arguments. Prepends prefix before new-name"
  [prefix new-name orig-name & arglists]
  `(defn ~(symbol (str prefix new-name))
     ~@(for [args arglists]
         (let [arglist-split (dissect-arglist args)]
           `(~args
             ~(if (not-empty (second arglist-split))
                `(apply ~(symbol orig-name) ~@(first arglist-split) ~@(second arglist-split))
                `(~(symbol orig-name) ~@(first arglist-split))))))))

;;;

(defn generate-java-interface
  "Given a name of a file generates the code for the Java interface in
  that file. After this has been compiled it can be used to call
  conexp-clj functions from Java."
  [file-name]
  (let [methods (mapcat #(apply function-signatures %)
                        conexp-functions)
        methods (mapcat #(list (symbol "^{:static true}") %) methods)]
    (with-open [out (writer file-name)]
      (binding [*print-meta* true
                *out* out]
        (clojure.pprint/pprint
         `(do
            (ns ~'conexp.contrib.JavaInterface
              (:require conexp.main)
              (:gen-class
               :prefix ~'conexp-clj-
               :methods ~methods))

            (import 'conexp.fca.contexts.Context)
            (import 'conexp.fca.lattices.Lattice)
            (import 'conexp.fca.association_rules.Association-Rule)

            ~@(for [[new-name, ^clojure.lang.Var var] conexp-functions]
                (let [orig-name (symbol (str (.ns var)) (str (.sym var))),
                      arglists  (:arglists (meta var))]
                  (apply generate-definition
                         "conexp-clj-"
                         new-name
                         orig-name
                         arglists)))))))))

;;;

(generate-java-interface "src/conexp/contrib/JavaInterface.clj")
(compile 'conexp.contrib.JavaInterface)

;;;

nil
<commit_msg>Change renaming convention of "!" and "?"<commit_after>;; Copyright (c) <NAME>. All rights reserved.
;; The use and distribution terms for this software are covered by the
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
;; which can be found in the file LICENSE at the root of this distribution.
;; By using this software in any fashion, you are agreeing to be bound by
;; the terms of this license.
;; You must not remove this notice, or any other, from this software.

(ns conexp.contrib.java
  (:use conexp.base)
  (:use clojure.java.io)
  (:require conexp.main
            clojure.pprint))

;;;

(defn- to-valid-Java-name
  "Convert old-name to a valid Java variable name."
  [old-name]
  (let [new-name (-> (str old-name)
                     (.replaceAll "-" "_")
                     (.replaceAll " " "_")
                     (.replaceAll "!" "_f")   ;assume ! only at end
                     (.replaceAll "\\?" "_p") ;assume ? only at end
                     (.replaceAll "<" "_lt_")
                     (.replaceAll ">" "_gt_")
                     (.replaceAll "=" "_eq_"))]
    (symbol new-name)))

(defvar- conexp-functions
  (let [public-map (ns-publics 'conexp.main)]
    (reduce! (fn [map [sym, ^clojure.lang.Var var]]
               (if-not (.isMacro var)
                 (conj! map [(to-valid-Java-name sym) var])
                 map))
             {}
             public-map))
  "All functions exported by conexp-clj, as a set of Vars.")

(defn- dissect-arglist
  [arglist]
  (let [[a b] (split-with #(not= '& %) arglist)]
    [a (rest b)]))

(defn- function-signatures
  "Returns sequence of function signatures, each being suitable for
  gen-class."
  [new-name, ^clojure.lang.Var var]
  (let [arglists (:arglists (meta var)),
        return   (or (:tag (meta var)) 'Object),
        tag      (fn [x]
                   (let [tag (:tag (meta x))]
                     (if-not tag
                       'Object
                       (case tag
                         Lattice conexp.fca.lattices.Lattice
                         Context conexp.fca.contexts.Context
                         Association-Rule conexp.fca.association_rules.Association-Rule
                         tag))))]
    (if-not arglists
      nil
      (for [arglist arglists]
        (let [arglist-split (dissect-arglist arglist)]
          [new-name
           (if (empty? (second arglist-split))
             (vec (map tag (first arglist-split)))
             (conj (vec (map tag (first arglist-split)))
                   "[Ljava.lang.Object;"))
           return])))))

(defn- generate-definition
  "Generates function definition with name new-name, calling orig-name
  with supplied arguments. Prepends prefix before new-name"
  [prefix new-name orig-name & arglists]
  `(defn ~(symbol (str prefix new-name))
     ~@(for [args arglists]
         (let [arglist-split (dissect-arglist args)]
           `(~args
             ~(if (not-empty (second arglist-split))
                `(apply ~(symbol orig-name) ~@(first arglist-split) ~@(second arglist-split))
                `(~(symbol orig-name) ~@(first arglist-split))))))))

;;;

(defn generate-java-interface
  "Given a name of a file generates the code for the Java interface in
  that file. After this has been compiled it can be used to call
  conexp-clj functions from Java."
  [file-name]
  (let [methods (mapcat #(apply function-signatures %)
                        conexp-functions)
        methods (mapcat #(list (symbol "^{:static true}") %) methods)]
    (with-open [out (writer file-name)]
      (binding [*print-meta* true
                *out* out]
        (clojure.pprint/pprint
         `(do
            (ns ~'conexp.contrib.JavaInterface
              (:require conexp.main)
              (:gen-class
               :prefix ~'conexp-clj-
               :methods ~methods))

            (import 'conexp.fca.contexts.Context)
            (import 'conexp.fca.lattices.Lattice)
            (import 'conexp.fca.association_rules.Association-Rule)

            ~@(for [[new-name, ^clojure.lang.Var var] conexp-functions]
                (let [orig-name (symbol (str (.ns var)) (str (.sym var))),
                      arglists  (:arglists (meta var))]
                  (apply generate-definition
                         "conexp-clj-"
                         new-name
                         orig-name
                         arglists)))))))))

;;;

(generate-java-interface "src/conexp/contrib/JavaInterface.clj")
(compile 'conexp.contrib.JavaInterface)

;;;

nil

{'fraction_non_alphanumeric': 0.13140459363957596, 'fraction_numerical': 0.0008833922261484099, 'mean_word_length': 1.8223745715176067, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7220047', 'n_tokens_mistral': 2767, 'n_tokens_neox': 2629, 'n_words': 763}