Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
pashields committed Dec 26, 2013
0 parents commit f23e279
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/target
/classes
/checkouts
pom.xml
pom.xml.asc
*.jar
*.class
/.lein-*
/.nrepl-port
9 changes: 9 additions & 0 deletions project.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(defproject graf-znak "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.5.1"]
[org.clojure/core.typed "0.2.19"]
[org.clojure/algo.generic "0.1.1"]]
:core-typed {:check [graf-znak.core]})
84 changes: 84 additions & 0 deletions src/graf_znak/core.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
(ns graf-znak.core
(:require [clojure.core.typed :refer :all]
[clojure.algo.generic.functor :refer :all])
(:import [java.util.concurrent.atomic AtomicInteger]))

;; Type aliases
(def-alias hook-type (Coll (U Keyword String)))
(def-alias hooks-type (Coll hook-type))
(def-alias state-type (Map hook-type
(Ref1 (Map (Coll Any) AtomicInteger))))
(def-alias input-type (Map (U Keyword String) Any))

(ann ^:no-check clojure.core/not-any? (Fn [(Fn [Any -> Boolean]) (Seq Any)
-> Boolean]))
(ann ^:no-check clojure.core/alter (Fn [Any * -> Any]))
(ann ^:no-check clojure.algo.generic.functor/fmap
(All [x y k]
(Fn [(Fn [x -> y])
(Map k x) ->
(Map k y)])))

(defn> process-hook
"Processes a single input for a single hook"
:- Any
[state :- state-type hook :- hook-type val :- input-type]
(let [groups (get state hook)
group (map #(get val %) hook)]
(assert (not (nil? groups)))
(when (not-any? nil? group)
(if (nil? (get @groups group))
(dosync
(alter groups assoc group (AtomicInteger.)))
(let [^AtomicInteger counter (get @groups group)]
(assert (not (nil? counter)))
(.incrementAndGet counter))))))

(defn> process
"Processes a single input for n hooks"
:- Number
[hooks :- hooks-type state :- state-type val :- input-type]
(count
(remove nil?
(for> :- Any [hook :- hook-type hooks]
(process-hook state hook val)))))

(defn> int-value
:- Int
[^AtomicInteger value :- AtomicInteger]
(.intValue value))

(defn> check-hook
"Returns all groups and their respective counts for a given hook."
:- (Map (Coll Any) Int)
[state :- state-type hook :- hook-type]
(let [categories (get state hook)]
(assert (not (nil? categories)))
(fmap int-value @categories)))

(defn> hook-state-factory
:- (Map (Coll Any) AtomicInteger)
[]
{})

(def-alias send-type (Fn [input-type -> Number]))
(def-alias check-type (Fn [hook-type -> (Map (Coll Any) Int)]))
(def-alias net-type (HMap :mandatory {:send send-type :check check-type}))

(defn> create-net
"Generates a new net."
:- net-type
[hooks :- hooks-type]
(let [state (zipmap hooks (repeatedly #(ref (hook-state-factory))))]
{:send (partial process hooks state)
:check (partial check-hook state)}))

(defn> check
:- (Map (Coll Any) Int)
[net :- net-type hook :- hook-type]
((:check net) hook))

(defn> send
:- Number
[net :- net-type val :- input-type]
((:send net) val))

0 comments on commit f23e279

Please sign in to comment.